/**
* 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;
}
}