批量生成100萬張小程序碼?瞭解一下。

引言

未標題-2.png

最近有一個生成不少小程序碼的需求,生成的小程序碼還要嵌入在指定的圖片模板上,就去找輪子,沒找到合適的輪子。。無奈之下就決定去擼一個。目前已經完成併發布npm。html

Github:github.com/Jon-Millent…git

需求

以下圖github

  • 生成帶參數的小程序二維碼
  • 要指定尺寸和位置到模板圖上
  • 要批量生成若干張

開始幹活

生成帶參數的小程序二維碼

經過官方文檔,列出了生成小程序二維碼的三種模式npm

  • createWXAQRCode 獲取小程序二維碼,適用於須要的碼數量較少的業務場景。經過該接口生成的小程序碼,永久有效,有數量限制。官方說明json

  • getWXACode 獲取小程序碼,適用於須要的碼數量較少的業務場景。經過該接口生成的小程序碼,永久有效,有數量限制。 官方說明小程序

  • getWXACodeUnlimit 獲取小程序碼,適用於須要的碼數量極多的業務場景。經過該接口生成的小程序碼,永久有效,數量暫無限制。 官方說明api

這些接口都要經過access_token來換取。讓咱們造個類數組

let AngerWechat = require('anger-wechat') // 微信操做輔助庫(本身寫的)

class miniQrcode {

   // 存放三種模式的接口
   constructor(config) {
        this.mode = {
          'getWXACode': 'https://api.weixin.qq.com/wxa/getwxacode',
          'getWXACodeUnlimit': 'https://api.weixin.qq.com/wxa/getwxacodeunlimit',
          'createWXAQRCode': 'https://api.weixin.qq.com/cgi-bin/wxaapp/createwxaqrcode',
        }
        
        // 初始化微信輔助庫
        this.$wx = new AngerWechat({
          appId: this.config.appId, // appId 必傳
          appSecret: this.config.appSecret, // appSecret 必傳
        })
        
        // 臨時數據存放文件,用於存放access_token,由於access_token有2個小時的生存期,避免重複獲取
        this.databasePath = path.join(__dirname, '../', 'database.json')
   }
}
複製代碼

實現核心方法bash

// 生成核心方法
    async getWxQrcodeInfo(concatConfig){
        // 獲取已經存放的文件裏的access_token,若是有的話而且有效的話就不用再掉接口
        let innerDatabase = this.getDatabase() 
        
        // 若是本地的數據沒有access_token 或者超過2個小時 就去請求獲取
        if(!innerDatabase.access_token ||  ((new Date().getTime() - innerDatabase.create_time) > 7200000) ) {
            let accessInfo = await this.$wx.getGlobalAccessToken()
            // 獲取access_token而後寫入文件
            // 具體代碼省略
        }
        
        
        // 獲取到access_token去請求接口
        
        let qrcodeInfo  = await this.postMan(
            this.getApiUrl(innerDatabase.access_token, concatConfig.mode), // 根據mode來區調用接口
            concatConfig.config // 用戶傳的參數
        )
        
        let returnData = {
    
        }
    
        if(qrcodeInfo.type.indexOf('image') !== -1) { //類型是圖片的就是獲取成功了
          // 請求成功 保存圖片
          returnData = {
            code: 200,
            image: qrcodeInfo.data,
            error: null
          }
        } else {
          returnData = {
            code: 500,
            error: JSON.stringify(qrcodeInfo.data.toString()),
            image: null
          }
        }
    
        return returnData
    }
複製代碼

寫好後讓咱們測試一下服務器

let qrocode = new miniQrcode({
      appId: 'xxx',
      appSecret: 'xxx'
    });
    let info = await qrocode.getWxQrcodeInfo({
	  mode: 'getWXACode',
	  config: {
	    path: `pages/index/main?id=123456`
	  },
	})
   fs.writeFileSync(`./output-juejin-test1.png`, info.image, 'utf8');
複製代碼

效果:

如何測試參數?我在這個已經發布的小程序裏面加了個彩蛋,就是長按紅色圈出區域兩次便可調出控制檯看參數

Screenshot_2018-11-17-10-55-13-286_com.tencent.mm.png

將二維碼合成到模板圖片裏面

這個操做依賴於sharp

