微信开发框架WxJava之微信公众号开发的入门使用篇

news2024/11/25 11:47:36

微信开发框架WxJava之微信公众号开发的入门使用篇

  • WxJava介绍
  • 微信公众号
    • 申请测试公众号
    • 测试公众号配置
  • WxJava微信公众号开发
    • 添加依赖
    • 配置微信参数
    • 实例化WxMpService
    • 对接微信公众号回调
    • 接收与回复消息
  • 微信消息路由器
    • WxMpMessageHandler
    • WxMessageInterceptor
    • 自定义Handle
    • 自定义Interceptor
    • 创建消息路由配置
    • 使用消息路由
    • 执行测试
  • access_token持久化

WxJava介绍

WxJava是一款基于Java语言的微信开发Java SDK,它提供了微信支付,开放平台,小程序,企业微信,公众号等多个平台的API接口,并将其封装为易于调用的Java方法,方便Java开发者快速开发与微信相关的应用。

GitHub地址:https://github.com/Wechat-Group/WxJava

使用WxJava只需要引入开发相关模块的maven依赖即可

<dependency>
  <groupId>com.github.binarywang</groupId>
  <artifactId>(不同模块参考下文)</artifactId>
  <version>4.5.0</version>
</dependency>
微信小程序:weixin-java-miniapp

微信支付:weixin-java-pay

微信开放平台:weixin-java-open

公众号(包括订阅号和服务号):weixin-java-mp

企业号/企业微信:weixin-java-cp

微信公众号

如果没有个人微信号或者企业微信号,可以申请测试公众号,并且拥有所有接口权限,推荐。

申请测试公众号

访问申请测试公众号,申请一个测试的微信公众号,测试微信公众号拥有所有高级功能。

在这里插入图片描述

测试公众号配置

申请测试公众号后,会分配一个测试的appid和秘钥,接着配置一个可用于内网穿透的地址

注意:URL地址指向本地开发能访问的某个接口
在这里插入图片描述

扫描测试号二维码以关注测试公众号,同时获取用户openid

在这里插入图片描述

WxJava微信公众号开发

WxJava对应的微信公众号开发文档

添加依赖

非Spring Boot:
在这里插入图片描述

        <dependency>
            <groupId>com.github.binarywang</groupId>
            <artifactId>weixin-java-mp</artifactId>
            <version>4.5.0</version>
        </dependency>

Spring Boot:
在这里插入图片描述

        <dependency>
            <groupId>com.github.binarywang</groupId>
            <artifactId>wx-java-mp-spring-boot-starter</artifactId>
            <version>4.5.0</version>
        </dependency>

配置微信参数

非Spring Boot方式引入依赖,需要自定义微信相关配置信息,同时需要初始化一个WxMpService实例。

# 自定义微信相关配置信息
wx:
  # 消息模板ID
  templateId: o9YG7vWS8It-mddU2Wnknf1jgzTqZtLeBQRLhF54SXQ
  mp:
    # 微信公众号的appid
    appId: wxba7358c0c621200d
    # 信公众号的app secret
    secret: a0e9521e29a07e298ccba5b2c239958d
    # 微信公众号的toke
    token: token
    # 微信公众号的EncodingAESKey
    aesKey:

Spring Boot方式引入依赖,需要按约定进行微信相关配置,然后就可以直接进行相关开发。

具体配置参考:wx-java-mp-spring-boot-starter配置

