小程序实现设备消息订阅
一、说明
先说明一下什么是小程序的消息订阅,其实就是在小程序进行某个消息的订阅,订阅以后就可以在微信收到推送的消息了。推送走的服务端,在服务端调用微信的推送接口,然后推送至指定的微信用户。
二、创建模版
消息订阅是有个消息模版概念的,一般分为以下三种:
1.一次性订阅
2.长期订阅
3.设备消息订阅
设备消息订阅也是长期订阅。
这里以其举例,设备消息订阅需要先创建硬件设备,先去小程序管理台进行操作,如下图:
添加了设备后,消息订阅那会有该设备相应的长期消息订阅。然后可以创建消息模版,可以看到每个消息有自己的模版ID,这个在之后会用到。具体如下图:
从消息模版列表点进去详情之后可以看到详细内容,这里的详细内容格式后面会用到,具体如下图:
三、代码实现
代码实现分为小程序和服务端两部分。
1.小程序
小程序主要就是通过消息模版id和设备modelId来进行订阅。代码如下:
Page({
data: {
settingData: [
{
'tempId': 'modelId',
'title': '门锁安全告警',
'content': '未订阅'
},
{
'tempId': 'modelId',
'title': '门锁撬动告警',
'content': '未订阅'
},
{
'tempId': 'modelId',
'title': '门锁故障告警',
'content': '未订阅'
},
{
'tempId': 'modelId',
'title': '开关门提醒',
'content': '未订阅'
},
{
'tempId': 'modelId',
'title': '有人逗留提醒',
'content': '未订阅'
},
{
'tempId': 'modelId',
'title': '门锁电量不足提醒',
'content': '未订阅'
},
]
],
},
// ================== 页面加载
onLoad(options) {
this.getSettings();
},
// ================== 页面显示
onShow() {
this.getSettings();
},
// ================== 渲染订阅列表
getSettings() {
let that = this;
wx.getSetting({ withSubscriptions: true, success(res) {
console.log(" 获取状态 = ",res);
var settingDic = res.subscriptionsSetting.itemSettings; // 设置的状态
console.log('订阅数据为->' + JSON.stringify(settingDic))
for (let key in settingDic) {
for (let i = 0; i < that.data.settingData[0].length; i++) {
var object = that.data.settingData[0][i];
if (object['tempId'] == key) {
if (settingDic[key] == 'accept') {
that.data.settingData[0][i].content = '接收';
}
if (settingDic[key] == 'acceptWithForcePush') {
that.data.settingData[0][i].content = '接收并提醒';
}
if (settingDic[key] == 'reject') {
that.data.settingData[0][i].content = '已订阅,不接收';
}
}
}
}
// 刷新数据
that.setData({ settingData: that.data.settingData })
}})
},
// ================== 订阅事件
tableCellItemEvent(e) {
console.log(" 点击事件 = ", e.detail.tempId, app.getUserId());
console.log(" 点击内容 = ", e.detail.content);
let that = this;
// ================== 未订阅
if (e.detail.content === '未订阅') {
wx.showLoading({ title: '加载中···', mask: true });
let dicA = { sn: app.getUserId(),
modelId: '设备modelId' }
deviceAPI.getSnTicket(dicA, (snTicket) => {
console.log(" 获取票据信息 = ",snTicket);
wx.hideLoading();
// 弹出订阅授权框
let dic = { tmplIds: [e.detail.tempId + ''],
sn: app.getUserId() + '',
snTicket: snTicket + '',
modelId: "设备modelId",}
console.log('dic=>>>',dic);
wx.requestSubscribeDeviceMessage({ tmplIds: [e.detail.tempId + ''],
sn: app.getUserId() + '',
snTicket: snTicket + '',
modelId: "设备modelId", success(res) {
// "允许" 回调
console.log('允许" 回调==>',res)
that.getSettings();
},fail(res) {
// "取消" 回调
console.log(res)
}})
})
return;
}
// ================== 不接收
if (e.detail.content === '不接收' || e.detail.content === '已订阅,不接收') {
this.setData({
tipsBox:"tipsBox",
tipsMsg:" 该消息已订阅,但是未打开提醒,如需打开,请前往'设置'->'通知管理'->'接收并提醒' "
});
return;
}
// ================== 接收
if (e.detail.content === "接收") {
this.setData({
tipsBox:"tipsBox",
tipsMsg:" 该消息已订阅,但是未打开提醒,如需打开,请前往'设置'->'通知管理'->'接收并提醒' "
});
return;
}
// ================== 接收并提醒
if (e.detail.content === '接收并提醒') {
this.setData({
tipsBox:"tipsBox",
tipsMsg:" 该消息已设置接收并提醒,确定更改吗"
});
return;
}
}
})
说明:
1.样式这里就不放了
2.这里主要就是渲染下订阅列表,然后点击时进行订阅,直接将settingData渲染就行。
3.其中deviceAPI.getSnTicket是服务端实现的一个获取票据的接口,会在下文讲到。
2、服务端
1.获取票据
public String getSnTicket(String appid, String sn, String modelId){
Map<String,String> requestUrlParam = new HashMap<>();
requestUrlParam.put("access_token", getAccessToken(appid));
Map<String,Object> requestBodyParam = new HashMap<>();
requestBodyParam.put("sn", sn);
requestBodyParam.put("model_id", modelId);
String requestUrl = "https://api.weixin.qq.com/wxa/getsnticket";
log.info("get sn ticket -> <request={}>", JSON.toJSONString(requestBodyParam));
JSONObject jsonObject = JSON.parseObject(sendPost(requestUrl, requestUrlParam, JSON.toJSONString(requestBodyParam)));
log.info("get sn ticket -> <response={}>", jsonObject.toJSONString());
return jsonObject.getString("sn_ticket");
}
说明:
1.这里appid是你的小程序的appid,注意在小程序调接口时加上,我的是放在全局,所以看不到。
2.sn和modelId是小程序传的参数
3.getAccessToken是获取接口调用凭证,在下面会讲到
4.返回值是获取的票据
2.接口调用凭证
/**
* 接口调用凭证
*/
private String getAccessToken(String appid, String secret) {
Map<String,String> requestUrlParam = new HashMap<>();
requestUrlParam.put("appid", appId); //开发者设置中的appId
requestUrlParam.put("secret", secret); //开发者设置中的appSecret
requestUrlParam.put("grant_type", "client_credential"); //默认参数
log.info("get access token -> <request={}>", JSON.toJSONString(requestUrlParam));
String requestUrl = "https://api.weixin.qq.com/cgi-bin/token";
JSONObject jsonObject = JSON.parseObject(sendPost(requestUrl, requestUrlParam, null));
log.info("get access token -> <response={}>", jsonObject.toJSONString());
return jsonObject.getString("access_token");
}
说明:
1.这里appid是你的小程序的appid
2.secret是小程序的秘钥
3.推送消息
/**
* 向用户发送设备消息
*/
public JSONObject hardwareDeviceSend(String appid, List<String> openIds, String templateId, String modelId){
Map<String, Map<String, String>> data = new HashMap<>();
Map<String, String> timeMap = new HashMap<>();
timeMap.put("value", DateUtils.getDateFormat(System.currentTimeMillis()));
data.put("time1", timeMap);
Map<String, String> tipMap = new HashMap<>();
tipMap.put("value", pushMessage);
data.put("enum_string2", tipMap);
String page = "/pages/home/home?params="+param; // 消息订阅跳转地址(对应微信小程序相应页面)
Map<String,Object> requestUrlParam = new HashMap<>();
requestUrlParam.put("access_token", getAccessToken(appid));
Map<String,Object> requestBodyParam = new HashMap<>();
requestBodyParam.put("to_openid_list", openIds);
requestBodyParam.put("template_id", templateId);
requestBodyParam.put("sn", sn);
requestBodyParam.put("model_id", modelId);
requestBodyParam.put("data", data);
requestBodyParam.put("page", page);
// developer为开发版; trial为体验版: formal为正式版: 默认为正式版
requestBodyParam.put("miniprogram_state", "formal"); // 微信小程序版本切换配置
log.info("hardware device send -> <request={}>", JSON.toJSONString(requestBodyParam));
String requestUrl = "https://api.weixin.qq.com/cgi-bin/message/device/subscribe/send";
JSONObject jsonObject = JSON.parseObject(sendPost(requestUrl, requestUrlParam, JSON.toJSONString(requestBodyParam)));
log.info("hardware device send -> <response={}>", jsonObject.toJSONString());
return jsonObject;
}
说明:
1.data中的参数根据消息模版列表中的详细内容格式来组装
2.page是你微信收到推送后点击时跳转的页面
3.appId是小程序的appid
4.openIds是要推送的为i想你用户的openId列表,可以一次性推送多个
5.templateId是消息模版的templateId
6.modelId是设备的modelId
7.sendPost是http工具请求方法,这个自己实现。jsonObject是推送的结果。
四、总结
总结一下设备消息推送的总流程,大概分为以下五步:
1.设备接入
2.获取模版ID
3.获取设备票据
4.发起订阅
5.发送设备消息