引言
最近公司的微信小程序项目由于业务需求需要实现二维码推广海报,而小程序的服务端代码是用node.js实现的,由于是第一次使用node.js作为服务端来实现图片的相关处理,不免走了一些坑。所以为了避免大家也像我一样花费不必要的时间爬坑,就将我再开发过程中遇到的一些过程记录下来,供大家参考,水平有限,请相关大神多多指教。
基础知识及准备工作
在开始之前,希望你对下面两个工具的知识有一定的了解
-
request
; -
images
;
准备海报背景图一张
获取微信小程序二维码
获取微信小程序二维码的方式主要有三个,具体详情请参考微信小程序官方文档;这里我们选用getWXACodeUnlimit
接口: https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=ACCESS_TOKEN
。
关于微信二维码的获取有几点需要特别注意:
- POST 参数需要转成 JSON 字符串,不支持 form 表单提交;
- 只能生成已发布的小程序的二维码。
获取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)
})
总结
- 小程序必须发布后才能获取二维码
- 获取二维码二进制数据时,一定要注意编码问题,
encoding: null
,encoding: null
,encoding: null
,重要的事说三遍。