Java开发微信公众号之整合weixin-java-tools框架开发微信公众号

article/2025/10/8 15:47:07

微信开发者接入文档 : https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421135319

微信公众平台测试账号申请: http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login

一、前言

首先,在要做微信项目开发前,大家都会去了解微信公众号的类型和注册流程,以及不同公众号的功能使用权限,这个我前面文章也有过介绍,做微信开发公众号最起码得是一个已认证的服务号, 强调一下,这里我是指企业项目哈;另外订阅号现在是不支持认证了,所以订阅号没有开发者相关的权限,因此订阅号只能够大家自己玩玩自媒体啦,企业项目开发的话还是得申请已认证的服务号或者已认证的企业号;当然如果是自己学习研究的话,直接去微信公众平台申请测试号即可,不过这里提前说下,测试号功能权限有限哦,不过大部分常用接口权限还都是有的,日常企业开发或者自己玩用来调试足够了。

另外,关于微信公众号的类型和注册流程请参考这篇: Java微信公众号开发之初步认识微信公众平台 

其次,本篇文章我主要记录如何将开源微信SDK框架所提供的demo:https://github.com/binarywang/weixin-java-mp-demo-springmvc 接入到我们自己的项目中,用于微信公众号后台项目的开发,避免重复造轮子,而且人家写的也很好可以借鉴借鉴,因为里面有一套写的比较好的路由规则和微信接入入口的接口,这些都是微信开发必不可少的工作,整合了这个demo,就不用我们自己再去写了,接下来关于写在前面的话,比较重要,请大家一定要认真阅读;

二、写在前面的话

我项目所使用的架构师基于传统的: Spring+SpringMVC+Mybatis+Shiro ,以下简称SSM,若你所使用的框架是SpringBoot快速开发框架,请移步这篇文章: SpringBoot 系列教程(六十五):Spring Boot整合WxJava开发微信公众号

1、Spring+SpringMVC+Mybatis框架

在整合微信框架weixin-java-tools之前,我假设你们已经使用Spring+SpringMVC+Mybatis技术栈搭建好了一套SSM框架。我要做的就是把 weixin-java-mp-demo-springmvc 这个demo项目里面封装的一些比较好的类加到我们自己的项目框架中去。

2、weixin-java-tools介绍

微信系列项目开发我们选用当下微信比较热门的框架WxJava,前名叫weixin-java-tools,后改名叫 WxJava (微信开发 Java SDK),是一款涵盖了微信支付开放平台小程序企业微信/企业号公众号等后端开发的SDK,该SDK封装了微信公众平台上大部分Api接口,我们开发时直接调用这个SDK里面的接口即可,同时作者针对WxJava 这个SDK还提供了一些接入的Demo,可能是为了方便开发者更快的介入这款SDK吧,而我们的主要目的就是引入WxJava 依赖和作者提供接入的demo即可。

本次我们单纯的是为了开发微信公众号项目,那么我们只需要使用到weixin-java-tools中的微信公众号模块weixin-java-mp ,WxJava框架如下:

3、Maven引用微信公众号SDK方式

  Maven引入微信公众号模块依赖如下:

  <!-- 微信框架 参考:https://github.com/Wechat-Group/weixin-java-tools --><dependency><groupId>com.github.binarywang</groupId><artifactId>weixin-java-mp</artifactId><version>3.0.0</version></dependency>

4、内网穿透

关于微信开发,有个东西很重要,微信开发需要使用内网穿透才可以进行开发调试,也就是将本地localhost地址通过内网穿透,映射到外网去,通过外网才可以和微信的服务器进行消息通讯,数据的传输,这里我用过好几种内网穿透,为了避免大家不知道怎么选择,我推荐大家选择Natapp,Natapp很稳定,速度也快,https://natapp.cn/ ,单纯的微信开发调试选择购买9元每个月的隧道就行了,免费的域名随时变动,而且不稳定,因此不推荐大家使用,具体使用和配置参考:内网穿透常用的工具

说明:  内网穿透是微信开发必不可少的,上面给大家介绍了使用natapp并不是给他打广告,也没有任何合作,我纯粹是为了大家少走弯路才提及哦,市场上内网穿透种类也有很多种,大家可以自行选择。

5. 微信公众平台测试账号申请与功能权限列表

