WxJava微信公眾號開發(fā)入門實戰(zhàn)
WxJava介紹
WxJava是一款基于Java語言的微信開發(fā)Java SDK,它提供了微信支付,開放平臺,小程序,企業(yè)微信,公眾號等多個平臺的API接口,并將其封裝為易于調(diào)用的Java方法,方便Java開發(fā)者快速開發(fā)與微信相關(guān)的應(yīng)用。
GitHub地址:https://github.com/Wechat-Group/WxJava
使用WxJava只需要引入開發(fā)相關(guān)模塊的maven依賴即可
<dependency> <groupId>com.github.binarywang</groupId> <artifactId>(不同模塊參考下文)</artifactId> <version>4.5.0</version> </dependency>
微信小程序:weixin-java-miniapp
微信支付:weixin-java-pay
微信開放平臺:weixin-java-open
公眾號(包括訂閱號和服務(wù)號):weixin-java-mp
企業(yè)號/企業(yè)微信:weixin-java-cp
微信公眾號
如果沒有個人微信號或者企業(yè)微信號,可以申請測試公眾號,并且擁有所有接口權(quán)限,推薦。
申請測試公眾號
訪問申請測試公眾號,申請一個測試的微信公眾號,測試微信公眾號擁有所有高級功能。

測試公眾號配置
申請測試公眾號后,會分配一個測試的appid和秘鑰,接著配置一個可用于內(nèi)網(wǎng)穿透的地址
注意:URL地址指向本地開發(fā)能訪問的某個接口

掃描測試號二維碼以關(guān)注測試公眾號,同時獲取用戶openid

