| @@ -6,11 +6,15 @@ import com.iformall.common.Result; | |||||
| import com.iformall.common.ResultData; | import com.iformall.common.ResultData; | ||||
| import com.iformall.domain.po.*; | import com.iformall.domain.po.*; | ||||
| import com.iformall.enums.*; | import com.iformall.enums.*; | ||||
| import com.iformall.mp.service.WxMpManager; | |||||
| import com.iformall.mp.utils.MpUtil; | |||||
| import com.iformall.service.*; | import com.iformall.service.*; | ||||
| import com.iformall.service.wechat.WxOpenService; | import com.iformall.service.wechat.WxOpenService; | ||||
| import io.swagger.annotations.Api; | import io.swagger.annotations.Api; | ||||
| import io.swagger.annotations.ApiOperation; | import io.swagger.annotations.ApiOperation; | ||||
| import me.chanjar.weixin.common.error.WxErrorException; | import me.chanjar.weixin.common.error.WxErrorException; | ||||
| import me.chanjar.weixin.mp.api.WxMpMessageRouter; | |||||
| import me.chanjar.weixin.mp.api.WxMpService; | |||||
| import me.chanjar.weixin.mp.bean.kefu.WxMpKefuMessage; | import me.chanjar.weixin.mp.bean.kefu.WxMpKefuMessage; | ||||
| import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; | import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; | ||||
| import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; | import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; | ||||
| @@ -59,10 +63,13 @@ public class WechatCalllbackController extends BaseController { | |||||
| @Autowired | @Autowired | ||||
| private MailService mailService; | private MailService mailService; | ||||
| @Autowired | |||||
| private WxMpManager mpManager; | |||||
| @RequestMapping(value = "/notify", method = RequestMethod.POST) | @RequestMapping(value = "/notify", method = RequestMethod.POST) | ||||
| @ApiOperation("接收ticket回调") | @ApiOperation("接收ticket回调") | ||||
| public Object receiveTicket(HttpServletRequest request) throws IOException { | public Object receiveTicket(HttpServletRequest request) throws IOException { | ||||
| logger.info("[" +getIpAddr() + "]接收微信回调 /wxOpen/notify"); | |||||
| logger.info("[" + getIpAddr() + "]接收微信回调 /wxOpen/notify"); | |||||
| InputStream inStream = request.getInputStream(); | InputStream inStream = request.getInputStream(); | ||||
| ByteArrayOutputStream outSteam = new ByteArrayOutputStream(); | ByteArrayOutputStream outSteam = new ByteArrayOutputStream(); | ||||
| byte[] buffer = new byte[1024]; | byte[] buffer = new byte[1024]; | ||||
| @@ -77,10 +84,10 @@ public class WechatCalllbackController extends BaseController { | |||||
| inStream.close(); | inStream.close(); | ||||
| String timestamp = request.getParameter("timestamp"); | String timestamp = request.getParameter("timestamp"); | ||||
| String nonce = request.getParameter("nonce"); | |||||
| String nonce = request.getParameter("nonce"); | |||||
| String signature = request.getParameter("signature"); | String signature = request.getParameter("signature"); | ||||
| String encType = request.getParameter("encrypt_type"); | String encType = request.getParameter("encrypt_type"); | ||||
| String msgSignature= request.getParameter("msg_signature"); | |||||
| String msgSignature = request.getParameter("msg_signature"); | |||||
| /* | /* | ||||
| // 测试数据 | // 测试数据 | ||||
| @@ -108,19 +115,19 @@ public class WechatCalllbackController extends BaseController { | |||||
| WxOpenXmlMessage inMessage = WxOpenXmlMessage.fromEncryptedXml(resultxml, | WxOpenXmlMessage inMessage = WxOpenXmlMessage.fromEncryptedXml(resultxml, | ||||
| openService.getWxOpenConfigStorage(), timestamp, nonce, msgSignature); | openService.getWxOpenConfigStorage(), timestamp, nonce, msgSignature); | ||||
| this.logger.info("接收微信回调,消息解密后内容为:{} ", inMessage.toString()); | this.logger.info("接收微信回调,消息解密后内容为:{} ", inMessage.toString()); | ||||
| if(inMessage.getInfoType().equals(EnumWxAuthorizationInfoType.COMPONENT_VERIFY_TICKET.getMessage())) { | |||||
| if (inMessage.getInfoType().equals(EnumWxAuthorizationInfoType.COMPONENT_VERIFY_TICKET.getMessage())) { | |||||
| // 保存component_verify_ticket | // 保存component_verify_ticket | ||||
| componentVerifyTicketService.saveOrUpdate(new WxComponentVerifyTicket(){ | |||||
| componentVerifyTicketService.saveOrUpdate(new WxComponentVerifyTicket() { | |||||
| { | { | ||||
| setComponentVerifyTicket(inMessage.getComponentVerifyTicket()); | setComponentVerifyTicket(inMessage.getComponentVerifyTicket()); | ||||
| setCreateTime(new Date(Long.valueOf(inMessage.getCreateTime() * 1000))); | setCreateTime(new Date(Long.valueOf(inMessage.getCreateTime() * 1000))); | ||||
| setComponentAppid(inMessage.getAppId()); | setComponentAppid(inMessage.getAppId()); | ||||
| setDeadline(new Date(Long.valueOf(System.currentTimeMillis() + (60*60*1000)))); | |||||
| setDeadline(new Date(Long.valueOf(System.currentTimeMillis() + (60 * 60 * 1000)))); | |||||
| } | } | ||||
| }); | }); | ||||
| } else if (inMessage.getInfoType().equals(EnumWxAuthorizationInfoType.AUTHORIZED.getMessage()) || | } else if (inMessage.getInfoType().equals(EnumWxAuthorizationInfoType.AUTHORIZED.getMessage()) || | ||||
| inMessage.getInfoType().equals(EnumWxAuthorizationInfoType.UPDATEAUTHORIZED.getMessage()) | inMessage.getInfoType().equals(EnumWxAuthorizationInfoType.UPDATEAUTHORIZED.getMessage()) | ||||
| ) { | |||||
| ) { | |||||
| try { | try { | ||||
| WxOpenQueryAuthResult queryAuthResult = openService.getWxOpenComponentService().getQueryAuth(inMessage.getAuthorizationCode()); | WxOpenQueryAuthResult queryAuthResult = openService.getWxOpenComponentService().getQueryAuth(inMessage.getAuthorizationCode()); | ||||
| logger.info("getQueryAuth", queryAuthResult); | logger.info("getQueryAuth", queryAuthResult); | ||||
| @@ -129,7 +136,7 @@ public class WechatCalllbackController extends BaseController { | |||||
| queryAuthResult.getAuthorizationInfo().getAuthorizerAppid()); | queryAuthResult.getAuthorizationInfo().getAuthorizerAppid()); | ||||
| logger.info(openAuthorizerInfoResult.toString()); | logger.info(openAuthorizerInfoResult.toString()); | ||||
| // save auth info | // save auth info | ||||
| authorizerInfoService.saveOrUpdate(new WxAuthorizerInfo(){ | |||||
| authorizerInfoService.saveOrUpdate(new WxAuthorizerInfo() { | |||||
| { | { | ||||
| setAuthorizerAppid(openAuthorizerInfoResult.getAuthorizationInfo().getAuthorizerAppid()); | setAuthorizerAppid(openAuthorizerInfoResult.getAuthorizationInfo().getAuthorizerAppid()); | ||||
| setAlias(openAuthorizerInfoResult.getAuthorizerInfo().getAlias()); | setAlias(openAuthorizerInfoResult.getAuthorizerInfo().getAlias()); | ||||
| @@ -143,7 +150,7 @@ public class WechatCalllbackController extends BaseController { | |||||
| logger.error(e.getMessage()); | logger.error(e.getMessage()); | ||||
| } | } | ||||
| } else if (inMessage.getInfoType().equals(EnumWxAuthorizationInfoType.UNAUTHORIZED.getMessage())) { | } else if (inMessage.getInfoType().equals(EnumWxAuthorizationInfoType.UNAUTHORIZED.getMessage())) { | ||||
| authorizerInfoService.saveOrUpdate(new WxAuthorizerInfo(){ | |||||
| authorizerInfoService.saveOrUpdate(new WxAuthorizerInfo() { | |||||
| { | { | ||||
| setAuthorizerAppid(inMessage.getAuthorizerAppid()); | setAuthorizerAppid(inMessage.getAuthorizerAppid()); | ||||
| setAuthorizationStatus(EnumWxAuthorizationStatus.UNAUTHORIZED.getCode()); | setAuthorizationStatus(EnumWxAuthorizationStatus.UNAUTHORIZED.getCode()); | ||||
| @@ -163,8 +170,16 @@ public class WechatCalllbackController extends BaseController { | |||||
| @RequestMapping(value = "/{appId}/callback") | @RequestMapping(value = "/{appId}/callback") | ||||
| @ApiOperation("消息回调") | @ApiOperation("消息回调") | ||||
| public Object callback(@PathVariable("appId") String appId, HttpServletRequest request) throws IOException { | |||||
| logger.info("[" +getIpAddr() + "]接收微信APP回调 /{appId}/callback"); | |||||
| @ResponseBody | |||||
| public String callback(@PathVariable("appId") String appId, HttpServletRequest request) throws IOException { | |||||
| logger.info("[" + getIpAddr() + "]接收微信APP回调 /{appId}/callback"); | |||||
| String timestamp = request.getParameter("timestamp"); | |||||
| String nonce = request.getParameter("nonce"); | |||||
| String signature = request.getParameter("signature"); | |||||
| String encType = request.getParameter("encrypt_type"); | |||||
| String openid = request.getParameter("openid"); | |||||
| String msgSignature = request.getParameter("msg_signature"); | |||||
| InputStream inStream = request.getInputStream(); | InputStream inStream = request.getInputStream(); | ||||
| ByteArrayOutputStream outSteam = new ByteArrayOutputStream(); | ByteArrayOutputStream outSteam = new ByteArrayOutputStream(); | ||||
| byte[] buffer = new byte[1024]; | byte[] buffer = new byte[1024]; | ||||
| @@ -178,27 +193,24 @@ public class WechatCalllbackController extends BaseController { | |||||
| outSteam.close(); | outSteam.close(); | ||||
| inStream.close(); | inStream.close(); | ||||
| String timestamp = request.getParameter("timestamp"); | |||||
| String nonce = request.getParameter("nonce"); | |||||
| String signature = request.getParameter("signature"); | |||||
| String encType = request.getParameter("encrypt_type"); | |||||
| String openid = request.getParameter("openid"); | |||||
| String msgSignature= request.getParameter("msg_signature"); | |||||
| logger.info("接收微信APP回调:[appId=[{}], openid=[{}], signature=[{}], encType=[{}], msgSignature=[{}]," | logger.info("接收微信APP回调:[appId=[{}], openid=[{}], signature=[{}], encType=[{}], msgSignature=[{}]," | ||||
| + " timestamp=[{}], nonce=[{}], requestBody=[\n{}\n] ", | + " timestamp=[{}], nonce=[{}], requestBody=[\n{}\n] ", | ||||
| appId, openid, signature, encType, msgSignature, timestamp, nonce, resultxml); | appId, openid, signature, encType, msgSignature, timestamp, nonce, resultxml); | ||||
| // 第三方平台一定接收的是加密的消息 | |||||
| if (!StringUtils.equalsIgnoreCase("aes", encType) | if (!StringUtils.equalsIgnoreCase("aes", encType) | ||||
| || !openService.getWxOpenComponentService().checkSignature(timestamp, nonce, signature)) { | || !openService.getWxOpenComponentService().checkSignature(timestamp, nonce, signature)) { | ||||
| throw new IllegalArgumentException("非法请求,可能属于伪造的请求!"); | throw new IllegalArgumentException("非法请求,可能属于伪造的请求!"); | ||||
| } | } | ||||
| WxAppinfo appinfo = appinfoService.getByAppId(appId); | |||||
| String out = ""; | String out = ""; | ||||
| // aes加密的消息 | // aes加密的消息 | ||||
| WxMpXmlMessage inMessage = WxOpenXmlMessage.fromEncryptedMpXml(resultxml, | WxMpXmlMessage inMessage = WxOpenXmlMessage.fromEncryptedMpXml(resultxml, | ||||
| openService.getWxOpenConfigStorage(), timestamp, nonce, msgSignature); | openService.getWxOpenConfigStorage(), timestamp, nonce, msgSignature); | ||||
| logger.info("接收微信APP回调,消息解密后内容为:\n{}", inMessage.toString()); | logger.info("接收微信APP回调,消息解密后内容为:\n{}", inMessage.toString()); | ||||
| // 全网发布测试用例 | // 全网发布测试用例 | ||||
| /* | |||||
| if (StringUtils.equalsAnyIgnoreCase(appId, "wx570bc396a51b8ff8", "wxd101a85aa106f53e")) { | if (StringUtils.equalsAnyIgnoreCase(appId, "wx570bc396a51b8ff8", "wxd101a85aa106f53e")) { | ||||
| try { | try { | ||||
| if (StringUtils.equals(inMessage.getMsgType(), "text")) { | if (StringUtils.equals(inMessage.getMsgType(), "text")) { | ||||
| @@ -222,9 +234,12 @@ public class WechatCalllbackController extends BaseController { | |||||
| } catch (WxErrorException e) { | } catch (WxErrorException e) { | ||||
| logger.error("callback", e); | logger.error("callback", e); | ||||
| } | } | ||||
| } else { | |||||
| } | |||||
| */ | |||||
| if(appinfo.getType().equals(EnumAppType.B.getCode()) || appinfo.getType().equals(EnumAppType.C.getCode())) { | |||||
| // 小程序 | |||||
| /**判断消息类型,调用对应的方法*/ | /**判断消息类型,调用对应的方法*/ | ||||
| switch (inMessage.getMsgType()){ | |||||
| switch (inMessage.getMsgType()) { | |||||
| case "event": { | case "event": { | ||||
| switch (inMessage.getEvent()) { | switch (inMessage.getEvent()) { | ||||
| case "weapp_audit_success": { // 审核成功 | case "weapp_audit_success": { // 审核成功 | ||||
| @@ -246,18 +261,6 @@ public class WechatCalllbackController extends BaseController { | |||||
| out = WxOpenXmlMessage.wxMpOutXmlMessageToEncryptedXml(outMessage, openService.getWxOpenConfigStorage()); | out = WxOpenXmlMessage.wxMpOutXmlMessageToEncryptedXml(outMessage, openService.getWxOpenConfigStorage()); | ||||
| logger.info(out); | logger.info(out); | ||||
| } | } | ||||
| /* | |||||
| else { | |||||
| WxMpXmlOutMessage outMsg = new WxMpXmlOutTextMessage(); | |||||
| outMsg.setCreateTime(System.currentTimeMillis()); | |||||
| outMsg.setToUserName(inMessage.getFromUser()); | |||||
| outMsg.setFromUserName(inMessage.getToUser()); | |||||
| outMsg.setMsgType("text"); | |||||
| ((WxMpXmlOutTextMessage) outMsg).setContent(inMessage.getContent()); | |||||
| out = WxOpenXmlMessage.wxMpOutXmlMessageToEncryptedXml(outMsg, wxOpenService.getWxOpenConfigStorage()); | |||||
| } | |||||
| */ | |||||
| else { | else { | ||||
| out = "success"; | out = "success"; | ||||
| } | } | ||||
| @@ -265,9 +268,21 @@ public class WechatCalllbackController extends BaseController { | |||||
| default: | default: | ||||
| return "success"; | return "success"; | ||||
| } | } | ||||
| } else { | |||||
| // 公众号 | |||||
| WxMpService mpService = MpUtil.getMpService(appinfo); | |||||
| try { | |||||
| WxMpXmlOutMessage outMessage = mpManager.getRouter(mpService).route(inMessage); | |||||
| if (outMessage == null) { | |||||
| this.logger.info("2 return: success"); | |||||
| return "success"; | |||||
| } | |||||
| out = outMessage.toEncryptedXml(mpService.getWxMpConfigStorage()); | |||||
| } catch (Exception e) { | |||||
| logger.error("路由消息时出现异常!", e); | |||||
| } | |||||
| } | } | ||||
| return out; | return out; | ||||
| } | } | ||||
| @@ -275,8 +290,8 @@ public class WechatCalllbackController extends BaseController { | |||||
| WxWeappAuditStatus auditStatus = weappAuditStatusService.getByAppId(appId); | WxWeappAuditStatus auditStatus = weappAuditStatusService.getByAppId(appId); | ||||
| if(auditStatus != null) { | |||||
| if(success) { | |||||
| if (auditStatus != null) { | |||||
| if (success) { | |||||
| auditStatus.setAuditStatus(EnumWeappAuditStatus.SUCCESS.getCode()); | auditStatus.setAuditStatus(EnumWeappAuditStatus.SUCCESS.getCode()); | ||||
| auditStatus.setAuditErrCode(""); | auditStatus.setAuditErrCode(""); | ||||
| } else { | } else { | ||||
| @@ -289,21 +304,21 @@ public class WechatCalllbackController extends BaseController { | |||||
| // 发邮件 | // 发邮件 | ||||
| WxAppinfo appinfo = appinfoService.getByAppId(appId); | WxAppinfo appinfo = appinfoService.getByAppId(appId); | ||||
| if(appinfo != null) { | |||||
| if (appinfo != null) { | |||||
| SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式 | SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式 | ||||
| StringBuilder titleSB = new StringBuilder(); | StringBuilder titleSB = new StringBuilder(); | ||||
| if(appinfo.getType().equals(EnumAppType.C.getCode())) { | |||||
| if (appinfo.getType().equals(EnumAppType.C.getCode())) { | |||||
| titleSB.append("C端小程序"); | titleSB.append("C端小程序"); | ||||
| } else if(appinfo.getType().equals(EnumAppType.B.getCode())) { | |||||
| } else if (appinfo.getType().equals(EnumAppType.B.getCode())) { | |||||
| titleSB.append("B端小程序"); | titleSB.append("B端小程序"); | ||||
| } else if(appinfo.getType().equals(EnumAppType.MP_S.getCode())) { | |||||
| } else if (appinfo.getType().equals(EnumAppType.MP_S.getCode())) { | |||||
| titleSB.append("公众号-服务号"); | titleSB.append("公众号-服务号"); | ||||
| } else if(appinfo.getType().equals(EnumAppType.MP_P.getCode())) { | |||||
| } else if (appinfo.getType().equals(EnumAppType.MP_P.getCode())) { | |||||
| titleSB.append("公众号-订阅号"); | titleSB.append("公众号-订阅号"); | ||||
| } | } | ||||
| titleSB.append(appinfo.getName()); | titleSB.append(appinfo.getName()); | ||||
| if(success) { | |||||
| if (success) { | |||||
| titleSB.append("审核通过"); | titleSB.append("审核通过"); | ||||
| } else { | } else { | ||||
| titleSB.append("审核未通过"); | titleSB.append("审核未通过"); | ||||
| @@ -311,13 +326,13 @@ public class WechatCalllbackController extends BaseController { | |||||
| StringBuilder sb = new StringBuilder(); | StringBuilder sb = new StringBuilder(); | ||||
| sb.append(df.format(new Date())).append("\n"); | sb.append(df.format(new Date())).append("\n"); | ||||
| if(success) { | |||||
| if (success) { | |||||
| sb.append("审核通过\n"); | sb.append("审核通过\n"); | ||||
| } else { | } else { | ||||
| sb.append("审核未通过\n").append("原因").append(reason); | sb.append("审核未通过\n").append("原因").append(reason); | ||||
| } | } | ||||
| String[] receivers = new String[] {"wangmei@iformall.com", "wuguoqiang@iformall.com", "huanghui@iformall.com", "sunmingming@iformall.com"}; | |||||
| String[] receivers = new String[]{"wangmei@iformall.com", "wuguoqiang@iformall.com", "huanghui@iformall.com", "sunmingming@iformall.com"}; | |||||
| //发送邮件 | //发送邮件 | ||||
| mailService.sendSimpleMail(receivers, titleSB.toString(), sb.toString()); | mailService.sendSimpleMail(receivers, titleSB.toString(), sb.toString()); | ||||
| @@ -326,15 +341,15 @@ public class WechatCalllbackController extends BaseController { | |||||
| @GetMapping(value = "/createOpenPlatform") | @GetMapping(value = "/createOpenPlatform") | ||||
| @ApiOperation("创建微信开放平台") | @ApiOperation("创建微信开放平台") | ||||
| public ResultData createOpenPlatform(@RequestParam(value="appId") String appId) { | |||||
| public ResultData createOpenPlatform(@RequestParam(value = "appId") String appId) { | |||||
| Gson gson = new GsonBuilder().create(); | Gson gson = new GsonBuilder().create(); | ||||
| try { | try { | ||||
| String responseStr = openService.getWxOpenComponentService().getWxMpServiceByAppid(appId).createOpenPlatform(appId); | String responseStr = openService.getWxOpenComponentService().getWxMpServiceByAppid(appId).createOpenPlatform(appId); | ||||
| logger.info(responseStr); | logger.info(responseStr); | ||||
| WxOpenPlatformResult openPlatformResult = gson.fromJson(responseStr, WxOpenPlatformResult.class); | WxOpenPlatformResult openPlatformResult = gson.fromJson(responseStr, WxOpenPlatformResult.class); | ||||
| if(openPlatformResult.isSuccess()) { | |||||
| if (openPlatformResult.isSuccess()) { | |||||
| WxAuthorizerInfo authorizerInfo = authorizerInfoService.getByAppId(appId); | WxAuthorizerInfo authorizerInfo = authorizerInfoService.getByAppId(appId); | ||||
| if(authorizerInfo != null) { | |||||
| if (authorizerInfo != null) { | |||||
| authorizerInfo.setId(authorizerInfo.getId()); | authorizerInfo.setId(authorizerInfo.getId()); | ||||
| authorizerInfo.setOpenAppid(openPlatformResult.getOpenAppid()); | authorizerInfo.setOpenAppid(openPlatformResult.getOpenAppid()); | ||||
| authorizerInfoService.updateOpenAppid(authorizerInfo); | authorizerInfoService.updateOpenAppid(authorizerInfo); | ||||
| @@ -355,7 +370,7 @@ public class WechatCalllbackController extends BaseController { | |||||
| String responseStr = openService.getWxOpenComponentService().getWxMpServiceByAppid(appId).bindOpenPlatform(appId, openAppId); | String responseStr = openService.getWxOpenComponentService().getWxMpServiceByAppid(appId).bindOpenPlatform(appId, openAppId); | ||||
| logger.info(responseStr); | logger.info(responseStr); | ||||
| WxOpenResult openResult = gson.fromJson(responseStr, WxOpenResult.class); | WxOpenResult openResult = gson.fromJson(responseStr, WxOpenResult.class); | ||||
| if(openResult.isSuccess()) { | |||||
| if (openResult.isSuccess()) { | |||||
| return new ResultData(); | return new ResultData(); | ||||
| } | } | ||||
| return new ResultData(Result.ERROR, responseStr); | return new ResultData(Result.ERROR, responseStr); | ||||
| @@ -373,7 +388,7 @@ public class WechatCalllbackController extends BaseController { | |||||
| String responseStr = openService.getWxOpenComponentService().getWxMpServiceByAppid(appId).unbindOpenPlatform(appId, openAppId); | String responseStr = openService.getWxOpenComponentService().getWxMpServiceByAppid(appId).unbindOpenPlatform(appId, openAppId); | ||||
| logger.info(responseStr); | logger.info(responseStr); | ||||
| WxOpenResult openResult = gson.fromJson(responseStr, WxOpenResult.class); | WxOpenResult openResult = gson.fromJson(responseStr, WxOpenResult.class); | ||||
| if(openResult.isSuccess()) { | |||||
| if (openResult.isSuccess()) { | |||||
| return new ResultData(); | return new ResultData(); | ||||
| } | } | ||||
| return new ResultData(Result.ERROR, responseStr); | return new ResultData(Result.ERROR, responseStr); | ||||
| @@ -391,7 +406,7 @@ public class WechatCalllbackController extends BaseController { | |||||
| String responseStr = openService.getWxOpenComponentService().getWxMpServiceByAppid(appId).getBindOpenPlatform(appId); | String responseStr = openService.getWxOpenComponentService().getWxMpServiceByAppid(appId).getBindOpenPlatform(appId); | ||||
| logger.info(responseStr); | logger.info(responseStr); | ||||
| WxOpenPlatformResult openPlatformResult = gson.fromJson(responseStr, WxOpenPlatformResult.class); | WxOpenPlatformResult openPlatformResult = gson.fromJson(responseStr, WxOpenPlatformResult.class); | ||||
| if(openPlatformResult.isSuccess()) { | |||||
| if (openPlatformResult.isSuccess()) { | |||||
| return new ResultData(openPlatformResult.getOpenAppid()); | return new ResultData(openPlatformResult.getOpenAppid()); | ||||
| } | } | ||||
| return new ResultData(Result.ERROR, responseStr); | return new ResultData(Result.ERROR, responseStr); | ||||
| @@ -0,0 +1,17 @@ | |||||
| package com.iformall.mp.builder; | |||||
| import me.chanjar.weixin.mp.api.WxMpService; | |||||
| import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; | |||||
| import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; | |||||
| import org.slf4j.Logger; | |||||
| import org.slf4j.LoggerFactory; | |||||
| /** | |||||
| * @author Stormeye | |||||
| */ | |||||
| public abstract class AbstractBuilder { | |||||
| protected final Logger logger = LoggerFactory.getLogger(getClass()); | |||||
| public abstract WxMpXmlOutMessage build(String content, | |||||
| WxMpXmlMessage wxMessage, WxMpService service); | |||||
| } | |||||
| @@ -0,0 +1,24 @@ | |||||
| package com.iformall.mp.builder; | |||||
| import me.chanjar.weixin.mp.api.WxMpService; | |||||
| import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; | |||||
| import me.chanjar.weixin.mp.bean.message.WxMpXmlOutImageMessage; | |||||
| import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; | |||||
| /** | |||||
| * @author Binary Wang(https://github.com/binarywang) | |||||
| */ | |||||
| public class ImageBuilder extends AbstractBuilder { | |||||
| @Override | |||||
| public WxMpXmlOutMessage build(String content, WxMpXmlMessage wxMessage, | |||||
| WxMpService service) { | |||||
| WxMpXmlOutImageMessage m = WxMpXmlOutMessage.IMAGE().mediaId(content) | |||||
| .fromUser(wxMessage.getToUser()).toUser(wxMessage.getFromUser()) | |||||
| .build(); | |||||
| return m; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,22 @@ | |||||
| package com.iformall.mp.builder; | |||||
| import me.chanjar.weixin.mp.api.WxMpService; | |||||
| import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; | |||||
| import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; | |||||
| import me.chanjar.weixin.mp.bean.message.WxMpXmlOutTextMessage; | |||||
| /** | |||||
| * @author Binary Wang(https://github.com/binarywang) | |||||
| */ | |||||
| public class TextBuilder extends AbstractBuilder { | |||||
| @Override | |||||
| public WxMpXmlOutMessage build(String content, WxMpXmlMessage wxMessage, | |||||
| WxMpService service) { | |||||
| WxMpXmlOutTextMessage m = WxMpXmlOutMessage.TEXT().content(content) | |||||
| .fromUser(wxMessage.getToUser()).toUser(wxMessage.getFromUser()) | |||||
| .build(); | |||||
| return m; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,49 @@ | |||||
| package com.iformall.mp.controller; | |||||
| import com.iformall.common.ResultData; | |||||
| import com.iformall.mp.service.WxMpManager; | |||||
| import me.chanjar.weixin.common.error.WxErrorException; | |||||
| import me.chanjar.weixin.mp.api.WxMpService; | |||||
| import me.chanjar.weixin.mp.bean.result.WxMpUser; | |||||
| import me.chanjar.weixin.mp.bean.result.WxMpUserList; | |||||
| import org.apache.commons.lang3.StringUtils; | |||||
| import org.slf4j.Logger; | |||||
| import org.slf4j.LoggerFactory; | |||||
| import org.springframework.beans.factory.annotation.Autowired; | |||||
| import org.springframework.web.bind.annotation.GetMapping; | |||||
| import org.springframework.web.bind.annotation.PathVariable; | |||||
| import org.springframework.web.bind.annotation.RequestMapping; | |||||
| import org.springframework.web.bind.annotation.RestController; | |||||
| import java.util.List; | |||||
| /** | |||||
| * @author Stormeye | |||||
| */ | |||||
| @RestController | |||||
| @RequestMapping("/wx/{account}/mem") | |||||
| public class WxMemController { | |||||
| private final Logger logger = LoggerFactory.getLogger(this.getClass()); | |||||
| @Autowired | |||||
| private WxMpManager wxMpManager; | |||||
| @GetMapping("/syncAccountFansList") | |||||
| public ResultData syncAccountFansList(@PathVariable String account) throws WxErrorException { | |||||
| final WxMpService wxService = wxMpManager.getMpService(account); | |||||
| WxMpUserList mpUserList = wxService.getUserService().userList(null); | |||||
| logger.info(mpUserList.toString()); | |||||
| List<WxMpUser> userList = wxService.getUserService().userInfoList(mpUserList.getOpenids()); | |||||
| logger.info(userList.toString()); | |||||
| while(StringUtils.isNotBlank(mpUserList.getNextOpenid())) { | |||||
| mpUserList = wxService.getUserService().userList(mpUserList.getNextOpenid()); | |||||
| logger.info(mpUserList.toString()); | |||||
| if(mpUserList.getOpenids().size() > 0) { | |||||
| userList = wxService.getUserService().userInfoList(mpUserList.getOpenids()); | |||||
| logger.info(userList.toString()); | |||||
| } | |||||
| } | |||||
| return new ResultData(); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,190 @@ | |||||
| package com.iformall.mp.controller; | |||||
| import com.iformall.mp.service.WxMpManager; | |||||
| import me.chanjar.weixin.common.api.WxConsts; | |||||
| import me.chanjar.weixin.common.bean.menu.WxMenu; | |||||
| import me.chanjar.weixin.common.bean.menu.WxMenuButton; | |||||
| import me.chanjar.weixin.common.error.WxErrorException; | |||||
| import me.chanjar.weixin.mp.bean.menu.WxMpGetSelfMenuInfoResult; | |||||
| import me.chanjar.weixin.mp.bean.menu.WxMpMenu; | |||||
| import org.springframework.beans.factory.annotation.Autowired; | |||||
| import org.springframework.web.bind.annotation.*; | |||||
| import org.springframework.web.context.request.RequestContextHolder; | |||||
| import org.springframework.web.context.request.ServletRequestAttributes; | |||||
| import javax.servlet.http.HttpServletRequest; | |||||
| import java.net.MalformedURLException; | |||||
| import java.net.URL; | |||||
| import static me.chanjar.weixin.common.api.WxConsts.MenuButtonType; | |||||
| /** | |||||
| * @author Stormeye | |||||
| */ | |||||
| @RestController | |||||
| @RequestMapping("/wx/menu/{account}") | |||||
| public class WxMenuController { | |||||
| @Autowired | |||||
| private WxMpManager wxMpManager; | |||||
| /** | |||||
| * <pre> | |||||
| * 自定义菜单创建接口 | |||||
| * 详情请见:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141013&token=&lang=zh_CN | |||||
| * 如果要创建个性化菜单,请设置matchrule属性 | |||||
| * 详情请见:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1455782296&token=&lang=zh_CN | |||||
| * </pre> | |||||
| * | |||||
| * @return 如果是个性化菜单,则返回menuid,否则返回null | |||||
| */ | |||||
| @PostMapping("/create") | |||||
| public String menuCreate(@PathVariable String account, @RequestBody WxMenu menu) throws WxErrorException { | |||||
| return wxMpManager.getMpService(account).getMenuService().menuCreate(menu); | |||||
| } | |||||
| @GetMapping("/create") | |||||
| public String menuCreateSample(@PathVariable String account) throws WxErrorException, MalformedURLException { | |||||
| WxMenu menu = new WxMenu(); | |||||
| WxMenuButton button1 = new WxMenuButton(); | |||||
| button1.setType(MenuButtonType.CLICK); | |||||
| button1.setName("今日歌曲"); | |||||
| button1.setKey("V1001_TODAY_MUSIC"); | |||||
| // WxMenuButton button2 = new WxMenuButton(); | |||||
| // button2.setType(WxConsts.BUTTON_MINIPROGRAM); | |||||
| // button2.setName("小程序"); | |||||
| // button2.setAppId("wx286b93c14bbf93aa"); | |||||
| // button2.setPagePath("pages/lunar/index.html"); | |||||
| // button2.setUrl("http://mp.weixin.qq.com"); | |||||
| WxMenuButton button3 = new WxMenuButton(); | |||||
| button3.setName("菜单"); | |||||
| menu.getButtons().add(button1); | |||||
| // menu.getButtons().add(button2); | |||||
| menu.getButtons().add(button3); | |||||
| WxMenuButton button31 = new WxMenuButton(); | |||||
| button31.setType(MenuButtonType.VIEW); | |||||
| button31.setName("搜索"); | |||||
| button31.setUrl("http://www.soso.com/"); | |||||
| WxMenuButton button32 = new WxMenuButton(); | |||||
| button32.setType(MenuButtonType.VIEW); | |||||
| button32.setName("视频"); | |||||
| button32.setUrl("http://v.qq.com/"); | |||||
| WxMenuButton button33 = new WxMenuButton(); | |||||
| button33.setType(MenuButtonType.CLICK); | |||||
| button33.setName("赞一下我们"); | |||||
| button33.setKey("V1001_GOOD"); | |||||
| WxMenuButton button34 = new WxMenuButton(); | |||||
| button34.setType(MenuButtonType.VIEW); | |||||
| button34.setName("获取用户信息"); | |||||
| ServletRequestAttributes servletRequestAttributes = | |||||
| (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); | |||||
| if (servletRequestAttributes != null) { | |||||
| HttpServletRequest request = servletRequestAttributes.getRequest(); | |||||
| URL requestURL = new URL(request.getRequestURL().toString()); | |||||
| String url = wxMpManager.getMpService(account) | |||||
| .oauth2buildAuthorizationUrl( | |||||
| String.format("%s://%s/wx/redirect/%s/greet", requestURL.getProtocol(), requestURL.getHost(), account), | |||||
| WxConsts.OAuth2Scope.SNSAPI_USERINFO, null); | |||||
| button34.setUrl(url); | |||||
| } | |||||
| button3.getSubButtons().add(button31); | |||||
| button3.getSubButtons().add(button32); | |||||
| button3.getSubButtons().add(button33); | |||||
| button3.getSubButtons().add(button34); | |||||
| return wxMpManager.getMpService(account).getMenuService().menuCreate(menu); | |||||
| } | |||||
| /** | |||||
| * <pre> | |||||
| * 自定义菜单创建接口 | |||||
| * 详情请见: https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141013&token=&lang=zh_CN | |||||
| * 如果要创建个性化菜单,请设置matchrule属性 | |||||
| * 详情请见:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1455782296&token=&lang=zh_CN | |||||
| * </pre> | |||||
| * | |||||
| * @param json | |||||
| * @return 如果是个性化菜单,则返回menuid,否则返回null | |||||
| */ | |||||
| @PostMapping("/createByJson") | |||||
| public String menuCreate(@PathVariable String account, @RequestBody String json) throws WxErrorException { | |||||
| return wxMpManager.getMpService(account).getMenuService().menuCreate(json); | |||||
| } | |||||
| /** | |||||
| * <pre> | |||||
| * 自定义菜单删除接口 | |||||
| * 详情请见: https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141015&token=&lang=zh_CN | |||||
| * </pre> | |||||
| */ | |||||
| @GetMapping("/delete") | |||||
| public void menuDelete(@PathVariable String account) throws WxErrorException { | |||||
| wxMpManager.getMpService(account).getMenuService().menuDelete(); | |||||
| } | |||||
| /** | |||||
| * <pre> | |||||
| * 删除个性化菜单接口 | |||||
| * 详情请见: https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1455782296&token=&lang=zh_CN | |||||
| * </pre> | |||||
| * | |||||
| * @param menuId 个性化菜单的menuid | |||||
| */ | |||||
| @GetMapping("/delete/{menuId}") | |||||
| public void menuDelete(@PathVariable String account, @PathVariable String menuId) throws WxErrorException { | |||||
| wxMpManager.getMpService(account).getMenuService().menuDelete(menuId); | |||||
| } | |||||
| /** | |||||
| * <pre> | |||||
| * 自定义菜单查询接口 | |||||
| * 详情请见: https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141014&token=&lang=zh_CN | |||||
| * </pre> | |||||
| */ | |||||
| @GetMapping("/get") | |||||
| public WxMpMenu menuGet(@PathVariable String account) throws WxErrorException { | |||||
| return wxMpManager.getMpService(account).getMenuService().menuGet(); | |||||
| } | |||||
| /** | |||||
| * <pre> | |||||
| * 测试个性化菜单匹配结果 | |||||
| * 详情请见: http://mp.weixin.qq.com/wiki/0/c48ccd12b69ae023159b4bfaa7c39c20.html | |||||
| * </pre> | |||||
| * | |||||
| * @param userid 可以是粉丝的OpenID,也可以是粉丝的微信号。 | |||||
| */ | |||||
| @GetMapping("/menuTryMatch/{userid}") | |||||
| public WxMenu menuTryMatch(@PathVariable String account, @PathVariable String userid) throws WxErrorException { | |||||
| return wxMpManager.getMpService(account).getMenuService().menuTryMatch(userid); | |||||
| } | |||||
| /** | |||||
| * <pre> | |||||
| * 获取自定义菜单配置接口 | |||||
| * 本接口将会提供公众号当前使用的自定义菜单的配置,如果公众号是通过API调用设置的菜单,则返回菜单的开发配置,而如果公众号是在公众平台官网通过网站功能发布菜单,则本接口返回运营者设置的菜单配置。 | |||||
| * 请注意: | |||||
| * 1、第三方平台开发者可以通过本接口,在旗下公众号将业务授权给你后,立即通过本接口检测公众号的自定义菜单配置,并通过接口再次给公众号设置好自动回复规则,以提升公众号运营者的业务体验。 | |||||
| * 2、本接口与自定义菜单查询接口的不同之处在于,本接口无论公众号的接口是如何设置的,都能查询到接口,而自定义菜单查询接口则仅能查询到使用API设置的菜单配置。 | |||||
| * 3、认证/未认证的服务号/订阅号,以及接口测试号,均拥有该接口权限。 | |||||
| * 4、从第三方平台的公众号登录授权机制上来说,该接口从属于消息与菜单权限集。 | |||||
| * 5、本接口中返回的图片/语音/视频为临时素材(临时素材每次获取都不同,3天内有效,通过素材管理-获取临时素材接口来获取这些素材),本接口返回的图文消息为永久素材素材(通过素材管理-获取永久素材接口来获取这些素材)。 | |||||
| * 接口调用请求说明: | |||||
| * http请求方式: GET(请使用https协议) | |||||
| * https://api.weixin.qq.com/cgi-bin/get_current_selfmenu_info?access_token=ACCESS_TOKEN | |||||
| * </pre> | |||||
| */ | |||||
| @GetMapping("/getSelfMenuInfo") | |||||
| public WxMpGetSelfMenuInfoResult getSelfMenuInfo(@PathVariable String account) throws WxErrorException { | |||||
| return wxMpManager.getMpService(account).getMenuService().getSelfMenuInfo(); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,150 @@ | |||||
| package com.iformall.mp.controller; | |||||
| import com.iformall.mp.service.WxMpManager; | |||||
| import me.chanjar.weixin.mp.api.WxMpService; | |||||
| import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; | |||||
| import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; | |||||
| import org.apache.commons.lang3.StringUtils; | |||||
| import org.slf4j.Logger; | |||||
| import org.slf4j.LoggerFactory; | |||||
| import org.springframework.beans.factory.annotation.Autowired; | |||||
| import org.springframework.stereotype.Controller; | |||||
| import org.springframework.web.bind.annotation.*; | |||||
| import javax.servlet.http.HttpServletRequest; | |||||
| import javax.servlet.http.HttpServletResponse; | |||||
| import java.io.ByteArrayOutputStream; | |||||
| import java.io.IOException; | |||||
| import java.io.InputStream; | |||||
| import java.io.PrintWriter; | |||||
| import java.nio.charset.Charset; | |||||
| /** | |||||
| * @author Stormeye | |||||
| */ | |||||
| @Controller | |||||
| @RequestMapping("/wx") | |||||
| public class WxMpCallBackController { | |||||
| private final Logger logger = LoggerFactory.getLogger(this.getClass()); | |||||
| @Autowired | |||||
| private WxMpManager wxMpManager; | |||||
| /** | |||||
| * GET请求:进行URL、Tocken 认证; | |||||
| * 1. 将token、timestamp、nonce三个参数进行字典序排序 | |||||
| * 2. 将三个参数字符串拼接成一个字符串进行sha1加密 | |||||
| * 3. 开发者获得加密后的字符串可与signature对比,标识该请求来源于微信 | |||||
| */ | |||||
| @GetMapping(value = "/{account}/message") | |||||
| @ResponseBody | |||||
| public void authGet(@PathVariable String account, HttpServletRequest request, HttpServletResponse response) throws IOException { | |||||
| String signature = request.getParameter("signature");// 微信加密签名 | |||||
| String timestamp = request.getParameter("timestamp");// 时间戳 | |||||
| String nonce = request.getParameter("nonce");// 随机数 | |||||
| String echostr = request.getParameter("echostr");// 随机字符串 | |||||
| if (StringUtils.isAnyBlank(signature, timestamp, nonce, echostr)) { | |||||
| throw new IllegalArgumentException("请求参数非法,请核实!"); | |||||
| } | |||||
| this.logger.info("接收到来自微信服务器的认证消息:[{}, {}, {}, {}]", | |||||
| signature, timestamp, nonce, echostr); | |||||
| // 数据库 -> | |||||
| final WxMpService wxService = wxMpManager.getMpService(account); | |||||
| if (wxService == null) { | |||||
| throw new IllegalArgumentException(String.format("未找到对应account=[%s]的配置,请核实!", account)); | |||||
| } | |||||
| if (wxService.checkSignature(timestamp, nonce, signature)) { | |||||
| logger.info("微信服务验证成功"); | |||||
| PrintWriter out = response.getWriter(); | |||||
| out.print(echostr); | |||||
| out.close(); | |||||
| } | |||||
| } | |||||
| /** | |||||
| * POST 请求:进行消息处理; | |||||
| */ | |||||
| @PostMapping(value = "/{account}/message") | |||||
| @ResponseBody | |||||
| public String post(@PathVariable String account, HttpServletRequest request) throws IOException { | |||||
| // 处理用户和微信公众账号交互消息 | |||||
| String signature = request.getParameter("signature");// 微信加密签名 | |||||
| String timestamp = request.getParameter("timestamp");// 时间戳 | |||||
| String nonce = request.getParameter("nonce");// 随机数 | |||||
| String openid = request.getParameter("openid"); | |||||
| String encType = request.getParameter("encrypt_type"); | |||||
| String msgSignature = request.getParameter("msg_signature"); | |||||
| if (StringUtils.isAnyBlank(signature, timestamp, nonce)) { | |||||
| throw new IllegalArgumentException("请求参数非法,请核实!"); | |||||
| } | |||||
| final WxMpService wxService = wxMpManager.getMpService(account); | |||||
| if (!wxService.checkSignature(timestamp, nonce, signature)) { | |||||
| throw new IllegalArgumentException("非法请求,可能属于伪造的请求!"); | |||||
| } | |||||
| InputStream inStream = request.getInputStream(); | |||||
| ByteArrayOutputStream outSteam = new ByteArrayOutputStream(); | |||||
| byte[] buffer = new byte[1024]; | |||||
| int len = 0; | |||||
| while ((len = inStream.read(buffer)) != -1) { | |||||
| outSteam.write(buffer, 0, len); | |||||
| } | |||||
| String requestBody = new String(outSteam.toByteArray(), Charset.forName("UTF-8")); | |||||
| logger.info(requestBody); | |||||
| outSteam.close(); | |||||
| inStream.close(); | |||||
| this.logger.info("\n接收微信请求:[openid=[{}], [signature=[{}], encType=[{}], msgSignature=[{}]," | |||||
| + " timestamp=[{}], nonce=[{}], requestBody=[\n{}\n] ", | |||||
| openid, signature, encType, msgSignature, timestamp, nonce, requestBody); | |||||
| String out = null; | |||||
| if (encType == null) { | |||||
| // 明文传输的消息 | |||||
| WxMpXmlMessage inMessage = WxMpXmlMessage.fromXml(requestBody); | |||||
| WxMpXmlOutMessage outMessage = this.route(inMessage, wxService); | |||||
| if (outMessage == null) { | |||||
| logger.info("1 return: success"); | |||||
| return "success"; | |||||
| } | |||||
| out = outMessage.toXml(); | |||||
| logger.info(out); | |||||
| } else if ("aes".equalsIgnoreCase(encType)) { | |||||
| // aes加密的消息 | |||||
| WxMpXmlMessage inMessage = WxMpXmlMessage.fromEncryptedXml(requestBody, wxService.getWxMpConfigStorage(), | |||||
| timestamp, nonce, msgSignature); | |||||
| this.logger.debug("\n消息解密后内容为:\n{} ", inMessage.toString()); | |||||
| WxMpXmlOutMessage outMessage = this.route(inMessage, wxService); | |||||
| if (outMessage == null) { | |||||
| this.logger.info("2 return: success"); | |||||
| return "success"; | |||||
| } | |||||
| logger.info(outMessage.toXml()); | |||||
| out = outMessage.toEncryptedXml(wxService.getWxMpConfigStorage()); | |||||
| } | |||||
| this.logger.info("\n组装回复信息:{}", out); | |||||
| return out; | |||||
| } | |||||
| private WxMpXmlOutMessage route(WxMpXmlMessage message, WxMpService wxService) { | |||||
| try { | |||||
| return wxMpManager.getRouter(wxService).route(message); | |||||
| } catch (Exception e) { | |||||
| this.logger.error("路由消息时出现异常!", e); | |||||
| } | |||||
| return null; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,44 @@ | |||||
| package com.iformall.mp.controller; | |||||
| import com.iformall.mp.service.WxMpManager; | |||||
| import me.chanjar.weixin.common.error.WxErrorException; | |||||
| import me.chanjar.weixin.mp.api.WxMpService; | |||||
| import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken; | |||||
| import me.chanjar.weixin.mp.bean.result.WxMpUser; | |||||
| import org.slf4j.Logger; | |||||
| import org.slf4j.LoggerFactory; | |||||
| import org.springframework.beans.factory.annotation.Autowired; | |||||
| import org.springframework.stereotype.Controller; | |||||
| import org.springframework.ui.ModelMap; | |||||
| import org.springframework.web.bind.annotation.PathVariable; | |||||
| import org.springframework.web.bind.annotation.RequestMapping; | |||||
| import org.springframework.web.bind.annotation.RequestParam; | |||||
| /** | |||||
| * @author Stormeye | |||||
| */ | |||||
| @Controller | |||||
| @RequestMapping("/wx/redirect/{account}") | |||||
| public class WxRedirectController { | |||||
| private final Logger logger = LoggerFactory.getLogger(this.getClass()); | |||||
| @Autowired | |||||
| private WxMpManager wxMpManager; | |||||
| @RequestMapping("/greet") | |||||
| public String greetUser(@PathVariable String account, @RequestParam String code, ModelMap map) { | |||||
| WxMpService mpService = wxMpManager.getMpService(account); | |||||
| try { | |||||
| WxMpOAuth2AccessToken accessToken = mpService.oauth2getAccessToken(code); | |||||
| WxMpUser user = mpService.oauth2getUserInfo(accessToken, null); | |||||
| map.put("user", user); | |||||
| } catch (WxErrorException e) { | |||||
| e.printStackTrace(); | |||||
| } | |||||
| return "greet_user"; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,29 @@ | |||||
| package com.iformall.mp.error; | |||||
| import org.springframework.stereotype.Controller; | |||||
| import org.springframework.web.bind.annotation.GetMapping; | |||||
| import org.springframework.web.bind.annotation.RequestMapping; | |||||
| /** | |||||
| * <pre> | |||||
| * 出错页面控制器 | |||||
| * Created by Binary Wang on 2018/8/25. | |||||
| * </pre> | |||||
| * | |||||
| * @author <a href="https://github.com/binarywang">Binary Wang</a> | |||||
| */ | |||||
| @Controller | |||||
| @RequestMapping("/error") | |||||
| public class ErrorController { | |||||
| @GetMapping(value = "/404") | |||||
| public String error404() { | |||||
| return "error"; | |||||
| } | |||||
| @GetMapping(value = "/500") | |||||
| public String error500() { | |||||
| return "error"; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,27 @@ | |||||
| package com.iformall.mp.error; | |||||
| import org.springframework.boot.web.server.ErrorPage; | |||||
| import org.springframework.boot.web.server.ErrorPageRegistrar; | |||||
| import org.springframework.boot.web.server.ErrorPageRegistry; | |||||
| import org.springframework.http.HttpStatus; | |||||
| import org.springframework.stereotype.Component; | |||||
| /** | |||||
| * <pre> | |||||
| * 配置错误状态与对应访问路径 | |||||
| * Created by Binary Wang on 2018/8/25. | |||||
| * </pre> | |||||
| * | |||||
| * @author <a href="https://github.com/binarywang">Binary Wang</a> | |||||
| */ | |||||
| @Component | |||||
| public class ErrorPageConfiguration implements ErrorPageRegistrar { | |||||
| @Override | |||||
| public void registerErrorPages(ErrorPageRegistry errorPageRegistry) { | |||||
| errorPageRegistry.addErrorPages( | |||||
| new ErrorPage(HttpStatus.NOT_FOUND, "/error/404"), | |||||
| new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR, "/error/500") | |||||
| ); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,12 @@ | |||||
| package com.iformall.mp.handler; | |||||
| import me.chanjar.weixin.mp.api.WxMpMessageHandler; | |||||
| import org.slf4j.Logger; | |||||
| import org.slf4j.LoggerFactory; | |||||
| /** | |||||
| * @author Binary Wang(https://github.com/binarywang) | |||||
| */ | |||||
| public abstract class AbstractHandler implements WxMpMessageHandler { | |||||
| protected Logger logger = LoggerFactory.getLogger(getClass()); | |||||
| } | |||||
| @@ -0,0 +1,25 @@ | |||||
| package com.iformall.mp.handler; | |||||
| import me.chanjar.weixin.common.session.WxSessionManager; | |||||
| import me.chanjar.weixin.mp.api.WxMpService; | |||||
| import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; | |||||
| import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; | |||||
| import org.springframework.stereotype.Component; | |||||
| import java.util.Map; | |||||
| /** | |||||
| * @author Binary Wang(https://github.com/binarywang) | |||||
| */ | |||||
| @Component | |||||
| public class KfSessionHandler extends AbstractHandler { | |||||
| @Override | |||||
| public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, | |||||
| Map<String, Object> context, WxMpService wxMpService, | |||||
| WxSessionManager sessionManager) { | |||||
| //TODO 对会话做处理 | |||||
| return null; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,44 @@ | |||||
| package com.iformall.mp.handler; | |||||
| import com.iformall.mp.builder.TextBuilder; | |||||
| import me.chanjar.weixin.common.session.WxSessionManager; | |||||
| import me.chanjar.weixin.mp.api.WxMpService; | |||||
| import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; | |||||
| import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; | |||||
| import org.springframework.stereotype.Component; | |||||
| import java.util.Map; | |||||
| import static me.chanjar.weixin.common.api.WxConsts.XmlMsgType; | |||||
| /** | |||||
| * @author Binary Wang(https://github.com/binarywang) | |||||
| */ | |||||
| @Component | |||||
| public class LocationHandler extends AbstractHandler { | |||||
| @Override | |||||
| public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, | |||||
| Map<String, Object> context, WxMpService wxMpService, | |||||
| WxSessionManager sessionManager) { | |||||
| if (wxMessage.getMsgType().equals(XmlMsgType.LOCATION)) { | |||||
| //TODO 接收处理用户发送的地理位置消息 | |||||
| try { | |||||
| String content = "感谢反馈,您的的地理位置已收到!"; | |||||
| return new TextBuilder().build(content, wxMessage, null); | |||||
| } catch (Exception e) { | |||||
| this.logger.error("位置消息接收处理失败", e); | |||||
| return null; | |||||
| } | |||||
| } | |||||
| //上报地理位置事件 | |||||
| this.logger.info("上报地理位置,纬度 : {},经度 : {},精度 : {}", | |||||
| wxMessage.getLatitude(), wxMessage.getLongitude(), String.valueOf(wxMessage.getPrecision())); | |||||
| //TODO 可以将用户地理位置信息保存到本地数据库,以便以后使用 | |||||
| return null; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,25 @@ | |||||
| package com.iformall.mp.handler; | |||||
| import com.iformall.mp.utils.JsonUtils; | |||||
| import me.chanjar.weixin.common.session.WxSessionManager; | |||||
| import me.chanjar.weixin.mp.api.WxMpService; | |||||
| import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; | |||||
| import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; | |||||
| import org.springframework.stereotype.Component; | |||||
| import java.util.Map; | |||||
| /** | |||||
| * @author Binary Wang(https://github.com/binarywang) | |||||
| */ | |||||
| @Component | |||||
| public class LogHandler extends AbstractHandler { | |||||
| @Override | |||||
| public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, | |||||
| Map<String, Object> context, WxMpService wxMpService, | |||||
| WxSessionManager sessionManager) { | |||||
| this.logger.info("\n接收到请求消息,内容:{}", JsonUtils.toJson(wxMessage)); | |||||
| return null; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,36 @@ | |||||
| package com.iformall.mp.handler; | |||||
| import me.chanjar.weixin.common.session.WxSessionManager; | |||||
| import me.chanjar.weixin.mp.api.WxMpService; | |||||
| import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; | |||||
| import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; | |||||
| import org.springframework.stereotype.Component; | |||||
| import java.util.Map; | |||||
| import static me.chanjar.weixin.common.api.WxConsts.MenuButtonType; | |||||
| /** | |||||
| * @author Binary Wang(https://github.com/binarywang) | |||||
| */ | |||||
| @Component | |||||
| public class MenuHandler extends AbstractHandler { | |||||
| @Override | |||||
| public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, | |||||
| Map<String, Object> context, WxMpService weixinService, | |||||
| WxSessionManager sessionManager) { | |||||
| String msg = String.format("type:%s, event:%s, key:%s", | |||||
| wxMessage.getMsgType(), wxMessage.getEvent(), | |||||
| wxMessage.getEventKey()); | |||||
| if (MenuButtonType.VIEW.equals(wxMessage.getEvent())) { | |||||
| return null; | |||||
| } | |||||
| return WxMpXmlOutMessage.TEXT().content(msg) | |||||
| .fromUser(wxMessage.getToUser()).toUser(wxMessage.getFromUser()) | |||||
| .build(); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,51 @@ | |||||
| package com.iformall.mp.handler; | |||||
| import com.iformall.mp.builder.TextBuilder; | |||||
| import me.chanjar.weixin.common.error.WxErrorException; | |||||
| import me.chanjar.weixin.common.session.WxSessionManager; | |||||
| import me.chanjar.weixin.mp.api.WxMpService; | |||||
| import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; | |||||
| import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; | |||||
| import org.apache.commons.lang3.StringUtils; | |||||
| import org.springframework.stereotype.Component; | |||||
| import java.util.Map; | |||||
| import static me.chanjar.weixin.common.api.WxConsts.XmlMsgType; | |||||
| /** | |||||
| * @author Binary Wang(https://github.com/binarywang) | |||||
| */ | |||||
| @Component | |||||
| public class MsgHandler extends AbstractHandler { | |||||
| @Override | |||||
| public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, | |||||
| Map<String, Object> context, WxMpService weixinService, | |||||
| WxSessionManager sessionManager) { | |||||
| if (!wxMessage.getMsgType().equals(XmlMsgType.EVENT)) { | |||||
| //TODO 可以选择将消息保存到本地 | |||||
| } | |||||
| //当用户输入关键词如“你好”,“客服”等,并且有客服在线时,把消息转发给在线客服 | |||||
| try { | |||||
| if (StringUtils.startsWithAny(wxMessage.getContent(), "你好", "客服") | |||||
| && weixinService.getKefuService().kfOnlineList() | |||||
| .getKfOnlineList().size() > 0) { | |||||
| return WxMpXmlOutMessage.TRANSFER_CUSTOMER_SERVICE() | |||||
| .fromUser(wxMessage.getToUser()) | |||||
| .toUser(wxMessage.getFromUser()).build(); | |||||
| } | |||||
| } catch (WxErrorException e) { | |||||
| e.printStackTrace(); | |||||
| } | |||||
| //TODO 组装回复消息 | |||||
| String content = "您好,有什么可以帮您";// "收到信息内容:" + JsonUtils.toJson(wxMessage); | |||||
| return new TextBuilder().build(content, wxMessage, weixinService); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,24 @@ | |||||
| package com.iformall.mp.handler; | |||||
| import me.chanjar.weixin.common.session.WxSessionManager; | |||||
| import me.chanjar.weixin.mp.api.WxMpService; | |||||
| import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; | |||||
| import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; | |||||
| import org.springframework.stereotype.Component; | |||||
| import java.util.Map; | |||||
| /** | |||||
| * @author Binary Wang(https://github.com/binarywang) | |||||
| */ | |||||
| @Component | |||||
| public class NullHandler extends AbstractHandler { | |||||
| @Override | |||||
| public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, | |||||
| Map<String, Object> context, WxMpService wxMpService, | |||||
| WxSessionManager sessionManager) { | |||||
| return null; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,8 @@ | |||||
| package com.iformall.mp.handler; | |||||
| /** | |||||
| * @author Binary Wang(https://github.com/binarywang) | |||||
| */ | |||||
| public abstract class ScanHandler extends AbstractHandler { | |||||
| } | |||||
| @@ -0,0 +1,27 @@ | |||||
| package com.iformall.mp.handler; | |||||
| import me.chanjar.weixin.common.session.WxSessionManager; | |||||
| import me.chanjar.weixin.mp.api.WxMpService; | |||||
| import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; | |||||
| import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; | |||||
| import org.springframework.stereotype.Component; | |||||
| import java.util.Map; | |||||
| /** | |||||
| * 门店审核事件处理 | |||||
| * | |||||
| * @author Binary Wang(https://github.com/binarywang) | |||||
| */ | |||||
| @Component | |||||
| public class StoreCheckNotifyHandler extends AbstractHandler { | |||||
| @Override | |||||
| public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, | |||||
| Map<String, Object> context, WxMpService wxMpService, | |||||
| WxSessionManager sessionManager) { | |||||
| // TODO 处理门店审核事件 | |||||
| return null; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,70 @@ | |||||
| package com.iformall.mp.handler; | |||||
| import com.iformall.mp.builder.TextBuilder; | |||||
| import me.chanjar.weixin.common.error.WxErrorException; | |||||
| import me.chanjar.weixin.common.session.WxSessionManager; | |||||
| import me.chanjar.weixin.mp.api.WxMpService; | |||||
| import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; | |||||
| import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; | |||||
| import me.chanjar.weixin.mp.bean.result.WxMpUser; | |||||
| import org.springframework.stereotype.Component; | |||||
| import java.util.Map; | |||||
| /** | |||||
| * @author Binary Wang(https://github.com/binarywang) | |||||
| */ | |||||
| @Component | |||||
| public class SubscribeHandler extends AbstractHandler { | |||||
| @Override | |||||
| public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, | |||||
| Map<String, Object> context, WxMpService weixinService, | |||||
| WxSessionManager sessionManager) throws WxErrorException { | |||||
| this.logger.info("新关注用户 OPENID: " + wxMessage.getFromUser()); | |||||
| // 获取微信用户基本信息 | |||||
| try { | |||||
| WxMpUser userWxInfo = weixinService.getUserService() | |||||
| .userInfo(wxMessage.getFromUser(), null); | |||||
| if (userWxInfo != null) { | |||||
| // TODO 可以添加关注用户到本地数据库 | |||||
| } | |||||
| } catch (WxErrorException e) { | |||||
| if (e.getError().getErrorCode() == 48001) { | |||||
| this.logger.info("该公众号没有获取用户信息权限!"); | |||||
| } | |||||
| } | |||||
| WxMpXmlOutMessage responseResult = null; | |||||
| try { | |||||
| responseResult = this.handleSpecial(wxMessage); | |||||
| } catch (Exception e) { | |||||
| this.logger.error(e.getMessage(), e); | |||||
| } | |||||
| if (responseResult != null) { | |||||
| return responseResult; | |||||
| } | |||||
| try { | |||||
| return new TextBuilder().build("感谢关注", wxMessage, weixinService); | |||||
| } catch (Exception e) { | |||||
| this.logger.error(e.getMessage(), e); | |||||
| } | |||||
| return null; | |||||
| } | |||||
| /** | |||||
| * 处理特殊请求,比如如果是扫码进来的,可以做相应处理 | |||||
| */ | |||||
| private WxMpXmlOutMessage handleSpecial(WxMpXmlMessage wxMessage) | |||||
| throws Exception { | |||||
| //TODO | |||||
| return null; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,27 @@ | |||||
| package com.iformall.mp.handler; | |||||
| import me.chanjar.weixin.common.session.WxSessionManager; | |||||
| import me.chanjar.weixin.mp.api.WxMpService; | |||||
| import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; | |||||
| import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; | |||||
| import org.springframework.stereotype.Component; | |||||
| import java.util.Map; | |||||
| /** | |||||
| * @author Binary Wang(https://github.com/binarywang) | |||||
| */ | |||||
| @Component | |||||
| public class UnsubscribeHandler extends AbstractHandler { | |||||
| @Override | |||||
| public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, | |||||
| Map<String, Object> context, WxMpService wxMpService, | |||||
| WxSessionManager sessionManager) { | |||||
| String openId = wxMessage.getFromUser(); | |||||
| this.logger.info("取消关注用户 OPENID: " + openId); | |||||
| // TODO 可以更新本地数据库为取消关注状态 | |||||
| return null; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,116 @@ | |||||
| package com.iformall.mp.manager; | |||||
| import com.iformall.domain.po.WxAppinfo; | |||||
| import com.iformall.mp.handler.*; | |||||
| import com.iformall.mp.utils.MpUtil; | |||||
| import com.iformall.service.WxAppinfoService; | |||||
| import me.chanjar.weixin.mp.api.WxMpMessageRouter; | |||||
| import me.chanjar.weixin.mp.api.WxMpService; | |||||
| import me.chanjar.weixin.mp.constant.WxMpEventConstants; | |||||
| import org.springframework.beans.factory.annotation.Autowired; | |||||
| import org.springframework.stereotype.Service; | |||||
| import static me.chanjar.weixin.common.api.WxConsts.*; | |||||
| /** | |||||
| * wechat mp configuration | |||||
| * | |||||
| * @author Binary Wang(https://github.com/binarywang) | |||||
| */ | |||||
| @Service | |||||
| public class WxMpManager { | |||||
| @Autowired | |||||
| private WxAppinfoService appinfoService; | |||||
| @Autowired | |||||
| private LogHandler logHandler; | |||||
| @Autowired | |||||
| private NullHandler nullHandler; | |||||
| @Autowired | |||||
| private KfSessionHandler kfSessionHandler; | |||||
| @Autowired | |||||
| private StoreCheckNotifyHandler storeCheckNotifyHandler; | |||||
| @Autowired | |||||
| private LocationHandler locationHandler; | |||||
| @Autowired | |||||
| private MenuHandler menuHandler; | |||||
| @Autowired | |||||
| private MsgHandler msgHandler; | |||||
| @Autowired | |||||
| private UnsubscribeHandler unsubscribeHandler; | |||||
| @Autowired | |||||
| private SubscribeHandler subscribeHandler; | |||||
| public WxMpMessageRouter getRouter(WxAppinfo appinfo) { | |||||
| WxMpService mpService = MpUtil.getMpService(appinfo); | |||||
| if(mpService != null) { | |||||
| return newRouter(mpService); | |||||
| } | |||||
| return null; | |||||
| } | |||||
| public WxMpMessageRouter getRouter(WxMpService mpService) { | |||||
| return newRouter(mpService); | |||||
| } | |||||
| private WxMpMessageRouter newRouter(WxMpService wxMpService) { | |||||
| final WxMpMessageRouter newRouter = new WxMpMessageRouter(wxMpService); | |||||
| // 记录所有事件的日志 (异步执行) | |||||
| newRouter.rule().handler(this.logHandler).next(); | |||||
| // 接收客服会话管理事件 | |||||
| newRouter.rule().async(false).msgType(XmlMsgType.EVENT) | |||||
| .event(WxMpEventConstants.CustomerService.KF_CREATE_SESSION) | |||||
| .handler(this.kfSessionHandler).end(); | |||||
| newRouter.rule().async(false).msgType(XmlMsgType.EVENT) | |||||
| .event(WxMpEventConstants.CustomerService.KF_CLOSE_SESSION) | |||||
| .handler(this.kfSessionHandler) | |||||
| .end(); | |||||
| newRouter.rule().async(false).msgType(XmlMsgType.EVENT) | |||||
| .event(WxMpEventConstants.CustomerService.KF_SWITCH_SESSION) | |||||
| .handler(this.kfSessionHandler).end(); | |||||
| // 门店审核事件 | |||||
| newRouter.rule().async(false).msgType(XmlMsgType.EVENT) | |||||
| .event(WxMpEventConstants.POI_CHECK_NOTIFY) | |||||
| .handler(this.storeCheckNotifyHandler).end(); | |||||
| // 自定义菜单事件 | |||||
| newRouter.rule().async(false).msgType(XmlMsgType.EVENT) | |||||
| .event(MenuButtonType.CLICK).handler(this.menuHandler).end(); | |||||
| // 点击菜单连接事件 | |||||
| newRouter.rule().async(false).msgType(XmlMsgType.EVENT) | |||||
| .event(MenuButtonType.VIEW).handler(this.nullHandler).end(); | |||||
| // 关注事件 | |||||
| newRouter.rule().async(false).msgType(XmlMsgType.EVENT) | |||||
| .event(EventType.SUBSCRIBE).handler(this.subscribeHandler) | |||||
| .end(); | |||||
| // 取消关注事件 | |||||
| newRouter.rule().async(false).msgType(XmlMsgType.EVENT) | |||||
| .event(EventType.UNSUBSCRIBE) | |||||
| .handler(this.unsubscribeHandler).end(); | |||||
| // 上报地理位置事件 | |||||
| newRouter.rule().async(false).msgType(XmlMsgType.EVENT) | |||||
| .event(EventType.LOCATION).handler(this.locationHandler) | |||||
| .end(); | |||||
| // 接收地理位置消息 | |||||
| newRouter.rule().async(false).msgType(XmlMsgType.LOCATION) | |||||
| .handler(this.locationHandler).end(); | |||||
| // 扫码事件 | |||||
| newRouter.rule().async(false).msgType(XmlMsgType.EVENT) | |||||
| .event(EventType.SCAN).handler(this.nullHandler).end(); | |||||
| // 默认 | |||||
| newRouter.rule().async(false).handler(this.msgHandler).end(); | |||||
| return newRouter; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,123 @@ | |||||
| package com.iformall.mp.service; | |||||
| import com.iformall.domain.po.WxAppinfo; | |||||
| import com.iformall.mp.handler.*; | |||||
| import com.iformall.mp.utils.MpUtil; | |||||
| import com.iformall.service.WxAppinfoService; | |||||
| import me.chanjar.weixin.mp.api.WxMpMessageRouter; | |||||
| import me.chanjar.weixin.mp.api.WxMpService; | |||||
| import me.chanjar.weixin.mp.constant.WxMpEventConstants; | |||||
| import org.springframework.beans.factory.annotation.Autowired; | |||||
| import org.springframework.stereotype.Service; | |||||
| import static me.chanjar.weixin.common.api.WxConsts.*; | |||||
| /** | |||||
| * wechat mp configuration | |||||
| * | |||||
| * @author Binary Wang(https://github.com/binarywang) | |||||
| */ | |||||
| @Service | |||||
| public class WxMpManager { | |||||
| @Autowired | |||||
| private WxAppinfoService appinfoService; | |||||
| @Autowired | |||||
| private LogHandler logHandler; | |||||
| @Autowired | |||||
| private NullHandler nullHandler; | |||||
| @Autowired | |||||
| private KfSessionHandler kfSessionHandler; | |||||
| @Autowired | |||||
| private StoreCheckNotifyHandler storeCheckNotifyHandler; | |||||
| @Autowired | |||||
| private LocationHandler locationHandler; | |||||
| @Autowired | |||||
| private MenuHandler menuHandler; | |||||
| @Autowired | |||||
| private MsgHandler msgHandler; | |||||
| @Autowired | |||||
| private UnsubscribeHandler unsubscribeHandler; | |||||
| @Autowired | |||||
| private SubscribeHandler subscribeHandler; | |||||
| public WxMpMessageRouter getRouter(String appId) { | |||||
| WxMpService mpService = getMpService(appId); | |||||
| if(mpService != null) { | |||||
| return newRouter(mpService); | |||||
| } | |||||
| return null; | |||||
| } | |||||
| public WxMpMessageRouter getRouter(WxMpService mpService) { | |||||
| return newRouter(mpService); | |||||
| } | |||||
| public WxMpService getMpService(String appId) { | |||||
| WxAppinfo appinfo = appinfoService.getByAppId(appId); | |||||
| if(appinfo == null) | |||||
| return null; | |||||
| return MpUtil.getMpService(appinfo); | |||||
| } | |||||
| private WxMpMessageRouter newRouter(WxMpService wxMpService) { | |||||
| final WxMpMessageRouter newRouter = new WxMpMessageRouter(wxMpService); | |||||
| // 记录所有事件的日志 (异步执行) | |||||
| newRouter.rule().handler(this.logHandler).next(); | |||||
| // 接收客服会话管理事件 | |||||
| newRouter.rule().async(false).msgType(XmlMsgType.EVENT) | |||||
| .event(WxMpEventConstants.CustomerService.KF_CREATE_SESSION) | |||||
| .handler(this.kfSessionHandler).end(); | |||||
| newRouter.rule().async(false).msgType(XmlMsgType.EVENT) | |||||
| .event(WxMpEventConstants.CustomerService.KF_CLOSE_SESSION) | |||||
| .handler(this.kfSessionHandler) | |||||
| .end(); | |||||
| newRouter.rule().async(false).msgType(XmlMsgType.EVENT) | |||||
| .event(WxMpEventConstants.CustomerService.KF_SWITCH_SESSION) | |||||
| .handler(this.kfSessionHandler).end(); | |||||
| // 门店审核事件 | |||||
| newRouter.rule().async(false).msgType(XmlMsgType.EVENT) | |||||
| .event(WxMpEventConstants.POI_CHECK_NOTIFY) | |||||
| .handler(this.storeCheckNotifyHandler).end(); | |||||
| // 自定义菜单事件 | |||||
| newRouter.rule().async(false).msgType(XmlMsgType.EVENT) | |||||
| .event(MenuButtonType.CLICK).handler(this.menuHandler).end(); | |||||
| // 点击菜单连接事件 | |||||
| newRouter.rule().async(false).msgType(XmlMsgType.EVENT) | |||||
| .event(MenuButtonType.VIEW).handler(this.nullHandler).end(); | |||||
| // 关注事件 | |||||
| newRouter.rule().async(false).msgType(XmlMsgType.EVENT) | |||||
| .event(EventType.SUBSCRIBE).handler(this.subscribeHandler) | |||||
| .end(); | |||||
| // 取消关注事件 | |||||
| newRouter.rule().async(false).msgType(XmlMsgType.EVENT) | |||||
| .event(EventType.UNSUBSCRIBE) | |||||
| .handler(this.unsubscribeHandler).end(); | |||||
| // 上报地理位置事件 | |||||
| newRouter.rule().async(false).msgType(XmlMsgType.EVENT) | |||||
| .event(EventType.LOCATION).handler(this.locationHandler) | |||||
| .end(); | |||||
| // 接收地理位置消息 | |||||
| newRouter.rule().async(false).msgType(XmlMsgType.LOCATION) | |||||
| .handler(this.locationHandler).end(); | |||||
| // 扫码事件 | |||||
| newRouter.rule().async(false).msgType(XmlMsgType.EVENT) | |||||
| .event(EventType.SCAN).handler(this.nullHandler).end(); | |||||
| // 默认 | |||||
| newRouter.rule().async(false).handler(this.msgHandler).end(); | |||||
| return newRouter; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,16 @@ | |||||
| package com.iformall.mp.utils; | |||||
| import com.google.gson.Gson; | |||||
| import com.google.gson.GsonBuilder; | |||||
| /** | |||||
| * @author Binary Wang(https://github.com/binarywang) | |||||
| */ | |||||
| public class JsonUtils { | |||||
| public static String toJson(Object obj) { | |||||
| Gson gson = new GsonBuilder() | |||||
| .setPrettyPrinting() | |||||
| .create(); | |||||
| return gson.toJson(obj); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,22 @@ | |||||
| package com.iformall.mp.utils; | |||||
| import com.iformall.domain.po.WxAppinfo; | |||||
| import me.chanjar.weixin.mp.api.WxMpInMemoryConfigStorage; | |||||
| import me.chanjar.weixin.mp.api.WxMpService; | |||||
| import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl; | |||||
| /** | |||||
| * @author Stormeye | |||||
| */ | |||||
| public class MpUtil { | |||||
| static public WxMpService getMpService(WxAppinfo appinfo) { | |||||
| WxMpInMemoryConfigStorage configStorage = new WxMpInMemoryConfigStorage(); | |||||
| configStorage.setAppId(appinfo.getAppId()); | |||||
| configStorage.setSecret(appinfo.getSecret()); | |||||
| configStorage.setToken(appinfo.getToken()); | |||||
| configStorage.setAesKey(appinfo.getAesKey()); | |||||
| WxMpService service = new WxMpServiceImpl(); | |||||
| service.setWxMpConfigStorage(configStorage); | |||||
| return service; | |||||
| } | |||||
| } | |||||