微信公众平台测试账号申请: http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login

接口功能权限列表:

 

三、整合weixin-java-mp-demo-springmvc

1、Demo项目

  1. 在码云和 GitHub 上均可访问,会尽量保持同步,请根据自己情况选用。
  2. 一般来说,Github上的版本应该是最新的,但也有可能没及时同步,此种情况下请以 Github 上的版本为准,有问题也请在 Github 对应项目 Issues 页面提问)。
  3. 欢迎提供更多的 demo 实现。

2、Spring Boot Starter 实现

  • 微信支付:点击查看使用方法
  • 微信公众号:点击查看使用方法
  • 微信小程序:点击查看使用方法

3、Demo 列表

  1. 微信支付 Demo:GitHub、码云
  2. 企业号/企业微信 Demo:GitHub、码云
  3. 微信小程序 Demo:GitHub、码云
  4. 开放平台 Demo:GitHub、码云
  5. 公众号 Demo:
    • 使用 Spring MVC 实现的公众号 Demo:GitHub、码云
    • 使用 Spring Boot 实现的公众号 Demo(支持多公众号):GitHub、码云
    • 含公众号和部分微信支付代码的 Demo:GitHub、码云

注: 如果你的项目是SpringBoot框架, 可以下载Demo列表中的SpringBoot版,接入方式都一样,参照后续步骤

4、下载weixin-java-demo-springmvc的demo

下载地址:  https://github.com/Wechat-Group/weixin-java-demo-springmvc     

5、微信路由WeixinService核心类

demo下载下来后,看一下WeixinService代码,里面涉及到作者自己写的路由,如果不想自己写路由,可以直接借鉴复用

package com.github.binarywang.demo.spring.service;import javax.annotation.PostConstruct;import me.chanjar.weixin.mp.constant.WxMpEventConstants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import com.github.binarywang.demo.spring.config.WxMpConfig;
import com.github.binarywang.demo.spring.handler.AbstractHandler;
import com.github.binarywang.demo.spring.handler.KfSessionHandler;
import com.github.binarywang.demo.spring.handler.LocationHandler;
import com.github.binarywang.demo.spring.handler.LogHandler;
import com.github.binarywang.demo.spring.handler.MenuHandler;
import com.github.binarywang.demo.spring.handler.MsgHandler;
import com.github.binarywang.demo.spring.handler.NullHandler;
import com.github.binarywang.demo.spring.handler.StoreCheckNotifyHandler;
import com.github.binarywang.demo.spring.handler.SubscribeHandler;
import com.github.binarywang.demo.spring.handler.UnsubscribeHandler;import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.mp.api.WxMpInMemoryConfigStorage;
import me.chanjar.weixin.mp.api.WxMpMessageRouter;
import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl;
import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfOnlineList;
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;import static me.chanjar.weixin.common.api.WxConsts.*;/*** * @author Binary Wang**/
@Service
public class WeixinService extends WxMpServiceImpl {private final Logger logger = LoggerFactory.getLogger(this.getClass());@Autowiredprotected LogHandler logHandler;@Autowiredprotected NullHandler nullHandler;@Autowiredprotected KfSessionHandler kfSessionHandler;@Autowiredprotected StoreCheckNotifyHandler storeCheckNotifyHandler;@Autowiredprivate WxMpConfig wxConfig;@Autowiredprivate LocationHandler locationHandler;@Autowiredprivate MenuHandler menuHandler;@Autowiredprivate MsgHandler msgHandler;@Autowiredprivate UnsubscribeHandler unsubscribeHandler;@Autowiredprivate SubscribeHandler subscribeHandler;private WxMpMessageRouter router;@PostConstructpublic void init() {final WxMpInMemoryConfigStorage config = new WxMpInMemoryConfigStorage();config.setAppId(this.wxConfig.getAppid());// 设置微信公众号的appidconfig.setSecret(this.wxConfig.getAppsecret());// 设置微信公众号的app corpSecretconfig.setToken(this.wxConfig.getToken());// 设置微信公众号的tokenconfig.setAesKey(this.wxConfig.getAesKey());// 设置消息加解密密钥super.setWxMpConfigStorage(config);this.refreshRouter();}private void refreshRouter() {final WxMpMessageRouter newRouter = new WxMpMessageRouter(this);// 记录所有事件的日志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.getMenuHandler()).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.getSubscribeHandler()).end();// 取消关注事件newRouter.rule().async(false).msgType(XmlMsgType.EVENT).event(EventType.UNSUBSCRIBE).handler(this.getUnsubscribeHandler()).end();// 上报地理位置事件newRouter.rule().async(false).msgType(XmlMsgType.EVENT).event(EventType.LOCATION).handler(this.getLocationHandler()).end();// 接收地理位置消息newRouter.rule().async(false).msgType(XmlMsgType.LOCATION).handler(this.getLocationHandler()).end();// 扫码事件newRouter.rule().async(false).msgType(XmlMsgType.EVENT).event(EventType.SCAN).handler(this.getScanHandler()).end();// 默认newRouter.rule().async(false).handler(this.getMsgHandler()).end();this.router = newRouter;}public WxMpXmlOutMessage route(WxMpXmlMessage message) {try {return this.router.route(message);}catch (Exception e) {this.logger.error(e.getMessage(), e);}return null;}public boolean hasKefuOnline() {try {WxMpKfOnlineList kfOnlineList = this.getKefuService().kfOnlineList();return kfOnlineList != null && kfOnlineList.getKfOnlineList().size() > 0;}catch (Exception e) {this.logger.error("获取客服在线状态异常: " + e.getMessage(), e);}return false;}protected MenuHandler getMenuHandler() {return this.menuHandler;}protected SubscribeHandler getSubscribeHandler() {return this.subscribeHandler;}protected UnsubscribeHandler getUnsubscribeHandler() {return this.unsubscribeHandler;}protected AbstractHandler getLocationHandler() {return this.locationHandler;}protected MsgHandler getMsgHandler() {return this.msgHandler;}protected AbstractHandler getScanHandler() {return null;}}

3、接入项目

从这一步开始,我们就把上面的weixin-java-demo-springmvc demo代码接入到我们已经搭建好框架的项目中去

