背景
前段时间公司内部有一个安卓小项目,安卓内部调用前端的H5做展示,我负责H5这一块的开发
产品提了一个需求,在项目里面增加展示公司的一个微分销小程序的小程序码,这里简单记录一下自己的做这个功能的经历和踩的坑
技术架构
负责的H5项目采用的前后端分离的架构
前端页面部分用的 vue2
应用层采用 nodejs (koa2) ,通过nodejs去调用后端的SOA服务来封装应用层的接口
思路
1.小程序文档中提供了对应的方法去动态生成一张小程序码的图片,所需参数可以详见小程序的官方文档;
2.和小程序开发的同事确定好生成小程序码所需要的参数,针对我这个项目就是'pages/index/index?sellerId=xxx',sellerId参数处理这里不做介绍,根据实际项目而异;
3.小程序接口返回一个buffer,调用Nodejs的fs.writeFileSync方法将这个buffer转换成一张图片并保存在指定路径,返回这个路径
4.前端页面中得到这个路径后去请求这张图片,这时候需要node端做好对应的路径处理,我这里用的是koa-static,当请求指定路径的时候能指向对应的资源(生成的图片);
5.前端获取到图片资源后再发一个请求删除这张图片,因为小程序码是有有效时间的,所以每次都得重新生成,临时文件已经没有作用了
nodejs(koa2)生成图片方法
exports.getWechatSalesQrcode = async function (ctx, next) {
try {
let bodyParams = ctx.request.body;
let miniProgramConfig = Object.assign({}, constants.MINI_PROGRAM_CONFIG[bodyParams.brandCode]);
miniProgramConfig.path = 'pages/index/index?sellerId=35226134'; // todo 先写死sellerId
if (!miniProgramConfig) {
ctx.body = {
success: false
}
}
let qrcodePhotoNameUrl = await generateMiniProgramQrcodeImg(miniProgramConfig, 'weidian');
ctx.body = {
url: qrcodePhotoNameUrl
};
} catch (e) {
ctx.body = {
success: false
}
}
};
/**
* 生产小程序二维码图片url
* @param miniProgramConfig 小程序配置
* @param fileName 二维码图片名
* @param fileType 图片类型
* @returns {Promise<string>}
*/
async function generateMiniProgramQrcodeImg(miniProgramConfig, fileName = 'qrcode', fileType = 'png') {
let imgBuffer = await getMiniProgramQrcodePromise(miniProgramConfig);
let time = new Date().getTime();
let qrcodePhotoName = fileName + time + '.' + fileType;
fs.writeFileSync('./public/pic/' + qrcodePhotoName, imgBuffer);
return '/api/media/pic/' + qrcodePhotoName;
}
/***
* 调用小程序服务端接口生成对应小程序二维码
* @param param 包含小程序的appid和secret 入口path 图片宽度width
* @returns {Promise<any>}
*/
function getMiniProgramQrcodePromise(param) {
return new Promise(resolve => {
let url = `https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${param.appid}&secret=${param.secret}`
request(url, {}, function (error, response, body) {
if (response.statusCode === 200 && body) {
let access_token = JSON.parse(body).access_token;
let qrcodeUrl = `https://api.weixin.qq.com/cgi-bin/wxaapp/createwxaqrcode?access_token=${access_token}`;
request.post({
url: qrcodeUrl,
body: {
scene: 1049,
path: param.path,
width: param.width || 280
},
encoding: null, // request默认会进行编码,设置为null使其不要编码原因返回
json: true,
}, function (error, response, body) {
let imgBuffer = Buffer.from(body, 'binary');
resolve(imgBuffer);
});
} else {
resolve(false);
}
});
})
}
常量配置
// 微分销小程序配置
exports.MINI_PROGRAM_CONFIG = {
'6': {
appid: "xxx",
secret: "xxxx"
}
};
koa2提供静态资源访问
var koa = require('koa');
var app = new koa();
var serve = require('koa-static-server')
app.use(serve({ rootDir: './public/pic', rootPath: '/api/media/pic' }));
app.use(serve({ rootDir: './public/pdf', rootPath: '/api/media/pdf' }));
前端代码 vue2
<template>
<section class="get-coupon-area">
<div class="inside-coupon-content">
<div class="get-coupon-content">
<div class="qrcode-img">
<img v-show="qrCodeUrl" :src="qrCodeUrl" @load="loadImgSuccess">
</div>
</div>
</div>
</section>
</template>
export default {
name: 'get-coupon',
data() {
return {
qrCodeUrl: '',
couponPasscode: '',
qrCodeFileName: ''
}
},
mounted() {
getWechatSalesQrcode({brandCode: this.brandCode, clerkNo: this.clerkNo}).then(res => {
if (res && res.url) {
this.qrCodeUrl = '/api/media/pic/' + res.url;
this.qrCodeFileName = res.url;
let img = new Image();
img.src = this.qrCodeUrl;
img.onload = function () {
unlinkImg({fileName: res.url}).then(res => {
console.log('图片删除成功!')
});
};
// console.log(this.qrCodeUrl);
}
});
}
}
nginx修改
开发这个功能的时候在我本地调试是没有问题的,但是到了生产的时候发现获取图片的时候404,排查了代码没有发现问题。。
后来想到了是否是nginx配置的问题,之前为了节省带宽和缓解服务器的压力,跟运维约定好一些静态资源到制定的目录获取,而且设置缓存时间
针对我这个需求的话因为小程序码是动态生成的,不能缓存,而且不在约定好的那个位置,所以这个配置的影响了获取图片
原先的配置
location ~ .*\.(html|htm|gif|jpg|jpeg|bmp|png|ico|txt|js|css)$
{
root /data/static/xxxx/dist;
expires 7d;
}
修改方案
因为生成的图片是png格式的,其他静态资源没有png格式的,所以和运维商量了一下nginx配置中去掉了png格式,这样就可以正常获取
参考链接:blog.csdn.net/uikoo9/arti…