# 公众号配置(必填)
wx.mp.appId = appId
wx.mp.secret = @secret
wx.mp.token = @token
wx.mp.aesKey = @aesKey
# 存储配置redis(可选)
wx.mp.config-storage.type = Jedis                     # 配置类型: Memory(默认), Jedis, RedisTemplate
wx.mp.config-storage.key-prefix = wx                  # 相关redis前缀配置: wx(默认)
wx.mp.config-storage.redis.host = 127.0.0.1
wx.mp.config-storage.redis.port = 6379
#单机和sentinel同时存在时,优先使用sentinel配置
#wx.mp.config-storage.redis.sentinel-ips=127.0.0.1:16379,127.0.0.1:26379
#wx.mp.config-storage.redis.sentinel-name=mymaster
# http客户端配置
wx.mp.config-storage.http-client-type=httpclient      # http客户端类型: HttpClient(默认), OkHttp, JoddHttp
wx.mp.config-storage.http-proxy-host=
wx.mp.config-storage.http-proxy-port=
wx.mp.config-storage.http-proxy-username=
wx.mp.config-storage.http-proxy-password=
# 公众号地址host配置
#wx.mp.hosts.api-host=http://proxy.com/
#wx.mp.hosts.open-host=http://proxy.com/
#wx.mp.hosts.mp-host=http://proxy.com/

wx-java-mp-spring-boot-starter主要自动配置了如下两个对象:

WxMpService:可以完成微信公众号提供的各种功能

WxMpConfigStorage:保存了微信公众号配置信息

实例化WxMpService

非Spring Boot方式引入依赖则需要自己实例化WxMpService对象。

1.创建WxMpProperties类,封装微信配置参数信息。

@Component
@Data
@ConfigurationProperties(prefix = "wx.mp")
public class WxMpProperties {

    /**
     * 设置微信公众号的appid
     */
    private String appId;

    /**
     * 设置微信公众号的app secret
     */
    private String secret;

    /**
     * 设置微信公众号的token
     */
    private String token;

    /**
     * 设置微信公众号的EncodingAESKey
     */
    private String aesKey;
}

2.创建WxMpConfiguration类,用于配置WxJava相关的实例对象。

@Configuration
public class WxMpConfiguration {

    @Autowired
    private WxMpProperties wxMpProperties;


    /**
     * 微信客户端配置存储
     */
    @Bean
    public WxMpConfigStorage wxMpConfigStorage() {
        WxMpDefaultConfigImpl configStorage = new WxMpDefaultConfigImpl();
        // 设置微信公众号appId
        configStorage.setAppId(wxMpProperties.getAppId());
        // 设置微信公众号appSecret
        configStorage.setSecret(wxMpProperties.getSecret());
        // 设置微信公众号的token
        configStorage.setToken(wxMpProperties.getToken());
        // 设置微信公众号的EncodingAESKey
        configStorage.setAesKey(wxMpProperties.getAesKey());
        return configStorage;
    }

    /**
     * WxMpService多个实现类 声明一个实例
     */
    @Bean
    public WxMpService wxMpService() {
        WxMpService wxMpService = new WxMpServiceImpl();
        wxMpService.setWxMpConfigStorage(wxMpConfigStorage());
        return wxMpService;
    }
}

对接微信公众号回调

注意:编写业务处理的接口对应测试公众号中配置的接口地址。

@Slf4j
@RestController
public class TestController {

    @Autowired
    private WxMpService wxMpService;

    /**
     * 验证消息的确来自微信服务器
     * <p>
     * 开发者通过检验signature对请求进行校验。若确认此次GET请求来自微信服务器,请原样返回echostr参数内容,则接入生效
     *
     * @param signature 微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。
     * @param timestamp 时间戳
     * @param nonce     随机数
     * @param echostr   随机字符串
     * @return
     */
    @GetMapping("send")
    public String configAccess(String signature, String timestamp, String nonce, String echostr) {
        // 校验签名
        if (!wxMpService.checkSignature(timestamp, nonce, signature)) {
            log.error("签名校验 ===》 非法请求");
            // 消息签名不正确,说明不是公众平台发过来的消息
            return null;
        }

        log.error("签名校验 ===》 验证成功");
        // 返回echostr
        return echostr;
    }
 }

在这里插入图片描述

接收与回复消息

