該篇文章主要講的是後臺如何對小程序登錄的用戶進行通知。
ps:由於開發時間和寫文章時間間隔過久,細節上的可能不是很詳細,但是會把整體功能,以及代碼實現貼上來。
通知效果:
解釋: 簡單的說就是用戶登陸過小程序那便可以,將自己想要推送的內容發送到用戶的微信當中,微信當中有一個叫服務通知的東西,推送的內容會在上面顯示。
上面這種消息模板是在微信公衆平臺–>功能–>模板消息下面配置的,具體模板顯示內容可以調整。
1. 推送必須的東西
首先呢這兩個一個叫小程序Id一個叫小程序密鑰這兩個是可以在微信公衆平臺查到的。
接下來有三個url這個是發送推送消息必不可少的,第一個url是獲取小程序全局唯一後臺接口調用憑據;第二個接口是微信小程序推送接口,第三個接口是簡單講就是獲取openId。然後微信開發者公衆平臺開發接口目錄如下:微信公衆平臺開放接口
//獲取access_token
private final static String ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&";
//推送url
private final static String PUSH_URL = "https://api.weixin.qq.com/cgi-bin/message/wxopen/template/send?access_token=";
//根據code換取openId
//本接口應在後端服務器調用
private final static String CODE_URL = "https://api.weixin.qq.com/sns/jscode2session?appid=";
以上這5個算是準備工作吧,然後接下來就是正式進入推送了。
2. 首先我們創建一個獲取openId的工具類
根據官方文檔和摸索一下,這個獲取openId還是很簡單的。
官方上的解釋是: 登錄憑證校驗。通過 wx.login() 接口獲得臨時登錄憑證 code 後傳到開發者服務器調用此接口完成登錄流程。
也就是說上面說的第三個接口,通過把code傳遞到後臺,然後通過後臺調用第三個接口,便可以獲取我們想得到接口,具體代碼如下:
//獲取小程序codeid換取openid
public static String getOpenId(String codeId) {
String url = CODE_URL + APP_ID + "&secret=" + SECRET + "&js_code=" + codeId + "&grant_type=authorization_code";
PrintWriter out = null;
BufferedReader in = null;
String line;
StringBuffer sb = new StringBuffer();
try {
URL realUrl = new URL(url);
// 打開和URL之間的連接
URLConnection conn = realUrl.openConnection();
// 設置通用的請求屬性 設置請求格式
//設置返回類型
conn.setRequestProperty("contentType", "text/plain");
//設置請求類型
conn.setRequestProperty("content-type", "application/x-www-form-urlencoded");
//設置超時時間
conn.setConnectTimeout(1000);
conn.setReadTimeout(1000);
conn.setDoOutput(true);
conn.connect();
// 獲取URLConnection對象對應的輸出流
out = new PrintWriter(conn.getOutputStream());
// flush輸出流的緩衝
out.flush();
// 定義BufferedReader輸入流來讀取URL的響應 設置接收格式
in = new BufferedReader(
new InputStreamReader(conn.getInputStream(), "UTF-8"));
while ((line = in.readLine()) != null) {
sb.append(line);
}
JSONObject jsonObject = JSONObject.parseObject(sb.toString());
return jsonObject.get("openid").toString();
} catch (Exception e) {
e.printStackTrace();
}
//使用finally塊來關閉輸出流、輸入流
finally {
try {
if (out != null) {
out.close();
}
if (in != null) {
in.close();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
return null;
}
這樣我們就換取用戶的唯一標識 openId,具體上面的代碼可以直接複用也比較簡單就不多囉嗦了。
3. 接下來呢我們就要獲取access_token(本接口應在後端服務器調用)
關於access_token的官方解釋: 獲取小程序全局唯一後臺接口調用憑據(access_token)。調用各後臺接口時都需使用 access_token,開發者需要進行妥善保存。
看官方的解釋我們不難理解,access_token是調用微信後臺接口比不可少的東西。注意事項官方也很明確的寫出來瞭如下:
獲取access_token工具類如下:
public static JSONObject getAccessToken() {
String url = ACCESS_TOKEN_URL + "appid=" + APP_ID + "&secret=" + SECRET;
PrintWriter out = null;
BufferedReader in = null;
String line;
StringBuffer sb = new StringBuffer();
try {
URL realUrl = new URL(url);
// 打開和URL之間的連接
URLConnection conn = realUrl.openConnection();
// 設置通用的請求屬性 設置請求格式
//設置返回類型
conn.setRequestProperty("contentType", "text/plain");
//設置請求類型
conn.setRequestProperty("content-type", "application/x-www-form-urlencoded");
//設置超時時間
conn.setConnectTimeout(1000);
conn.setReadTimeout(1000);
conn.setDoOutput(true);
conn.connect();
// 獲取URLConnection對象對應的輸出流
out = new PrintWriter(conn.getOutputStream());
// flush輸出流的緩衝
out.flush();
// 定義BufferedReader輸入流來讀取URL的響應 設置接收格式
in = new BufferedReader(
new InputStreamReader(conn.getInputStream(), "UTF-8"));
while ((line = in.readLine()) != null) {
sb.append(line);
}
// 將獲得的String對象轉爲JSON格式
JSONObject jsonObject = JSONObject.parseObject(sb.toString());
return jsonObject;
} catch (Exception e) {
e.printStackTrace();
}
//使用finally塊來關閉輸出流、輸入流
finally {
try {
if (out != null) {
out.close();
}
if (in != null) {
in.close();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
return null;
}
解釋已經很詳細了,最後再說一些細節的操作先把工具類放出來。
4.推送工具類 (本接口應在後端服務器調用)
推送的具體實現具體的參數啊,還是查看官方文檔再次不多贅述了。模板消息推送官方解釋
代碼如下:
/**
* 推送工具類
* @author 柚子
* @date 2018/12/25
* @param params 推送消息內容
* @param accessToken
* @return boolean
*/
public static boolean setPush(String params, String accessToken) {
boolean flag = false;
String url = PUSH_URL + accessToken;
OutputStream outputStream = null;
InputStreamReader inputStreamReader = null;
InputStream inputStream = null;
BufferedReader bufferedReader = null;
HttpsURLConnection connection = null;
try {
// 創建URL對象
URL realUrl = new URL(url);
// 打開連接 獲取連接對象
connection = (HttpsURLConnection) realUrl.openConnection();
// 設置請求編碼
connection.addRequestProperty("encoding", "UTF-8");
// 設置允許輸入
connection.setDoInput(true);
// 設置允許輸出
connection.setDoOutput(true);
connection.setRequestMethod("POST");
connection.setRequestProperty("content-type", "application/x-www-form-urlencoded");
// 當outputStr不爲null時向輸出流寫數據
if (null != params) {
outputStream = connection.getOutputStream();
// 注意編碼格式
outputStream.write(params.getBytes("UTF-8"));
outputStream.close();
}
// 從輸入流讀取返回內容
inputStream = connection.getInputStream();
inputStreamReader = new InputStreamReader(inputStream, "utf-8");
bufferedReader = new BufferedReader(inputStreamReader);
String str = null;
StringBuffer buffer = new StringBuffer();
while ((str = bufferedReader.readLine()) != null) {
buffer.append(str);
}
JSONObject jsonObject = JSONObject.parseObject(buffer.toString());
int errorCode = jsonObject.getInteger("errcode");
String errorMessage = jsonObject.getString("errmsg");
if (errorCode == 0) {
flag = true;
} else {
logger.info("模板消息發送失敗:" + errorCode + "," + errorMessage);
flag = false;
}
} catch (IOException e) {
e.printStackTrace();
} finally {
// 依次關閉打開的輸入流
try {
connection.disconnect();
bufferedReader.close();
inputStreamReader.close();
inputStream.close();
// 依次關閉打開的輸出流
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return flag;
}
請求數據的示例在官網當中是有的,json形式的數據也就是對應params參數,accessToken參數我們是通過傳遞進來的當然也可以寫死。
5.最後的實現描述
關於推送的實現的描述:
代碼如下所示:
/**
* 功能描述
*
* @param openId 小程序openId
* @param formId 小程序formId
* @param title 通知標題
* @param content 通知內容
* @return boolean
* @author youzi
* @date 2018/12/14
*/
private boolean pushNoticeUtil(String openId, String formId, String title,String content) {
logger.info("pushNoticeUtil方法開始");
//緩存access_token
if (redisUtils.get("access_token") == null || redisUtils.get("access_token").toString() == "") {
JSONObject jsonObject = getAccessToken();
if (jsonObject.get("expires_in") != null && jsonObject.get("expires_in").toString() != ""
&& Integer.parseInt(jsonObject.get("expires_in").toString()) == 7200) {
redisUtils.set("access_token", jsonObject.get("access_token"), 2 * 60 * 60L);
}
}
JSONObject jsonObject1 = new JSONObject();
jsonObject1.put("touser", openId);
// DINING_TEMPLATE 模板Id 微信公衆平臺添加模板時生成的ID
jsonObject1.put("template_id", DINING_TEMPLATE);
jsonObject1.put("form_id", formId);
JSONObject jsonObject2 = new JSONObject();
JSONObject jsonObject3 = new JSONObject();
jsonObject3.put("value", title);
jsonObject2.put("keyword1", jsonObject3);
jsonObject3 = new JSONObject();
jsonObject3.put("value", content);
jsonObject2.put("keyword2", jsonObject3);
jsonObject1.put("data", jsonObject2);
boolean pushResult = setPush(jsonObject1.toString(), redisUtils.get("access_token"));
logger.info("pushNoticeUtil方法結束:推送結果" + pushResult);
return pushResult;
}
疑問: formId是什麼? 簡單的將就是小程序發送請求傳遞的一個東西,作用是用戶發送消息模板消息,具體的獲取官方文檔如下:獲取formId
只是簡單的解釋一下可能不是很清楚,但是隻要知道想要推送消息,那就必須要formId。
整體流程:
首先微信小程序登錄,登錄我們會獲取到openId,將其和自己後臺登錄綁定到一起這樣我們就可以保存下來openId用來推送,然後我們在小程序登錄的時候模擬發送請求獲取多個formId,將獲取到的formId和openId保存到數據庫表中,但是要注意formId是有時效性的如果時效了,推送也會推送不到用戶。
然後我們便可以準備推送了,推送時我們可以先獲取accessToken,將accessToken 放進redis裏面設置過期時間,如果過期了我們重新獲取,否則不需要重新獲取,官方的建議也是如此。然後組裝我們的推送數據,具體的組裝數據需要根據模板確定,但是形式上是一樣,然後調用推送此時便可以發現推送成功了。
最後: 如果還有疑問的話大家可以聯繫我,一起探討一下qq704273004,謝謝。