?? ? ? ?* 源碼已經(jīng)上傳到資源處,需要的話點(diǎn)擊跳轉(zhuǎn)下載 |??源碼下載
????????在上一篇內(nèi)容當(dāng)中在微信小程序中實(shí)現(xiàn)訂閱消息功能,都在客戶端(小程序)中來實(shí)現(xiàn)的,在客戶端中模擬了服務(wù)器端來進(jìn)行發(fā)送訂閱消息的功能,那么本篇就將上一篇內(nèi)容中僅在客戶端中實(shí)現(xiàn)發(fā)送訂閱消息功能進(jìn)行一個(gè)分離,使用 Node.js 搭載后臺(tái)服務(wù)器進(jìn)行操作,客戶端(小程序)通過請(qǐng)求提交數(shù)據(jù)信息到服務(wù)器,由服務(wù)器來發(fā)送訂閱消息,如果你在沒有讀在客戶端模擬服務(wù)器端的上一篇內(nèi)容來此篇目的話可能需要有一些吃力,至少需要了解它的一個(gè)基本流程,那么本篇內(nèi)容在客戶端的內(nèi)容不再?gòu)念^開始講起僅簡(jiǎn)單概述,重點(diǎn)還是在如何搭載后臺(tái)以及完成客戶端向服務(wù)器端進(jìn)行提交數(shù)據(jù)請(qǐng)求處理后發(fā)送訂閱消息,筆者建議小白從上一篇內(nèi)容開始,再讀本篇內(nèi)容,可以知道在客戶端模擬后端服務(wù)器和搭載后臺(tái)服務(wù)器有哪些異同點(diǎn),大大提高你的認(rèn)識(shí),下面進(jìn)入正題。
完成效果
下面來看一下完成的效果:?
客戶端頁(yè)面編寫
<!-- index.html -->
<!-- 頂部 -->
<view class="content">
<view class="head">
當(dāng)前操作員:{{admin}}
</view>
<block wx:if="{{!hasUserInfo}}">
<button bindtap="getUserProfile">獲取</button>
</block>
<block wx:else>
<form bindsubmit="formSubmit">
<view class="log">
<view class="log_title">
<text>日志類型</text>
<picker bindchange="changeTitle" name="title" value="{{index}}" range="{{logArray}}">
<view class="nowing">{{logArray[index]}}</view>
</picker>
</view>
<view class="log_date">
<text>日期選擇</text>
<picker mode="date" name="date" value="{{date}}" bindchange="bindDateChange">
<view class="nowing">{{date}}</view>
</picker>
</view>
<view class="log_person">
<text>提醒人</text>
<input type="text" name="remind" bindinput="bindRemindPer" bindtap ="allowSubscribeMessage" placeholder="例如:小明(參考)" value="{{remind}}"/>
</view>
<view class="log_tip">
<text>溫馨提示</text>
<input type="text" name="tip" bindinput="bindTipCont" value="{{tip}}"/>
</view>
<button form-type="submit" disabled="{{ remind == '' ? true : false}}">發(fā)送</button>
<view class="errMsg">{{ remind == '' ? 'tips:需要填寫提醒人名稱才可發(fā)送!' : '' }}</view>
</view>
</form>
</block>
</view>
客戶端代碼編寫
? ? ? ? 將前面客戶端編寫代碼進(jìn)行整理,在這里面需要填寫你申請(qǐng)的訂閱模板的id,以及form表單提交的內(nèi)容待寫,需要服務(wù)器端搭載編寫請(qǐng)求接口供客戶端發(fā)起請(qǐng)求。
// index.js
const app = getApp()
const time = require('../../utils/util')
const tempid = '' // 填寫上你自己的訂閱模板id [未提交日志模板]
Page({
data:{
index: 0 , // 默認(rèn)為0,日?qǐng)?bào)
logArray:['日?qǐng)?bào)','周報(bào)','月報(bào)'],
admin:'', // 操作員
lTitle:'未提交日志提醒', // 提醒標(biāo)題
date: time.formateTime(new Date()) // 日期(格式化)
remind:'', // 提醒人,默認(rèn)admin
tip:'尚未提交日志', // 溫馨提示內(nèi)容
},
// 獲取提醒標(biāo)題
changeTitle(e){
this.setData({ index : e.detail.value })
},
// 獲取日期選擇
bindDateChange(e){
this.setData({ date : e.detail.value })
},
// 獲取提醒人
bindRemindPer(e){
this.setData({ remind : e.detail.value })
},
// 獲取提示內(nèi)容
bindTipCont(e){
console.log(e)
this.setData({ tip : e.detail.value })
},
// 獲取用戶信息
getUserProfile(e) {
// 推薦使用wx.getUserProfile獲取用戶信息,開發(fā)者每次通過該接口獲取用戶個(gè)人信息均需用戶確認(rèn),開發(fā)者妥善保管用戶快速填寫的頭像昵稱,避免重復(fù)彈窗
wx.getUserProfile({
desc: '展示用戶信息', // 聲明獲取用戶個(gè)人信息后的用途,后續(xù)會(huì)展示在彈窗中,請(qǐng)謹(jǐn)慎填寫
success: (res) => {
this.setData({
admin: res.userInfo.nickName,
hasUserInfo: true
})
}
})
},
// 獲取用戶權(quán)限 - 待寫
allowSubscribeMessage(){
// hasSubscribeMessage 授權(quán)狀態(tài)
if (!app.globalData.hasSubscribeMessage) {
wx.requestSubscribeMessage({
tmplIds: [tempid], // 在此處填寫模板id
success(res) {
console.log('獲取權(quán)限:',res)
app.globalData.hasSubscribeMessage = res.errMsg.split(':')[1]
}
})
}
},
// 表單提交
formSubmit(e){
// e.detail.value 可以拿到用戶提交表單的數(shù)據(jù)
// console.log(e.detail.value)
let formInfo = e.detail.value
formInfo.title = this.data.logArray[formInfo.title]
wx.login({
timeout: 2000,
// 成功后會(huì)返回code,將code提交給服務(wù)器
success: res =>{
// 獲取到code
console.log('獲取到code:' + res.code)
console.log(res)
// 提交服務(wù)器 -- 待寫
}
})
}
})
日期格式化文件
? ? ? ? 引入 util/util.js 中存放著公共函數(shù),有處理日期格式化函數(shù),在index.js中來調(diào)用。
// 格式化日期
function formatTime(date) {
var year = date.getFullYear()
var month = date.getMonth() + 1
var day = date.getDate()
return [year, month, day].map(formatNumber).join('-')
}
function formatNumber(n) {
n = n.toString()
return n[1] ? n : '0' + n
}
module.exports = {
formatTime
}
下面開始進(jìn)入本篇內(nèi)容的一個(gè)重點(diǎn)部分,使用Node.js搭載后臺(tái)服務(wù)器,那么對(duì)這塊內(nèi)容不熟悉的可以看一下這篇內(nèi)容??微信小程序搭載node.js服務(wù)器(簡(jiǎn)),同時(shí)還可以到Node專欄學(xué)習(xí)一些關(guān)于Node.js的基礎(chǔ)知識(shí)。
使用Node.js搭載后臺(tái)服務(wù)器
? ? ? ? 檢查Node.js這些就不再講了,在 微信小程序搭載node.js服務(wù)器(簡(jiǎn)) 當(dāng)中已經(jīng)講過了!創(chuàng)建一個(gè)存放后臺(tái)的文件夾,使用CMD命令切換到此目錄之下,輸入如下命令:
npm init -y
? ? ? ? 使用如下命令來安裝 express 框架:
npm i express -S
?????????在目錄下創(chuàng)建index.js文件作為啟動(dòng)文件。
? ? ? ? ?使用代碼編譯器 ( 這里使用的是VSCode ) 打開index.js進(jìn)行代碼編寫如下代碼:
const express = require('express')
const app = express()
// 解析表單 - 待寫
app.get('/',(req,res)=>{
res.send('ok')
})
// 監(jiān)聽 3000 端口號(hào) | 127.0.0.1:3000
app.listen('3000',()=>{
console.log('Server Running ...')
})
? ? ? ? ?測(cè)試一下,切出CMD命令窗口輸入 node index.js (可安裝nodemon)
? ? ? ? ?在瀏覽器的url地址上輸入請(qǐng)求地址: http://127.0.0.1:3000/ ,會(huì)返回 res.send " ok "
? ? ? ? 接下來開始編寫客戶端需要請(qǐng)求的接口。
解析表單
? ? ? ? body-parser是一個(gè)常用的express中間件,主要就是對(duì) http 的請(qǐng)求體進(jìn)行解析。否則前臺(tái)發(fā)出請(qǐng)求所帶的請(qǐng)求體無法被后端進(jìn)行解析獲取。
// 解析表單
app.use(express.json());
app.use(express.urlencoded({extended : false}))
? ? ? ? 如果引入使用 bod-parser ,可以如下來引入編寫(但沒有必要,需要安裝body-parser,可以使用express框架中的。)
npm i body-parser
const bodyParser = require('body-parser')
// 解析表單
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended : false}))
獲取Openid
? ? ? ? 獲取Openid從上一篇內(nèi)容就已然知道,獲取Openid需要3個(gè)參數(shù),分別是 code ,appid 和 appsecret ;appid 和 appsecret 可以在?微信公眾平臺(tái)?上登錄獲取,主要是 code 參數(shù),code參數(shù)可以在客戶端 (小程序) 通過 wx.login() 方法進(jìn)行獲取,然后發(fā)送到服務(wù)器端,再由服務(wù)器端發(fā)起請(qǐng)求小程序API拿到用戶的Openid。
// index.js - 客戶端
...
// 表單提交
formSubmit(e){
// e.detail.value 可以拿到用戶提交表單的數(shù)據(jù)
// console.log(e.detail.value)
let formInfo = e.detail.value
formInfo.title = this.data.logArray[formInfo.title]
wx.login({
timeout: 2000,
// 成功后會(huì)返回code,將code提交給服務(wù)器
success: res =>{
// 獲取到code
console.log('獲取到code:' + res.code)
console.log(res)
// 提交服務(wù)器
wx.request({
url: 'http://127.0.0.1:3000/getOpenId',
method: 'POST',
data: {
code: res.code
},
success: res=>{
// 待寫
}
})
}
})
}
...
? ? ? ? 通過 wx.request() 方法請(qǐng)求接口 http://127.0.0.1:3000/getOpenId ,請(qǐng)求參數(shù)就是 wx.login 獲取到的code,下面來后臺(tái)編寫這個(gè)請(qǐng)求接口。
// index.js - 服務(wù)端
const express = require('express')
const app = express()
// 解析表單
app.use(express.json());
app.use(express.urlencoded({extended : false}))
// 用戶信息
var user = {
appid: '', // 填寫你自己的appid ( 微信公眾平臺(tái)獲取 )
secret: '', // 填寫你自己的appsecret密鑰 ( 微信公眾平臺(tái)獲取 )
openid: ''
}
// 模板ID - template_id
const temp_id = '' // 填寫你申請(qǐng)選用的模板id
app.get('/',(req,res)=>{
res.send('ok')
})
// 獲取Openid請(qǐng)求接口
app.get('/getOpenId',(req,res)=>{
// 待寫
})
// 監(jiān)聽 3000 端口號(hào) | 127.0.0.1:3000
app.listen('3000',()=>{
console.log('Server Running ...')
})
...
// 獲取Openid請(qǐng)求接口
app.get('/getOpenId',(req,res)=>{
// console.log(req.body) 含有code參數(shù)
console.log("客戶端發(fā)來:",req.query.code)
let data = req.query.code
// 獲取Openid函數(shù)
getOpenid(data,(result)=>{
// 保存openid待用
console.log('用戶OpenId:',result.data.openid)
user.openid = result.data.openid
res.send({ 'request' : 'ok' })
})
})
// 監(jiān)聽 3000 端口號(hào) | 127.0.0.1:3000
app.listen('3000',()=>{
console.log('Server Running ...')
})
// 獲取Openid處理函數(shù) - 待寫
? ? ? ? ?getOpenid(data,callback) ,通過req.body可以拿到客戶端發(fā)過來的請(qǐng)求參數(shù)code,結(jié)合服務(wù)器端的appid參數(shù)和secrest參數(shù)就可以向往小程序API發(fā)起請(qǐng)求返回 Openid進(jìn)行保存??梢钥匆幌鹿俜轿臋n內(nèi)容?小程序登錄 | 微信開放文檔?,如下請(qǐng)求小程序API
GET https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code
?????????在編寫接口之前這三個(gè)參數(shù)是可以獲取到的,我們可以使用這個(gè)API接口測(cè)試工具測(cè)試一下,測(cè)試API工具有很多像Postman,Apifox 等這些,然后將這個(gè)三個(gè)參數(shù)攜帶過去看能夠獲取這個(gè)Openid 。
? ? ? ? 在客戶端中拿到了code,appid和appsecret已經(jīng)有了的,測(cè)試一下向微信API接口發(fā)起請(qǐng)求是否能夠拿到Openid.
? ? ? ? 下面在服務(wù)端安裝一個(gè)在Vue中常講到的HTTP數(shù)據(jù)請(qǐng)求庫(kù)axios,使用這個(gè)可能大家會(huì)比較熟悉一些,使用如下命令安裝:
npm i axios -S
const express = require('express')
const app = express()
const axios = require('axios')
// 解析表單
// 用戶信息
// 模板ID - template_id
app.get('/',(req,res)=>{ ... })
// 獲取Openid請(qǐng)求接口
app.get('/getOpenId',(req,res)=>{ ... })
// 監(jiān)聽 3000 端口號(hào) | 127.0.0.1:3000
app.listen(3000,()=>{ ... })
// 獲取Openid處理函數(shù) - 通過code獲取openid
function getOpenid(data,success){
axios({
url:'https://api.weixin.qq.com/sns/jscode2session?appid=' + user.appid + '&secret=' + user.secret + '&js_code=' + data + '&grant_type=authorization_code',
method: 'GET',
})
.then((res)=>{
// 成功返回 openid
// console.log(res.data.openid)
user.openid = res.data.openid
success(res)
})
.catch((err)=>{ console.log(err) })
}
? ? ? ? 通過向微信API請(qǐng)求獲取登陸憑證校驗(yàn)返回Openid進(jìn)行保存。獲取Openid之后下面進(jìn)行發(fā)布訂閱消息。?
發(fā)布訂閱消息
????????客戶端請(qǐng)求 http://127.0.0.1:3000/getOpenId,請(qǐng)求成功之后返回 res.send({ 'request' : 'ok' }),客戶端可以進(jìn)行一個(gè)判斷成功之后將表單數(shù)據(jù)進(jìn)行一個(gè)提交。
// index.js - 客戶端
...
// 表單提交
formSubmit(e){
// e.detail.value 可以拿到用戶提交表單的數(shù)據(jù)
// console.log(e.detail.value)
let formInfo = e.detail.value
formInfo.title = this.data.logArray[formInfo.title]
wx.login({
timeout: 2000,
// 成功后會(huì)返回code,將code提交給服務(wù)器
success: res =>{
// 獲取到code
console.log('獲取到code:' + res.code)
console.log(res)
// 提交服務(wù)器
wx.request({
url: 'http://127.0.0.1:3000/getOpenId',
method: 'POST',
data: {
code: res.code
},
success: res=>{
if(res.data.request === 'ok'){
wx.request({
url: 'http://127.0.0.1:3000/sendTempMsg',
methods: 'POST',
data:{
formInfo : formInfo
},
success: res=>{
if(res.data.request === 'ok'){
wx.showToast({
title: '訂閱消息發(fā)送成功',
icon: 'success'
})
}
}
})
}
}
})
}
})
}
...
? ? ? ? 通過客戶端使用wx.login拿到code參數(shù)之后向后端發(fā)起請(qǐng)求http://127.0.0.1:3000/getOpenId,后端響應(yīng)請(qǐng)求后并發(fā)起請(qǐng)求微信API做登錄憑證校驗(yàn),請(qǐng)求成功后會(huì)返回session_key和openid,此時(shí)可以將拿到的openid進(jìn)行保存,同時(shí)響應(yīng)客戶端res.send({ 'request': 'ok'?}). 下面來編寫由服務(wù)器發(fā)送訂閱模板消息的接口。
const express = require('express')
const app = express()
const axios = require('axios')
// 解析表單
// 用戶信息
// 模板ID - template_id
app.get('/',(req,res)=>{ ... })
// 獲取Openid請(qǐng)求接口
app.get('/getOpenId',(req,res)=>{ ... })
// 發(fā)送訂閱消息接口
app.post('/sendTempMsg',(req,res)=>{
// 待寫
})
// 監(jiān)聽 3000 端口號(hào) | 127.0.0.1:3000
app.listen(3000,()=>{ ... })
// 獲取Openid處理函數(shù) - 通過code獲取openid
? ? ? ? 客戶端提交表單數(shù)據(jù)信息,在服務(wù)器通過req.body.formInfo獲取
// 發(fā)送訂閱消息接口
app.post('/sendTempMsg',(req,res)=>{
console.log("客戶端發(fā)來:" ,req.body)
lef formInfo = req.body.formInfo
sendTempMsg(formInfo,(result)=>{
console.log('訂閱消息發(fā)送結(jié)果:', result.data)
res.send({ 'request': 'ok' })
})
})
// 發(fā)送訂閱消息函數(shù)處理
sendTempMsg(formInfo,success){
// 待寫
}
? ? ? ? 發(fā)送訂閱消息模板還需要的參數(shù)有access_token,access_token是后臺(tái)接口調(diào)用憑據(jù),獲取之后可以通過發(fā)送訂閱消息API實(shí)現(xiàn)訂閱消息的發(fā)送。下面先來獲取access_token,這里附上官方文檔的獲取接口調(diào)用憑據(jù) | 微信開放文檔。
GET https://api.weixin.qq.com/cgi-bin/token
? ? ? ? 這里可以使用這個(gè)API接口測(cè)試工具進(jìn)行測(cè)試,測(cè)試是否可以拿到這個(gè)access_token.
// 發(fā)送訂閱消息函數(shù)處理
sendTempMsg(formInfo,success){
// 獲取接口調(diào)用憑據(jù)
getAccessToken((res)=>{
// 待寫
}
}
// 獲取access_token函數(shù)
function getAccessToken(success){
let url = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=' + user.appid + '&secret=' + user.secret
axios({
url,
method: 'GET',
}).then((res)=>{
// console.log(res.data.access_token) // access_token
success(res)
}).catch((err)=>{
console.log(err)
})
}
? ? ? ? 拿到 access_token 之后,訂閱模板內(nèi)容信息,然后請(qǐng)求微信API接口發(fā)送訂閱消息。
// 發(fā)送訂閱消息函數(shù)處理
sendTempMsg(formInfo,success){
// 獲取接口調(diào)用憑據(jù)
getAccessToken((res)=>{
// 訂閱模板
var temp = {
"touser": user.openid,
"template_id": temp_id,
"data": {
"phrase1": { "value": formInfo.title },
"date2": { "value": formInfo.date },
"name3": {"value": formInfo.remind },
"thing4": { "value": formInfo.tip }
},
"miniprogram_state": "developer",
"lang": "zh_CN"
}
console.log("模板信息",temp)
let token = res.data.access_token
console.log('獲取到的access_token:',token)
// 發(fā)送訂閱API
let url = 'https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=' + token
axios({
url,
method: 'POST',
data: temp
}).then((res)=>{
success(res)
}).catch((err)=>{
console.log(err)
})
}
}
? ? ? ? 到這里已經(jīng)代碼已經(jīng)全部編寫完成了,下面來測(cè)試一下。
測(cè)試效果
1. 啟動(dòng)后臺(tái)服務(wù)器端
? ? ? ? 使用 node index.js 命令(安裝了 nodemon 可以使用命令 nodemon index.js)
2. 獲取用戶信息進(jìn)入界面
3. 填寫提醒人獲取訂閱消息權(quán)限??
4. 點(diǎn)擊發(fā)送,成功會(huì)返回提示
5. 查看服務(wù)器端信息(發(fā)送成功)
6. 查看手機(jī)或者電腦微信的服務(wù)通知
? ? ? ? ?到這里我們就完成了對(duì)服務(wù)器端的編寫,如果你僅是對(duì)服務(wù)器端的內(nèi)容做了解的話到這里就已經(jīng)結(jié)束了,下面是對(duì)客戶端的一些內(nèi)容做調(diào)整。
客戶端接口封裝
? ? ? ? 可以看一下客戶端的請(qǐng)求方式,下面來將其進(jìn)行一個(gè)接口的封裝,這里可以結(jié)合之前關(guān)于封裝接口的文章 :?封裝小程序request請(qǐng)求[接口函數(shù)]
wx.request({
url: 'http://127.0.0.1:3000/getOpenId',
method: 'GET',
data:{
code:res.code
},
success: res=>{
console.log(res)
if(res.data.request === 'ok' && res.statusCode === 200){
wx.request({
url: 'http://127.0.0.1:3000/sendTempMsg',
method:'POST',
data:{
formInfo : formInfo
},
success: res=>{
if(res.data.request === 'ok'){
wx.showToast({
title: '訂閱消息發(fā)送成功',
icon: 'success'
})
}
}
})
}
}
})
? ? ? ? ?下面來對(duì)接口進(jìn)行一個(gè)封裝,在util目錄下創(chuàng)建request.js文件來封裝request請(qǐng)求模塊,這里暫不對(duì)封裝內(nèi)容進(jìn)行修改,延用之前已經(jīng)封裝過的模塊。
// request.js
// 封裝數(shù)據(jù)請(qǐng)求request
const BASE_URL = 'http://127.0.0.1:3000'; // 基礎(chǔ)地址
export default function request(url,params={}){
return new Promise((resolve,reject)=>{
wx.showLoading({ // 請(qǐng)求提示
title: '正在加載中...',
})
wx.request({
url: BASE_URL + url, // 請(qǐng)求url地址
data: params.data || {}, // 請(qǐng)求參數(shù)
header: params.header || {}, // 請(qǐng)求頭
method: params.method || 'GET', // 請(qǐng)求方式
dataType: 'json', // 返回?cái)?shù)據(jù)類型
success: (res)=> { // 成功調(diào)用
console.log(res)
wx.hideLoading(); // 關(guān)閉請(qǐng)求提示
resolve(res.data) // 成功處理res.data中的數(shù)據(jù)
},
fail: (err)=> { // 失敗調(diào)用
wx.hideLoading(); // 關(guān)閉請(qǐng)求提示
wx.showToast({ // 提示錯(cuò)誤信息
title: err.errMsg || '請(qǐng)求錯(cuò)誤!',
})
reject(err) // 失敗處理err
}
})
})
}
? ? ? ? 封裝完成之后需要來在 util 目錄下來創(chuàng)建 wxApi.js 文件來封裝各個(gè)接口模塊:
// wxApi.js
import request from './request'
// 獲取OpenId
export const reqOpenId = (code)=> request('/getOpenId',{ data:{code} })
// 發(fā)送訂閱消息
export const reqSendTempMsg = (formInfo)=> request('/sendTempMsg',{data:{formInfo},method:'POST'})
? ? ? ? 在客戶端的 index.js 文件中來引入接口并使用:
const {reqOpenId,reqSendTempMsg } = require('../../utils/wxApi')
...
formSubmit(e){
...
// 提交服務(wù)器
reqOpenId(res.code).then((res)=>{
if(res.request === 'ok'){
reqSendTempMsg(formInfo).then((res)=>{
if(res.request === 'ok'){
wx.showToast({
title: '訂閱消息發(fā)送成功',
icon: 'success'
})
}
})
}
})
}
? ? ? ? 當(dāng)然這里還可以更簡(jiǎn)潔一下,那么剩下就留給讀者來進(jìn)行發(fā)揮,感謝大家的支持!??!文章來源:http://www.zghlxwxcb.cn/news/detail-436019.html
文章來源地址http://www.zghlxwxcb.cn/news/detail-436019.html
到了這里,關(guān)于微信小程序?qū)崿F(xiàn)訂閱消息功能(Node服務(wù)器篇)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!