小程式傳送模版訊息之 nodejs 實現
阿新 • • 發佈:2018-12-20
功能分析
現需要實現一個使用者報名成功通知到功能,管理員在後臺稽核之後,會通過使用者的申請,同時傳送小程式報名成功的模版訊息到使用者的微信上。
首先需要分析一下微信傳送模版訊息的介面
//模版訊息的結構 let opts = { touser: param.openid, //目標使用者的openid template_id: template_id, //模版訊息的id,需要在小程式管理配置獲得 form_id: param.formId,//當前使用者通過表單提交行為獲得的formId 有效期7天 data: { "keyword1": { "value": '值1', "color": "#1d1d1d" }, "keyword2": { "value": 值2, "color": "#1d1d1d" } } }
//傳送小程式模版訊息的請求 let data = { method: 'POST', //請求介面 需要一個生成有效期為兩小時的 accessToken,見下方程式碼 url: `https://api.weixin.qq.com/cgi-bin/message/wxopen/template/send?access_token=${accessToken}`, //將模版訊息的結構字元畫 body: JSON.stringify(opts), header: { 'content-type': 'application/json' // 預設值 } }
//請求獲取臨時 AccessToken 的 Promise函式 const request = require('request'); const fetchAccessTokenReq = new Promise((resolve, reject) => { let APPID = '你的小程式appid'; let secret = '你的小程式appsecret'; let url = `https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${APPID}&secret=${secret}` request.get(url, (err, response, data) => { if (err) { resolve(false); } else { let AccessToken = JSON.parse(data); resolve(AccessToken); } }) })
表單收集
假設活動欄位設計為如下
const bookingrecord = mongoose.Schema({
activity_id: String, //使用者請求的參加活動的id
activity_content: Object, //活動物件
openid: String, //參加使用者的openid
submit: Object,// 提交表單
isAllow: Boolean, //是否已經同意
formId:String //表單id 也可以為單個使用者儲存
})
在小程式的form
表單中間通過 submit
提交獲取到 formid
,通過 post
請求提交併儲存到資料庫
// 在page 的 form 表單中收集
<form class='section' bindsubmit="bindFromSubmit" report-submit='true' report-submit='true'>
<text class='fontbold'>活動報名</text>
<text class='col'>* 真實姓名</text>
<input placeholder='真實姓名' data-key='realName' name=''></input>
<text class='col'>* 聯絡方式</text>
<input placeholder='可以聯絡到你的方式 微信/手機' data-key='contact'' name=''></input>
<text class='col'>* 備註</text>
<textarea placeholder='備註' data-key='remark'/ name=''>
<button class='main' form-type='submit' hover-class='none' wx:if='{{submit.realName && submit.contact && submit.remark}}'>提交報名</button>
<button class='default' hover-class='none' wx:else>不可提交</button>
</form>
// submit.js
bindFromSubmit: function(e) {
let formId = e.detail.formId;
}
這樣就能為每一個使用者申請的報名記錄記錄一個 formId
,同時也應該儘可能多的為單個使用者儲存,以防其他需求。
使用Promise整合請求
當管理員通過申請者的申請時,會將單條申請記錄的欄位更新,然後傳送一條模版訊息到使用者的微信上,假設 formid
有效的情況下,使用 promise
依次處理請求,我儘量將程式碼寫的淺顯易懂。
// 通過報名申請並向報名者傳送小程式模版訊息
router.post('/api/allowApplyAndSendTemplateMsg', (req, res) => {
let _body = req.body;
let template_id = `模版id`; //模版訊息的id
// 資料庫操作
const updataCurrentOjbectAllow = new Promise((resolve, reject) => {
db.bookingrecord.updateOne({ '_id': object._id }, { $set: { 'isAllow': true } }).exec((err, doc) => {
if (err) {
resolve(false)
} else {
resolve(true);
}
})
})
// 獲取token
const fetchAccessTokenReq = new Promise((resolve, reject) => {
const APPID = 'appid';
const secret = 'secret';
const url = `https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${APPID}&secret=${secret}`
request.get(url, (err, response, data) => {
if (err) {
resolve(false)
} else {
let AccessToken = JSON.parse(data);
resolve(AccessToken);
}
})
})
// promise all
Promise.all([updataCurrentOjbectAllow, fetchAccessTokenReq]).then((response) => {
let db_options_res = response[0];
let accessToken = response[1].access_token;
sendTemplateMessage(object, db_options_res, accessToken).then(_res => {
if (_res) {
return res.json({
code: 1,
msg: '傳送成功',
result: 'send template message success'
})
}
}).catch(err => {
// 錯誤處理
})
}).catch((err) => {
// 錯誤處理
})
const sendTemplateMessage = (param, dbres, accessToken) => {
return new Promise((resolve, reject) => {
if (!dbres) {
return res.json({
code: 0,
msg: '資料庫寫入失敗',
result: 'db updata fail'
})
}
let opts = {
touser: param.openid,
template_id: template_id,
form_id: param.formId,
data: {
"keyword1": {
"value": '說明2',
"color": "#1d1d1d"
},
"keyword7": {
"value": '說明2',
"color": "#1d1d1d"
}
}
}
let data = {
method: 'POST',
url: `https://api.weixin.qq.com/cgi-bin/message/wxopen/template/send?access_token=${accessToken}`,
body: JSON.stringify(opts),
header: {
'content-type': 'application/json' // 預設值
}
}
request(data, function(error, response, data) {
let result = JSON.parse(data);
if (result.errcode == '0' && result.errmsg === 'ok') {
resolve(result)
} else {
reject(result)
}
});
})
}
})
其他問題 ⚠️
accessToken
在使用過之後會失效,需要重新獲取。