WeixinMPController.java 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. package com.kym.miniapp.controller;
  2. import cn.dev33.satoken.annotation.SaIgnore;
  3. import com.kym.common.annotation.ApiLog;
  4. import com.kym.common.annotation.SysLog;
  5. import com.kym.common.utils.wx.WxPbUtil;
  6. import com.kym.common.R;
  7. import com.kym.service.MpRelationService;
  8. import com.kym.service.wechat.WeixinMPService;
  9. import jakarta.servlet.http.HttpServletRequest;
  10. import com.alibaba.fastjson2.JSON;
  11. import me.chanjar.weixin.mp.api.WxMpService;
  12. import jakarta.servlet.http.HttpServletResponse;
  13. import lombok.extern.slf4j.Slf4j;
  14. import me.chanjar.weixin.common.error.WxErrorException;
  15. import org.springframework.http.MediaType;
  16. import org.springframework.stereotype.Controller;
  17. import org.springframework.web.bind.annotation.GetMapping;
  18. import org.springframework.web.bind.annotation.PostMapping;
  19. import org.springframework.web.bind.annotation.RequestMapping;
  20. import org.springframework.web.bind.annotation.ResponseBody;
  21. import java.io.PrintWriter;
  22. @Controller
  23. @RequestMapping("wx")
  24. @Slf4j
  25. public class WeixinMPController {
  26. private final WeixinMPService weixinMPService;
  27. private final MpRelationService mpRelationService;
  28. private final WxMpService wxMpService;
  29. public WeixinMPController(WeixinMPService weixinMPService, MpRelationService mpRelationService,
  30. WxMpService wxMpService) {
  31. this.weixinMPService = weixinMPService;
  32. this.mpRelationService = mpRelationService;
  33. this.wxMpService = wxMpService;
  34. }
  35. /**
  36. * 消息通知(订阅、用户消息)
  37. */
  38. @PostMapping(value = "notify", produces = MediaType.TEXT_XML_VALUE)
  39. @ApiLog(value = "微信公众号服务器推送消息", ignoreParams = true)
  40. public void handleMessage(HttpServletRequest request, HttpServletResponse response) {
  41. weixinMPService.handleWxMPNotify(request, response);
  42. }
  43. /**
  44. * 微信服务器token验证
  45. */
  46. @GetMapping(value = "notify")
  47. @SaIgnore
  48. @SysLog("微信服务器token验证")
  49. public void checkSign(HttpServletResponse response, String signature, String timestamp, String nonce, String echostr) {
  50. String responseVal = echostr;
  51. try {
  52. boolean resp = WxPbUtil.checkSign(signature, timestamp, nonce);
  53. if (!resp) {
  54. responseVal = "failure";
  55. log.error("wxpb check sign ERR!!!!");
  56. }
  57. } catch (Exception e) {
  58. responseVal = "failure";
  59. } finally {
  60. try {
  61. PrintWriter writer = response.getWriter();
  62. writer.print(responseVal);
  63. writer.flush();
  64. writer.close();
  65. } catch (Exception e) {
  66. log.error(e.getMessage(), e);
  67. }
  68. }
  69. }
  70. /**
  71. * 导出当前公众号自定义菜单结构(调试用)
  72. */
  73. @GetMapping(value = "/exportMenu")
  74. @ResponseBody
  75. public R<?> exportMenu() {
  76. try {
  77. var menu = wxMpService.getMenuService().menuGet();
  78. return R.success(JSON.toJSONString(menu));
  79. } catch (WxErrorException e) {
  80. log.error("导出菜单失败", e);
  81. return R.failed(-1, "导出失败: " + e.getMessage());
  82. }
  83. }
  84. /**
  85. * 通过 API 创建公众号自定义菜单(服务器推送启用后使用)
  86. */
  87. @PostMapping(value = "/createMenu")
  88. @ResponseBody
  89. public R<?> createMenu() {
  90. try {
  91. String menuJson = "{\"button\":[{\"type\":\"view\",\"name\":\"停车减免\",\"url\":\"https://cloud.yeswash.cn/parking.html\"},{\"type\":\"view\",\"name\":\"商家入口\",\"url\":\"https://cloud.yeswash.cn/h5#/\"}]}";
  92. log.info("创建菜单: {}", menuJson);
  93. String result = wxMpService.getMenuService().menuCreate(menuJson);
  94. log.info("菜单创建结果: {}", result);
  95. return R.success(result);
  96. } catch (WxErrorException e) {
  97. log.error("创建菜单失败: {}", e.getMessage(), e);
  98. return R.failed(e.getError().getErrorCode(), e.getError().getErrorMsg());
  99. } catch (Exception e) {
  100. log.error("创建菜单异常", e);
  101. return R.failed(500, e.getMessage());
  102. }
  103. }
  104. /**
  105. * 手动同步公众号关注用户(一次性触发)
  106. */
  107. @GetMapping(value = "/syncMpUsers")
  108. @SaIgnore
  109. @ResponseBody
  110. public R<?> syncMpUsers() {
  111. try {
  112. mpRelationService.batchBindMpUser();
  113. return R.success("同步完成");
  114. } catch (WxErrorException e) {
  115. log.error("手动同步公众号用户失败", e);
  116. return R.failed(-1, "同步失败: " + e.getMessage());
  117. }
  118. }
  119. }