Subversion Repositories SmartDukaan

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
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&amp;body=Hello%20from%20cpass
34
 *   GET /cpass-test/document?mobile=9876543210&amp;link=https://host/file.pdf&amp;filename=INV.pdf&amp;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
}