赞
踩
微信小程序生态1-初识小程序
微信小程序生态2-创建一个微信小程序
微信小程序生态3-微信小程序登录流程设计
微信小程序生态4-扫普通二维码进入小程序、打开短链接进入小程序
微信小程序生态5-微信公众号扫码登录PC端网页
微信小程序生态6-微信公众号授权登录(适用于H5小程序)
微信小程序生态7-微信公众号设置IP白名单
微信小程序生态8-基于weixin-java-mp实现微信公众号被动回复消息
微信小程序生态9-微信开放平台unionId机制介绍
微信小程序生态10-微信公众号token验证失败
微信小程序生态11-一个二维码同时支持微信、钉钉、支付宝扫码打开小程序
微信小程序生态12-微信小程序开发设置中服务器域名和业务域名
微信小程序生态13-微信公众号自定义菜单、个性化菜单配置
微信小程序生态14-下线已发布的小程序
微信小程序生态15- 批量提交微信小程序审核的一种方式
在微信里有这样一个公众号【华为运动健康】,当点击最新排行的时候,公众号就会发送今天最新的运动步数给你。如下图:
这里有两种格式的消息
1、有头像框,有聊天框——普通消息
2、消息有样式、颜色等——模板消息
本篇文章主要介绍的就是如何让微信公众号自动回复消息
参考文档链接:https://developers.weixin.qq.com/doc/offiaccount/Message_Management/Passive_user_reply_message.html
开发之前,给大家介绍一个weixin-java-tools
简单介绍一下:
1、微信各种平台的api它都集成了,直接调用就行,不用自己维护微信官方url、各种常量、accessToken等;
2、微信那艹蛋的xml返回数据格式可以直接使用对象进行构建,它已经做好了封装;
3、WxMpMessageRouter非常好用,将微信的各种事件进行分发处理,示例如下:
maven引入:
<!-- weixin-java-mp SDK框架-->
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-mp</artifactId>
<version>3.6.0</version>
</dependency>
github地址如下:https://github.com/binarywang/weixin-java-mp-demo
wiki文档如下:https://github.com/Wechat-Group/WxJava/wiki
SpringBoot-WeChat示例参考项目:https://github.com/Thinkingcao/SpringBootLearning/tree/master/springboot-wechat
签名校验代码如下:
@RequestMapping(value = "handleWxEvent", method = RequestMethod.POST, produces = "application/xml; charset=UTF-8") @ResponseBody public String handleWxEvent(@RequestBody String requestBody, @RequestParam("signature") String signature, @RequestParam("timestamp") String timestamp, @RequestParam("nonce") String nonce, @RequestParam("openid") String openid, @RequestParam(name = "encrypt_type", required = false) String encType, @RequestParam(name = "msg_signature", required = false) String msgSignature){ //微信加密签名 String signature = request.getParameter("signature"); //时间戳 String timestamp = request.getParameter("timestamp"); //随机数 String nonce = request.getParameter("nonce"); //随机字符串 String echostr = request.getParameter("echostr"); //接入验证 if (checkSignature(signature, timestamp, nonce, gzhToken)) { log.info("微信公众号校验完成echostr:[{}]", echostr); try { //这样写可以防止服务器给返回的字符串加上双引号,导致验证失败 response.getWriter().print(echostr); } catch (IOException e) { log.error("输出返回值异常", e); } return; } throw new DscException(ErrorCodeEnum.SYSTEM_EXCEPTION, "解析签名发生异常"); } /** * 校验签名 * * @param signature 签名 * @param timestamp 时间戳 * @param nonce 随机数 * @return 布尔值 */ public static boolean checkSignature(String signature, String timestamp, String nonce, String token) { String checkText = null; if (null != signature) { //对ToKen,timestamp,nonce 按字典排序 String[] paramArr = new String[]{token, timestamp, nonce}; Arrays.sort(paramArr); //将排序后的结果拼成一个字符串 String content = paramArr[0].concat(paramArr[1]).concat(paramArr[2]) try { MessageDigest md = MessageDigest.getInstance("SHA-1"); //对接后的字符串进行sha1加密 byte[] digest = md.digest(content.toString().getBytes()); checkText = byteToStr(digest); } catch (Exception e) { log.error("解码发生异常", e); } } //将加密后的字符串与signature进行对比 return checkText != null ? checkText.equals(signature.toUpperCase()) : false; }
WxMpService功能很多如验证消息的确来自微信服务器、获取access_token、进行相应的公众号切换…
WxMpMessageRouter:微信消息路由器,通过代码化的配置,把来自微信的消息交给handler处理
说明:
配置路由规则时要按照从细到粗的原则,否则可能消息可能会被提前处理
默认情况下消息只会被处理一次,除非使用 WxMpMessageRouterRule.next()
规则的结束必须用WxMpMessageRouterRule.end()或者WxMpMessageRouterRule.next(),否则不会生效
WxMpConfig.class
import com.google.common.collect.Maps; import me.chanjar.weixin.common.api.WxConsts; import me.chanjar.weixin.mp.api.WxMpMessageRouter; import me.chanjar.weixin.mp.api.WxMpService; import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl; import me.chanjar.weixin.mp.config.WxMpConfigStorage; import me.chanjar.weixin.mp.config.impl.WxMpDefaultConfigImpl; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.util.Map; import static me.chanjar.weixin.common.api.WxConsts.EventType.SUBSCRIBE; import static me.chanjar.weixin.common.api.WxConsts.EventType.UNSUBSCRIBE; import static me.chanjar.weixin.common.api.WxConsts.XmlMsgType.EVENT; import static me.chanjar.weixin.mp.constant.WxMpEventConstants.CustomerService.*; import static me.chanjar.weixin.mp.constant.WxMpEventConstants.POI_CHECK_NOTIFY; @Configuration public class WxMpConfig { /** * 设置微信公众号的appid */ @Value("${gzh.appId}") private String appId; /** * 设置微信公众号的app secret */ @Value("${gzh.appSecret}") private String secret; /** * 设置微信公众号的token */ @Value("${gzh.token}") private String token; /** * 设置微信公众号的EncodingAESKey */ @Value("${gzh.aesKey}") private String aesKey; /** * 日志处理 */ @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; @Autowired private ScanHandler scanHandler; @Autowired private TextMsgHandler textMsgHandler; @Autowired private ImgHandler imgHandler; @Bean("wxMpService") public WxMpService wxMpService() { WxMpDefaultConfigImpl wxMpDefaultConfig = new WxMpDefaultConfigImpl(); wxMpDefaultConfig.setAppId(appId); wxMpDefaultConfig.setSecret(secret); wxMpDefaultConfig.setToken(token); wxMpDefaultConfig.setAesKey(aesKey); Map<String, WxMpConfigStorage> configMap = Maps.newHashMap(); configMap.put(appId,wxMpDefaultConfig); WxMpService service = new WxMpServiceImpl(); service.setMultiConfigStorages(configMap); return service; } @Bean public WxMpMessageRouter messageRouter(WxMpService wxMpService) { final WxMpMessageRouter newRouter = new WxMpMessageRouter(wxMpService); // 记录所有事件的日志 (异步执行) newRouter.rule().handler(this.logHandler).next(); // 接收客服会话管理事件 newRouter.rule().async(false).msgType(EVENT).event(KF_CREATE_SESSION) .handler(this.kfSessionHandler).end(); newRouter.rule().async(false).msgType(EVENT).event(KF_CLOSE_SESSION) .handler(this.kfSessionHandler).end(); newRouter.rule().async(false).msgType(EVENT).event(KF_SWITCH_SESSION) .handler(this.kfSessionHandler).end(); // 门店审核事件 newRouter.rule().async(false).msgType(EVENT).event(POI_CHECK_NOTIFY).handler(this.storeCheckNotifyHandler).end(); // 自定义菜单事件 newRouter.rule().async(false).msgType(EVENT).event(WxConsts.EventType.CLICK).handler(this.menuHandler).end(); // 点击菜单连接事件 newRouter.rule().async(false).msgType(EVENT).event(WxConsts.EventType.VIEW).handler(this.nullHandler).end(); // 关注事件 newRouter.rule().async(false).msgType(EVENT).event(SUBSCRIBE).handler(this.subscribeHandler).end(); // 取消关注事件 newRouter.rule().async(false).msgType(EVENT).event(UNSUBSCRIBE).handler(this.unsubscribeHandler).end(); // 上报地理位置事件 newRouter.rule().async(false).msgType(EVENT).event(WxConsts.EventType.LOCATION).handler(this.locationHandler).end(); // 接收地理位置消息 newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.LOCATION).handler(this.locationHandler).end(); // 扫码事件 newRouter.rule().async(false).msgType(EVENT).event(WxConsts.EventType.SCAN).handler(this.scanHandler).end(); // 文本消息处理 newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.TEXT).handler(this.textMsgHandler).end(); // 图片消息处理 newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.IMAGE).handler(this.imgHandler).end(); // 默认 newRouter.rule().async(false).handler(this.msgHandler).end(); return newRouter; } }
package com.example.wxmsg.wxmp.handler;
import me.chanjar.weixin.mp.api.WxMpMessageHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @dessc 父类
*/
public abstract class AbstractHandler implements WxMpMessageHandler {
protected Logger logger = LoggerFactory.getLogger(getClass());
}
package com.example.wxmsg.wxmp.handler; import java.util.Map; import me.chanjar.weixin.common.api.WxConsts; 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; /** * @desc 图片处理器 */ @Component public class ImgHandler extends AbstractHandler { @Override public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> map, WxMpService wxMpService, WxSessionManager wxSessionManager) throws WxErrorException { // msgType 消息类型 String msgType = wxMessage.getMsgType(); // content 消息内容 String content = wxMessage.getContent(); if (msgType.equals(WxConsts.XmlMsgType.IMAGE)) { //TODO: 如果需要做微信消息日志存储,可以在这里进行日志存储到数据库,这里省略不写。 } // 获取微信用户基本信息 WxMpUser userWxInfo = wxMpService.getUserService().userInfo(wxMessage.getFromUser(), "zh_CN"); if (null != userWxInfo) { return WxMpXmlOutMessage .IMAGE() .mediaId("1C72rnlYrj7ZqBiRGdKCoS54AXQwSo4iULd9qRhOC-U") .fromUser(wxMessage.getToUser()) .toUser(wxMessage.getFromUser()) .build(); } return null; } }
package com.example.wxmsg.wxmp.handler; import java.util.Map; 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; /** * @desc 客户对话处理 */ @Component public class KfSessionHandler extends AbstractHandler { @Override public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context, WxMpService wxMpService, WxSessionManager sessionManager) { //TODO 对会话做处理 return null; } }
package com.example.wxmsg.wxmp.handler; import java.util.Map; import com.example.wxmsg.wxmp.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 static me.chanjar.weixin.common.api.WxConsts.XmlMsgType; /** * @desc 地理位置处理 */ @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; } }
package com.example.wxmsg.wxmp.handler; import java.util.Map; import com.example.wxmsg.wxmp.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; /** * @author 日志处理 */ @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; } }
package com.example.wxmsg.wxmp.handler; import java.util.Map; 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 static me.chanjar.weixin.common.api.WxConsts.EventType; /** * @desc 公众号菜单处理 */ @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 (EventType.VIEW.equals(wxMessage.getEvent())) { return null; } return WxMpXmlOutMessage .TEXT() .content(msg) .fromUser(wxMessage.getToUser()) .toUser(wxMessage.getFromUser()) .build(); } }
package com.example.wxmsg.wxmp.handler; import java.util.Map; import com.example.wxmsg.wxmp.builder.TextBuilder; import com.example.wxmsg.wxmp.utils.JsonUtils; 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 static me.chanjar.weixin.common.api.WxConsts.XmlMsgType; /** * @desc 消息对话处理 */ @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); } }
package com.example.wxmsg.wxmp.handler; import java.util.Map; 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; /** * @desc null回复处理 */ @Component public class NullHandler extends AbstractHandler { @Override public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context, WxMpService wxMpService, WxSessionManager sessionManager) { return null; } }
package com.example.wxmsg.wxmp.handler; import java.util.Map; import com.example.wxmsg.wxmp.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.springframework.stereotype.Component; /** * @desc 扫码处理 */ @Component public class ScanHandler extends AbstractHandler { @Override public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> map, WxMpService wxMpService, WxSessionManager wxSessionManager) throws WxErrorException { // 扫码事件处理 this.logger.info("扫码用户 OPENID: " + wxMessage.getFromUser()); //todo 处理扫码相关的操作 try { //从diamond中获取标准话术 return new TextBuilder().build("感谢订阅", wxMessage, wxMpService); } catch (Exception e) { this.logger.error(e.getMessage(), e); } return null; } }
package com.example.wxmsg.wxmp.handler; import java.util.Map; 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; /** * @desc 门店审核事件处理 */ @Component public class StoreCheckNotifyHandler extends AbstractHandler { @Override public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context, WxMpService wxMpService, WxSessionManager sessionManager) { // TODO 处理门店审核事件 return null; } }
package com.example.wxmsg.wxmp.handler; import java.util.Map; 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.config.WxMpConfigStorage; import org.springframework.stereotype.Component; import com.example.wxmsg.wxmp.builder.TextBuilder; /** * @desc 订阅处理 */ @Component public class SubscribeHandler extends AbstractHandler { @Override public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context, WxMpService weixinService, WxSessionManager sessionManager) throws WxErrorException { try { WxMpConfigStorage wxMpConfigStorage = weixinService.getWxMpConfigStorage(); this.logger.info("当前公众号AppId:[{}];新关注用户 OPENID: [{}]", wxMpConfigStorage.getAppId(), wxMessage.getFromUser()); // TODO: 2023/3/27 此处可以循环调用KfSessionHandler发送消息 //默认返回一条信息 return new TextBuilder().build("订阅成功", wxMessage, weixinService); } catch ( Exception e) { this.logger.error(e.getMessage(), e); } return null; } }
package com.example.wxmsg.wxmp.handler; import java.util.Map; 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.config.WxMpConfigStorage; import org.springframework.stereotype.Component; /** * @desc: 文本类型消息处理-TEXT */ @Component public class TextMsgHandler extends AbstractHandler { @Override public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> map, WxMpService wxMpService, WxSessionManager wxSessionManager) throws WxErrorException { WxMpConfigStorage wxMpConfigStorage = wxMpService.getWxMpConfigStorage(); this.logger.info("当前公众号AppId:[{}];新关注用户 OPENID: [{}]", wxMpConfigStorage.getAppId(), wxMessage.getFromUser()); //公众号对话处理 return null; } }
package com.example.wxmsg.wxmp.handler; import java.util.Map; 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; /** * @desc 订阅取消管理 */ @Component public class UnsubscribeHandler extends AbstractHandler { @Override public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context, WxMpService wxMpService, WxSessionManager sessionManager) { String openId = wxMessage.getFromUser(); //根据openId查询unionId this.logger.info("取消关注用户 OPENID: " + openId); return null; } }
import me.chanjar.weixin.mp.api.WxMpService; import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; /** * @desc 微信回复消息构建类 */ public abstract class AbstractBuilder { /** * 构建xml消息内容 * * @param content 消息内容 * @param wxMessage 消息对象 * @param service * @return */ public abstract WxMpXmlOutMessage build(String content, WxMpXmlMessage wxMessage, WxMpService service); }
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; /** * @desc 构建图文消息 */ 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; } }
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; /** * @desc 构建纯文本消息 */ 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; } }
需要注意的是:
(1)消息回复的类型有文本、图片、图文、语音、视频、音乐等;
(2)图片、视频等消息都需要先上传到素材库并获取该素材的mediaId;
(3)回复的消息还可以是小程序卡片,但需要保证当前小程序必须绑定在该公众号下
(4)假如服务器无法保证在五秒内处理并回复,也必须回复,这样微信服务器才不会对此作任何处理,并且不会发起重试(这种情况下,可以使用客服消息接口进行异步回复),否则,将出现严重的错误提示
import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import me.chanjar.weixin.mp.api.WxMpMessageRouter; 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.web.bind.annotation.*; @Slf4j @AllArgsConstructor @RestControllerpublic class WxPortalController { private final WxMpService wxService; private final WxMpMessageRouter messageRouter; @PostMapping(value="handleWxEvent",produces = "application/xml; charset=UTF-8") public String handleWxEvent(@PathVariable String appid, @RequestBody String requestBody, @RequestParam("signature") String signature, @RequestParam("timestamp") String timestamp, @RequestParam("nonce") String nonce, @RequestParam("openid") String openid, @RequestParam(name = "encrypt_type", required = false) String encType, @RequestParam(name = "msg_signature", required = false) String msgSignature) { log.info("\n接收微信请求:[openid=[{}], [signature=[{}], encType=[{}], msgSignature=[{}]," + " timestamp=[{}], nonce=[{}], requestBody=[\n{}\n] ", openid, signature, encType, msgSignature, timestamp, nonce, requestBody); if (!wxService.checkSignature(timestamp, nonce, signature)) { throw new IllegalArgumentException("非法请求,可能属于伪造的请求!"); } String out = null; if (encType == null) { // 明文传输的消息 WxMpXmlMessage inMessage = WxMpXmlMessage.fromXml(requestBody); WxMpXmlOutMessage outMessage = this.route(inMessage); if (outMessage == null) { return ""; } out = outMessage.toXml(); } else if ("aes".equalsIgnoreCase(encType)) { // aes加密的消息 WxMpXmlMessage inMessage = WxMpXmlMessage.fromEncryptedXml(requestBody, wxService.getWxMpConfigStorage(), timestamp, nonce, msgSignature); log.debug("\n消息解密后内容为:\n{} ", inMessage.toString()); WxMpXmlOutMessage outMessage = this.route(inMessage); if (outMessage == null) { return ""; } out = outMessage.toEncryptedXml(wxService.getWxMpConfigStorage()); } log.debug("\n组装回复信息:{}", out); return out; } private WxMpXmlOutMessage route(WxMpXmlMessage message) { try { return this.messageRouter.route(message); } catch (Exception e) { log.error("路由消息时出现异常!", e); } return null; } }
这里我们可以看到,关注【乡荣】公众号后,不仅回复了信息,而且是两条。实现思路:
(1)第一条消息,当用户订阅公众号时会调用SubscribeHandler,该handler会返回一个WxMpXmlOutMessage,这个就是默认返回值
(2)第二条消息,我们可以使用【微信客服】发送,直接使用下面的方法进行发送
wxService.getKefuService().sendKefuMessage(WxMpKefuMessage
.TEXT()
.toUser(wxMessage.getFromUser())
.content("客服回复内容")
.build());
回复小程序卡片这个功能在微信公众平台是找不到的,这个功能只能使用代码实现,这里就体现出代码的强大了
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。