教你如何使用springboot开发微信公众号之两处改动轻松升级到多公众号

引言

如果你正在开发微信公众号,那么这个项目一定不能错过: WxJava - 微信开发 Java SDK

真的可以少走很多弯路,之前使用wx-java-mp-spring-boot-starter快速集成了单个微信公众号,想来只能部署一个公众号太过单一需求,本想着如何研究一下多公众号部署教程,没想到人家自己就提供了wx-java-mp-multi-spring-boot-starter.

话不多说,直接上核心代码,相信有点基础的开发者都能看得懂,不啰嗦,上干货!

如果还没有开发过微信公众号,建议先从这篇系列文章开始,结尾也提供了相关文章链接.

这么小而美的取关功能为什么无法实现呢?为了它,我决定入坑开发微信公众号!

单账号公众号如何集成到springboot项目

以下是最精简的核心代码,如果想要了解更详细配置可参考官方文档: wx-java-mp-spring-boot-starter

最终实现效果如下:

支持自动回复消息,不仅包括关键词回复,收到消息回复以及被关注回复等常规消息,还能接收到用户取消订阅等特殊事件的消息推送.

  • pom.xml依赖文件

当前最新版本4.6.0,点击这里查询最新版[https://developer.aliyun.com/mvn/search}(https://developer.aliyun.com/mvn/search)

<dependency>
    <groupId>com.github.binarywang</groupId>
    <artifactId>wx-java-mp-spring-boot-starter</artifactId>
    <version>4.6.3.B</version>
    <type>pom</type>
</dependency>
  • application.yml配置文件
# 雪之梦技术驿站
wx:
  mp:
    # 单公众号配置(必填)
    app-id: yourappid
    secret: yoursecret
    token: yourtoken
    aes-key: youraeskey
  • WxMpController.java接口请求

这是java后台服务自动和微信公众号服务器后台交互的唯一途径,通过暴露出公共接口开放给微信公众号服务器,来完成消息的验证以及自动回复等相关接口调用.

验证消息来自微信服务器

验证签名无误后原封不动返回随机字符串echostr文本格式

@AnonymousGetMapping(produces = "text/plain;charset=utf-8")
public String checkSignature(@PathVariable String appId,
                             @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) {
    // 校验签名
    log.info("签名校验 ===》 微信加密签名: {} 时间戳: {} 随机数: {} 随机字符串: {}",signature,timestamp,nonce,echostr);
    if (StringUtils.isAnyBlank(signature, timestamp, nonce, echostr)) {
        throw new IllegalArgumentException("非法请求,可能属于伪造的请求!");
    }
    if (!wxMpService.switchover(appId)) {
        throw new IllegalArgumentException(String.format("未找到对应appId=[%s]的配置,请核实!", appId));
    }
    if (!wxMpService.checkSignature(timestamp, nonce, signature)) {
        log.error("签名校验 ===》 非法请求");
        throw new IllegalArgumentException("非法请求,可能属于伪造的请求!");
    }
    log.info("签名校验 ===》 验证成功");
    return echostr;
}

接收并自动回复微信公众号消息

支持明文和密文两种加密方式,测试时建议明文不需要加密解密,正式上线时请改为密文方式,同时要支持加解密等协议规范.

@AnonymousPostMapping(produces = "text/xml; charset=UTF-8")
public String replyMessage(
        @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 encryptType,
        @RequestParam(name = "msg_signature", required = false) String msgSignature) {
    if (!wxMpService.switchover(appId)) {
        throw new IllegalArgumentException(String.format("未找到对应appId=[%s]的配置,请核实!", appId));
    }
    if (!wxMpService.checkSignature(timestamp, nonce, signature)) {
        throw new IllegalArgumentException("非法请求,可能属于伪造的请求!");
    }

    // 消息加解密方式
    String out = null;
    if (encryptType == null) {
        // 明文传输的消息
        WxMpXmlMessage inMessage = WxMpXmlMessage.fromXml(requestBody);
        WxMpXmlOutMessage outMessage = myWxMpService.replyWxMpMsg(inMessage);
        if (outMessage == null) {
            return "";
        }
        out = outMessage.toXml();
    } else if ("aes".equalsIgnoreCase(encryptType)) {
        // aes加密的消息
        WxMpXmlMessage inMessage = WxMpXmlMessage.fromEncryptedXml(requestBody, wxMpService.getWxMpConfigStorage(),timestamp, nonce, msgSignature);
        WxMpXmlOutMessage outMessage = myWxMpService.replyWxMpMsg(inMessage);
        if (outMessage == null) {
            return "";
        }
        out = outMessage.toEncryptedXml(wxMpService.getWxMpConfigStorage());
    }
    return out;
}

通过上述的简单配置即可实现验证微信公众号消息以及接收消息时的被动回复,更多高级功能需要开通相关权限,实测下来能用的权限主要就是消息回复和永久素材两大板块,其余权限只能望洋兴叹!

升级到多账号原来竟如此简单

只需要更换多公众号以来,动态获取当前公众号即可轻松实现单账号到多账号的升级迁移工作,竟然如此简单!

详细配置可参考官方文档: wx-java-mp-multi-spring-boot-starter

如果是从单账号升级到多账号,只需要两处更改.

  • 变更maven依赖wx-java-mp-multi-spring-boot-starter
  • 变更WxMpController注入类private final WxMpMultiServices wxMpMultiServices

如果是直接集成多公众号,请忽略上述内容,直接按照下面的教程整合到已有的springboot项目即可.

  • pom.xml依赖文件

<dependency>
    <groupId>com.github.binarywang</groupId>
    <artifactId>wx-java-mp-multi-spring-boot-starter</artifactId>
    <version>4.6.3.B</version>
</dependency>
  • application.yml配置文件

多账号配置时这里使用了一个小技巧,通过请求路径区分具体的公众号,即应用的id就是app-id.

  • WxMpController.java接口请求

验证消息来自微信服务器

验证签名无误后原封不动返回随机字符串echostr文本格式

@AnonymousGetMapping(produces = "text/plain;charset=utf-8")
public String checkSignature(@PathVariable String appId,
                             @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) {
     // 获取当前公众号服务类
    WxMpService wxMpService = wxMpMultiServices.getWxMpService(appId);        
    // 校验签名
    log.info("签名校验 ===》 微信加密签名: {} 时间戳: {} 随机数: {} 随机字符串: {}",signature,timestamp,nonce,echostr);
    if (StringUtils.isAnyBlank(signature, timestamp, nonce, echostr)) {
        throw new IllegalArgumentException("非法请求,可能属于伪造的请求!");
    }
    if (!wxMpService.switchover(appId)) {
        throw new IllegalArgumentException(String.format("未找到对应appId=[%s]的配置,请核实!", appId));
    }
    if (!wxMpService.checkSignature(timestamp, nonce, signature)) {
        log.error("签名校验 ===》 非法请求");
        throw new IllegalArgumentException("非法请求,可能属于伪造的请求!");
    }
    log.info("签名校验 ===》 验证成功");
    return echostr;
}

相对比单公众号不能直接注入相关的service,需要根据公众号id动态获取WxMpService实现类.

接收并自动回复微信公众号消息

支持明文和密文两种加密方式

@AnonymousPostMapping(produces = "text/xml; charset=UTF-8")
public String replyMessage(
        @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 encryptType,
        @RequestParam(name = "msg_signature", required = false) String msgSignature) {
     // 获取当前公众号服务类
    WxMpService wxMpService = wxMpMultiServices.getWxMpService(appId);
    if (!wxMpService.switchover(appId)) {
        throw new IllegalArgumentException(String.format("未找到对应appId=[%s]的配置,请核实!", appId));
    }
    if (!wxMpService.checkSignature(timestamp, nonce, signature)) {
        throw new IllegalArgumentException("非法请求,可能属于伪造的请求!");
    }

    // 消息加解密方式
    String out = null;
    if (encryptType == null) {
        // 明文传输的消息
        WxMpXmlMessage inMessage = WxMpXmlMessage.fromXml(requestBody);
        WxMpXmlOutMessage outMessage = myWxMpService.replyWxMpMsg(inMessage);
        if (outMessage == null) {
            return "";
        }
        out = outMessage.toXml();
    } else if ("aes".equalsIgnoreCase(encryptType)) {
        // aes加密的消息
        WxMpXmlMessage inMessage = WxMpXmlMessage.fromEncryptedXml(requestBody, wxMpService.getWxMpConfigStorage(),timestamp, nonce, msgSignature);
        WxMpXmlOutMessage outMessage = myWxMpService.replyWxMpMsg(inMessage);
        if (outMessage == null) {
            return "";
        }
        out = outMessage.toEncryptedXml(wxMpService.getWxMpConfigStorage());
    }
    return out;
}

两个公众号的微信公众号后台完全按照统一的开发配置服务器url,java后台根据不同的appid识别到具体公众号,轻松实现统一管理.

通过聊天回复能力也可以看到现在的回复能力是统一的,如何实现差异化设置?

// 应用 1 的 WxMpService
WxMpService wxMpService1 = wxMpMultiServices.getWxMpService("tenantId1");
WxMpUserService userService1 = wxMpService1.getUserService();
userService1.userInfo("xxx");
// todo ...

// 应用 2 的 WxMpService
WxMpService wxMpService2 = wxMpMultiServices.getWxMpService("tenantId2");
WxMpUserService userService2 = wxMpService2.getUserService();
userService2.userInfo("xxx");

我们的配置文件tenantId1就是appid1,tenantId2就是appid2,直接区分出公众号.

可以看到具体的消息对象包含了发送消息来源以及公众号id gh_XXXXXX,也是可以区分出公众号.

{
    "allFieldsMap": {
        "Content": "你是谁?",
        "CreateTime": "1724281534",
        "ToUserName": "gh_XXXXXX",
        "FromUserName": "XXXXXX_kM",
        "MsgType": "text",
        "MsgId": "24685777429644709"
    },
    "articleUrlResult": {},
    "content": "你是谁?",
    "createTime": 1724281534,
    "fromUser": "XXXXXX_kM",
    "hardWare": {},
    "msgId": 24685777429644709,
    "msgType": "text",
    "scanCodeInfo": {},
    "sendLocationInfo": {},
    "sendPicsInfo": {
        "picList": []
    },
    "toUser": "gh_XXXXXX"
}

引入ai智障回复

保持微信公众号后台自动回复相同的逻辑,当收到消息时开启ai智能回复.

编程时需要考虑关键词回复和收到消息回复不能有冲突,关键词回复直接返回消息,其余的消息则默认启用自动回复.

想要体验ai智障回复的用户直接搜索: 雪之梦技术驿站或者情感美食 均已实现相同回复.

总结

本文主要介绍了SpringBoot开发微信公众号的正确姿势,通过优秀项目WxJava实现快速整合到已有项目.

优秀的项目不单单支持微信公众号,还支持超级多的微信全家桶.

  • 微信小程序:weixin-java-miniapp
  • 微信支付:weixin-java-pay
  • 微信开放平台:weixin-java-open
  • 公众号(包括订阅号和服务号):weixin-java-mp
  • 企业号/企业微信:weixin-java-cp

原来是单个微信公众号,升级到多公众号设置也可以如此简单,更换maven依赖,通过WxMpMultiServices实现类动态获取原来单一微信公众号服务类WxMpService,其余代码均可保持不变.

// 获取当前公众号服务类
WxMpService wxMpService = wxMpMultiServices.getWxMpService(appId);

最后,欢迎关注公众号情感美食每日分享一道家常菜,来一起分享深夜emo小故事.

公众号开发系列文章

黑夜里和自己的对话

  • 32
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Spring Boot 是一种用于开发 Java 应用程序的框架,它简化了传统 Java 开发的繁琐过程,使开发人员可以更快速地构建高效的应用程序。UniApp 是一个跨平台的开发框架,它可以同时开发 Android、iOS 和 Web 应用程序,极大地提高了开发效率和项目的可维护性。 微信公众号开发是指基于微信平台的应用程序开发,通过微信公众号,我们可以实现与用户的互动交流、推送消息、提供各种服务等。 在使用 Spring Boot 和 UniApp 进行微信公众号开发时,可以采用前后端分离的开发模式。前端使用 UniApp 进行界面设计和用户交互的开发后端使用 Spring Boot 进行业务逻辑的处理和数据的存储。 首先,我们需要在微信公众平台注册一个开发者账号,获取到相应的公众号信息和接口权限。 接下来,前端开发人员可以使用 UniApp 进行公众号的界面设计和交互逻辑的编写。UniApp 提供了丰富的组件和模板,可以方便地实现各种界面效果,并且可以使用 Vue.js 进行数据的绑定与处理。 后端开发人员使用 Spring Boot 进行接口的开发和业务逻辑的处理。可以使用 Spring Boot 提供的丰富的功能和插件来简化开发,比如使用 Spring Data JPA 来操作数据库,使用 Spring Security 来实现用户认证与权限控制等。 最后,前后端通过接口进行数据的传输和交互,前端将用户的操作发送到后端进行处理,并将后端返回的数据展示给用户。 通过采用 Spring Boot 和 UniApp 进行微信公众号开发,可以充分发挥两者的优势,快速构建高效的应用程序,实现与用户的互动和服务。同时,由于使用的是跨平台的开发框架,可以方便地同时开发多个平台的应用程序,提高开发效率和项目的可维护性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

snowdreams1006

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值