微信小程序訂閱消息官方文檔地址:https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/subscribe-message.html
小程序用訂閱消息替換了模板推送,今天我們就共同學習如何在Java后台編寫小程序訂閱消息推送的知識。
發送訂閱消息三步走
1.拿到用戶的openid
2.獲取access_token
3.調用小程序消息推送的接口
一,獲取用戶的openid(用戶唯一標識)
openid是由前端傳到后端的,我們只需要接收即可
二,獲取access_token
官方介紹:access_token是小程序全局唯一后台接口調用憑據,調用絕大多數后台接口時都需使用。開發者可以通過 getAccessToken接口獲取並進行妥善保存。為了access_token 的安全性,后端 API 不能直接在小程序內通過 wx.request 調用,即api.weixin.qq.com 不能被配置為服務器域名。開發者應在后端服務器使用getAccessToken獲取 access_token,並調用相關 API;
其實通俗的講,access_token就是小程序官方給我們提供的一個憑證,你要調用小程序官方的接口,就必須先拿到access_token。所以下面先講下如果獲取access_token
grant_type是一個固定的值,只有appid和secret是需要我們填入的,這兩個值在我們的小程序后台就可以拿到。
注意點: access_token 的存儲與更新
1.access_token的存儲至少要保留 512 個字符空間
2.access_token的有效期目前為 2 個小時,需定時刷新,重復獲取將導致上次獲取的 access_token失效
3.建議開發者使用中控服務器統一獲取和刷新 access_token ,其他業務邏輯服務器所使用的access_token 均來自於該中控服務器,不應該各自去刷新,否則容易造成沖突,導致 access_token 覆蓋而影響業務
4.access_token 的有效期通過返回的 expires_in 來傳達,目前是7200秒之內的值,中控服務器需要根據這個有效時間提前去刷新。在刷新過程中,中控服務器可對外繼續輸出的老access_token ,此時公眾平台后台會保證在5分鍾內,新老 access_token 都可用,這保證了第三方業務的平滑過渡
5.access_token 的有效時間可能會在未來有調整,所以中控服務器不僅需要內部定時主動刷新,還需要提供被動刷新access_token 的接口,這樣便於業務服務器在API調用獲知 access_token 已超時的情況下,可以觸發 access_token 的刷新流程
所以要在獲取到access_token的時候,把access_token存到數據庫,或者存到本地緩存,並且還要記錄當前時間,后面再用的時候先判斷這個access_token有沒有超過2個小時,如果超過2個小時的話,就要重新獲取了。
三,發送消息到小程序
我們通過上面第二步,成功的獲取到了access_token。下面就要調用小程序官方為我們提供的發送消息的接口了。先看下官方文檔。
這里需要注意的一點是,我們要給用戶發送消息,就必須引導用戶授權,就是下面這個圖
因為用戶不點擊允許,你是沒有辦法給用戶推送消息的。每一次授權只允許發送一條消息,所以如果你想盡量多的發送消息,就得盡量多的引導用戶授權。
推送的代碼如下圖:
可以看到,我們這里需要定義用戶的openid,模板id,跳轉路徑,模板消息內容等,參數是否必填參考上圖官方文檔
這些都定義好以后,我們就可以提供一個服務給到Java的其他代碼調用,或者提供一個接口供外界傳入openid,然后給對應的用戶推送消息了
測試:在瀏覽器里調用上面接口,可以看到下圖所示,說明消息推送成功。
推送效果圖
下面我把完整的代碼貼出來給到大家。
兩個推送消息相關數據類如下:
1:WxMssVo(用來封裝請求官方接口的參數)
package com.qcl.demo; import java.util.Map; /* * 小程序推送所需數據 * */ public class WxMssVo { private String touser;//用戶openid private String template_id;//訂閱消息模版id private String page = "pages/index/index";//默認跳到小程序首頁 private Map<String, TemplateData> data=new HashMap<String,TemplateData>;//推送文字 public String getTouser() { return touser; } public void setTouser(String touser) { this.touser = touser; } public String getTemplate_id() { return template_id; } public void setTemplate_id(String template_id) { this.template_id = template_id; } public String getPage() { return page; } public void setPage(String page) { this.page = page; } public Map<String, TemplateData> getData() { return data; } public void setData(Map<String, TemplateData> data) { this.data = data; } }
2:TemplateData (用來定義消息的內容)
package com.qcl.demo; public class TemplateData { private String value;
public TemplateData(String value) { this.value = value; } public String getValue() { return value; } public void setValue(String value) { this.value = value; } }
controller接口
package com.qcl.demo; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestClientException; import org.springframework.web.client.RestTemplate; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** * 發送小程序訂閱消息 */ @RestController public class SendWxMessage { /* * 發送訂閱消息 * */ @GetMapping("/pushOneUser") public String pushOneUser() { return push("o3DoL0WEdzcJ20AVJg1crP96gbjM"); } public String push(String openid) { RestTemplate restTemplate = new RestTemplate(); //這里簡單起見我們每次都獲取最新的access_token(時間開發中,應該在access_token快過期時再重新獲取) String url = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=" + getAccessToken(); //拼接推送的模版 WxMssVo wxMssVo = new WxMssVo(); wxMssVo.setTouser(openid);//用戶的openid(要發送給那個用戶,通常這里應該動態傳進來的) wxMssVo.setTemplate_id("CFeSWarQLMPyPjwmiy6AV4eB-IZcipu48V8bFLkBzTU");//訂閱消息模板id wxMssVo.setPage("pages/index/index"); Map<String, TemplateData> m = new HashMap<>(3); m.put("thing1", new TemplateData("小程序入門課程")); m.put("thing6", new TemplateData("杭州浙江大學")); m.put("thing7", new TemplateData("第一章第一節")); wxMssVo.setData(m); ResponseEntity<String> responseEntity = restTemplate.postForEntity(url, wxMssVo, String.class); return responseEntity.getBody(); } @GetMapping("/getAccessToken") public String getAccessToken() { RestTemplate restTemplate = new RestTemplate(); Map<String, String> params = new HashMap<>(); params.put("APPID", "wx7c54942dfc87f4d8"); // params.put("APPSECRET", "5873a729c365b65ab42bb5fc82d2ed49"); // ResponseEntity<String> responseEntity = restTemplate.getForEntity( "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={APPID}&secret={APPSECRET}", String.class, params); String body = responseEntity.getBody(); JSONObject object = JSON.parseObject(body); String Access_Token = object.getString("access_token"); String expires_in = object.getString("expires_in"); System.out.println("有效時長expires_in:" + expires_in); return Access_Token; } }
ok,到這里我們就可以完整的實現Java發送小程序消息的功能了~~~