package com.gustz.dove.mpcli.api.message.service.impl; import java.io.StringReader; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import org.dom4j.Document; import org.dom4j.io.SAXReader; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.sinovatech.rd.wcsb.cli.api.app.service.impl.ClientAppService; import com.sinovatech.rd.wcsb.cli.api.app.vo.ClientAppVo; import com.sinovatech.rd.wcsb.cli.api.customer.vo.TextCust; import com.sinovatech.rd.wcsb.cli.api.message.req.CommEventMsgReq; import com.sinovatech.rd.wcsb.cli.api.message.req.MsgBaseReq; import com.sinovatech.rd.wcsb.cli.api.message.service.impl.MessageServiceImpl; import com.sinovatech.rd.wcsb.cli.api.security.service.impl.EncryptServiceImpl; import com.sinovatech.rd.wcsb.cli.api.service.dict.EventTypeDict; import com.sinovatech.rd.wcsb.cli.api.service.util.AppLogStyle; import com.sinovatech.rd.wcsb.cli.api.service.util.ClientConstants; import com.sinovatech.rd.wcsb.mpcli.api.customer.req.TextCustReq; import com.sinovatech.rd.wcsb.mpcli.api.customer.req.TextCustReq.TextBodyCustReq; import com.sinovatech.rd.wcsb.mpcli.api.customer.service.CustomerMpService; import com.sinovatech.rd.wcsb.mpcli.api.message.service.MessageMpService; import com.sinovatech.rd.wcsb.mpcli.api.security.service.OauthMpService; /** * * TODO: 消息处理服务的接口实现 * * @author ZHENFENG ZHANG * @since [ Aug 3, 2015 ] */ @Service public class MessageMpServiceImpl extends MessageServiceImpl implements MessageMpService { private final Logger logger = LoggerFactory.getLogger(getClass()); @Autowired private ClientAppService clientAppService; @Autowired private CustomerMpService customerMpService; @Autowired private OauthMpService oauthMpService; /** * 转发接收订阅、服务号的消息 * * <pre> * 1、直接回复空串(指字节长度为0的空字符串,而不是XML结构体中content字段的内容为空) * 2、直接回复success * </pre> * @param encryptType * @param msgSignature * @param timestamp * @param nonce * @param postData * @return */ @Override public String dispatcherMsg(String encryptType, String msgSignature, String timestamp, String nonce, String postData) { AppLogStyle appLogs = new AppLogStyle(); appLogs.begin(String.format("转发接收订阅、服务号的消息,msgSignature[ %1$s ],timestamp[ %2$s ],nonce[ %3$s ],encryptType[ %4$s ] ", msgSignature, timestamp, nonce, encryptType)); try { Document doc = new SAXReader().read(new StringReader(postData)); // 订阅、服务号 String _toUserName = doc.selectSingleNode(MsgBaseReq.TO_USER_NAME_XPATH).getText(); if (!this.hasUserName(appLogs, "接收的订阅、服务号", _toUserName)) { return ""; } ClientAppVo _appVo = clientAppService.getActiveCacheByAcc().get(_toUserName); if (!this.hasClientApp(appLogs, "订阅、服务原始ID", _appVo, _toUserName)) { return ""; } String newPostData = postData; if (EncryptServiceImpl.AES_ETYPE.equalsIgnoreCase(encryptType)) { // 微信解密消息 newPostData = this.decryptMsg(_appVo, msgSignature, timestamp, nonce, doc); } // 发送方的账号 String _fromUserName = CommEventMsgReq.toBean(EventTypeDict.ENTER_AGENT, newPostData).getFromUserName(); if (!this.hasUserName(appLogs, "发送方的账号", _fromUserName)) { return ""; } // OAuth授权URL String oauthCbUrl = oauthMpService.getSnsapiBaseUrl(_appVo.getCliAppCode(), _toUserName); // 本地的加密消息 newPostData = this.localEncryptMsg(newPostData, oauthCbUrl); // 直接推送到接入的客户端APP if (!this.hasSendToCliApp(appLogs, _appVo, _fromUserName, newPostData)) { return ""; } // 自动回复消息 this.doAutoReplyMsg(_appVo, doc); // return ClientConstants.SUCCESS_RSP; } catch (Exception e) { appLogs.error("处理接收的订阅、服务号消息异常\n", e); } finally { appLogs.end(); } return ""; } /** * 自动回复消息(客服回复) * * <pre> * 异步发送客服消息 * </pre> * @param eventType 事件类型 * @param toUserName 接收者 * @param fromUserName 发送者 * @param cliAppCode 客户端APP编码 * @param content 消息内容 */ @Override public void autoReplyMsg(final String eventType, final String toUserName, final String fromUserName, final String cliAppCode, final String content) { // 不需要校验客户端应用 this.setCheckCliApp(false); // 根据事件类型过滤回复语 if (EventTypeDict.SUBSCRIBE.name().equalsIgnoreCase(eventType)) { // 关注事件 ExecutorService exeService = Executors.newSingleThreadExecutor(); exeService.execute(new Runnable() { @Override public void run() { // 文本消息请求的报文 TextBodyCustReq body = new TextBodyCustReq(toUserName, new TextCust(content)); logger.info("MP客服自动回复消息..."); // 发送客服消息 customerMpService.sendCustomerMsg(System.currentTimeMillis(), cliAppCode, new TextCustReq(fromUserName, body)); } }); } } }