最近有一個生成不少小程序碼的需求,生成的小程序碼還要嵌入在指定的圖片模板上,就去找輪子,沒找到合適的輪子。。無奈之下就決定去擼一個。目前已經完成併發布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');
複製代碼
效果:
如何測試參數?我在這個已經發布的小程序裏面加了個彩蛋,就是長按紅色圈出區域兩次
便可調出控制檯看參數
這個操做依賴於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');
複製代碼
正常狀況下,批量生成100
張須要62.556秒
,平均每張須要0.62556秒
,1萬張大概須要 1.73小時
。 批量示例代碼
使用微信開發者工具能夠進行模擬參數調試
這裏我提供了一個測試接口,能夠帶參數生成線上的小程序碼,用來調試
[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
複製代碼
這兩種生成的參數,生成二維碼數量有限,參數直接跟在path路徑後面,例如:
let info = await qrocode.getWxQrcodeInfo({
mode: 'createWXAQRCode',
config: {
page: `pages/index/main?sgr=521314&i=loveyou`
},
})
複製代碼
這個能夠生成無限個,可是隻能攜帶有侷限性的參數scene
,在這裏推薦一種解析方式 key:value-key:value
let info = await qrocode.getWxQrcodeInfo({
mode: 'getWXACodeUnlimit',
config: {
page: `pages/index/main`,
scene: 'i:loveyou-sgr:521314'
},
})
複製代碼
解析示例
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
}
},
複製代碼
在開發者工具中例以下面模擬