/** * Copyright (c) 2011-2014, James Zhan 詹波 (inlet@126.com). *

* Licensed under the Apache License, Version 2.0 (the "License"); */ package com.zzwtec.wechat.sdk.inlet; import com.jfinal.kit.StrKit; import com.zzwtec.wechat.sdk.aop.annotation.ZZWAround; import com.zzwtec.wechat.sdk.aop.annotation.ZZWMsgController; import com.zzwtec.wechat.sdk.aop.inject.impl.ApiHandler; import com.zzwtec.wechat.sdk.api.ApiConfigKit; import com.zzwtec.wechat.sdk.kit.MsgEncryptKit; import com.zzwtec.wechat.sdk.msg.InMsgParser; import com.zzwtec.wechat.sdk.msg.in.*; import com.zzwtec.wechat.sdk.msg.in.card.*; import com.zzwtec.wechat.sdk.msg.in.event.*; import com.zzwtec.wechat.sdk.msg.in.speech_recognition.InSpeechRecognitionResults; import com.zzwtec.wechat.sdk.msg.out.OutMsg; import com.zzwtec.wechat.sdk.msg.out.OutTextMsg; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import static com.zzwtec.wechat.sdk.utils.RenderUtil.renderText; /** * 接收微信服务器消息,自动解析成 InMsg 并分发到相应的处理方法 */ @ZZWMsgController public abstract class MsgController { private static final Logger log = LoggerFactory.getLogger(MsgController.class); @Autowired private HttpServletRequest request; private static final ThreadLocal INM_SGXMLT_CONTEXT = new ThreadLocal<>(); private static final ThreadLocal IN_MSGT_CONTEXT = new ThreadLocal<>(); /** * weixin 公众号服务器调用唯一入口,即在开发者中心输入的 URL 必须要指向此 action */ @ZZWAround(ApiHandler.class) @RequestMapping public @ResponseBody ModelAndView index(@RequestBody(required = false) String xmlMsg) throws RuntimeException { if (ApiConfigKit.getApiConfig().isEncryptMessage()) { xmlMsg = MsgEncryptKit.decrypt(xmlMsg, request.getParameter("timestamp"), request.getParameter("nonce"), request.getParameter("msg_signature")); } INM_SGXMLT_CONTEXT.set(xmlMsg); // 开发模式输出微信服务发送过来的 xml 消息 if (ApiConfigKit.isDevMode()) { log.info("-------------------------------receive start-------------------------------------------------\n"); log.info("\n接收消息:\n{}",xmlMsg); log.info("--------------------------------receive end--------------------------------------------------\n"); } try { if (StrKit.isBlank(xmlMsg)) { throw new RuntimeException("未接受到微信参数"); } // 解析消息并根据消息类型分发到相应的处理方法 InMsg msg = getInMsg(); if (msg instanceof InTextMsg) { processInTextMsg((InTextMsg) msg); } else if (msg instanceof InImageMsg) { processInImageMsg((InImageMsg) msg); } else if (msg instanceof InSpeechRecognitionResults){ //update by unas at 2016-1-29, 由于继承InVoiceMsg,需要在InVoiceMsg前判断类型 processInSpeechRecognitionResults((InSpeechRecognitionResults) msg); } else if (msg instanceof InVoiceMsg) { processInVoiceMsg((InVoiceMsg) msg); } else if (msg instanceof InVideoMsg) { processInVideoMsg((InVideoMsg) msg); } else if (msg instanceof InShortVideoMsg){ //支持小视频 processInShortVideoMsg((InShortVideoMsg) msg); } else if (msg instanceof InLocationMsg) { processInLocationMsg((InLocationMsg) msg); } else if (msg instanceof InLinkMsg) { processInLinkMsg((InLinkMsg) msg); } else if (msg instanceof InCustomEvent) { processInCustomEvent((InCustomEvent) msg); } else if (msg instanceof InFollowEvent) { processInFollowEvent((InFollowEvent) msg); } else if (msg instanceof InQrCodeEvent) { processInQrCodeEvent((InQrCodeEvent) msg); } else if (msg instanceof InLocationEvent) { processInLocationEvent((InLocationEvent) msg); } else if (msg instanceof InMassEvent) { processInMassEvent((InMassEvent) msg); } else if (msg instanceof InMenuEvent) { processInMenuEvent((InMenuEvent) msg); } else if (msg instanceof InTemplateMsgEvent) { processInTemplateMsgEvent((InTemplateMsgEvent) msg); } else if (msg instanceof InShakearoundUserShakeEvent) { processInShakearoundUserShakeEvent((InShakearoundUserShakeEvent) msg); } else if (msg instanceof InVerifySuccessEvent) { processInVerifySuccessEvent((InVerifySuccessEvent) msg); } else if (msg instanceof InVerifyFailEvent) { processInVerifyFailEvent((InVerifyFailEvent) msg); } else if (msg instanceof InPoiCheckNotifyEvent) { processInPoiCheckNotifyEvent((InPoiCheckNotifyEvent) msg); } else if (msg instanceof InWifiEvent) { processInWifiEvent((InWifiEvent) msg); } else if (msg instanceof InUserCardEvent) { processInUserCardEvent((InUserCardEvent) msg); } else if (msg instanceof InUpdateMemberCardEvent) { processInUpdateMemberCardEvent((InUpdateMemberCardEvent) msg); } else if (msg instanceof InUserPayFromCardEvent) { processInUserPayFromCardEvent((InUserPayFromCardEvent) msg); } else if (msg instanceof InMerChantOrderEvent) { processInMerChantOrderEvent((InMerChantOrderEvent) msg); } else if (msg instanceof InCardPassCheckEvent) { processInCardPassCheckEvent((InCardPassCheckEvent) msg); } else if (msg instanceof InCardPayOrderEvent) { processInCardPayOrderEvent((InCardPayOrderEvent) msg); } else if (msg instanceof InCardSkuRemindEvent) { processInCardSkuRemindEvent((InCardSkuRemindEvent) msg); } else if (msg instanceof InUserConsumeCardEvent) { processInUserConsumeCardEvent((InUserConsumeCardEvent) msg); } else if (msg instanceof InUserGetCardEvent) { processInUserGetCardEvent((InUserGetCardEvent) msg); } else if (msg instanceof InUserGiftingCardEvent) { processInUserGiftingCardEvent((InUserGiftingCardEvent) msg); } else if (msg instanceof InNotDefinedEvent) { log.error("未能识别的事件类型。 消息 xml 内容为:\n" + xmlMsg); processIsNotDefinedEvent((InNotDefinedEvent) msg); } else if (msg instanceof InNotDefinedMsg) { log.error("未能识别的消息类型。 消息 xml 内容为:\n" + xmlMsg); processIsNotDefinedMsg((InNotDefinedMsg) msg); } }catch (Exception e){ log.error("微信流程处理失败!",e); throw e; }finally { INM_SGXMLT_CONTEXT.remove(); IN_MSGT_CONTEXT.remove(); } return null; } /** * 在接收到微信服务器的 InMsg 消息后后响应 OutMsg 消息 * * @param outMsg 输出对象 */ public void render(OutMsg outMsg) { String outMsgXml = outMsg.toXml(); // 开发模式向控制台输出即将发送的 OutMsg 消息的 xml 内容 if (ApiConfigKit.isDevMode()) { log.info("-------------------------------send start-------------------------------------------------\n"); log.info("\n发送消息:\n{}",outMsgXml); log.info("--------------------------------send end--------------------------------------------------\n"); } // 是否需要加密消息 if (ApiConfigKit.getApiConfig().isEncryptMessage()) { outMsgXml = MsgEncryptKit.encrypt(outMsgXml, request.getParameter("timestamp"), request.getParameter("nonce")); } renderText(outMsgXml, "text/xml"); } /** * 消息输出 * @param content 输出的消息 */ public void renderOutTextMsg(String content) { OutTextMsg outMsg = new OutTextMsg(getInMsg()); outMsg.setContent(content); render(outMsg); } public InMsg getInMsg() { InMsg inMsg = IN_MSGT_CONTEXT.get(); if (inMsg == null){ inMsg = InMsgParser.parse(INM_SGXMLT_CONTEXT.get()); IN_MSGT_CONTEXT.set(inMsg); } return inMsg; } /** * 处理接收到的文本消息 * @param inTextMsg 处理接收到的文本消息 */ protected abstract void processInTextMsg(InTextMsg inTextMsg); /** * 处理接收到的图片消息 * @param inImageMsg 处理接收到的图片消息 */ protected abstract void processInImageMsg(InImageMsg inImageMsg); /** * 处理接收到的语音消息 * @param inVoiceMsg 处理接收到的语音消息 */ protected abstract void processInVoiceMsg(InVoiceMsg inVoiceMsg); /** * 处理接收到的视频消息 * @param inVideoMsg 处理接收到的视频消息 */ protected abstract void processInVideoMsg(InVideoMsg inVideoMsg); /** * 处理接收到的小视频消息 * @param inShortVideoMsg 处理接收到的小视频消息 */ protected abstract void processInShortVideoMsg(InShortVideoMsg inShortVideoMsg); /** * 处理接收到的地址位置消息 * @param inLocationMsg 处理接收到的地址位置消息 */ protected abstract void processInLocationMsg(InLocationMsg inLocationMsg); /** * 处理接收到的链接消息 * @param inLinkMsg 处理接收到的链接消息 */ protected abstract void processInLinkMsg(InLinkMsg inLinkMsg); /** * 处理接收到的多客服管理事件 * @param inCustomEvent 处理接收到的多客服管理事件 */ protected abstract void processInCustomEvent(InCustomEvent inCustomEvent); /** * 处理接收到的关注/取消关注事件 * @param inFollowEvent 处理接收到的关注/取消关注事件 */ protected abstract void processInFollowEvent(InFollowEvent inFollowEvent); /** * 处理接收到的扫描带参数二维码事件 * @param inQrCodeEvent 处理接收到的扫描带参数二维码事件 */ protected abstract void processInQrCodeEvent(InQrCodeEvent inQrCodeEvent); /** * 处理接收到的上报地理位置事件 * @param inLocationEvent 处理接收到的上报地理位置事件 */ protected abstract void processInLocationEvent(InLocationEvent inLocationEvent); /** * 处理接收到的群发任务结束时通知事件 * @param inMassEvent 处理接收到的群发任务结束时通知事件 */ protected abstract void processInMassEvent(InMassEvent inMassEvent); /** * 处理接收到的自定义菜单事件 * @param inMenuEvent 处理接收到的自定义菜单事件 */ protected abstract void processInMenuEvent(InMenuEvent inMenuEvent); /** * 处理接收到的语音识别结果 * @param inSpeechRecognitionResults 处理接收到的语音识别结果 */ protected abstract void processInSpeechRecognitionResults(InSpeechRecognitionResults inSpeechRecognitionResults); /** * 处理接收到的模板消息是否送达成功通知事件 * @param inTemplateMsgEvent 处理接收到的模板消息是否送达成功通知事件 */ protected abstract void processInTemplateMsgEvent(InTemplateMsgEvent inTemplateMsgEvent); /** * 处理微信摇一摇事件 * @param inShakearoundUserShakeEvent 处理微信摇一摇事件 */ protected abstract void processInShakearoundUserShakeEvent(InShakearoundUserShakeEvent inShakearoundUserShakeEvent); /** * 资质认证成功 || 名称认证成功 || 年审通知 || 认证过期失效通知 * @param inVerifySuccessEvent 资质认证成功 || 名称认证成功 || 年审通知 || 认证过期失效通知 */ protected abstract void processInVerifySuccessEvent(InVerifySuccessEvent inVerifySuccessEvent); /** * 资质认证失败 || 名称认证失败 * @param inVerifyFailEvent 资质认证失败 || 名称认证失败 */ protected abstract void processInVerifyFailEvent(InVerifyFailEvent inVerifyFailEvent); /** * 门店在审核事件消息 * @param inPoiCheckNotifyEvent 门店在审核事件消息 */ protected abstract void processInPoiCheckNotifyEvent(InPoiCheckNotifyEvent inPoiCheckNotifyEvent); /** * WIFI连网后下发消息 by unas at 2016-1-29 * @param inWifiEvent WIFI连网后下发消息 */ protected abstract void processInWifiEvent(InWifiEvent inWifiEvent); /** * 1. 微信会员卡二维码扫描领取接口 * 2. 微信会员卡激活接口 * 3. 卡券删除事件推送 * 4. 从卡券进入公众号会话事件推送 * @param inUserCardEvent InUserCardEvent */ protected abstract void processInUserCardEvent(InUserCardEvent inUserCardEvent); /** * 微信会员卡积分变更 * @param inUpdateMemberCardEvent 微信会员卡积分变更 */ protected abstract void processInUpdateMemberCardEvent(InUpdateMemberCardEvent inUpdateMemberCardEvent); /** * 微信会员卡快速买单 * @param inUserPayFromCardEvent 微信会员卡快速买单 */ protected abstract void processInUserPayFromCardEvent(InUserPayFromCardEvent inUserPayFromCardEvent); /** * 微信小店订单支付成功接口消息 * @param inMerChantOrderEvent 微信小店订单支付成功接口消息 */ protected abstract void processInMerChantOrderEvent(InMerChantOrderEvent inMerChantOrderEvent); // /** * 没有找到对应的事件消息 * @param inNotDefinedEvent 没有对应的事件消息 */ protected abstract void processIsNotDefinedEvent(InNotDefinedEvent inNotDefinedEvent); /** * 没有找到对应的消息 * @param inNotDefinedMsg 没有对应消息 */ protected abstract void processIsNotDefinedMsg(InNotDefinedMsg inNotDefinedMsg); /** * 卡券转赠事件推送 * @param msg 卡券转赠事件推送 */ protected abstract void processInUserGiftingCardEvent(InUserGiftingCardEvent msg); /** * 卡券领取事件推送 * @param msg 卡券领取事件推送 */ protected abstract void processInUserGetCardEvent(InUserGetCardEvent msg); /** * 卡券核销事件推送 * @param msg 卡券核销事件推送 */ protected abstract void processInUserConsumeCardEvent(InUserConsumeCardEvent msg); /** * 卡券库存报警事件 * @param msg 卡券库存报警事件 */ protected abstract void processInCardSkuRemindEvent(InCardSkuRemindEvent msg); /** * 券点流水详情事件 * @param msg 券点流水详情事件 */ protected abstract void processInCardPayOrderEvent(InCardPayOrderEvent msg); /** * 审核事件推送 * @param msg 审核事件推送 */ protected abstract void processInCardPassCheckEvent(InCardPassCheckEvent msg); public HttpServletRequest getRequest() { return request; } }