處理微信公衆號消息回調

1、背景

上一節中,咱們知道如何接入微信公衆號,可是以後公衆號會與咱們進行交互,那麼微信公衆號如何通知到咱們本身的服務器呢?咱們知道咱們接入的時候提供的url是 GET /mp/entry,那麼公衆號以後產生的事件將會以 POST /mp/entry 發送到咱們本身的服務器上。html

2、代碼實現,此處仍是使用 weixin-java-mp 這個框架實現

一、引入 weixin-java-mp

<dependency>
    <groupId>com.github.binarywang</groupId>
     <artifactId>weixin-java-mp</artifactId>
     <version>4.0.0</version>
 </dependency>

二、編寫 配置

@Configuration
public class WxMpConfiguration {

    @Autowired
    private WxMpProperties wxMpProperties;
    @Autowired
    private SubscribeHandler subscribeHandler;
    @Autowired
    private UnsubscribeHandler unsubscribeHandler;

    @Bean
    public WxMpService wxMpService() {
        WxMpServiceImpl wxMpService = new WxMpServiceImpl();
        wxMpService.setWxMpConfigStorage(wxMpConfigStorage());
        // 設置多個微信公衆號的配置
        // wxMpService.setMultiConfigStorages();
        return wxMpService;
    }

    /**
     * 這個地方的配置是保存在本地,生產環境須要本身擴展,能夠保存在Redis中等等
     *
     * @return WxMpConfigStorage
     */
    public WxMpConfigStorage wxMpConfigStorage() {
        WxMpDefaultConfigImpl storage = new WxMpDefaultConfigImpl();
        storage.setAppId(wxMpProperties.getAppId());
        storage.setSecret(wxMpProperties.getAppSecret());
        storage.setAesKey(wxMpProperties.getAesKey());
        storage.setToken(wxMpProperties.getToken());
        return storage;
    }

    @Bean
    public WxMpMessageRouter messageRouter(WxMpService wxMpService) {
        WxMpMessageRouter router = new WxMpMessageRouter(wxMpService);
        // 消息去重
        router.setMessageDuplicateChecker(new WxMessageInMemoryDuplicateChecker());

        // 關注事件
        router.rule().async(false).msgType(EVENT).event(SUBSCRIBE)
                .handler(this.subscribeHandler)
                .end();
        // 取消關注事件
        router.rule().async(false).msgType(EVENT).event(UNSUBSCRIBE)
                .handler(this.unsubscribeHandler)
                .end();
        return router;
    }
}

一、公衆號回調給咱們的消息會經過 WxMpMessageRouter 來處理。
二、配置的時候須要作好消息的去重處理,若是咱們的服務器5s種沒給微信服務器響應,微信服務器會重試 3次
三、處理消息實現WxMpMessageHandler接口java

三、回調入口

/**
     * 微信回調
     *
     * @param requestBody
     * @param signature
     * @param timestamp
     * @param nonce
     * @param openid
     * @param encType
     * @param msgSignature
     * @return
     */
    @PostMapping("/mp/entry")
    public String entryCallback(@RequestBody String requestBody,
                                @RequestParam("signature") String signature,
                                @RequestParam("timestamp") String timestamp,
                                @RequestParam("nonce") String nonce,
                                @RequestParam("openid") String openid,
                                @RequestParam(name = "encrypt_type", required = false) String encType,
                                @RequestParam(name = "msg_signature", required = false) String msgSignature) {
        log.info("\n接收微信請求:[openid=[{}], [signature=[{}], encType=[{}], msgSignature=[{}],"
                        + " timestamp=[{}], nonce=[{}], requestBody=[\n{}\n] ",
                openid, signature, encType, msgSignature, timestamp, nonce, requestBody);

        if (!wxMpService.checkSignature(timestamp, nonce, signature)) {
            throw new IllegalArgumentException("非法請求,可能屬於僞造的請求!");
        }

        String out = null;
        if (encType == null) {
            // 明文傳輸的消息
            WxMpXmlMessage inMessage = WxMpXmlMessage.fromXml(requestBody);
            WxMpXmlOutMessage outMessage = this.wxMpMessageRouter.route(inMessage);
            if (outMessage == null) {
                return "";
            }
            out = outMessage.toXml();
        } else if ("aes".equalsIgnoreCase(encType)) {
            // aes加密的消息
            WxMpXmlMessage inMessage = WxMpXmlMessage.fromEncryptedXml(requestBody, wxMpService.getWxMpConfigStorage(),
                    timestamp, nonce, msgSignature);
            log.info("\n消息解密後內容爲:\n[{}] ", inMessage.toString());
            WxMpXmlOutMessage outMessage = this.wxMpMessageRouter.route(inMessage);
            if (outMessage == null) {
                return "";
            }
            out = outMessage.toEncryptedXml(wxMpService.getWxMpConfigStorage());
        }
        log.info("\n組裝回覆信息:[{}]", out);
        return out;
    }

3、參考文檔

一、公衆號消息加解密
二、接收普通消息
三、接收事件消息git

4、代碼實現

https://gitee.com/huan1993/wechat-developmentgithub

相關文章
相關標籤/搜索