搞了两天,法克啊
官网参考:
获取不限制的小程序码
https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/qrcode-link/qr-code/getUnlimitedQRCode.html
业务背景:
A小程序是商户端,B小程序是会员端;
商户需要在A小程序中生成B小程序的小程序码让会员扫码访问;
代码主要逻辑
使用了小程序官方的云函数和云储存
- 使用触发器定时获取B小程序的 Access Token,并存储到数据库。
- 从数据库中获取 B小程序的 Access Token,通过 HTTPS 请求方式获取小程序图片二进制,并存储到云存储。
- 判断云存储中是否有小程序码,没有则通过云函数获取。
云函数触发器配置
官网参考:
https://developers.weixin.qq.com/miniprogram/dev/wxcloud/guide/functions/triggers.html
config.json 文件代码,每小时定时执行一次
{
"permissions": {
"openapi": [
]
},
"triggers": [
{
"name": "access_token_trigger",
"type": "timer",
"config": "0 0 * * * * *"
}
]
}
云函数执行代码
index.js 文件代码
......
// 云函数入口函数
exports.main = async (event, context) => {
// 判断调用来源是触发器
if(wxContext.SOURCE === 'wx_trigger') {
// 刷新 access token
return update_access_token(event, wxContext)
}
}
......
// 刷新 access token
async function update_access_token(event, wxContext) {
const now_date = new Date()
try {
// 使用 HTTPS GET 请求方式获取会员端 Access Token
let grant_type = 'client_credential' // 填写:'client_credential'
let appid = '******************' // 会员端 AppID
let secret = '********************************' // 会员端 AppSecret(不能泄露给他人)
let base_url = 'https://api.weixin.qq.com/cgi-bin/token' // 如果在测试环境调该接口,则线上对应的access_token会失效(未验证)
let token_url = base_url + '?grant_type=' + grant_type + '&appid=' + appid + '&secret=' + secret
const token_response = await axios.get(token_url)
let access_token = token_response.data.access_token
let expires_in = token_response.data.expires_in
// 存储会员端 Access Token
return await db.collection(SR_SETTINGS_TABLE).where({
_id: 'PK000001', // 该表只有一条主键固定的记录
}).update({
data: {
sr_customer_access_token: _.push({
each: [{
at: access_token,
ei: expires_in,
ud: now_date,
ut: now_date.getTime()
}],
position: 0,
slice: 72
})
}
})
} catch (e) {
console.error(e)
}
}
从数据库中获取 Access Token,然后调用接口获取小程序码图片二进制,并上传到云存储中
// 生成商户小程序码
async function generate_wxcode(event, wxContext) {
try {
// 从数据库中获取 Access Token
const result = await db.collection(SR_SETTINGS_TABLE).where({
_id: 'PK000001',
})
.field({
_id: true,
sr_customer_access_token: true,
})
.limit(1)
.get()
if(result.errMsg != 'collection.get:ok' || result.data.length==0) {
return result
}
let access_token = result.data[0].sr_customer_access_token[0].at
// 获取不限制的小程序码
let wxacode_url = 'https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=' + access_token
const wxacode_response = await axios.post(wxacode_url, // HTTPS POST 请求方式
{
path: 'pages/main/main', // 注意不是 page,而是 path
scene: 'merchant_id=' + event.data.merchant_id, // scene 最大32个可见字符
check_path: false, // 参数名是 check_path ,不是 check_page 。
env_version: 'develop', // 正式版 "release",体验版 "trial",开发版 "develop"
width: 320
},
{
responseType: 'arraybuffer'
}
)
// 云存储小程序码
let cloudUrlMainDirectory = event.data.cloudUrlMainDirectory
let cloudPath = cloudUrlMainDirectory +'/' + event.data.merchant_id + '/wxacode/' + 'wxacode.jpg'
const uploadResult = await cloud.uploadFile({
cloudPath: cloudPath,
fileContent: wxacode_response.data,
})
// 返回云存储文件ID
return {
data: { wxacodeCloudPath: uploadResult.fileID },
errMsg: 'collection.get:ok',
}
} catch (e) {
console.error(e)
return e
}
}
小程序码Cloud ID固定,前端可以判断是否存在
// 尝试从云存储获取小程序码
let fileID = this.data.cloudUrlBase+'/'+this.data.cloudUrlMainDirectory+'/'+this.data.merchant_info._id+'/wxacode/wxacode.jpg'
console.log(fileID)
wx.cloud.downloadFile({
fileID: fileID,
success (res) {
console.log('从云存储获取小程序码成功')
that.setData({ wxacodeCloudPath: res.tempFilePath })
},
fail(res) {
// 获取失败则生成小程序码
console.log('从云存储获取小程序码失败')
let merchant_id = that.data.merchant_info._id
if(merchant_id) {
that.callGenerateWxCode(merchant_id)
}
}
})
// 生成商户小程序码
async callGenerateWxCode(merchant_id) {
var that = this
await app.call({
type: 'generate_wxcode',
data: {
merchant_id: merchant_id,
cloudUrlMainDirectory: that.data.cloudUrlMainDirectory
},
tips: '获取中'
}).then((res) => {
that.parseGenerateWxCode(res)
})
},
// 解析云函数返回结果
parseGenerateWxCode(res) {
try {
// 获取云存储的商户小程序码
let wxacodeCloudPath = res.data.wxacodeCloudPath
this.setData({ wxacodeCloudPath: wxacodeCloudPath })
} catch (error) {
console.error(error)
let title = '提示'
let content = '生成商户小程序码发生异常'
this.popupModalMessage(title, content)
}
},