WxMpXmlOutTextMessage是同步回复给微信消息的对象,不同类型的消息类型可以用不同的方式构造

    @RequestMapping("send")
    public String send(@RequestBody String requestBody, @RequestParam("signature") String signature, @RequestParam("timestamp") String timestamp, @RequestParam("nonce") String nonce) {
        // 校验签名
        if (!wxMpService.checkSignature(timestamp, nonce, signature)) {
            log.error("签名校验 ===》 非法请求");
            // 消息签名不正确,说明不是公众平台发过来的消息
            return null;
        }
        log.error("签名校验 ===》 验证成功");

        // 解析消息体,封装为对象
        WxMpXmlMessage xmlMessage = WxMpXmlMessage.fromXml(requestBody);
        // 接收消息内容
        String inContent = xmlMessage.getContent();

        // 响应的消息内容
        String outContent;
        // 根据不同的关键字回复消息
        if (inContent.contains("hello")) {
            outContent = "hello world";
        } else if (inContent.contains("java")) {
            outContent = "hello java";
        } else {
            outContent = "服务繁忙,暂时不能回复";
        }

        // 构造响应消息对象
        WxMpXmlOutTextMessage outTextMessage = WxMpXmlOutMessage.TEXT().content(outContent).fromUser(xmlMessage.getToUser())
                .toUser(xmlMessage.getFromUser()).build();

        // 将响应消息转换为xml格式返回
        return outTextMessage.toXml();
    }

在这里插入图片描述

微信消息路由器

微信推送给公众号的消息类型很多,而公众号也需要针对用户不同的输入做出不同的反应。避免出现很多if/else判断,可以使用WxMpMessageRouter来对消息进行路由

WxMpMessageRouter支持从4个角度对消息进行匹配:

msgType

event

eventKey

content

具体参考:微信消息路由器

WxMpMessageHandler

针对不同类型的消息处理,需要自己实现消息处理器,消息处理器必须实现WxMpMessageHandler接口

public interface WxMpMessageHandler {

  /**
   *
   * @param wxMessage
   * @param context  上下文,如果同一个路由规则内的handler或interceptor之间有信息要传递,可以用这个
   * @param wxMpService
   * @return xml格式的消息,如果在异步规则里处理的话,可以返回null
   */
  public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,
                                  Map<String, Object> context,
                                  WxMpService wxMpService,
                                  WxSessionManager sessionManager);

}

WxMessageInterceptor

还可以添加拦截器,支持在处理微信公众号消息时添加拦截器以进行消息的预处理、过滤等操作。自定义实现拦截处理器,实现WxMessageHandler接口

public interface WxMpMessageInterceptor {

  /**
   * 拦截微信消息
   * @param wxMessage
   * @param context  上下文,如果handler或interceptor之间有信息要传递,可以用这个
   * @param wxMpService
   * @return  true代表OK,false代表不OK
   */
  public boolean intercept(WxMpXmlMessage wxMessage,
                           Map<String, Object> context,
                           WxMpService wxMpService,
                           WxSessionManager sessionManager);

}

自定义Handle

@Component
public class MyTextHandler implements WxMpMessageHandler {
    @Override
    public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context, WxMpService wxMpService, WxSessionManager sessionManager) throws WxErrorException {

        // 接收消息内容
        String inContent = wxMessage.getContent();

        // 响应的消息内容
        String outContent;
        // 根据不同的关键字回复消息
        if (inContent.contains("hello")) {
            outContent = "hello world";
        } else if (inContent.contains("java")) {
            outContent = "hello java";
        } else if (inContent.contains("***")) {
            outContent = "请文明用语";
        } else {
            outContent = "服务繁忙,暂时不能回复";
        }

        // 构造响应消息对象
        return WxMpXmlOutMessage.TEXT().content(outContent).fromUser(wxMessage.getToUser())
                .toUser(wxMessage.getFromUser()).build();
    }
}

自定义Interceptor

/**
 * 对微信公众号消息进行预处理、过滤等操作,根据具体业务需求决定是否允许继续执行后面的路由处理方法
 * <p>
 * 如果要中止消息的继续处理,即表示拦截了这个消息,需要返回 false。否则,在执行完当前拦截器操作后,允许消息的继续处理,返回 true
 */
@Component
public class MyTextInterceptor implements WxMpMessageInterceptor {