WxJava微信公眾號開發(fā)
WxJava對應(yīng)的微信公眾號開發(fā)文檔
添加依賴
非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>配置微信參數(shù)
非Spring Boot方式引入依賴,需要自定義微信相關(guān)配置信息,同時需要初始化一個WxMpService實例。
# 自定義微信相關(guān)配置信息
wx:
# 消息模板ID
templateId: o9YG7vWS8It-mddU2Wnknf1jgzTqZtLeBQRLhF54SXQ
mp:
# 微信公眾號的appid
appId: wxba7358c0c621200d
# 信公眾號的app secret
secret: a0e9521e29a07e298ccba5b2c239958d
# 微信公眾號的toke
token: token
# 微信公眾號的EncodingAESKey
aesKey:Spring Boot方式引入依賴,需要按約定進行微信相關(guān)配置,然后就可以直接進行相關(guān)開發(fā)。
具體配置參考: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 # 相關(guān)redis前綴配置: wx(默認) wx.mp.config-storage.redis.host = 127.0.0.1 wx.mp.config-storage.redis.port = 6379 #單機和sentinel同時存在時,優(yōu)先使用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.創(chuàng)建WxMpProperties類,封裝微信配置參數(shù)信息。
@Component
@Data
@ConfigurationProperties(prefix = "wx.mp")
public class WxMpProperties {
/**
* 設(shè)置微信公眾號的appid
*/
private String appId;
/**
* 設(shè)置微信公眾號的app secret
*/
private String secret;
/**
* 設(shè)置微信公眾號的token
*/
private String token;
/**
* 設(shè)置微信公眾號的EncodingAESKey
*/
private String aesKey;
}2.創(chuàng)建WxMpConfiguration類,用于配置WxJava相關(guān)的實例對象。
@Configuration
public class WxMpConfiguration {
@Autowired
private WxMpProperties wxMpProperties;
/**
* 微信客戶端配置存儲
*/
@Bean
public WxMpConfigStorage wxMpConfigStorage() {
WxMpDefaultConfigImpl configStorage = new WxMpDefaultConfigImpl();
// 設(shè)置微信公眾號appId
configStorage.setAppId(wxMpProperties.getAppId());
// 設(shè)置微信公眾號appSecret
configStorage.setSecret(wxMpProperties.getSecret());
// 設(shè)置微信公眾號的token
configStorage.setToken(wxMpProperties.getToken());
// 設(shè)置微信公眾號的EncodingAESKey
configStorage.setAesKey(wxMpProperties.getAesKey());
return configStorage;
}
/**
* WxMpService多個實現(xiàn)類 聲明一個實例
*/
@Bean
public WxMpService wxMpService() {
WxMpService wxMpService = new WxMpServiceImpl();
wxMpService.setWxMpConfigStorage(wxMpConfigStorage());
return wxMpService;
}
}對接微信公眾號回調(diào)
注意:編寫業(yè)務(wù)處理的接口對應(yīng)測試公眾號中配置的接口地址。
@Slf4j
@RestController
public class TestController {
@Autowired
private WxMpService wxMpService;
/**
* 驗證消息的確來自微信服務(wù)器
* <p>
* 開發(fā)者通過檢驗signature對請求進行校驗。若確認此次GET請求來自微信服務(wù)器,請原樣返回echostr參數(shù)內(nèi)容,則接入生效
*
* @param signature 微信加密簽名,signature結(jié)合了開發(fā)者填寫的token參數(shù)和請求中的timestamp參數(shù)、nonce參數(shù)。
* @param timestamp 時間戳
* @param nonce 隨機數(shù)
* @param echostr 隨機字符串
* @return
*/
@GetMapping("send")
public String configAccess(String signature, String timestamp, String nonce, String echostr) {
// 校驗簽名
if (!wxMpService.checkSignature(timestamp, nonce, signature)) {
log.error("簽名校驗 ===》 非法請求");
// 消息簽名不正確,說明不是公眾平臺發(fā)過來的消息
return null;
}
log.error("簽名校驗 ===》 驗證成功");
// 返回echostr
return echostr;
}
}
接收與回復(fù)消息
WxMpXmlOutTextMessage是同步回復(fù)給微信消息的對象,不同類型的消息類型可以用不同的方式構(gòu)造
@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("簽名校驗 ===》 非法請求");
// 消息簽名不正確,說明不是公眾平臺發(fā)過來的消息
return null;
}
log.error("簽名校驗 ===》 驗證成功");
// 解析消息體,封裝為對象
WxMpXmlMessage xmlMessage = WxMpXmlMessage.fromXml(requestBody);
// 接收消息內(nèi)容
String inContent = xmlMessage.getContent();
// 響應(yīng)的消息內(nèi)容
String outContent;
// 根據(jù)不同的關(guān)鍵字回復(fù)消息
if (inContent.contains("hello")) {
outContent = "hello world";
} else if (inContent.contains("java")) {
outContent = "hello java";
} else {
outContent = "服務(wù)繁忙,暫時不能回復(fù)";
}
// 構(gòu)造響應(yīng)消息對象
WxMpXmlOutTextMessage outTextMessage = WxMpXmlOutMessage.TEXT().content(outContent).fromUser(xmlMessage.getToUser())
.toUser(xmlMessage.getFromUser()).build();
// 將響應(yīng)消息轉(zhuǎn)換為xml格式返回
return outTextMessage.toXml();
}
微信消息路由器
微信推送給公眾號的消息類型很多,而公眾號也需要針對用戶不同的輸入做出不同的反應(yīng)。避免出現(xiàn)很多if/else判斷,可以使用WxMpMessageRouter來對消息進行路由
WxMpMessageRouter支持從4個角度對消息進行匹配:
msgType event eventKey content
具體參考:微信消息路由器
WxMpMessageHandler
針對不同類型的消息處理,需要自己實現(xiàn)消息處理器,消息處理器必須實現(xiàn)WxMpMessageHandler接口
public interface WxMpMessageHandler {
/**
*
* @param wxMessage
* @param context 上下文,如果同一個路由規(guī)則內(nèi)的handler或interceptor之間有信息要傳遞,可以用這個
* @param wxMpService
* @return xml格式的消息,如果在異步規(guī)則里處理的話,可以返回null
*/
public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,
Map<String, Object> context,
WxMpService wxMpService,
WxSessionManager sessionManager);
}WxMessageInterceptor
還可以添加攔截器,支持在處理微信公眾號消息時添加攔截器以進行消息的預(yù)處理、過濾等操作。自定義實現(xiàn)攔截處理器,實現(xiàn)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 {
// 接收消息內(nèi)容
String inContent = wxMessage.getContent();
// 響應(yīng)的消息內(nèi)容
String outContent;
// 根據(jù)不同的關(guān)鍵字回復(fù)消息
if (inContent.contains("hello")) {
outContent = "hello world";
} else if (inContent.contains("java")) {
outContent = "hello java";
} else if (inContent.contains("***")) {
outContent = "請文明用語";
} else {
outContent = "服務(wù)繁忙,暫時不能回復(fù)";
}
// 構(gòu)造響應(yīng)消息對象
return WxMpXmlOutMessage.TEXT().content(outContent).fromUser(wxMessage.getToUser())
.toUser(wxMessage.getFromUser()).build();
}
}自定義Interceptor
/**
* 對微信公眾號消息進行預(yù)處理、過濾等操作,根據(jù)具體業(yè)務(wù)需求決定是否允許繼續(xù)執(zhí)行后面的路由處理方法
* <p>
* 如果要中止消息的繼續(xù)處理,即表示攔截了這個消息,需要返回 false。否則,在執(zhí)行完當(dāng)前攔截器操作后,允許消息的繼續(xù)處理,返回 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;
}
}創(chuàng)建消息路由配置
將不同類型的消息交給不同的消息處理器來處理。路由對象為WxMpMessageRouter
@Configuration
public class MessageRouterConfig {
@Autowired
private WxMpService wxMpService;
@Autowired
private MyTextHandler textHandler;
@Autowired
private MyTextInterceptor textInterceptor;
@Bean
public WxMpMessageRouter messageRouter() {
// 創(chuàng)建消息路由
final WxMpMessageRouter router = new WxMpMessageRouter(wxMpService);
// 添加一個同步處理文本消息的路由規(guī)則 同時添加interceptor、handler
router.rule().async(false).msgType(WxConsts.XmlMsgType.TEXT).interceptor(textInterceptor).handler(textHandler).end();
return router;
}
}使用消息路由
在Controller中注入WxMpMessageRouter,將消息路由到對應(yīng)的處理器
@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("簽名校驗 ===》 非法請求");
// 消息簽名不正確,說明不是公眾平臺發(fā)過來的消息
return null;
}
log.error("簽名校驗 ===》 驗證成功");
// 解析消息體,封裝為對象
WxMpXmlMessage xmlMessage = WxMpXmlMessage.fromXml(requestBody);
WxMpXmlOutMessage outMessage = null;
try {
// 將消息路由給對應(yīng)的處理器,獲取響應(yīng)
outMessage = wxMpMessageRouter.route(xmlMessage);
} catch (Exception e) {
log.error("消息路由異常", e);
}
// 將響應(yīng)消息轉(zhuǎn)換為xml格式返回
return outMessage == null ? null : outMessage.toXml();
}
}執(zhí)行測試

access_token持久化
WxMpConfigStorage是維護微信公眾號相關(guān)信息的地方,里面包含
appid、appsecret、token、aes encoding key、access token等信息。
在與微信API交互過程中,首先需要獲取
access_token,但是獲取access_token的微信接口有調(diào)用次數(shù)限制,并且每次交互中都需要去獲取access_token,需要重新發(fā)起網(wǎng)絡(luò)請求,效率低,沒過期就調(diào)用可能會因為達到次數(shù)上限而獲取失敗。
如果是分布式的環(huán)境下,每個服務(wù)都要各自去獲取這些信息,因此,可以將這些信息存儲到數(shù)據(jù)庫或分布式緩存中,以便各個節(jié)點能夠共享數(shù)據(jù)信息,尤其是
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注意:當(dāng)type使用redisTemplate,則需要單獨引入spring-boot-starter-data-redis依賴
接下來,在與微信公眾號交互過程中,就會先需要獲取access_token,然后將其存入redis

到此這篇關(guān)于WxJava微信公眾號開發(fā)入門實戰(zhàn)的文章就介紹到這了,更多相關(guān)WxJava 入門內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
maven項目test執(zhí)行main找不到資源文件的問題及解決
這篇文章主要介紹了maven項目test執(zhí)行main找不到資源文件的問題及解決,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-03-03
Spring中ClassPathXmlApplicationContext類的使用詳解
這篇文章主要介紹了Spring中ClassPathXmlApplicationContext類的使用詳解,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-01-01
IntelliJ IDEA 2021.1 EAP 4 發(fā)布:字體粗細可調(diào)整Git commit template 支持
這篇文章主要介紹了IntelliJ IDEA 2021.1 EAP 4 發(fā)布:字體粗細可調(diào)整,Git commit template 支持,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-02-02
Mockito mock Kotlin Object類方法報錯解決方法
這篇文章主要介紹了Mockito mock Kotlin Object類方法報錯解決方法,本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細內(nèi)容,需要的朋友可以參考下2021-09-09
Java國際化簡介_動力節(jié)點Java學(xué)院整理
這篇文章主要為大家簡單介紹了Java國際化的相關(guān)資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-07-07

