更新:
關(guān)于小程序訂閱消息之一次性訂閱:
一次性訂閱是指授權(quán)一次方可接收一次消息;這個最好的應用場景就是自己給自己發(fā)送消息,比如訂單,當自己下單成功時,調(diào)用此接口,會在微信服務(wù)消息收到下單成功通知等具體詳情。 如果是給別人發(fā),一次性訂閱就不適合,類似你想給某個人發(fā)送消息,那你還得提前跟他說你進小程序授權(quán)一下消息模板,不然就收不到消息.....WTF....這樣就很雞肋! 一次性消息訂閱就是一對一模式,授權(quán)一次才能接收到一次消息,如果你發(fā)送了兩條消息,但對方只授權(quán)一次,那他也只能接收一次消息。
微信小程序之訂閱消息(一次性訂閱示例)
第一步. 訂閱消息模板
可選公共模板,如果不滿足可以自己申請;
記住模板Id,之后需要用到。
第二步. 調(diào)用微信訂閱消息服務(wù):
登錄成功時調(diào)用微信訂閱消息服務(wù)(也可以用在發(fā)送方法里邊,我想的是登錄成功后提示一次就行):
uni.requestSubscribeMessage({ //獲取下發(fā)權(quán)限
tmplIds: ['fWxR5XXXXXXXXXXXX'], //模板ID
success(res) {
console.log('已授權(quán)接收訂閱消息')
}
});
//這里的tmplIds是消息模板集合,可放多個如:
// tmplIds: ['fWxR5XXXXXXXXXXXXXXXXX','xxxxxxxxxxxxx'.....],
第三步 獲取用戶OpenId
openId:微信編碼,唯一標識,消息發(fā)送給誰就填誰的openId。
我的思路是登錄成功之后就調(diào)用接口獲取到用戶openid,之后存到數(shù)據(jù)庫對應用戶,用的時候直接??;
要獲取openid就得先獲取授權(quán)code,微信有接口:
1.前端:
wx.login({
success (res) {
if (res.code) {
//發(fā)起網(wǎng)絡(luò)請求
//使用 code 換取 openid 和 session_key 等信息
//將code傳到后臺服務(wù)器獲取openId
wx.request({
url: 'https://test.com/getOpenId', //僅為示例,并非真實的接口地址
data: {
code: res.code
},
header: {
'content-type': 'application/json' // 默認值
},
success (res) {
//成功獲取到openid
console.log(res.data)
}
})
} else {
console.log('登錄失??!' + res.errMsg)
}
}
})
2.java后端:
@PostMapping(value="/getOpenId")
public String getOpenId(String code) throws Exception{
String appId = "你的小程序AppId";
String appSecret ="你的小程序AppSecret ";
//微信小程序固定接口
String WX_URL = "https://api.weixin.qq.com/sns/jscode2session?appid="+appId +"&secret="+appSecret+"&js_code="+code+"&grant_type=authorization_code";
if(StringUtil.isEmpty(code)){
//缺少參數(shù)code
return null;
}else {
String requestUrl = WX_URL;
// 發(fā)起GET請求獲取憑證
JSONObject jsonObject = CommonUtil.httpsRequest(requestUrl, "GET", null);
if (jsonObject != null) {
try {
//獲取成功
String openid = jsonObject.getString("openid");
String sessionKey = jsonObject.getString("session_key");
return openid;
} catch (JSONException e) {
//失敗
return null;
}
}else {
//失敗
return null;
}
}
return null;
}
我的做法:
在用戶登錄時,就主動獲取code和用戶id發(fā)送到后臺獲取到openid,根據(jù)用戶id將openid存到對應數(shù)據(jù)庫,用的時候取出來。
第四步 發(fā)送消息
1.前端:
var Obj = {
"touser": openId,//接收人的openId
"template_id": "fWxR5XXXXXXXXXXX",//訂閱消息模板ID
"page":"pages/business/business-audit/business-audit",//微信端收到消息時,點擊進入的頁面
"miniprogram_state":"trial",//這是代表體驗版,上線需該為正式版(默認為正式版)
"lang":"zh_CN",//語言
"data": {
"thing6": {
"value": "外出報備審核"
},
"thing18": {
"value": "您有1條新的待審核數(shù)據(jù)"
},
"thing37": {
"value": myself.tools.getUserInfo().name //人名
} ,
"time38": {
"value": myself.tools.dateFormate(new Date(), "YYYY-MM-DD HH:mm:ss")//時間
}
}
}
var jsonData = JSON.stringify(Obj );
wx.request({
url: 'https://test.com/gsendWxTempleMsg', //僅為示例,并非真實的接口地址
data:{
jsonData:jsonData
},
header: {
'content-type': 'application/json' // 默認值
},
success (res) {
//成功
}
})
其中,data對應模板:
2.java后端:
@PostMapping(value = "/wx/sendMessage")
public AjaxJson sendWxTempleMsg(String jsonData) throws Exception {
if(StringUtil.isBlank(jsonData)){
return error("消息推送失敗,缺少消息模板信息");
}
String appId = "你的小程序AppId";
String appSecret ="你的小程序AppSecret ";
String ACCESS_TOKEN = getToken(appId, appSecret);//這里需要獲取access_token
String url = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token="+ACCESS_TOKEN;
// 發(fā)起請求,返回JSON字符串
JSONObject jsonObject = CommonUtil.httpsRequest(url , "POST", jsonData);//官方文檔指定POST方式發(fā)送
if(jsonObject.get("errcode").equals("0")||jsonObject.get("errmsg").equals("ok")){
return success("消息推送成功");
}else{
return error("消息推送失敗");
}
}
其中g(shù)etToken方法:
/**
* @param appId
* @param appSecret
* @return
*/
public static String getToken(String appId, String appSecret) {
String requestUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="+appId+"&secret="+appSecret+"";
// logger.info(requestUrl);
// 發(fā)起GET請求獲取憑證
JSONObject jsonObject = CommonUtil.httpsRequest(requestUrl, "GET", null);
if (jsonObject != null) {
if (jsonObject.getString("errcode") == null) {
return jsonObject.getString("access_token");
} else {
return null;
}
} else {
return null;
}
}
至此,消息發(fā)送成功!文章來源:http://www.zghlxwxcb.cn/news/detail-721953.html
注:java后臺用到的工具類
CommonUtil:文章來源地址http://www.zghlxwxcb.cn/news/detail-721953.html
/**
* 類名: CommonUtil.java</br>
* 描述: http請求工具類</br>
*/
public class CommonUtil {
private static Logger log = LoggerFactory.getLogger(CommonUtil.class);//日志類(可刪除)
/**
* 發(fā)送https請求
* @param requestUrl 請求地址
* @param requestMethod 請求方式(GET、POST)
* @param outputStr 提交的數(shù)據(jù)
* @return JSONObject(通過JSONObject.get(key)的方式獲取json對象的屬性值)
*/
public static JSONObject httpsRequest(String requestUrl, String requestMethod, String outputStr) {
JSONObject jsonObject = null;
try {
// 創(chuàng)建SSLContext對象,并使用我們指定的信任管理器初始化
TrustManager[] tm = { new MyX509TrustManager() };
SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
sslContext.init(null, tm, new java.security.SecureRandom());
// 從上述SSLContext對象中得到SSLSocketFactory對象
SSLSocketFactory ssf = sslContext.getSocketFactory();
URL url = new URL(requestUrl);
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
conn.setSSLSocketFactory(ssf);
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setUseCaches(false);
// 設(shè)置請求方式(GET/POST)
conn.setRequestMethod(requestMethod);
// 當outputStr不為null時向輸出流寫數(shù)據(jù)
if (null != outputStr) {
OutputStream outputStream = conn.getOutputStream();
// 注意編碼格式
outputStream.write(outputStr.getBytes("UTF-8"));
outputStream.close();
}
// 從輸入流讀取返回內(nèi)容
InputStream inputStream = conn.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String str = null;
StringBuffer buffer = new StringBuffer();
while ((str = bufferedReader.readLine()) != null) {
buffer.append(str);
}
// 釋放資源
bufferedReader.close();
inputStreamReader.close();
inputStream.close();
inputStream = null;
conn.disconnect();
jsonObject = JSONObject.parseObject(buffer.toString());
} catch (ConnectException ce) {
log.error("連接超時:{}", ce);
} catch (Exception e) {
log.error("https請求異常:{}", e);
}
return jsonObject;
}
/**
* 發(fā)送https請求
*
* @param requestUrl
* 請求地址
* @param requestMethod
* 請求方式(GET、POST)
* @param outputStr
* 提交的數(shù)據(jù)
* @return JSONObject(通過JSONObject.get(key)的方式獲取json對象的屬性值)
*/
public static AjaxJson httpsRequestStream(String requestUrl, String requestMethod, String outputStr,
String basePath, Long id) {
AjaxJson aj = new AjaxJson();
try {
// 創(chuàng)建SSLContext對象,并使用我們指定的信任管理器初始化
TrustManager[] tm = { new MyX509TrustManager() };
SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
sslContext.init(null, tm, new java.security.SecureRandom());
// 從上述SSLContext對象中得到SSLSocketFactory對象
SSLSocketFactory ssf = sslContext.getSocketFactory();
URL url = new URL(requestUrl);
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
conn.setSSLSocketFactory(ssf);
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setUseCaches(false);
// 設(shè)置請求方式(GET/POST)
conn.setRequestMethod(requestMethod);
// 當outputStr不為null時向輸出流寫數(shù)據(jù)
if (null != outputStr) {
OutputStream outputStream = conn.getOutputStream();
// 注意編碼格式
outputStream.write(outputStr.getBytes("UTF-8"));
outputStream.close();
}
InputStream inputStream = conn.getInputStream();
String fileUrl = File.separator + "images" + File.separator + "standaqrcode" + File.separator + "stand" + id + ".jpg";
String savePath = basePath + fileUrl;
// System.out.println(savePath);
aj = inputStreamToImage(inputStream, savePath, "jpg");
inputStream.close();
inputStream = null;
conn.disconnect();
// 從輸入流讀取返回內(nèi)容
aj.setSuccess(true);
aj.put("data", fileUrl);
return aj;
} catch (ConnectException ce) {
log.error("連接超時:{}", ce);
aj.setSuccess(false);
aj.setMsg("鏈接超時:" + ce);
return aj;
} catch (Exception e) {
log.error("https請求異常:{}", e);
aj.setSuccess(false);
aj.setMsg("https請求異常:" + e);
return aj;
}
}
/**
* 將字符流轉(zhuǎn)換為圖片文件
* @param input 字符流
* @param savePath 圖片需要保存的路徑
* @param 類型 jpg/png等
* @return
*/
private static AjaxJson inputStreamToImage(InputStream input, String savePath, String type) {
AjaxJson aj = new AjaxJson();
try {
File file = null;
file = new File(savePath);
String paramPath = file.getParent(); // 路徑
String fileName = file.getName(); //
String newName = fileName.substring(0, fileName.lastIndexOf(".")) + "." + type;// 根據(jù)實際返回的文件類型后綴
savePath = paramPath + File.separator + newName;
if (!file.exists()) {
File dirFile = new File(paramPath);
dirFile.mkdirs();
}
file = new File(savePath);
FileOutputStream output = new FileOutputStream(file);
int len = 0;
byte[] array = new byte[1024];
while ((len = input.read(array)) != -1) {
output.write(array, 0, len);
}
output.flush();
output.close();
aj.setSuccess(true);
aj.setMsg("save success!");
} catch (FileNotFoundException e) {
e.printStackTrace();
aj.setSuccess(false);
aj.setMsg(e.getMessage());
} catch (IOException e) {
e.printStackTrace();
aj.setSuccess(false);
aj.setMsg(e.getMessage());
}
return aj;
}
}
到了這里,關(guān)于微信小程序--訂閱消息的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!