const sharp = require('sharp');

class miniSharp {

  constructor(templateUrl){
    this.templateUrl = templateUrl
  }

  // 重置圖片大小
  async resizeQrcode(imageBuffer, config){
    return new Promise(resolve => {

      sharp(imageBuffer).resize(config.width, config.width).toBuffer().then(function(outputBuffer) {
        resolve(outputBuffer)
      });

    })
  }
  
  // 合併圖片
  async concatImage(buffer, config){
    return new Promise(resolve => {
      sharp(this.templateUrl)
        .overlayWith(buffer, {
          top: config.top,
          left: config.left
        }).toBuffer().then(function(outputBuffer) {
          resolve(outputBuffer)
        });
    })
  }

  // 主函數
  async renderImage(qrcodeBuffer, config){

    let resizeQrcodeBuffer = await this.resizeQrcode(qrcodeBuffer, config)
    let concatQrocdeBuffer = await this.concatImage(resizeQrcodeBuffer, config)

    return concatQrocdeBuffer
  }

}

module.exports = miniSharp

複製代碼

測試一下

let qrocode = new miniQrcode({
      appId: 'xxxx',
      appSecret: 'xxx'
    });
    
    let mySharp = new miniSharp('./template.png');

    let info = await qrocode.getWxQrcodeInfo({
      mode: 'getWXACode',
      config: {
        path: `pages/index/main?id=123456`
      },
    })
    
    let renderBuffer = await mySharp.renderImage(info.image, // 二維碼圖片的 buffer 數組 
    { 
      width: 200, // 從新設置二維碼寬度
      left: 362, // x軸偏移
      top: 53 // y軸偏移
    })
    
    fs.writeFileSync(`./output-juejin-test1.png`, renderBuffer, 'utf8');
複製代碼

template.png

批量處理

正常狀況下,批量生成100張須要62.556秒,平均每張須要0.62556秒,1萬張大概須要 1.73小時批量示例代碼

關於調試

使用微信開發者工具能夠進行模擬參數調試

QQ截圖20181117104623.png

測試接口

這裏我提供了一個測試接口,能夠帶參數生成線上的小程序碼,用來調試

[get] http://wx.toolos.cc 參數

  • mode 必傳 [createWXAQRCode | getWXACode | getWXACodeUnlimit] 之一

注意

  • 其餘參數對應上面的文檔的mode對應的參數,path 或者 page 須要 encodeURIComponent 一下
  • 目前小程序只有一個路徑 pages/index/main
  • 線上服務器配置低

示例

http://wx.toolos.cc/?mode=createWXAQRCode&path=pages%2Findex%2Fmain
複製代碼

關於參數模式

createWXAQRCode & getWXACode

這兩種生成的參數,生成二維碼數量有限,參數直接跟在path路徑後面,例如:

let info = await qrocode.getWxQrcodeInfo({
  mode: 'createWXAQRCode',
  config: {
    page: `pages/index/main?sgr=521314&i=loveyou`
  },
})
複製代碼

output-createWXAQRCode.png

getWXACodeUnlimit

這個能夠生成無限個,可是隻能攜帶有侷限性的參數scene,在這裏推薦一種解析方式 key:value-key:value

let info = await qrocode.getWxQrcodeInfo({
  mode: 'getWXACodeUnlimit',
  config: {
    page: `pages/index/main`,
    scene: 'i:loveyou-sgr:521314'
  },
})
複製代碼

output-getWXACodeUnlimit.png

解析示例

onLoad (query) {
  // scene 須要使用 decodeURIComponent 才能獲取到生成二維碼時傳入的 scene
  this.scene = decodeURIComponent(query.scene)
  this.queryJson = JSON.stringify(query)

  // 嘗試解析 scene 格式: shop:1-id:2

  try {
    let oneArr = this.scene.split('-')
    let twoJson = {}
    for(let i=0; i<oneArr.length; i++) {
      let target = oneArr[i].split(':')
      twoJson[target[0]] = target[1]
    }
    this.twoJson = JSON.stringify(twoJson)

  } catch(e) {
    this.twoJson = e
  }

},
複製代碼

在開發者工具中例以下面模擬

QQ截圖20181117104623.png
相關文章
相關標籤/搜索