您當前位置>首頁 » 新聞資訊 » 小(xiǎo)程序相(xiàng)關 >
微(wēi)信小(xiǎo)程序之生(shēng)成自(z→ ↕ì)定義參數(shù)小(xiǎo)程序二維碼
發表時(shí)間(jiān):2021-1-11
發布人(rén):葵宇科(kē)技(jì)
浏覽次數(shù):97
掃碼已經成為(wèi)一(yī)種常見(jiàn)又(yòu)方便的(de±€)進入移動應用(yòng)的(de)途徑,可(kě)以把線上(shàng)線下(≈ ₩xià)的(de)用(yòng)戶流量帶入你(nǐ)的(de)移動<↑≤應用(yòng)中來(lái)。微(wēi)信小(xiǎo)程序也(yě)提供∞&÷↕了(le)掃碼進入的(de)功能(néng),可(kě)以通(tōng)過掃描二維☆$♠₩碼或者微(wēi)信小(xiǎo)程序專有(yǒu)的(de)小(xiǎo)程>£¥π序碼,進入到(dào)相(xiàng)應的(de)小(xiǎo)程序頁面♦ ÷。
微(wēi)信官方提供了(le)3個(gè)不(bù)同的(de)REST ≤ $API用(yòng)于生(shēng)成帶參數(shù)的(de)小(xiǎo)程序碼或者二≤φ維碼,可(kě)在掃碼後進入指定的(de)小(xiǎo)程序頁面,其♥σ&≥中接口A和(hé)C能(néng)生(shēng)成的(de)圖片總數(shù)量有(yǒu)≈≤&↓限制(zhì)(10萬張),對(duì)于那(nà)£¥♣∑種需要(yào)生(shēng)成大(dà)量二維碼的(de)&使用(yòng)場(chǎng)景(比如(rú)為(wèi)每個(g₹≈è)訂單生(shēng)成一(yī)個(gè)二維碼、餐廳的(de)每張餐桌生(shēng)成一₽≈(yī)個(gè)二維碼等)是(shì)遠(yuǎn)±∞遠(yuǎn)不(bù)能(néng)滿足需求的(de)。而接"∞口B可(kě)以解決這(zhè)個(gè)問(wèn)題,我們這(z≥↓hè)次主要(yào)來(lái)看(kàn)一(yī)下(xià)如(r×≤≈∏ú)何使用(yòng)這(zhè)個(gè)接口。
總體(tǐ)的(de)思路(lù)是(shì):在我們的(de)後端開(kāi)發一(yī)♦個(gè)API,在其中調用(yòng)微(wēi)信的(de)二維碼接口,調用(yòng)€γ成功後會(huì)得(de)到(dào)二維碼圖片的(de)二進制(zh∏γ±ì)流,最後将這(zhè)個(gè)二進制(zhì)★ ×流輸出到(dào)前台。
以下(xià)步驟中的(de)後端代碼是(shì)基于Nod₽ e.js進行(xíng)編寫,并使用(yòng)了(le)Koa 2框架。代碼僅供參考。
步驟1:獲取重要(yào)參數(shù)access_token
調用(yòng)獲取小(xiǎo)程序二維碼的(de)REST AP↓λ✔&I需要(yào)一(yī)個(gè)很(hěn)重要(yào)的(d∞§e)參數(shù):access_token
,這(zhè)是(shì)用(yòng)于獲取微(wēi)®φ$™信公衆平台API訪問(wèn)權限的(de)重要(yào)參數(shù),做(zuò)過微(λ ≈wēi)信公衆号HTML5開(kāi)發的(de)朋(péng)友(yǒu)對>✔(duì)其肯定非常熟悉。沒接觸過的(de)話(huà),可(kě)以看(kàn)一(yī)下(♣>"xià)微(wēi)信公衆平台的(de)文(wén)檔。
調用(yòng)微(wēi)信公衆平台的(de)API,已經有(yǒu)很↔♣∞(hěn)多(duō)成熟的(de)開(kāi)源SDK可(kě)以使用(β✘yòng),從(cóng)Github上(shàng)可(kě)以搜到(dào)很(hěn)λ"γ多(duō)不(bù)同語言實現(xiàn)的(de)SDK。由于我用(yòng♥₹)的(de)是(shì)Node.js開(kāi)發,所以使用(§₩ yòng)了(le)co-wechat-api。
以下(xià)是(shì)使用(yòng)co-wechat-api
來(lái)獲取access_token
的(de)基本用(yòng)法:
const WechatAPI = require('co-wechat-api')
const wxAppAPI = new WechatAPI('小(xiǎo)程序的(de)app id', '小(xiǎo)程序的(de)app secret')
const token = await wxAppAPI.ensureAccessToken()
console.log(token.accessToken)
步驟2:拼接url,發送請(qǐng)求獲取二維碼圖片
const fs = require('fs')
const axios = require('axios')
// 拼接url
const url = `https://api.weixin.qq.com/wxa/getwxaco σdeunlimit?access_token=${token.accessToken}`
// 發送POST請(qǐng)求
const response = await axios.post(url, {
page: '小(xiǎo)程序中Page的(de)路(lù)徑',
scene: '自(zì)定義參數(shù),格式你(nǐ)自(zì)己決定'
}, { responseType: 'stream' })
// 将請(qǐng)求結果中的(de)二進制(zhì)流寫入到(dào)本地(€♠dì)文(wén)件(jiàn)qrcode.png
response.data.pipe(fs.createWriteStream('qrcode.png'))
在上(shàng)面的(de)代碼中,我們将access_token
作(zuò)為(wèi)query string參數(shù)拼接到(dào)url上(shàn£×g),然後向這(zhè)個(gè)url發送POST
請(qǐng)求,傳遞的(de)參數(shù)主要(yào)☆ε是(shì)page
和(hé)scene
,其中page
參數(shù)是(shì)掃碼後進入的(de)小(xi≥♠÷¶ǎo)程序頁面路(lù)徑(比如(rú)pages/index/index,并且不(bβ'♣ù)能(néng)攜帶參數(shù)),而scene
則傳入的(de)是(shì)我們的(de)自(zì)定義參₩ λ數(shù)。
其實經過這(zhè)一(yī)步,你(nǐ)就(jiù)已經可(kě)以在你(nǐ)的(d≈©✔e)磁盤上(shàng)找到(dào)這(zhè)張小(xiǎ☆©♥o)程序碼的(de)圖片了(le),用(yòng)微(wēi)信掃一(yī)下(₩'€xià)這(zhè)張圖片,就(jiù)能(néng)進入你(nǐ)的(de)小(xiǎ× ∏o)程序頁面。
步驟3:将二維碼圖片輸出
雖然我們已經獲取到(dào)了(le)小(xiǎo)程序碼圖片,但(dàn)是(shì)現₽®(xiàn)在它還(hái)隻是(shì)躺在我們的(de)服務器(qì)端。而通(tō≥ng)常實際情況是(shì),我們需要(yào)在小(xiǎ∞"∞≥o)程序頁面上(shàng)去(qù)顯示這(zhè)張圖片,讓用(yò βng)戶去(qù)保存和(hé)分(fēn)享它。因此,我們需要(yào)把這(zhè)γ×張圖片通(tōng)過我們的(de)API進行(xíng)輸出。以下(πφxià)是(shì)基于koa 2的(de)示例代碼:
const fs = require('fs')
const Router = require('koa-router')
const router = new Router()
router.get('/wx/common/qrcode', async (ctx) => {
const stream = fs.createReadStream(‘qrcode.png’)
ctx.body = stream
})
步驟4:在小(xiǎo)程序中顯示
在小(xiǎo)程序中顯示該圖片就(jiù)非常簡單了(le),直接使用(yònβ®g)<image>
組件(jiàn)來(lái)進行(xíng)展示:
<image src="https://your-domain.com/wx/common/qrcode" style="width:200px;height:200px"></image>
附錄:稍微(wēi)完備一(yī)些(xiē)的(de)服務端代碼
上(shàng)面4個(gè)步驟中給出的(de)示例代ε↑♣碼隻是(shì)為(wèi)了(le)配合說(shuō)明(mín≈®g)各個(gè)步驟,代碼比較簡陋,下(xià)面是(shì)經過稍微(wēi)的(de)組織過♣∏γ₽的(de)代碼,供參考:
- 路(lù)由部分(fēn)的(de)代碼:
const Router = require('koa-router')
const PassThrough = require('stream').PassThrough;
const wxapi = require('../services/wxapi')
const router = new Router()
router.get('/wx/common/qrcode', async (ctx) => {
const stream = await wxapi.getWxaCodeUnlimit({
page: 'pages/profile/profile',
scene: 'abc123'
})
ctx.body = stream.pipe(PassThrough())
})
- Service部分(fēn)的(de)代碼:
const fs = require('fs')
const path = require('path')
const crypto = require('crypto')
const bluebird = require('bluebird')
const axios = require('axios')
const WechatAPI = require('co-wechat-api')
const wxAppAPI = new WechatAPI('小(xiǎo)程序的(de)app id', '小(xiǎo)程序的(de)app secret')
function sha1(message) {
return crypto.createHash('sha1').update(message, 'utf8').digest('hex')
}
module.exports = {
async getWxaCodeUnlimit({ page, scene }) {
// 圖片文(wén)件(jiàn)名使用(yòng)page和(hé)scene等☆ φ₹數(shù)據生(shēng)成Hash
// 以避免重複生(shēng)成內(nèi)容相(xiàng)同的(de)βα小(xiǎo)程序碼
const fileName = sha1(page + scene)
const filePath = path.join(__dirname, `../../qrcode/${fileName}.png`)
let readable
try {
// 檢測該名字的(de)小(xiǎo)程序碼圖片文(wén✘')件(jiàn)是(shì)否已存在
await bluebird.promisify(fs.access)(filePath, fs.constants.R_OK);
readable = fs.createReadStream(filePath)
} catch (e) {
// 小(xiǎo)程序碼不(bù)存在,則創建一(yī)張新的(de)
const token = await wxAppAPI.ensureAccessToken()
const response = await axios({
method: 'post',
url: 'https://api.weixin.qq.com/wxa/getwxacodeunlimitε♥',
responseType: 'stream',
params: { access_token: token.accessToken },
data: { page, scene }
})
readable = response.data
readable.pipe(fs.createWriteStream(filePath))
}
// 返回該小(xiǎo)程序碼圖片的(de)文(wén)件(jiεε↓àn)流
return readable
}
}
祝大(dà)家(jiā)開(kāi)發出更好(hǎo)的(de)小(xiǎo)程序!