| 36969 |
vikas |
1 |
package com.spice.profitmandi.web.controller;
|
|
|
2 |
|
|
|
3 |
import com.spice.profitmandi.service.NotificationService;
|
|
|
4 |
import com.spice.profitmandi.service.whatsapp.CpassWhatsappService;
|
|
|
5 |
import com.spice.profitmandi.service.whatsapp.WhatsappMessageType;
|
|
|
6 |
import org.apache.logging.log4j.LogManager;
|
|
|
7 |
import org.apache.logging.log4j.Logger;
|
|
|
8 |
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
9 |
import org.springframework.beans.factory.annotation.Value;
|
|
|
10 |
import org.springframework.http.ResponseEntity;
|
|
|
11 |
import org.springframework.transaction.annotation.Transactional;
|
|
|
12 |
import org.springframework.web.bind.annotation.GetMapping;
|
|
|
13 |
import org.springframework.web.bind.annotation.RequestMapping;
|
|
|
14 |
import org.springframework.web.bind.annotation.RequestParam;
|
|
|
15 |
import org.springframework.web.bind.annotation.RestController;
|
|
|
16 |
|
|
|
17 |
import java.util.Arrays;
|
|
|
18 |
import java.util.LinkedHashMap;
|
|
|
19 |
import java.util.List;
|
|
|
20 |
import java.util.Map;
|
|
|
21 |
|
|
|
22 |
/**
|
|
|
23 |
* Manual verification endpoints for the cpass (notify24x7 CPaaS) WhatsApp gateway.
|
|
|
24 |
*
|
|
|
25 |
* <p>These call {@link CpassWhatsappService} directly, regardless of the {@code whatsapp.provider}
|
|
|
26 |
* flag, so cpass can be exercised end-to-end against the configured gateway. The raw gateway
|
|
|
27 |
* response is returned in {@code gatewayResponse} on success; any transport / config failure is
|
|
|
28 |
* returned in {@code error}. Endpoints are unauthenticated (see {@code WebMVCConfig} whitelist) and
|
|
|
29 |
* intended for testing only — remove or secure before relying on them in production.</p>
|
|
|
30 |
*
|
|
|
31 |
* <p>Examples:
|
|
|
32 |
* <pre>
|
|
|
33 |
* GET /cpass-test/text?mobile=9876543210&body=Hello%20from%20cpass
|
|
|
34 |
* GET /cpass-test/document?mobile=9876543210&link=https://host/file.pdf&filename=INV.pdf&caption=Your%20invoice
|
|
|
35 |
* </pre>
|
|
|
36 |
* </p>
|
|
|
37 |
*/
|
|
|
38 |
@RestController
|
|
|
39 |
@RequestMapping("/cpass-test")
|
|
|
40 |
@Transactional(rollbackFor = Throwable.class)
|
|
|
41 |
public class CpassTestController {
|
|
|
42 |
|
|
|
43 |
private static final Logger LOGGER = LogManager.getLogger(CpassTestController.class);
|
|
|
44 |
|
|
|
45 |
@Autowired
|
|
|
46 |
private CpassWhatsappService cpassWhatsappService;
|
|
|
47 |
|
|
|
48 |
@Autowired
|
|
|
49 |
private NotificationService notificationService;
|
|
|
50 |
|
|
|
51 |
@Value("${whatsapp.provider:cpass}")
|
|
|
52 |
private String whatsappProvider;
|
|
|
53 |
|
|
|
54 |
@Value("${prod:false}")
|
|
|
55 |
private boolean isProd;
|
|
|
56 |
|
|
|
57 |
@GetMapping("/text")
|
|
|
58 |
public ResponseEntity<?> text(@RequestParam String mobile, @RequestParam String body) {
|
|
|
59 |
LOGGER.info("cpass-test text: mobile={}", mobile);
|
|
|
60 |
try {
|
|
|
61 |
return ResponseEntity.ok(ok("text", mobile, cpassWhatsappService.sendTextDebug(mobile, body)));
|
|
|
62 |
} catch (Exception e) {
|
|
|
63 |
LOGGER.error("cpass-test text failed", e);
|
|
|
64 |
return ResponseEntity.ok(err("text", mobile, e));
|
|
|
65 |
}
|
|
|
66 |
}
|
|
|
67 |
|
|
|
68 |
@GetMapping("/image")
|
|
|
69 |
public ResponseEntity<?> image(@RequestParam String mobile, @RequestParam String link,
|
|
|
70 |
@RequestParam(required = false) String caption) {
|
|
|
71 |
LOGGER.info("cpass-test image: mobile={} link={}", mobile, link);
|
|
|
72 |
try {
|
|
|
73 |
return ResponseEntity.ok(ok("image", mobile, cpassWhatsappService.sendImageDebug(mobile, link, caption)));
|
|
|
74 |
} catch (Exception e) {
|
|
|
75 |
LOGGER.error("cpass-test image failed", e);
|
|
|
76 |
return ResponseEntity.ok(err("image", mobile, e));
|
|
|
77 |
}
|
|
|
78 |
}
|
|
|
79 |
|
|
|
80 |
@GetMapping("/document")
|
|
|
81 |
public ResponseEntity<?> document(@RequestParam String mobile, @RequestParam String link,
|
|
|
82 |
@RequestParam(required = false) String caption,
|
|
|
83 |
@RequestParam(required = false) String filename) {
|
|
|
84 |
LOGGER.info("cpass-test document: mobile={} link={} filename={}", mobile, link, filename);
|
|
|
85 |
try {
|
|
|
86 |
return ResponseEntity.ok(ok("document", mobile,
|
|
|
87 |
cpassWhatsappService.sendDocumentDebug(mobile, link, caption, filename)));
|
|
|
88 |
} catch (Exception e) {
|
|
|
89 |
LOGGER.error("cpass-test document failed", e);
|
|
|
90 |
return ResponseEntity.ok(err("document", mobile, e));
|
|
|
91 |
}
|
|
|
92 |
}
|
|
|
93 |
|
|
|
94 |
/**
|
|
|
95 |
* Sends a template via cpass. Supports every variant: body variables ({@code body}, comma-separated),
|
|
|
96 |
* a media header ({@code headerType}=image|video|document + {@code mediaUrl}, plus {@code filename} for
|
|
|
97 |
* documents), and a dynamic URL call-to-action button ({@code ctaUrl} at {@code ctaIndex}). Omit all
|
|
|
98 |
* optional params for a no-variable template.
|
|
|
99 |
*/
|
|
|
100 |
@GetMapping("/template")
|
|
|
101 |
public ResponseEntity<?> template(@RequestParam String mobile, @RequestParam String name,
|
|
|
102 |
@RequestParam(required = false, defaultValue = "en") String lang,
|
|
|
103 |
@RequestParam(required = false) String body,
|
|
|
104 |
@RequestParam(required = false) String headerType,
|
|
|
105 |
@RequestParam(required = false) String mediaUrl,
|
|
|
106 |
@RequestParam(required = false) String filename,
|
|
|
107 |
@RequestParam(required = false) String ctaUrl,
|
|
|
108 |
@RequestParam(required = false, defaultValue = "0") String ctaIndex) {
|
|
|
109 |
LOGGER.info("cpass-test template: mobile={} name={} lang={} header={} cta={}", mobile, name, lang, headerType, ctaUrl);
|
|
|
110 |
// body is a comma-separated list of body-variable values; omit for a no-variable template.
|
|
|
111 |
List<String> params = (body == null || body.isEmpty()) ? null : Arrays.asList(body.split(","));
|
|
|
112 |
try {
|
|
|
113 |
return ResponseEntity.ok(ok("template", mobile,
|
|
|
114 |
cpassWhatsappService.sendTemplateDebug(mobile, name, lang, headerType, mediaUrl, filename, params, ctaIndex, ctaUrl)));
|
|
|
115 |
} catch (Exception e) {
|
|
|
116 |
LOGGER.error("cpass-test template failed", e);
|
|
|
117 |
return ResponseEntity.ok(err("template", mobile, e));
|
|
|
118 |
}
|
|
|
119 |
}
|
|
|
120 |
|
|
|
121 |
/**
|
|
|
122 |
* Sends through {@link NotificationService} so the message goes via the <b>active</b> provider
|
|
|
123 |
* (gupshup or cpass per {@code whatsapp.provider}) — i.e. the real production path, not cpass
|
|
|
124 |
* directly. Pass {@code mediaUrl} (+ optional {@code filename}/{@code type}) for a media message;
|
|
|
125 |
* otherwise a text message is sent. Note: text sends are gated by {@code prod=true} in the
|
|
|
126 |
* service, while media sends go out regardless.
|
|
|
127 |
*/
|
|
|
128 |
@GetMapping("/provider-send")
|
|
|
129 |
public ResponseEntity<?> providerSend(@RequestParam String mobile,
|
|
|
130 |
@RequestParam(required = false) String body,
|
|
|
131 |
@RequestParam(required = false) String title,
|
|
|
132 |
@RequestParam(required = false) String mediaUrl,
|
|
|
133 |
@RequestParam(required = false) String filename,
|
|
|
134 |
@RequestParam(required = false, defaultValue = "DOCUMENT") String type) {
|
|
|
135 |
LOGGER.info("cpass-test provider-send: provider={} mobile={} media={}", whatsappProvider, mobile, mediaUrl);
|
|
|
136 |
Map<String, Object> resp = new LinkedHashMap<>();
|
|
|
137 |
resp.put("type", "provider-send");
|
|
|
138 |
resp.put("provider", whatsappProvider);
|
|
|
139 |
resp.put("mobile", mobile);
|
|
|
140 |
resp.put("prod", isProd);
|
|
|
141 |
try {
|
|
|
142 |
boolean sent;
|
|
|
143 |
if (mediaUrl != null && !mediaUrl.isEmpty()) {
|
|
|
144 |
sent = notificationService.sendWhatsappMediaMessage(body, mobile, mediaUrl, filename, parseType(type));
|
|
|
145 |
} else {
|
|
|
146 |
sent = notificationService.sendWhatsappMessage(body, title, mobile);
|
|
|
147 |
}
|
|
|
148 |
resp.put("ok", true);
|
|
|
149 |
resp.put("sent", sent);
|
|
|
150 |
if (!sent) {
|
|
|
151 |
resp.put("note", "sent=false — a text send returns false unless prod=true; media sends go out regardless. See the provider response in logs.");
|
|
|
152 |
}
|
|
|
153 |
} catch (Exception e) {
|
|
|
154 |
LOGGER.error("cpass-test provider-send failed", e);
|
|
|
155 |
resp.put("ok", false);
|
|
|
156 |
resp.put("error", e.getClass().getSimpleName() + ": " + e.getMessage());
|
|
|
157 |
}
|
|
|
158 |
return ResponseEntity.ok(resp);
|
|
|
159 |
}
|
|
|
160 |
|
|
|
161 |
private WhatsappMessageType parseType(String type) {
|
|
|
162 |
try {
|
|
|
163 |
return WhatsappMessageType.valueOf(type.toUpperCase());
|
|
|
164 |
} catch (Exception e) {
|
|
|
165 |
return WhatsappMessageType.DOCUMENT;
|
|
|
166 |
}
|
|
|
167 |
}
|
|
|
168 |
|
|
|
169 |
private Map<String, Object> ok(String type, String mobile, String gatewayResponse) {
|
|
|
170 |
Map<String, Object> body = new LinkedHashMap<>();
|
|
|
171 |
body.put("ok", true);
|
|
|
172 |
body.put("type", type);
|
|
|
173 |
body.put("mobile", mobile);
|
|
|
174 |
body.put("gatewayResponse", gatewayResponse);
|
|
|
175 |
body.put("note", "ok=true means the gateway was reached; inspect gatewayResponse for the message id or any error, and check the recipient's WhatsApp for delivery.");
|
|
|
176 |
return body;
|
|
|
177 |
}
|
|
|
178 |
|
|
|
179 |
private Map<String, Object> err(String type, String mobile, Exception e) {
|
|
|
180 |
Map<String, Object> body = new LinkedHashMap<>();
|
|
|
181 |
body.put("ok", false);
|
|
|
182 |
body.put("type", type);
|
|
|
183 |
body.put("mobile", mobile);
|
|
|
184 |
body.put("error", e.getClass().getSimpleName() + ": " + e.getMessage());
|
|
|
185 |
return body;
|
|
|
186 |
}
|
|
|
187 |
}
|