微信公众号开发学习笔记1

Posted by Young Sheep on July 2, 2023

由于最近的项目需要用到微信公众号开发,然后就发现了大佬的WxJava项目,一个非常全面的微信开发 Java SDK👍。 WxJava支持包括微信支付、开放平台、公众号、企业微信/企业号、小程序等微信功能模块的后端开发,功能十分强大,基本上微信开发平台的接口都实现了,而且开发文档十分的详细,且有很多优秀的案例可以学习,简直是用SpringBoot实现公众号开发的最佳选择。

引入依赖

1
2
3
4
5
<dependency>
	<groupId>com.github.binarywang</groupId>
	<artifactId>weixin-java-mp</artifactId>
	<version>4.5.0</version>
</dependency>

配置类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
@AllArgsConstructor //lombok的自动将bean注入的注解,非常好用,不用在Autowired类的构造方法了
@Configuration
@EnableConfigurationProperties(WxMpProperties.class)
public class WxMpConfiguration {

	//这些Handler都是针对微信开发文档给出的特定事件编写的处理类,WxMp中已经全部实现,直接复制代码进项目即可,根据业务逻辑进行修改,在特定事件触发时自动调用
    private final LogHandler logHandler;
    private final NullHandler nullHandler;
    private final KfSessionHandler kfSessionHandler;
    private final StoreCheckNotifyHandler storeCheckNotifyHandler;
    private final LocationHandler locationHandler;
    private final MenuHandler menuHandler;
    private final MsgHandler msgHandler;
    private final UnsubscribeHandler unsubscribeHandler;
    private final SubscribeHandler subscribeHandler;
    private final ScanHandler scanHandler;
	
	//这是自定义的微信公共号变量类,便于从配置文件中写入
    private final WxMpProperties properties;


	//配置WxMpService,WxMpService中实现了微信公众号的大部分接口,在项目中自动注入便可调用
    @Bean
    public WxMpService wxMpService() {
        if (properties == null) {
            throw new RuntimeException("大哥,拜托先看下项目首页的说明(readme文件),添加下相关配置,注意别配错了!");
        }
        WxMpService wxMpService =  new WxMpServiceImpl();
        wxMpService.setMaxRetryTimes(3);
        WxMpDefaultConfigImpl configStorage = new WxMpDefaultConfigImpl();
        configStorage.setAppId(properties.getAppId());
        configStorage.setSecret(properties.getSecret());
        configStorage.setToken(properties.getToken());
        configStorage.setAesKey(properties.getAesKey());
        try {
            wxMpService.addConfigStorage(properties.getAppId(),configStorage);
        }catch (NullPointerException e){
            Logger logger = LoggerFactory.getLogger(getClass());
            logger.info("需初始化configStorageMap...");
            Map<String, WxMpConfigStorage> configStorages = new HashMap<>(4);
            configStorages.put(properties.getAppId(),configStorage);
            wxMpService.setMultiConfigStorages(configStorages,properties.getAppId());
        }
        return wxMpService;
    }

	//注入特定事件的路由,由于我的项目业务逻辑比较简单,就没关注这些特定事件
    @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(EventType.CLICK).handler(this.menuHandler).end();

        // 点击菜单连接事件
        newRouter.rule().async(false).msgType(EVENT).event(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(EventType.LOCATION).handler(this.locationHandler).end();

        // 接收地理位置消息
        newRouter.rule().async(false).msgType(XmlMsgType.LOCATION).handler(this.locationHandler).end();

        // 扫码事件
        newRouter.rule().async(false).msgType(EVENT).event(EventType.SCAN).handler(this.scanHandler).end();

        // 默认
        newRouter.rule().async(false).handler(this.msgHandler).end();

        return newRouter;
    }

}

配置公众号设置,从yml中读取

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
@Data
@ConfigurationProperties(prefix = "wx.mp")
public class WxMpProperties {
    /**
     * 测试网址,测试时需要设置本地代理,并在微信公众号页面配置代理的网址,这样才能接受微信公众号的认证信息
     */
    private String testUrl;
    /**
     * 前端跳转网址,方便设置跳转的地址
     */
    private String webUrl;

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

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

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

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

    @Override
    public String toString() {
        return JsonUtils.toJson(this);
    }
}