    @Override
    public boolean intercept(WxMpXmlMessage wxMpXmlMessage, Map<String, Object> map, WxMpService wxMpService, WxSessionManager wxSessionManager) throws WxErrorException {
        String msg = wxMpXmlMessage.getContent();
        String msgType = wxMpXmlMessage.getMsgType();
        if (msgType.equals("text") && msg.contains("混蛋")) {
            wxMpXmlMessage.setContent("***");
            return true;
        }
        return true;
    }
}

创建消息路由配置

将不同类型的消息交给不同的消息处理器来处理。路由对象为WxMpMessageRouter

@Configuration
public class MessageRouterConfig {
    @Autowired
    private WxMpService wxMpService;

    @Autowired
    private MyTextHandler textHandler;
    @Autowired
    private MyTextInterceptor textInterceptor;


    @Bean
    public WxMpMessageRouter messageRouter() {
        // 创建消息路由
        final WxMpMessageRouter router = new WxMpMessageRouter(wxMpService);
        // 添加一个同步处理文本消息的路由规则 同时添加interceptor、handler
        router.rule().async(false).msgType(WxConsts.XmlMsgType.TEXT).interceptor(textInterceptor).handler(textHandler).end();
        return router;
    }
}

使用消息路由

在Controller中注入WxMpMessageRouter,将消息路由到对应的处理器

@Slf4j
@RestController
public class TestController {

    @Autowired
    private WxMpService wxMpService;

    @Autowired
    private WxMpMessageRouter wxMpMessageRouter;

    @RequestMapping("send")
    public String configAccess(@RequestBody String requestBody, @RequestParam("signature") String signature, @RequestParam("timestamp") String timestamp, @RequestParam("nonce") String nonce) {
        // 校验签名
        if (!wxMpService.checkSignature(timestamp, nonce, signature)) {
            log.error("签名校验 ===》 非法请求");
            // 消息签名不正确,说明不是公众平台发过来的消息
            return null;
        }
        log.error("签名校验 ===》 验证成功");

        // 解析消息体,封装为对象
        WxMpXmlMessage xmlMessage = WxMpXmlMessage.fromXml(requestBody);
        WxMpXmlOutMessage outMessage = null;
        try {
            // 将消息路由给对应的处理器,获取响应
            outMessage = wxMpMessageRouter.route(xmlMessage);
        } catch (Exception e) {
            log.error("消息路由异常", e);
        }
        // 将响应消息转换为xml格式返回
        return outMessage == null ? null : outMessage.toXml();
    }
 }

执行测试

在这里插入图片描述

access_token持久化

WxMpConfigStorage是维护微信公众号相关信息的地方,里面包含appid、appsecret、token、aes encoding key、access token等信息。

在与微信API交互过程中,首先需要获取access_token,但是获取access_token的微信接口有调用次数限制,并且每次交互中都需要去获取access_token,需要重新发起网络请求,效率低,没过期就调用可能会因为达到次数上限而获取失败。

如果是分布式的环境下,每个服务都要各自去获取这些信息,因此,可以将这些信息存储到数据库或分布式缓存中,以便各个节点能够共享数据信息,尤其是access token

通常是将access_token持久化到redis,只需要额外在配置文件中增加redis配置即可。

wx:
  # 消息模板ID
  templateId: o9YG7vWS8It-mddU2Wnknf1jgzTqZtLeBQRLhF54SXQ
  mp:
    # 微信公众号的appid
    appId: wxba7358c0c621200d
    # 信公众号的app secret
    secret: a0e9521e29a07e298ccba5b2c239958d
    # 微信公众号的toke
    token: token
    # 微信公众号的EncodingAESKey
    aesKey:
    config-storage:
      # 配置类型: Memory(默认), Jedis, Redisson, RedisTemplate
      type: RedisTemplate
      # redis前缀配置: wx(默认)
      key-prefix: wx
      redis:
        host: 127.0.0.1
        port: 6379

注意:当type使用redisTemplate,则需要单独引入spring-boot-starter-data-redis依赖