 1、 首先在我的项目中新建包名为wechat

  

2、然后将下载的Demo中包aop、builder、config、controller、dto、handler、service包括一个配置文件wx.properties复制到我们自己的项目中

移植到我们自己项目中的效果图如下,红框是移植过来的文件和配置:

 

3、这一步我们需要将上一步中移植过来的的wx.properties加载到Spring容器中,随着web.xml一起加载初始化,具体见下面截图红框框出来的,在我们自己项目中配置wx.properties如下:

  wx.properties内容展示:

#=========微信公众号开发基本配置============
#微信公众号的appid
wx_appid=xxx
#微信公众号的appsecret
wx_appsecret=xxx
#微信公众号的token
wx_token=xxx
#微信公众号的消息加解密密钥aeskey
wx_aeskey=WoDWc9c9jseK4gYzOcZChVaGDkcLTgmoS3O2F7KZtWV

加载到Spring容器如下截图中红框所示

4、需要在wx.properties中配置微信公众平台的几个参数来接入微信服务器的验证参数 ,这里的=后面数值都要填上

#=========微信公众号开发基本配置============
#微信公众号的appid
wx_appid=xxx
#微信公众号的appsecret
wx_appsecret=xxx
#微信公众号的token
wx_token=xxx
#微信公众号的消息加解密密钥aeskey
wx_aeskey=WoDWc9c9jseK4gYzOcZChVaGDkcLTgmoS3O2F7KZtWV

5、微信的入口 :WxMpPortalController ,这里是跟微信公众平台配置我们项目服务器的URL交互类

package com.thinkgem.jeesite.modules.wechat.controller;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.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;import com.thinkgem.jeesite.modules.wechat.service.WXLogService;
import com.thinkgem.jeesite.modules.wechat.service.WeixinService;/*** * @ClassName: WxMpPortalController* @Description: 微信主入口* @author CaoWenCao* @date 2018年6月12日 下午10:13:57*/
@RestController
@RequestMapping("/wechat/portal")
public class WxMpPortalController {@Autowiredprivate WeixinService wxService;@Autowiredprivate WXLogService wXLogService;private final Logger logger = LoggerFactory.getLogger(this.getClass());/** 微信验签*/@ResponseBody@GetMapping(produces = "text/plain;charset=utf-8")public String authGet(@RequestParam(name = "signature", required = false) String signature, @RequestParam(name = "timestamp", required = false) String timestamp, @RequestParam(name = "nonce", required = false) String nonce,@RequestParam(name = "echostr", required = false) String echostr) {this.logger.info("\n接收到来自微信服务器的认证消息:[{}, {}, {}, {}]", signature, timestamp, nonce, echostr);if (StringUtils.isAnyBlank(signature, timestamp, nonce, echostr)) {throw new IllegalArgumentException("请求参数非法,请核实!");}if (this.getWxService().checkSignature(timestamp, nonce, signature)) {return echostr;}return "非法请求";}/** 消息转发---中转站 每次微信端的消息都会来到这里进行分发 对微信公众号相关的一些动作,都以报文形式推送到该接口,根据请求的类型,进行路由分发处理*/@ResponseBody@PostMapping(produces = "application/xml; charset=UTF-8")public String post(@RequestBody String requestBody, @RequestParam("signature") String signature, @RequestParam(name = "encrypt_type", required = false) String encType, @RequestParam(name = "msg_signature", required = false) String msgSignature,@RequestParam("timestamp") String timestamp, @RequestParam("nonce") String nonce) {this.logger.info("\n接收微信请求:[signature=[{}], encType=[{}], msgSignature=[{}]," + " timestamp=[{}], nonce=[{}], requestBody=[\n{}\n] ", signature, encType, msgSignature, timestamp, nonce, requestBody);if (!this.wxService.checkSignature(timestamp, nonce, signature)) {throw new IllegalArgumentException("非法请求,可能属于伪造的请求!");}String out = null;if (encType == null) {// 明文传输的消息WxMpXmlMessage inMessage = WxMpXmlMessage.fromXml(requestBody);// 如果是明文传输 ,保存 微信接收 信息,保存到数据库,用于微信消息管理中的客服互动wXLogService.doSaveReceiveLog(inMessage);//this.logger.info("\n保存微信接受信息WxMpXmlMessage:\n{}", inMessage);WxMpXmlOutMessage outMessage = this.getWxService().route(inMessage);if (outMessage == null) {return "";}out = outMessage.toXml();// 日志出口时,保存微信发出去的XML(给用户)wXLogService.doSaveMsgLogOut(outMessage);//this.logger.info("\n保存微信输出日志WxMpXmlOutMessage信息:\n{}", outMessage);}else if ("aes".equals(encType)) {// aes加密的消息WxMpXmlMessage inMessage = WxMpXmlMessage.fromEncryptedXml(requestBody, this.getWxService().getWxMpConfigStorage(), timestamp, nonce, msgSignature);this.logger.debug("\n消息解密后内容为:\n{} ", inMessage.toString());// 如果是密文传输 ,保存 微信接收 信息wXLogService.doSaveReceiveLog(inMessage);WxMpXmlOutMessage outMessage = this.getWxService().route(inMessage);if (outMessage == null) {return "";}out = outMessage.toEncryptedXml(this.getWxService().getWxMpConfigStorage());// 日志出口时,保存微信发出去的XML(给用户)wXLogService.doSaveMsgLogOut(outMessage);this.logger.info("\n保存微信输出日志WxMpXmlOutMessage信息:\n{}", outMessage);// 保存回复消息记录//wXLogService.doSaveReplyLog(outMessage);}this.logger.debug("\n组装回复信息:{}", out);return out;}protected WeixinService getWxService() {return this.wxService;}}

6、整合完成后项目完整截图

 

 

四、对接微信公众平台配置

1、消息传递流程

关于微信公众号后台开发发出消息和收到响应结果的一个流程,大家看下面这张图

这是大家在公众号后台回复关键字的情况。那么这个消息是怎么样一个传递流程呢?我们来看看下面这张图:

这张图,我给大家稍微解释下:

首先"4" 这个字符从公众号上发送到了微信服务器
接下来微信服务器会把 “4” 转发到我自己的服务器上
我们服务器收到 “4” 这个字符之后,就去数据库中查询,将查询的结果,按照腾讯要求的 XML 格式进行返回
微信服务器把从我的服务器收到的信息,再发回到微信上,于是小伙伴们就看到了返回结果了
大致的流程就是这个样子。

接下来我们就来看一下实现细节。
 

2. 公众号后台配置

开发的第一步,是微信服务器要验证我们自己的服务器是否有效。

首先我们登录微信公众平台官网后,在公众平台官网的 开发-基本设置 页面,勾选协议成为开发者,然后点击“修改配置”按钮,填写:

