工具:idea2018,jdk1.8,框架:springboot+thymeleaf
基礎搭建
說明,本專案著力於快速開發,前端頁面只做最基本的頁面跳轉和引數校驗。若是需要前後端分離,可參考一些開源的專案,如givebest/node.js-wechat-js-sdk
準備
一、測試/正式賬號公眾平臺測試賬號,根據上一篇註冊即可
二、web開發者工具,拖至文末,選擇適配版本下載即可。(因為微信部分URL需要許可權的校驗,只能在微信瀏覽器內開啟,而類似postman的第三方工具無法使用)
三、公網可訪問地址,如阿里雲,或內網穿透工具,可參考上一篇中【介面配置資訊修改】。(我的是http://chety.mynatapp.cc -> 127.0.0.1:8080,已開啟狀態)
四、訂閱測試號,掃描二維碼即可
開始開發——被動回覆
描述
向公眾號傳送訊息,公眾號原樣返回我們的內容,如傳送【你好】,公眾號回覆【你好】
實現思路
一、參考微信公眾平臺技術文件,選擇【訊息管理】模組中的【接收普通訊息】。
二、根據接收普通訊息的介紹,可知:
- 訊息型別分為:文字訊息,圖片訊息,語音訊息,視訊訊息等
- 訊息的資料包請求格式為xml,請求方式為post
- 訊息請求有重試和加密機制
- 接收訊息的URL與接入驗證的路徑一致,用請求方式來區分
三、引數介紹
如文字訊息,有訊息的傳送的接收方,訊息型別和內容等。可使用bean物件來封裝該訊息格式
ToUserName
:開發者微訊號,即目前我正在使用的測試公眾號FromUserName
:傳送方賬號,描述為一個openid
,即一個手機微信使用者在一公眾號下的唯一標識,無論何種客戶端裝置訪問,該id都是統一且唯一的。
注意:訊息的收發方是相對的,客戶端與服務端相反
程式碼開發
一、新建springboot專案,需要的核心依賴如下:
<dependencies>
<!-- web專案 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.0.1</version>
</dependency>
<!-- 引入thymeleaf -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- alibaba druid連線池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>
<!-- lombok JavaBean工具 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.8</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpcore</artifactId>
<version>4.4.11</version>
</dependency>
<!-- http客戶端工具 -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.9</version>
</dependency>
<!-- json轉換工具 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.58</version>
</dependency>
<!-- 資料庫可選,如專案需要本地儲存支付交易流水 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.26</version>
<scope>runtime</scope>
</dependency>
</dependencies>
複製程式碼
二、我這裡都使用預設配置,因此暫時不配置application.yml,各位根據自己的需要配置
傳送訊息
三、根據輸入訊息的欄位,封裝為bean物件
注意,xml中引數的鍵都是大寫,因此定義java引數時,需要使用註解或直接大寫命名
@Data // lombok,包含setter,getter,tostring
@XmlRootElement(name = "xml") // 根節點
@XmlAccessorType(XmlAccessType.FIELD) // 對映類中的所有欄位到XML
public class MsgSendEntity {
/**
* 公有部分
*/
// 開發者微訊號
@XmlElement(name = "ToUserName") // 指定名稱對映
private String toUserName;
// 傳送方帳號(一個OpenID)
@XmlElement(name = "FromUserName")
private String fromUserName;
// 訊息建立時間 (整型)
@XmlElement(name = "CreateTime")
private Long createTime;
// 訊息型別
@XmlElement(name = "MsgType")
private String msgType;
// 訊息id,64位整型
@XmlElement(name = "MsgId")
private Long msgId;
// 文字訊息內容
@XmlElement(name = "Content")
private String content;
}
複製程式碼
四、URL接入校驗介面,需公網可見或開啟內網穿透工具。詳細內容參考上一篇文章
@Controller
@RequestMapping("/api/v1/wechat1")
public class WeChatController {
/**
* url接入校驗
* @param signature 微信加密簽名,signature結合了開發者填寫的token引數和請求中的timestamp引數、nonce引數。
* @param timestamp 時間戳
* @param nonce 隨機數
* @param echostr 隨機字串
* @return 若校驗成功,原樣返回echostr引數內容
*/
@GetMapping("/gzh")
@ResponseBody
public String validate(String signature,String timestamp,String nonce,String echostr){
if (!WeChatUtil.checkSignature(signature, timestamp, nonce)) {
WeChatUtil.getLogger().info("WeChatController.validate -- 公眾號接入失敗");
return null;
}
WeChatUtil.getLogger().info("WeChatController.validate -- 公眾號接入成功,echostr:{}"+echostr);
return echostr;
}
}
複製程式碼
測試號管理配置如圖:
五、接收訊息介面(路徑與接入驗證URL的一致)
/**
* 公眾號訊息處理
* @param inMsg 客戶端輸入的訊息資訊
* @return 服務端返回資訊
*/
@PostMapping("gzh")
@ResponseBody
public Object handleMessage(@RequestBody InMsgEntity inMsg) {
return null;
}
複製程式碼
六、斷點除錯
微信在測試公眾號(已訂閱)傳送文字訊息
檢視斷點資訊,可以看到接收到文字訊息的欄位資訊
放行斷點,可以看到接收訊息時的重試機制
接收訊息
參考技術文件,這裡選擇【被動回覆訊息】
七、封裝【回覆文字訊息】的實體類
@Data
@XmlRootElement(name="xml")
@XmlAccessorType(XmlAccessType.FIELD)
public class MsgReplyEntity {
// 使用者的OpenID
private String ToUserName;
// 測試號的微訊號
private String FromUserName;
// 訊息建立時間 (整型)
private Long CreateTime;
// 訊息型別
private String MsgType;
// 文字訊息內容
private String Content;
}
複製程式碼
八、完善訊息處理介面的方法
@PostMapping("gzh")
@ResponseBody
public Object handleMessage(@RequestBody MsgSendEntity msgSend) {
// 服務端訊息回覆的實體類
MsgReplyEntity msgReply = new MsgReplyEntity();
// 根據接收的資訊回覆,接收和傳送方相反
msgReply.setFromUserName(msgSend.getToUserName());
msgReply.setToUserName(msgSend.getFromUserName());
msgReply.setCreateTime(new Date().getTime());
msgReply.setMsgType(msgSend.getMsgType());
// 訊息內容原樣返回
msgReply.setContent(msgSend.getContent());
return msgReply;
}
複製程式碼
測試樣例
一、客戶端傳送訊息測試
ok,公眾號的簡單被動文字訊息回覆就完成了。當然,其他的訊息型別也類似處理,只需簡單的判斷即可。