1. 程式人生 > >微信小程式之生成自定義引數小程式二維碼

微信小程式之生成自定義引數小程式二維碼

掃碼已經成為一種常見又方便的進入移動應用的途徑,可以把線上線下的使用者流量帶入你的移動應用中來。微信小程式也提供了掃碼進入的功能,可以通過掃描二維碼或者微信小程式專有的小程式碼,進入到相應的小程式頁面。

微信官方提供了3個不同的REST API用於生成帶引數的小程式碼或者二維碼,可在掃碼後進入指定的小程式頁面,其中介面A和C能生成的圖片總數量有限制(10萬張),對於那種需要生成大量二維碼的使用場景(比如為每個訂單生成一個二維碼、餐廳的每張餐桌生成一個二維碼等)是遠遠不能滿足需求的。而介面B可以解決這個問題,我們這次主要來看一下如何使用這個介面。

總體的思路是:在我們的後端開發一個API,在其中呼叫微信的二維碼介面,呼叫成功後會得到二維碼圖片的二進位制流,最後將這個二進位制流輸出到前臺。

以下步驟中的後端程式碼是基於Node.js進行編寫,並使用了Koa 2框架。程式碼僅供參考。

步驟1:獲取重要引數access_token

呼叫獲取小程式二維碼的REST API需要一個很重要的引數:access_token,這是用於獲取微信公眾平臺API訪問許可權的重要引數,做過微信公眾號HTML5開發的朋友對其肯定非常熟悉。沒接觸過的話,可以看一下微信公眾平臺的文件

呼叫微信公眾平臺的API,已經有很多成熟的開源SDK可以使用,從Github上可以搜到很多不同語言實現的SDK。由於我用的是Node.js開發,所以使用了co-wechat-api

以下是使用co-wechat-api

來獲取access_token的基本用法:

const WechatAPI = require('co-wechat-api')

const wxAppAPI = new WechatAPI('小程式的app id', '小程式的app secret')
const token = await wxAppAPI.ensureAccessToken()

console.log(token.accessToken)

步驟2:拼接url,傳送請求獲取二維碼圖片

const fs = require('fs')
const axios = require('axios')

// 拼接url
const url = `https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=${token.accessToken}`

// 傳送POST請求
const response = await axios.post(url, {
  page: '小程式中Page的路徑',
  scene: '自定義引數,格式你自己決定'
}, { responseType: 'stream' })

// 將請求結果中的二進位制流寫入到本地檔案qrcode.png
response.data.pipe(fs.createWriteStream('qrcode.png'))

在上面的程式碼中,我們將access_token作為query string引數拼接到url上,然後向這個url傳送POST請求,傳遞的引數主要是pagescene,其中page引數是掃碼後進入的小程式頁面路徑(比如pages/index/index,並且不能攜帶引數),而scene則傳入的是我們的自定義引數。

其實經過這一步,你就已經可以在你的磁碟上找到這張小程式碼的圖片了,用微信掃一下這張圖片,就能進入你的小程式頁面。

步驟3:將二維碼圖片輸出

雖然我們已經獲取到了小程式碼圖片,但是現在它還只是躺在我們的伺服器端。而通常實際情況是,我們需要在小程式頁面上去顯示這張圖片,讓使用者去儲存和分享它。因此,我們需要把這張圖片通過我們的API進行輸出。以下是基於koa 2的示例程式碼:

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:在小程式中顯示

在小程式中顯示該圖片就非常簡單了,直接使用<image>元件來進行展示:

  <image src="https://your-domain.com/wx/common/qrcode" style="width:200px;height:200px"></image>

附錄:稍微完備一些的服務端程式碼

上面4個步驟中給出的示例程式碼只是為了配合說明各個步驟,程式碼比較簡陋,下面是經過稍微的組織過的程式碼,供參考:

  • 路由部分的程式碼:
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部分的程式碼:
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('小程式的app id', '小程式的app secret')

function sha1(message) {
  return crypto.createHash('sha1').update(message, 'utf8').digest('hex')
}

module.exports = {

  async getWxaCodeUnlimit({ page, scene }) {
    // 圖片檔名使用page和scene等資料生成Hash
    // 以避免重複生成內容相同的小程式碼
    const fileName = sha1(page + scene)
    const filePath = path.join(__dirname, `../../qrcode/${fileName}.png`)

    let readable

    try {
      // 檢測該名字的小程式碼圖片檔案是否已存在
      await bluebird.promisify(fs.access)(filePath, fs.constants.R_OK);
      readable = fs.createReadStream(filePath)
    } catch (e) {
      // 小程式碼不存在,則建立一張新的
      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))
    }

    // 返回該小程式碼圖片的檔案流
    return readable
  }

}

祝大家開發出更好的小程式!



作者:一斤程式碼
連結:https://www.jianshu.com/p/3056754987e8
來源:簡書
簡書著作權歸作者所有,任何形式的轉載都請聯絡作者獲得授權並註明出處。