  • 服务器地址(URL)
  • Token
  • EncodingAESKey

开发者提交信息后,微信服务器将发送GET请求到填写的服务器地址URL上,GET请求携带四个参数:

参数描述
signature微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。
timestamp时间戳
nonce随机数
echostr随机字符串

 

 

 

 

 

原理: 开发者通过检验signature对请求进行校验(下面有校验方式)。若确认此次GET请求来自微信服务器,请原样返回echostr参数内容,则接入生效,成为开发者成功,否则接入失败。

signature验证结合了token,和请求中的timestamp参数,nonce参数

加密/校验流程如下:

  • 1. 将token、timestamp、nonce三个参数进行字典排序
  • 2. 将三个参数字符串拼接成一个字符串进行SHA散列加密
  • 3. 开发者获得加密后的字符串可与signature对比,标识该请求来源于微信

解释:

URL: 这里的 URL 配置好之后,我们需要针对这个 URL 开发两个接口,一个是 GET 请求的接口,这个接口用来做服务器有效性验证;另一个则是 POST 请求的接口,这个用来接收微信服务器发送来的消息。也就是说,微信服务器的消息都是通过 POST 请求发给我的。

Token: 可由开发者可以任意填写,用作生成签名(该 Token 会和接口 URL 中包含的 Token 进行比对,从而验证安全性)。

EncodingAESKey:  由开发者手动填写或随机生成,将用作消息体加解密密钥。

同时,开发者可选择消息加解密方式:明文模式、兼容模式和安全模式。明文模式就是我们自己的服务器收到微信服务器发来的消息是明文字符串,直接就可以读取并且解析,安全模式则是我们收到微信服务器发来的消息是加密的消息,需要我们手动解析后才能使用,一般无特殊要求默认使用明文模式。
 

3、服务器有效性校验Rest接口

我们需要在微信公众号后台配置URL访问这个Rest接口,这是与微信公众平台交互的门户入口。

package com.thinkgem.jeesite.modules.wechat.controller;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.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;import com.thinkgem.jeesite.modules.wechat.service.WXLogService;
import com.thinkgem.jeesite.modules.wechat.service.WeixinService;/*** * @ClassName: WxMpPortalController* @Description: 微信主入口* @author CaoWenCao* @date 2018年6月12日 下午10:13:57*/
@RestController
@RequestMapping("/wechat/portal")
public class WxMpPortalController {@Autowiredprivate WeixinService wxService;@Autowiredprivate WXLogService wXLogService;private final Logger logger = LoggerFactory.getLogger(this.getClass());/** 微信验签*/@ResponseBody@GetMapping(produces = "text/plain;charset=utf-8")public String authGet(@RequestParam(name = "signature", required = false) String signature, @RequestParam(name = "timestamp", required = false) String timestamp, @RequestParam(name = "nonce", required = false) String nonce,@RequestParam(name = "echostr", required = false) String echostr) {this.logger.info("\n接收到来自微信服务器的认证消息:[{}, {}, {}, {}]", signature, timestamp, nonce, echostr);if (StringUtils.isAnyBlank(signature, timestamp, nonce, echostr)) {throw new IllegalArgumentException("请求参数非法,请核实!");}if (this.getWxService().checkSignature(timestamp, nonce, signature)) {return echostr;}return "非法请求";}/** 消息转发---中转站 每次微信端的消息都会来到这里进行分发 对微信公众号相关的一些动作,都以报文形式推送到该接口,根据请求的类型,进行路由分发处理*/@ResponseBody@PostMapping(produces = "application/xml; charset=UTF-8")public String post(@RequestBody String requestBody, @RequestParam("signature") String signature, @RequestParam(name = "encrypt_type", required = false) String encType, @RequestParam(name = "msg_signature", required = false) String msgSignature,@RequestParam("timestamp") String timestamp, @RequestParam("nonce") String nonce) {this.logger.info("\n接收微信请求:[signature=[{}], encType=[{}], msgSignature=[{}]," + " timestamp=[{}], nonce=[{}], requestBody=[\n{}\n] ", signature, encType, msgSignature, timestamp, nonce, requestBody);if (!this.wxService.checkSignature(timestamp, nonce, signature)) {throw new IllegalArgumentException("非法请求,可能属于伪造的请求!");}String out = null;if (encType == null) {// 明文传输的消息WxMpXmlMessage inMessage = WxMpXmlMessage.fromXml(requestBody);// 如果是明文传输 ,保存 微信接收 信息,保存到数据库,用于微信消息管理中的客服互动wXLogService.doSaveReceiveLog(inMessage);//this.logger.info("\n保存微信接受信息WxMpXmlMessage:\n{}", inMessage);WxMpXmlOutMessage outMessage = this.getWxService().route(inMessage);if (outMessage == null) {return "";}out = outMessage.toXml();// 日志出口时,保存微信发出去的XML(给用户)wXLogService.doSaveMsgLogOut(outMessage);//this.logger.info("\n保存微信输出日志WxMpXmlOutMessage信息:\n{}", outMessage);}else if ("aes".equals(encType)) {// aes加密的消息WxMpXmlMessage inMessage = WxMpXmlMessage.fromEncryptedXml(requestBody, this.getWxService().getWxMpConfigStorage(), timestamp, nonce, msgSignature);this.logger.debug("\n消息解密后内容为:\n{} ", inMessage.toString());// 如果是密文传输 ,保存 微信接收 信息wXLogService.doSaveReceiveLog(inMessage);WxMpXmlOutMessage outMessage = this.getWxService().route(inMessage);if (outMessage == null) {return "";}out = outMessage.toEncryptedXml(this.getWxService().getWxMpConfigStorage());// 日志出口时,保存微信发出去的XML(给用户)wXLogService.doSaveMsgLogOut(outMessage);this.logger.info("\n保存微信输出日志WxMpXmlOutMessage信息:\n{}", outMessage);// 保存回复消息记录//wXLogService.doSaveReplyLog(outMessage);}this.logger.debug("\n组装回复信息:{}", out);return out;}protected WeixinService getWxService() {return this.wxService;}}

4、关于验证服务器地址的有效性

在配置我们自己开发的后台管理系统对接微信公众平台之前(也叫做接入开发者),我们来看一下后台管理系统需要哪些参数:

  •  appId : 微信appId
  •  secret :   微信secret
  •  token :    微信token
  •  aesKey  微信加解密密钥(用到消息加解密需配置)

在我们自己的后台项目配置文件中里配置这4个参数,接下来就是配置URL了,这个URL就是微信公众平台服务器跟我们自己的后台服务器产生事件消息推送的一根桥梁线,所以URL需要填写地址如:http://xxxx.natapp1.cc/greenwx/wechat/portal  。

 

5、关于事件推送

URL是用户与微信公众号交互时,产生的一些事件推送,微信服务器将这些事件推送到我们服务器的一个地址,填写了我们服务器的地址后,微信服务器就知道往这个URL所在的服务器推送消息,就可以产生交互。

  • 具体的事件推送有如下这些:

 

  • Get请求:

上面WxMpPortalController中有两个方法,这两个方法是微信服务器与我们自身服务器交流的一个门户入口,是连接微信服务器的大门,你需要理解的是,默认的微信验签会走authGet这个方法,请求方式是get,前面填写的4个参数就会在这个方法里走验签逻辑,验签不通过无法接入开发者模式;

  • Post请求

另外一个接口Post的作用就是当用户在与微信公众号事件推送时,微信服务器会把XML格式的消息通过我们填写的这个URL地址推送到我们后台服务器,这个时候是请求接口post, 请求方式是也是post,转发到post这个方法的接口上时,这个方法会根据消息类型判断,然后走路由转发,将请求转发到各个handler进行处理;

 