接下来,在与微信公众号交互过程中,就会先需要获取access_token,然后将其存入redis

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/613151.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Vue.js devtools运行但调试窗口未出现的解决方案

Vue.js devtools是一款基于Chrome浏览器的调试Vue.js应用的扩展程序。然而&#xff0c;有时即使该插件已经在运行&#xff0c;调试窗口也可能未出现。这主要可能有以下几个原因&#xff0c;并附有相应的解决方法&#xff1a; 1. Chrome扩展程序选项的问题 首先&#xff0c;右上…

关于数据挖掘的问题之经典案例

依据交易数据集 basket_data.csv挖掘数据中购买行为中的关联规则。 问题分析&#xff1a; 如和去对一个数据集进行关联规则挖掘&#xff0c;找到数据集中的项集之间的关联性。 处理步骤&#xff1a; 首先导入了两个库&#xff0c;pandas 库和 apyori 库。pandas 库是 Pytho…

二叉树基础知识力扣题构造二叉树总结

二叉树 如何理解二叉树&#xff0c;This is a question! 作者在去年被布置要求学习二叉树时对二叉树的理解并不是很深刻&#xff0c;甚至可以说是绕道走&#xff0c;但是Luck of the draw only draws the unlucky&#xff0c;在学期初考核时&#xff0c;作者三道二叉树题都没…

ArrayBlockingQueue中方法的基本使用

生产者生产数据 使用add()方法向队列中添加元素&#xff0c;在队列满的时候会抛出异常。 ArrayBlockingQueue是基于数组实现&#xff0c;初始化完成后长度是不可变的&#xff0c;在其构造方法中也都是有参构造&#xff0c;初始化对象时必须指定当前队列的长度。 使用offer()方…

day05——K-近邻算法

K-近邻算法 一、定义二、API三、实操&#xff1a;预测签到位置1&#xff0c;数据获取2&#xff0c;数据基本处理3&#xff0c;预测算法代码 四、调优1&#xff0c;什么是交叉验证2&#xff0c;超参数搜索-网格搜索(Grid Search)3&#xff0c;调优代码 五、KNN 算法总结 一、定义…

网工内推 | 应届生网工专场,最高15薪,有NP以上证书优先

01 智己汽车 &#x1f537;招聘岗位&#xff1a;网络工程师 &#x1f537;职责描述&#xff1a; 1.管理和运维支持网络基础设备&#xff08;防火墙&#xff0c;交换机&#xff0c;路由器&#xff0c;负载均衡、无线、准入等&#xff09;&#xff1b; 2.负责公司OA网络及公有云…

类和对象以及数组工具类的常用方法

文章目录 一、类和对象二、数组工具类的常用方法 一、类和对象 1、对象没人引用时&#xff0c;会被自动回收 2、对象一定在堆上&#xff0c;引用变量不一定在栈上 3、this表示当前对象的引用&#xff0c;谁调用eat方法(eat方法里有this)&#xff0c;谁就是this。this.data访问…

C++11 使用using定义别名(替代typedef)::作用域运算符

typedef 一切合法的变量的定义可以转换为类型 typedef unsigned int uint_t;示例如下&#xff1a; 使用 typedef 重定义类型是很方便的&#xff0c;但它也有一些限制&#xff0c;比如&#xff0c;无法重定义一个模板。 现在&#xff0c;在 C11 中终于出现了可以重定义一个模…

Kerberos从入门到精通以及案例实操系列(一)

1、Kerberos部署 1.1、Kerberos概述 1.1.1、什么是Kerberos Kerberos是一种计算机网络认证协议&#xff0c;用来在非安全网络中&#xff0c;对个人通信以安全的手段进行身份认证。这个词又指麻省理工学院为这个协议开发的一套计算机软件。软件设计上采用客户端/服务器结构&a…

STC89C52+DS18B20实现环境温度检测(数码管显示温度)

