微信小程序訂閱消息
此博客是為了記錄一下工作中對接小程序推送
- 所需的數據基本都是后台返回的
- 業務邏輯:
- 用戶在用戶列表中選擇一個需要接受消息推送的用戶,系統將數據按照消息模板推送給該用戶
- 用戶列表是后端數據渲染的,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 寫在了回調函數里... 沒有達到想要的效果)