|
@@ -0,0 +1,204 @@
|
|
|
+package com.management.platform.controller;
|
|
|
+
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
|
|
+import com.management.platform.entity.Custom;
|
|
|
+import com.management.platform.entity.MiniBindUser;
|
|
|
+import com.management.platform.entity.User;
|
|
|
+import com.management.platform.service.CustomService;
|
|
|
+import com.management.platform.service.MiniBindUserService;
|
|
|
+import com.management.platform.service.UserService;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.apache.commons.codec.digest.DigestUtils;
|
|
|
+import org.apache.commons.lang3.StringUtils;
|
|
|
+import org.dom4j.Document;
|
|
|
+import org.dom4j.DocumentHelper;
|
|
|
+import org.dom4j.Element;
|
|
|
+import org.springframework.web.bind.annotation.*;
|
|
|
+
|
|
|
+import javax.annotation.Resource;
|
|
|
+import java.util.Arrays;
|
|
|
+import java.util.Date;
|
|
|
+import java.util.List;
|
|
|
+
|
|
|
+@RestController
|
|
|
+@RequestMapping("/wechat")
|
|
|
+@Slf4j
|
|
|
+public class WechatCallbackController {
|
|
|
+ private final String TOKEN = "FireRockCRM2025";
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private MiniBindUserService miniBindUserService;
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private UserService userService;
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private CustomService customService;
|
|
|
+
|
|
|
+ // 微信配置验证接口(GET请求)
|
|
|
+ @GetMapping("/callback")
|
|
|
+ public String validate(@RequestParam("signature") String signature,
|
|
|
+ @RequestParam("timestamp") String timestamp,
|
|
|
+ @RequestParam("nonce") String nonce,
|
|
|
+ @RequestParam("echostr") String echostr) {
|
|
|
+ log.info("进入了微信配置验证接口");
|
|
|
+
|
|
|
+ // 1. 将Token、timestamp、nonce按字典序排序
|
|
|
+ String[] arr = new String[]{TOKEN, timestamp, nonce};
|
|
|
+ Arrays.sort(arr);
|
|
|
+
|
|
|
+ // 2. 拼接后SHA1加密
|
|
|
+ String joined = String.join("", arr);
|
|
|
+ String calculatedSignature = DigestUtils.sha1Hex(joined);
|
|
|
+
|
|
|
+ // 3. 验证签名
|
|
|
+ if (calculatedSignature.equals(signature)) {
|
|
|
+ log.info("Invalid signature==>GET请求验证签名成功");
|
|
|
+ return echostr; // 验证成功返回echostr
|
|
|
+ }
|
|
|
+ log.info("Invalid signature==>GET请求验证失败");
|
|
|
+ return "Invalid signature"; // 验证失败
|
|
|
+ }
|
|
|
+
|
|
|
+ @PostMapping(produces = "application/xml;charset=UTF-8",value = "/callback")
|
|
|
+ public String handleMessage(@RequestBody String xmlData) {
|
|
|
+ log.info("接收到微信消息/事件:\n{}", xmlData);
|
|
|
+ try {
|
|
|
+ Document document = DocumentHelper.parseText(xmlData);
|
|
|
+ Element root = document.getRootElement();
|
|
|
+
|
|
|
+ String msgType = root.elementText("MsgType");
|
|
|
+ if (!"event".equals(msgType)) {
|
|
|
+ return successResponse(root);
|
|
|
+ }
|
|
|
+
|
|
|
+ String event = root.elementText("Event");
|
|
|
+ String openId = root.elementText("FromUserName");
|
|
|
+
|
|
|
+ switch (event) {
|
|
|
+ case "subscribe": // 关注事件
|
|
|
+ log.info("用户关注: OpenID={}", openId);
|
|
|
+ handleSubscribe(openId);
|
|
|
+ return buildWelcomeMessage(root);
|
|
|
+
|
|
|
+ case "unsubscribe": // 取消关注事件
|
|
|
+ log.info("用户取消关注: OpenID={}", openId);
|
|
|
+ handleUnsubscribe(openId);
|
|
|
+ return successResponse(root);
|
|
|
+
|
|
|
+ case "SCAN": // 扫码事件(已关注用户)
|
|
|
+ log.info("已关注用户扫码: OpenID={}", openId);
|
|
|
+ handleScan(openId);
|
|
|
+ return successResponse(root);
|
|
|
+
|
|
|
+ default:
|
|
|
+ log.info("忽略的事件类型: {}", event);
|
|
|
+ return successResponse(root);
|
|
|
+ }
|
|
|
+
|
|
|
+ } catch (Exception e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ log.info("回调处理逻辑失败==>"+e.getMessage());
|
|
|
+ return "";
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ private void handleSubscribe(String openId) {
|
|
|
+ // 实现用户关注的业务逻辑
|
|
|
+ log.info("处理用户关注逻辑: {}", openId);
|
|
|
+ List<MiniBindUser> miniBindUserList = miniBindUserService.list(new QueryWrapper<MiniBindUser>().eq("openid", openId));
|
|
|
+ if (!miniBindUserList.isEmpty()) {
|
|
|
+ if (customService.count(new QueryWrapper<Custom>().eq("custom_name", openId))==0){
|
|
|
+ MiniBindUser miniBindUser = miniBindUserList.get(0);
|
|
|
+ Custom custom = new Custom();
|
|
|
+ custom.setCustomName(openId);//用户的openId
|
|
|
+ custom.setIsDelete(0);
|
|
|
+ custom.setCreateTime(new Date());
|
|
|
+ if (StringUtils.isNotEmpty(miniBindUser.getUserId())) {
|
|
|
+ custom.setInchargerId(miniBindUser.getUserId());
|
|
|
+ User user = userService.getById(miniBindUser.getUserId());
|
|
|
+ custom.setCompanyId(user != null ? user.getCompanyId() : null);
|
|
|
+ customService.save(custom);
|
|
|
+ log.info("新增客户成功");
|
|
|
+ }
|
|
|
+ }else {
|
|
|
+ log.info(openId+":系统中已存在对应的客户");
|
|
|
+ }
|
|
|
+ }else {
|
|
|
+ log.info(openId+":对应的客户,暂未绑定相关的销售人员");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void handleUnsubscribe(String openId) {
|
|
|
+ // 实现用户取消关注的业务逻辑
|
|
|
+ customService.remove(new QueryWrapper<Custom>().eq("custom_name", openId));
|
|
|
+ log.info("处理用户取消关注逻辑: {}", openId);
|
|
|
+ }
|
|
|
+
|
|
|
+ private void handleScan(String openId) {
|
|
|
+ log.info("处理用户扫码逻辑: {}", openId);
|
|
|
+ }
|
|
|
+
|
|
|
+ // ========== 响应消息构建方法 ==========
|
|
|
+
|
|
|
+ private String successResponse(Element root) {
|
|
|
+ return String.format(
|
|
|
+ "<xml>" +
|
|
|
+ "<ToUserName><![CDATA[%s]]></ToUserName>" +
|
|
|
+ "<FromUserName><![CDATA[%s]]></FromUserName>" +
|
|
|
+ "<CreateTime>%d</CreateTime>" +
|
|
|
+ "<MsgType><![CDATA[text]]></MsgType>" +
|
|
|
+ "<Content><![CDATA[success]]></Content>" +
|
|
|
+ "</xml>",
|
|
|
+ root.elementText("FromUserName"),
|
|
|
+ root.elementText("ToUserName"),
|
|
|
+ System.currentTimeMillis() / 1000);
|
|
|
+ }
|
|
|
+
|
|
|
+ private String errorResponse() {
|
|
|
+ return "error";
|
|
|
+ }
|
|
|
+
|
|
|
+ /* private String buildWelcomeMessage(Element root) {
|
|
|
+ String welcomeText = "感谢您的关注!\n" +
|
|
|
+ "请点击下方链接完成后续操作:\n" +
|
|
|
+ "https://mobcrm.ttkuaiban.com/guideAttentionToOfficialAccount\n" +
|
|
|
+ "(如果无法直接点击,请复制链接到浏览器打开)";
|
|
|
+
|
|
|
+ return String.format(
|
|
|
+ "<xml>" +
|
|
|
+ "<ToUserName><![CDATA[%s]]></ToUserName>" +
|
|
|
+ "<FromUserName><![CDATA[%s]]></FromUserName>" +
|
|
|
+ "<CreateTime>%d</CreateTime>" +
|
|
|
+ "<MsgType><![CDATA[text]]></MsgType>" +
|
|
|
+ "<Content><![CDATA[%s]]></Content>" +
|
|
|
+ "</xml>",
|
|
|
+ root.elementText("FromUserName"),
|
|
|
+ root.elementText("ToUserName"),
|
|
|
+ System.currentTimeMillis() / 1000,
|
|
|
+ welcomeText);
|
|
|
+ }*/
|
|
|
+
|
|
|
+ private String buildWelcomeMessage(Element root) {
|
|
|
+ return String.format(
|
|
|
+ "<xml>" +
|
|
|
+ "<ToUserName><![CDATA[%s]]></ToUserName>" +
|
|
|
+ "<FromUserName><![CDATA[%s]]></FromUserName>" +
|
|
|
+ "<CreateTime>%d</CreateTime>" +
|
|
|
+ "<MsgType><![CDATA[news]]></MsgType>" +
|
|
|
+ "<ArticleCount>1</ArticleCount>" +
|
|
|
+ "<Articles>" +
|
|
|
+ "<item>" +
|
|
|
+ "<Title><![CDATA[欢迎关注]]></Title>" + // 必须字段
|
|
|
+ "<Description><![CDATA[点击关注公众号]]></Description>" +
|
|
|
+ "<Url><![CDATA[https://mobcrm.ttkuaiban.com/guideAttentionToOfficialAccount]]></Url>" +
|
|
|
+ "</item>" +
|
|
|
+ "</Articles>" +
|
|
|
+ "</xml>",
|
|
|
+ root.elementText("FromUserName"),
|
|
|
+ root.elementText("ToUserName"),
|
|
|
+ System.currentTimeMillis() / 1000);
|
|
|
+ }
|
|
|
+
|
|
|
+}
|