JAVA微信公眾號開發 | 第一篇: 前期准備及實現自動回復(附源碼)
本系列文章是記錄自己微信公眾號的開發過程,也希望能為感興趣的其他人提供一些思路和幫助
歡迎轉發,轉發請在文前明顯位置,注明本文地址
項目源碼放到文末,需要自取
最終效果
前言
有一個特別坑的地方,需要提前說一下 個人訂閱號 現在已經沒有接口開發自定義菜單的權限了。
也就是說只能通過微信賬號后台自定義菜單,而不能通過接口開發自定義菜單。
但是接口開發和后台自定義兩者互斥
要想接口開發自定義菜單,就必須是認證公眾號,但是
wt fk
雞你太美 誒,,, 雞你太美
但是服務號申請也不難
雖然有這么多限制,我還是想去嘗試一下,興趣大於一切**
1.申請公眾號
- 登錄地址:https://mp.weixin.qq.com/,注冊-選擇類型,
- 對類型不清楚的點擊鏈接,賬號類型區別http://kf.qq.com/faq/170815aUZjeQ170815mU7bI7.html
- 公眾號申請流程:http://kf.qq.com/product/weixinmp.html#hid=99
申請服務號 還是比較麻煩的 但是服務號是直接展示在好友消息列表中 而訂閱號是展示在訂閱號消息
2.雲服務器或者其他外網映射工具
我用的是騰訊雲。其他外網映射工具在這里就不說了,搜一下很多
3.接口配置
進入配置頁面:基本配置 > 修改配置
- URL:中的IP地址,如果是騰訊雲則可以在雲服務器界面找自己的公網IP地址
- Token :可以自己隨意填,但是要和后面服務器的保持一致
點擊提交>確定
之后微信會自動向你的服務器發送GET請求並驗證你的服務器,因此我們需要完成了對GET請求的處理(后面有代碼講解,先不用點確定)
4.驗證消息的確來自微信服務器
開發者提交信息后,微信服務器將發送GET請求到填寫的服務器地址URL上,GET請求攜帶參數如下表所示:
參數 描述 signature 微信加密簽名,signature結合了開發者填寫的token參數和請求中的timestamp參數、nonce參數 timestamp 時間戳 nonce 隨機數 echostr 隨機字符串
開發者通過檢驗signature對請求進行校驗(下面有校驗方式)。若確認此次GET請求來自微信服務器,請原樣返回echostr參數內容,則> 接入生效,成為開發者成功,否則接入失敗。
加密/校驗流程如下:
1)將token、timestamp、nonce三個參數進行字典序排序
2)將三個參數字符串拼接成一個字符串進行sha1加密
3)開發者獲得加密后的字符串可與signature對比,標識該請求來源於微信
以上是來源 微信文檔,寫的很清楚了,擼代碼。
/**
* 處理微信服務器發來的get請求,進行簽名的驗證
* signature 微信端發來的簽名 * timestamp 微信端發來的時間戳
* nonce 微信端發來的隨機字符串
* echostr 微信端發來的驗證字符串
*/
@GetMapping(value = "wechat")
public String validate(@RequestParam(value = "signature") String signature,
@RequestParam(value = "timestamp") String timestamp,
@RequestParam(value = "nonce") String nonce,
@RequestParam(value = "echostr") String echostr) {
return WeChatUtil.checkSignature(signature, timestamp, nonce) ? echostr : null;
}
public static boolean checkSignature(String signature, String timestamp, String nonce) {
String[] arr = new String[] { WeChatContant.TOKEN, timestamp, nonce };
// 將token、timestamp、nonce三個參數進行字典序排序
sort(arr);
StringBuilder content = new StringBuilder();
for (int i = 0; i < arr.length; i++) {
content.append(arr[i]);
}
MessageDigest md = null;
String tmpStr = null;
try {
md = MessageDigest.getInstance("SHA-1");
// 將三個參數字符串拼接成一個字符串進行sha1加密
byte[] digest = md.digest(content.toString().getBytes());
tmpStr = byteToStr(digest);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
content = null;
// 將sha1加密后的字符串可與signature對比,標識該請求來源於微信
return tmpStr != null ? tmpStr.equals(signature.toUpperCase()) : false;
}
String[] arr = new String[] { WeChatContant.TOKEN, timestamp, nonce };
此處的WeChatContant.TOKEN
是個常量 public static final String TOKEN = "lhx";
必須和上文基本配置中的 此處隨便寫 保持一致
完成之后 把項目打個JAR包 扔到服務器上面(別忘安裝jdk,安裝方法百度搜一下)
此處用到的工具軟件:**Xshell 6 **和 Xftp 6
工具軟件放到文末,需要自取
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<configuration>
<!--此處填寫boot啟動類-->
<mainClass>com.lhx.wechat.WechatApplication</mainClass>
</configuration>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
項目源碼中添加了maven打包插件 可以直接maven clen package -> 可運行的jar包
項目源碼放到文末,需要自取
然后再回到 配置頁面:基本配置 > 修改配置 > 提交 >確定 網頁頂端會顯示提交成功
5.接收普通消息
當普通微信用戶向公眾賬號發消息時,微信服務器將POST消息的XML數據包到開發者填寫的URL上。
請注意:
1、關於重試的消息排重,推薦使用msgid排重。
2、微信服務器在五秒內收不到響應會斷掉連接,並且重新發起請求,總共重試三次。假如服務器無法保證在五秒內處理並回復,可以直接 回復空串,微信服務器不會對此作任何處理,並且不會發起重試。詳情請見“發送消息-被動回復消息”。
3、如果開發者需要對用戶消息在5秒內立即做出回應,即使用“發送消息-被動回復消息”接口向用戶被動回復消息時,可以在公眾平台官網的開發者中心處設置消息加密。開啟加密后,用戶發來的消息和開發者回復的消息都會被加密(但開發者通過客服接口等API調用形式向用戶發送消息,則不受影響)。關於消息加解密的詳細說明,請見“發送消息-被動回復消息加解密說明”。各消息類型的推送XML數據包結構如下:
<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>1348831860</CreateTime>
<MsgType><![CDATA[text]]></MsgType>
<Content><![CDATA[this is a test]]></Content>
<MsgId>1234567890123456</MsgId>
</xml>
參數 描述 ToUserName 開發者微信號 FromUserName 發送方帳號(一個OpenID) CreateTime 消息創建時間 (整型) MsgType 消息類型,文本為text Content 文本消息內容 MsgId 消息id,64位整型
文末有源碼
6.回復普通消息
當用戶發送消息給公眾號時(或某些特定的用戶操作引發的事件推送時),會產生一個POST請求,開發者可以在響應包(Get)中返回特> 定XML結構,來對該消息進行響應(現支持回復文本、圖片、圖文、語音、視頻、音樂)。嚴格來說,發送被動響應消息其實並不是一種> 接口,而是對微信服務器發過來消息的一次回復。需要的XML數據包結構如下:
回復文本消息
<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>12345678</CreateTime>
<MsgType><![CDATA[text]]></MsgType>
<Content><![CDATA[你好]]></Content>
</xml>
參數 是否必須 描述 ToUserName 是 接收方帳號(收到的OpenID) FromUserName 是 開發者微信號 CreateTime 是 消息創建時間 (整型) MsgType 是 消息類型,文本為text Content 是 回復的消息內容(換行:在content中能夠換行,微信客戶端就支持換行顯示)
文末有源碼
完整代碼
@PostMapping(value = "wechat")
public String textMessge(HttpServletRequest request) {
logger.info("wechat");
return javaMessageService.textMessage(request);
}
@Service
public class JavaMessageServiceImpl implements JavaMessageService {
private static final Logger logger = LoggerFactory.getLogger(JavaMessageServiceImpl.class);
@Override
public String textMessage(HttpServletRequest request) {
logger.info("進來了");
// xml格式的消息數據
String respXml = null;
// 默認返回的文本消息內容
String respContent;
try {
// 調用parseXml方法解析請求消息
Map<String,String> requestMap = WeChatUtil.parseXml(request);
// 消息類型
String msgType = requestMap.get(WeChatContant.MsgType);
String mes = null;
// 文本消息
if (msgType.equals(WeChatContant.REQ_MESSAGE_TYPE_TEXT)) {
mes =requestMap.get(WeChatContant.Content);
if(mes != null){
String content = checkResources(mes);
if(!StringUtils.isBlank(content)) {
return WeChatUtil.sendTextMsg(requestMap, content);
}
}
}
// 圖片消息
// ......
mes = mes == null ? "在嗎" : mes;
return WeChatUtil.sendTextMsg(requestMap, mes);
} catch (DocumentException e) {
return null;
} catch (Exception e) {
e.printStackTrace();
return null;
}
return null;
}
private String checkResources(String message){
String returnMessage = null;
if("加油".equals(message)){
returnMessage = "你也是";
return returnMessage;
}
if("我愛你".equals(message)){
returnMessage = "一見面就說愛?";
return returnMessage;
}
return null;
}
}
測試可以用postman 進行測試
項目源碼和本文用到的所有工具我已經打包好放在了微信公眾號中> "爪哇之父兄弟",
關注后,回復"公眾號源碼",即可獲取
如果你對本文有不對的地方或者遇到難題了 歡迎評論或者掃碼進群 一起討論 免費幫助
如果本文對你有幫助,請小編喝咖啡啊
公眾號 爪哇之父兄弟 | 微信 | 支付寶 | q群 |
---|---|---|---|
![]() |
![]() |
![]() |
![]() |