  • 最后

到此为止,接入完成,可以开始调SDK接口开发微信相关功能了,因为路由和服务器验证等等接口不用我们写了,这样我们只关注功能的实现就行了,框架的对接借鉴了demo中一些比较好的封装类,为开发时间节点省去了不少时间,如果对此文章有不懂流程的,请评论里留下问题,我会回复;

 

 


http://chatgpt.dhexx.cn/article/son4Tl5W.shtml

相关文章

微信公众号开发入门

实在是太折腾&#xff0c;太难懂了。也太坑了。 下面是这几天来&#xff0c;有关微信公众号的工作总结。算不上全面&#xff0c;只是作为一个初学者的记录&#xff0c;仅以备忘。 一、微信公众号开发&#xff0c;开发什么&#xff1f; 公众号与小程序不同。小程序类似手机AP…

微信公众平台快速开发框架源码

ASP.NET微信快速开发框架源码 微信公众平台快速开发框架源码 框架主要技术&#xff1a; ASP.NET MVC5、ASP.NET Identity、Bootstrap、KnockoutJs、Entity Framework等。 主要特色&#xff1a; 快速迭代开发&#xff0c;提供最好的威信开发框架&#xff1b; 基于ASP.NET MVC5Bo…

微信公众号开发,原来这么简单?[java框架]

终于有时间更新啦&#xff01;&#xff01;最新教程双手奉上&#xff01;公众号开发之wx-toolsspringboot应用实战-音乐爬虫推送[JAVA] 下面都是旧的教程&#xff0c;建议参考上面最新的教程~~ 可能你不知道&#xff0c;有个框架叫wx-tools&#xff08;小心翼翼地说&#xff09…

公众号开发(2) —— 盛派.net SDK + vue搭建微信公众号网页开发框架

需求&#xff1a;通过微信公众号菜单跳转到手机端网页&#xff0c;跳转后通过微信授权登录获取微信公众号用户的OpenId&#xff08;用户关注公众号后&#xff0c;用户在公众号的唯一凭证&#xff09;&#xff0c;通过OpenId和后台数据库用户信息绑定起来并实现一些业务逻辑。 技…

微信公众号开发框架讲解

微信公众号的开发在基于微信给的开发文档基础上&#xff0c;特别做微商城那底层用Java框架会相当方便。下面长沙Java培训给大家具体讲讲微信公众号开发框架&#xff1a; 核心框架&#xff1a;Spring Boot2 Spring Cloud Alibaba Spring Cloud Gateway 配置中心、注册中心&am…

人工智能博弈树极大极小搜索算法alpha-beta剪枝实现五子棋,带禁手

由于2020的特殊情况&#xff0c;导致了一个被拖了挺久的大作业。。。。 五子棋其实大家很多时候会在闲暇时刻和朋友随便玩玩&#xff0c;这不仅让我回忆起了高中时候摸鱼休息就喜欢和同学在自己打的格子中用铅笔来一盘五子棋&#xff0c;回想起来确实是至今以来最快乐的一段时光…

基于Python的人机交互的五子棋博弈树搜索

1. 算法原理 1.1 博弈树 博弈树针对的是二人零和博弈的问题&#xff0c;二人轮流行动&#xff0c;行动时令自己的优势最大。二人零和博弈有如下特点&#xff1a; 确定性&#xff1a;二人的行动有多种选择&#xff0c;但最终的行动是确定的信息完备性&#xff1a;博弈双方知道…

C++实现基于博弈树的5x5一子棋人机对战

基于博弈树的5x5一子棋人机对战 919106840637实验2 这是智能计算三个课程实验的第二个实验&#xff0c;即博弈树搜索 。我之前对博弈树的了解不多&#xff0c;所以实现起来比较的简略&#xff0c;仅仅是基本达到了要求 实验语言 C 实验内容 实践博弈树搜索——“5x5格子的一…

人工智能作业——搜索树博弈树一阶逻辑表达式CNF范式

1. 人工智能定义 1. 简述什么是人工智能 人工智能可分为两个维度:一个维度是从思维推理过程到行为结果(过程与结果);另一个维度是与人类表现的逼真度到数学与工程结合后的精确性(主观与客观)。 像人—样行动&#xff1a;图灵测试的途径&#xff1b;像人—样思考&#xff1a;认…

AlphaBeta剪枝算法求解博弈树最优选择 头歌实验平台

AlphaBeta剪枝算法求解博弈树最优选择 头歌实验平台 前言一、AlphaBeta剪枝是什么&#xff1f;1.由来, 最大最小决策树2.发展3. AlphaBeta剪枝 二、实验算法伪代码三、实验算法代码四、实验结果在这里插入图片描述 五、感谢 前言 产生本文的缘由 人工智能原理课程 可选实验 “…

并行博弈树搜索算法-第3篇 优秀的园丁:Alpha-Beta算法

3.1 Alpha-Beta算法 虽然博弈树的状态是有限的,但是状态个数却非常多.假设博弈树的深度为d,每个结点有b个分支,即分支因子&#xff08;branchingfactor&#xff09;为b,那么使用Min-Max方法搜索这个博弈树需要搜索个结点. 然而幸运的是,Min-Max方法的一些搜索是没有必要的,…

利用α-β搜索的博弈树算法编写一字棋游戏 python

游戏规则 “一字棋"游戏&#xff08;又叫"三子棋"或"井字棋”&#xff09;&#xff0c;是一款十分经典的益智小游戏。“井字棋"的棋盘很简单&#xff0c;是一个 33 的格子&#xff0c;很像中国文字中的"井"字&#xff0c;所以得名"井字…

博弈树 极小极大分析法

一、博弈概述 博弈特点&#xff1a; &#xff08;1&#xff09;博弈的初始格局是初始节点 &#xff08;2&#xff09;在博弈树中&#xff0c;“或”和“与”是交替出现的。自己一方的扩展节点是“或”关系&#xff0c;对方扩展的节点是“与”关系。双方轮流扩展节点。 &…

第6-2课:决策树、博弈树和行为树

在以各种“XX学习”为代表的人工智能技术普及之前,游戏里常见的角色 AI 都是各种预设的行为逻辑,比如博弈树和行为树,当然也会用到各种专家知识库。当这些预设的行为逻辑足够复杂的时候,往往会让游戏玩家觉得游戏里的人物很“智能”。从本质上来说,这些都还不算是真正的 A…

并行博弈树搜索算法-第4篇 更上一层楼:Alpha-Beta算法的改进

在Alpha-Beta算法被广泛运用后,对该算法的很多改进算法也相继被提出.这些改进算法主要在以下几个方面对Alpha-Beta算法进行改进[7]: 1. 择序&#xff08;ordering&#xff09;.在搜索博弈树时,内部结点有多个可能的移动.择序指的是搜索这些分支的顺序.择序影响着搜索叶结点的个…

博弈树的启发式搜索

什么是博弈树 在博弈过程中, 任何一方都希望自己取得胜利。因此,当某一方当前有多个行动方案可供选择时, 他总是挑选对自己最为有利而对对方最为不利的那个行动方案。 此时,如果我们站在A方的立场上,则可供A方选择的若干行动方案之间是“或”关系, 因为主动权操在A方手里,他或…

博弈树 α-β剪枝

由于搜索的复杂度有点高&#xff0c;所以在树上减少计算量肯定是剪枝了&#xff0c;这里我们把剪枝的办法称作的&#xff1a;α-β剪枝 我们在前面的文章中谈到&#xff0c;当第一次运作的是A&#xff0c;则所有的奇数深度的节点都是A做的选择&#xff0c;所有偶数深度的节点都…

博弈树优化

前言:   对弈类游戏的智能算法, 网上资料颇多, 大同小异. 然而书上得来终觉浅, 绝知此事要躬行. 结合了自己的工程实践, 简单汇总整理下. 一方面是对当年的经典<<PC游戏编程(人机博弈)>>表达敬意, 另一方面, 也想对自己当年的游戏编程人生做下回顾.   承接上两…

博弈树中关于α-β剪枝树要点

目录 一&#xff0c;α-β剪枝树搜索方法&#xff1a;深度优先&#xff08;DFS&#xff09;&#xff0c;一般从博弈树最左边开始一直搜索到最右边。 人工智能导论复习&#xff1a;| 一&#xff0c;α-β剪枝树搜索方法&#xff1a;深度优先&#xff08;DFS&#xff09;&#…

(只此一篇便绝b能懂的)五子棋AI算法原理,博弈树、极大极小搜索、αβ剪枝

我在最近撰写五子棋AI程序设计报告时&#xff0c;翻阅了很多的资料博客&#xff0c;但却发现大佬们的博客&#xff0c;没有一篇是能让我只看它就能理解全部的AI算法。在看了众多博客后&#xff0c;我终于对博弈树、极大极小搜索、αβ剪枝恍然大悟&#xff0c;其实这些看似高大…