微信小程序订阅消息
此博客是为了记录一下工作中对接小程序推送
- 所需的数据基本都是后台返回的
- 业务逻辑:
- 用户在用户列表中选择一个需要接受消息推送的用户,系统将数据按照消息模板推送给该用户
- 用户列表是后端数据渲染的,openid 作为属性渲染上去了(通过选择用户取到 openid)
- 提醒:接收订阅消息的对方用户需要先点击授权接收订阅消息才能收到消息
- 补充:网上说授权订阅一次只能接收一条消息,但我在开发环境中一次授权后好像能多次接收到订阅消息...
- 难道说的是授权一个模版只能接收到该模板对应的模板消息?
- 亦或是开发环境不受这个限制?
大前提歩鄹(要在网页上操作)
前提1:首先要用小程序管理员用户在微信公众平台中开通订阅消息权限(需要申请几天时间,所以要提前申请)
- 可以先用官方模版把流程走通,后续再替换成申请下来的业务模板(字段类型官方文档中有介绍)
获取接收订阅消息授权(授权后就可以给他发消息了)
前提2:接收推送消息的用户需要点击授权(通过点击函数来调起授权)
-
注意:如果 id 不对,连授权窗口都不会调起,建议写上 fail 回调,把错误信息打印出来
-
注意2:代码中的模版id换成自己的
// 关键代码
wx.requestSubscribeMessage({
tmplIds: [\'消息模版id\'], // 需要用户同意授权的消息模版id(可以一次性询问几个订阅消息授权)
success(res) {
// 用户同意授权的回调函数,此时已经可以给用户发起模板消息了(亲测这里已经可以发送了,但我的业务逻辑不是这里)
console.log(\'res\', res)
},
fail(err) {
// 这里可以捕捉到报错
console.log(err)
}
})
向用户发送订阅消息
js 代码(发送订阅消息这一步需要的参数)
- 关键函数官方文档:subscribeMessage.send
- 里面的 订阅消息参数值内容限制说明 一定要好好看看
提醒:能不能发出订阅消息,能不能点进去订阅消息还和
miniprogram_stat
参数的值有关
access_token
- 提前获取(我的是后端有个接口专门获取 access_token 的)
openid
接收消息用户的 openid- 提前获取(后端返回的用户列表,点击其中用户时获取到 openid)
template_id
消息模板 id(微信公众平台申请的,即小程序控制面板)- 需要提前好几天准备(此处可以先用官方模版先把流程走通)
page
点消息卡片进入到小程序的页面(可携带 url 参数)miniprogram_state
跳转小程序类型(一般写在配置中去读取,开发、线上环境改一下值就行)- 会直接影响到
data
与消息模板对应的字段- 与提前申请的模板消息对应起来(字段个数、值类型都不能错,否则会发不出去)
- 注意:代码中的模版id换成自己的(和前面授权的模版消息id对应起来)
recordDetail: function(event) {
var that = this
var openid = event.currentTarget.dataset.openid
var userName = event.currentTarget.dataset.username
console.log(openid)
wx.showModal({
// title: \'提示\',
content: \'是否推送给他/她\',
success (res) {
if (res.confirm) {
console.log(\'用户点击确定\')
// 在这里推送消息过去
// 先请求获取到 access_token----
wx.request({
url: urlList.getAccessToken,
method: \'POST\',
success: function (res) {
if (res.data.IsSuccess) {
that.setData({
access_token: res.data.ReturnData.access_token
})
// 发送订阅消息
wx.request({
url: urlList.sendMsg + \'?access_token=\' + that.data.access_token,
data: {
touser: openid,
template_id: \'模板消息id\',
page: \'pages/patrol_detail/patrol_detail?id=\' + that.data.id,
miniprogram_state: urlList.version,
// data: {
// "thing1": {
// "value": that.data.contractname
// },
// "number2": {
// "value":that.data.contractnum
// },
// "amount3": {
// "value": that.data.casenum
// },
// "phrase4": {
// "value": that.data.unitname
// },
// "thing6": {
// "value": that.data.head
// }
// }
data: {
"thing1": {
"value": that.data.contractname
},
"number2": {
"value":that.data.contractnum
},
"amount3": {
"value": \'10元\'
},
"phrase4": {
"value": \'五个纯汉字\'
},
"thing6": {
"value": that.data.head
}
}
},
method: \'post\',
success(res) {
console.log(res);
var paramErr = {
// 这些错误码都是自己代码的问题,对应官网文档转述成自己的话,控制台打个错误信息或者记录日志
// 43101 是用户授权问题,应该引导授权或怎么样
"40003": "openid为空或者不正确",
"40037": "订阅模板id为空或者不正确",
"47003": "模板参数不准确,可能为空或者不满足规则,errmsg会提示具体是哪个字段出错",
"41030": "page路径不正确,需要保证在现网版本小程序中存在,与app.json保持一致"
}
if(res.data.ReturnData.errcode in paramErr) {
wx.showModal({
title: \'提示\',
content: \'推送消息失败,请联系管理员,错误码:\' + res.data.ReturnData.errcode,
showCancel:false,
success(res) {
// 经测试,直接 return false 后面的代码依旧会执行(这是在 success 这个回调函数内,return 只是结束 success 这个回调函数,而不是想象的那样)
// return false
}
})
// 打印自定义后的错误信息,方便确定问题所在
console.log(paramErr[res.data.ReturnData.errcode])
} else if(res.data.ReturnData.errcode == "43101") {
// 43101 是用户授权问题,应该引导授权或怎么样
wx.showModal({
title: \'提示\',
content: \'对方未授权推送,无法推送消息\',
showCancel:false,
success(res) {
// 经测试,直接 return false 后面的代码依旧会执行(这是在 success 这个回调函数内,return 只是结束 success 这个回调函数,而不是想象的那样)
// return false
}
})
} else if(res.data.ReturnData.errcode == "0") {
// 正确的时候错误码是 0,为防止后续新增错误造成不好排查的错误,留一手
wx.showModal({
title: \'提示\',
content: \'推送成功\',
showCancel:false,
success(res) {
// 发起请求,绑定村庄负责人与巡查记录(把整改记录关联起来)
wx.request({
url: urlList.updateVillagehead + \'?id=\' + that.data.id + \'&villagehead=\' + userName,
method: \'POST\',
success: function (res) {
console.log(\'已将整改记录和村庄负责人关联起来\')
}
})
// wx.navigateTo({
// url: \'../patrol_detail/patrol_detail?id=\' + that.data.id + \'&nowSelectTab=待整改\'
// })
// wx.navigateTo({
// url: \'../renovate_record/renovate_record\'
// })
// 返回两层(推送页面、选择用户,不需要用户再返回回去)
wx.navigateBack({
delta: 2
})
}
})
} else {
wx.showModal({
title: \'提示\',
content: \'未知错误,发送失败\',
showCancel:false,
success(res) {
}
})
// 以上考虑之外的错误情况
console.log(\'错误码:\', res.data.ReturnData.errcode)
console.log(\'错误信息:\', res.data.ReturnData.errmsg)
}
},
fail: function() {
console.log("推送失败!")
}
})
}
}
})
} else if (res.cancel) {
console.log(\'用户点击取消\')
}
}
})
// wx.navigateTo({
// url: \'../patrol_record_item/patrol_record_item?contractnum=\' + contractnum + \'&contractname=\' + contractname
// })
},
备注:
- 此博客写于 2020.7.26 8:25,后续可能会因官方更新而失效
- 2020.7.29 15:32 更新,修复了代码中的逻辑缺陷(失败提示后不会再显示成功了,之前的 return 写在了回调函数里... 没有达到想要的效果)