Blame | Last modification | View Log | RSS feed
package com.spice.profitmandi.web.controller;import com.spice.profitmandi.service.NotificationService;import com.spice.profitmandi.service.whatsapp.CpassWhatsappService;import com.spice.profitmandi.service.whatsapp.WhatsappMessageType;import org.apache.logging.log4j.LogManager;import org.apache.logging.log4j.Logger;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Value;import org.springframework.http.ResponseEntity;import org.springframework.transaction.annotation.Transactional;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestParam;import org.springframework.web.bind.annotation.RestController;import java.util.Arrays;import java.util.LinkedHashMap;import java.util.List;import java.util.Map;/*** Manual verification endpoints for the cpass (notify24x7 CPaaS) WhatsApp gateway.** <p>These call {@link CpassWhatsappService} directly, regardless of the {@code whatsapp.provider}* flag, so cpass can be exercised end-to-end against the configured gateway. The raw gateway* response is returned in {@code gatewayResponse} on success; any transport / config failure is* returned in {@code error}. Endpoints are unauthenticated (see {@code WebMVCConfig} whitelist) and* intended for testing only — remove or secure before relying on them in production.</p>** <p>Examples:* <pre>* GET /cpass-test/text?mobile=9876543210&body=Hello%20from%20cpass* GET /cpass-test/document?mobile=9876543210&link=https://host/file.pdf&filename=INV.pdf&caption=Your%20invoice* </pre>* </p>*/@RestController@RequestMapping("/cpass-test")@Transactional(rollbackFor = Throwable.class)public class CpassTestController {private static final Logger LOGGER = LogManager.getLogger(CpassTestController.class);@Autowiredprivate CpassWhatsappService cpassWhatsappService;@Autowiredprivate NotificationService notificationService;@Value("${whatsapp.provider:cpass}")private String whatsappProvider;@Value("${prod:false}")private boolean isProd;@GetMapping("/text")public ResponseEntity<?> text(@RequestParam String mobile, @RequestParam String body) {LOGGER.info("cpass-test text: mobile={}", mobile);try {return ResponseEntity.ok(ok("text", mobile, cpassWhatsappService.sendTextDebug(mobile, body)));} catch (Exception e) {LOGGER.error("cpass-test text failed", e);return ResponseEntity.ok(err("text", mobile, e));}}@GetMapping("/image")public ResponseEntity<?> image(@RequestParam String mobile, @RequestParam String link,@RequestParam(required = false) String caption) {LOGGER.info("cpass-test image: mobile={} link={}", mobile, link);try {return ResponseEntity.ok(ok("image", mobile, cpassWhatsappService.sendImageDebug(mobile, link, caption)));} catch (Exception e) {LOGGER.error("cpass-test image failed", e);return ResponseEntity.ok(err("image", mobile, e));}}@GetMapping("/document")public ResponseEntity<?> document(@RequestParam String mobile, @RequestParam String link,@RequestParam(required = false) String caption,@RequestParam(required = false) String filename) {LOGGER.info("cpass-test document: mobile={} link={} filename={}", mobile, link, filename);try {return ResponseEntity.ok(ok("document", mobile,cpassWhatsappService.sendDocumentDebug(mobile, link, caption, filename)));} catch (Exception e) {LOGGER.error("cpass-test document failed", e);return ResponseEntity.ok(err("document", mobile, e));}}/*** Sends a template via cpass. Supports every variant: body variables ({@code body}, comma-separated),* a media header ({@code headerType}=image|video|document + {@code mediaUrl}, plus {@code filename} for* documents), and a dynamic URL call-to-action button ({@code ctaUrl} at {@code ctaIndex}). Omit all* optional params for a no-variable template.*/@GetMapping("/template")public ResponseEntity<?> template(@RequestParam String mobile, @RequestParam String name,@RequestParam(required = false, defaultValue = "en") String lang,@RequestParam(required = false) String body,@RequestParam(required = false) String headerType,@RequestParam(required = false) String mediaUrl,@RequestParam(required = false) String filename,@RequestParam(required = false) String ctaUrl,@RequestParam(required = false, defaultValue = "0") String ctaIndex) {LOGGER.info("cpass-test template: mobile={} name={} lang={} header={} cta={}", mobile, name, lang, headerType, ctaUrl);// body is a comma-separated list of body-variable values; omit for a no-variable template.List<String> params = (body == null || body.isEmpty()) ? null : Arrays.asList(body.split(","));try {return ResponseEntity.ok(ok("template", mobile,cpassWhatsappService.sendTemplateDebug(mobile, name, lang, headerType, mediaUrl, filename, params, ctaIndex, ctaUrl)));} catch (Exception e) {LOGGER.error("cpass-test template failed", e);return ResponseEntity.ok(err("template", mobile, e));}}/*** Sends through {@link NotificationService} so the message goes via the <b>active</b> provider* (gupshup or cpass per {@code whatsapp.provider}) — i.e. the real production path, not cpass* directly. Pass {@code mediaUrl} (+ optional {@code filename}/{@code type}) for a media message;* otherwise a text message is sent. Note: text sends are gated by {@code prod=true} in the* service, while media sends go out regardless.*/@GetMapping("/provider-send")public ResponseEntity<?> providerSend(@RequestParam String mobile,@RequestParam(required = false) String body,@RequestParam(required = false) String title,@RequestParam(required = false) String mediaUrl,@RequestParam(required = false) String filename,@RequestParam(required = false, defaultValue = "DOCUMENT") String type) {LOGGER.info("cpass-test provider-send: provider={} mobile={} media={}", whatsappProvider, mobile, mediaUrl);Map<String, Object> resp = new LinkedHashMap<>();resp.put("type", "provider-send");resp.put("provider", whatsappProvider);resp.put("mobile", mobile);resp.put("prod", isProd);try {boolean sent;if (mediaUrl != null && !mediaUrl.isEmpty()) {sent = notificationService.sendWhatsappMediaMessage(body, mobile, mediaUrl, filename, parseType(type));} else {sent = notificationService.sendWhatsappMessage(body, title, mobile);}resp.put("ok", true);resp.put("sent", sent);if (!sent) {resp.put("note", "sent=false — a text send returns false unless prod=true; media sends go out regardless. See the provider response in logs.");}} catch (Exception e) {LOGGER.error("cpass-test provider-send failed", e);resp.put("ok", false);resp.put("error", e.getClass().getSimpleName() + ": " + e.getMessage());}return ResponseEntity.ok(resp);}private WhatsappMessageType parseType(String type) {try {return WhatsappMessageType.valueOf(type.toUpperCase());} catch (Exception e) {return WhatsappMessageType.DOCUMENT;}}private Map<String, Object> ok(String type, String mobile, String gatewayResponse) {Map<String, Object> body = new LinkedHashMap<>();body.put("ok", true);body.put("type", type);body.put("mobile", mobile);body.put("gatewayResponse", gatewayResponse);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.");return body;}private Map<String, Object> err(String type, String mobile, Exception e) {Map<String, Object> body = new LinkedHashMap<>();body.put("ok", false);body.put("type", type);body.put("mobile", mobile);body.put("error", e.getClass().getSimpleName() + ": " + e.getMessage());return body;}}