微信小程式推廣二維碼海報Node.js實現版

WokerWong發表於2018-12-04

引言

最近公司的微信小程式專案由於業務需求需要實現二維碼推廣海報,而小程式的服務端程式碼是用node.js實現的,由於是第一次使用node.js作為服務端來實現圖片的相關處理,不免走了一些坑。所以為了避免大家也像我一樣花費不必要的時間爬坑,就將我再開發過程中遇到的一些過程記錄下來,供大家參考,水平有限,請相關大神多多指教。

基礎知識及準備工作

在開始之前,希望你對下面兩個工具的知識有一定的瞭解

  1. request;
  2. images;

準備海報背景圖一張

獲取微信小程式二維碼

獲取微信小程式二維碼的方式主要有三個,具體詳情請參考微信小程式官方文件;這裡我們選用getWXACodeUnlimit介面: https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=ACCESS_TOKEN

關於微信二維碼的獲取有幾點需要特別注意:

  1. POST 引數需要轉成 JSON 字串,不支援 form 表單提交;
  2. 只能生成已釋出的小程式的二維碼。

獲取ACCESS_TOKEN

由於該介面請求需攜帶ACCESS_TOKEN引數,所以第一步得先獲取它, 程式碼如下:

const request = require('request');

/**
 * [獲取ACCESS_TOKEN]
 * @param  {[String]} appid         [你的小程式appid]
 * @param  {[String]} secret        [你的小程式secretKey]   
 * @return {[Object]}               [Promise]
 */
function getAccessToken(appid,secret){
    const url = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=' +  appid + '&secret=' + secret
    return new Promise((resolve,reject)=>{
        request(url, function(error, res, body) {
            if (!error && res.statusCode === 200) {
                resolve(JSON.parse(body));
            } else {
                reject(error, body)
            }
        })
    })
}
複製程式碼

獲取小程式二維碼

獲取小程式二維碼的注意事項:

如果呼叫成功,會直接返回圖片二進位制內容,如果請求失敗,會返回 JSON 格式的資料。

由於二維碼獲取成功後返回的是圖片二進位制資料,可能瞭解node.js都會第一時間想到是用node.js的Buffer來處理二進位制資料。沒錯,確實是用Buffer,我最初的程式碼如下:

const images = require("images")

/**
 * [獲取二維碼]
 * @param  {[String]} access_token  [ACCESS_TOKEN]  
 * @return {[Object]}               [Promise]
 */
function getQR(access_token) {
    return new Promise((resolve,reject)=>{
        const params = {
            url: 'https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=' + access_token,
            method: "POST",
            json: true,
            headers: {
                "content-type": "application/json",
            },
            body: {
                scene: 'uid=123',
                width: 280
            }
        }
        request(params, function(error, res, body) {
            if (!error && res.statusCode == 200) {
                //測試: 從Buffer資料中解碼影象  正式執行請刪除
                images(new Buffer(body))
                
                resolve(new Buffer(body))
            } else {
                reject(error, body)
            }
        })
    })
}
複製程式碼

但執行發現,返回報錯資訊 Unknow format.於是網上各種找資料,花費了大量時間找到的都是些關於buffer如何讀本地檔案的資料文件。後來在論壇裡發現了一位好心人發來一篇文件給我。Node.js 不深也不淺得了解下編碼. 閱讀後發現原來是因為編碼的問題。具體原因可以看看那篇文章。其主要就是需要在request引數裡設定: encoding: null, 所以修改後的程式碼如下:

const images = require("images")

/**
 * [獲取二維碼]
 * @param  {[String]} access_token  [ACCESS_TOKEN]  
 * @return {[Object]}               [Promise]
 */
function getQR(access_token) {
    return new Promise((resolve,reject)=>{
        const params = {
            url: 'https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=' + access_token,
            method: "POST",
            json: true,
            encoding: null,
            headers: {
                "content-type": "application/json",
            },
            body: {
                scene: 'uid=123',
                width: 280
            }
        }
        request(params, function(error, res, body) {
            if (!error && res.statusCode == 200) {
                //測試: 從Buffer資料中解碼影象, 正式執行請刪除
                images(new Buffer(body))
                
                resolve(new Buffer(body))
            } else {
                reject(error, body)
            }
        })
    })
}
複製程式碼

結果執行成功!

使用images工具合成海報

獲取二維碼資料後,接下來就是需要將其更我們的海報背景圖合成並儲存或者上傳到第三方儲存伺服器上。關於images庫的使用請參考images官方文件, 下面直接上程式碼:

const images = require("images")

/**
 * [二維碼海報合成]
 * @param  {[Buffer]} buf  [二維碼圖片Buffer資料]
 */
function composite(buf) {
    images("./public/bg.png") //載入海報背景影象檔案
        .draw(images(buf), 60, 600) // 在(60,600)處繪製Logo
        .save("./public/output.jpg", { //儲存圖片到本地,圖片質量為50
            quality : 50
        });
}
複製程式碼

至此,所有功能已全部完成! 下面是簡單的完整執行程式碼:

    getAccessToken(appid, secret)
        .then(res => {
            return getQR(res.access_token)
        })
        .then(buf => {
            composite(buf)
        })
複製程式碼

總結

  1. 小程式必須釋出後才能獲取二維碼
  2. 獲取二維碼二進位制資料時,一定要注意編碼問題,encoding: nullencoding: nullencoding: null,重要的事說三遍。

此文章為萬文前端原創,特此宣告!

相關文章