一、项目介绍 温度检测是工业自动化、生产线等众多领域中常见的应用场景之一,能及时准确地监测温度对于保障生产安全和提高生产效率有着非常重要的作用。而在现代的电子制造行业中,使用单片机和传感器等电子元器件进行温度检测已经成为了一个比较成熟的技术方案。 本项目选…

Qcom_hexagon编译自动获取目录和特定文件的方法

一&#xff0c;简介 本文主要介绍&#xff0c;如何在高通hexagon ide中的hexagon.min中添加获取目录和.c文件的方法&#xff0c;供参考。 二&#xff0c;具体命令 OBJ_PATH : ./awinic_sp_module/algo_libINCLUDE_PATH : $(shell find $(OBJ_PATH ) -type d) SRC_C_FILE : …

synchronized 的底层原理

tip: 作为程序员一定学习编程之道&#xff0c;一定要对代码的编写有追求&#xff0c;不能实现就完事了。我们应该让自己写的代码更加优雅&#xff0c;即使这会费时费力。 文章目录 一、synchronized 的底层原理二、synchronized 的锁升级原理1、偏向锁2、轻量级锁3、重量级锁 一…

大幅提升iOS编译速度的cocoapods二进制化插件介绍

1. 背景 驾校一点通iOS项目是采用是cocoapods来管理组件的&#xff0c;又经过多年的组件化发展&#xff0c;目前组件已经达到了120的数量。在这种组件规模下&#xff0c;主工程的打包时间也从最开始的几分钟增加到十几分钟&#xff08;M1&#xff09;、二十几分钟&#xff08;…

restTemplate转发Https请求

代码架构 package com.http.controller;import com.http.RestTemplateConfig; import org.springframework.http.HttpMethod; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework…

Vercel部署个人博客

vercel 部署静态资源网站极其方便简单&#xff0c;并且有可观的访问速度&#xff0c;最主要的是免费部署。 如果你还没有尝试的话&#xff0c;强烈建议去使用一下。 演示博客演示http://202271.xyz/?vercel vercel 介绍 注册账号 进入Vercel官网https://vercel.com&#x…

Android studio安装教程(图文详解,简单搞定)

一 下载 根据自己计算机选择对应版本点击下载 https://developer.android.google.cn/studio 二 安装Android Studio Android Studio 是Google提供的一个Android开发环境&#xff0c;基于IntelliJ IDEA类似 Eclipse ADT&#xff0c;他集成了Android 所需的开发工具。需要注意…

RocketMq的集群的搭建(2主2从异步复制集群模式)

一 RocketMq集群搭建 1.1 说明 本案例采用2m-2s-async的方式搭建集群。 实际项目中&#xff0c;为了达到高可用&#xff0c;一般会使用dleger。 https://blog.csdn.net/wssc63262/article/details/126003507 1.2 集群规划说明 集群规划说明&#xff1a; nameserver是一个…

机器学习——集成学习(装袋法Bagging、提升法Boosting、梯度提升决策树GBDT、随机森林RF)

集成学习 集成学习通过构建并结合多个学习器来完成学习任务 集成方法是用多种学习方法的组合来获取比原方法更优的结果 使用于组合的算法是弱学习算法 即分类正确率仅比随机猜测略高的学习算法 但是组合之后的效果仍可能高于强学习算法 即集成之后的算法准确率和效率都很高…

# 车载软件架构 —— 闲聊几句AUTOSAR OS(三)

我是穿拖鞋的汉子,魔都中坚持长期主义的工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 没有人关注你。也无需有人关注你。你必须承认自己的价值,你不能站在他人的角度来反对自己。人生在世,最怕的就是把别人的眼光当成自己生活的唯一标准。到最…

程序员从0到收获心仪offer,我靠训练营实现了180度逆袭!

我相信&#xff0c;在未来的职场中&#xff0c;我也能通过这段时间养成的学习习惯和生活习惯让自己一步步成为更好的自己&#xff0c;以自己为荣 我在大学里主修计算机科学与技术&#xff0c;一个普通的院校&#xff0c;一个算是常见的专业&#xff0c;我知道我的学历和一些其他…