搞了兩天,法克啊
官網(wǎng)參考:
獲取不限制的小程序碼
https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/qrcode-link/qr-code/getUnlimitedQRCode.html
業(yè)務(wù)背景:
A小程序是商戶端,B小程序是會員端;
商戶需要在A小程序中生成B小程序的小程序碼讓會員掃碼訪問;
代碼主要邏輯
使用了小程序官方的云函數(shù)和云儲存
- 使用觸發(fā)器定時獲取B小程序的 Access Token,并存儲到數(shù)據(jù)庫。
- 從數(shù)據(jù)庫中獲取 B小程序的 Access Token,通過 HTTPS 請求方式獲取小程序圖片二進制,并存儲到云存儲。
- 判斷云存儲中是否有小程序碼,沒有則通過云函數(shù)獲取。
云函數(shù)觸發(fā)器配置
官網(wǎng)參考:
https://developers.weixin.qq.com/miniprogram/dev/wxcloud/guide/functions/triggers.html
config.json 文件代碼,每小時定時執(zhí)行一次
{
"permissions": {
"openapi": [
]
},
"triggers": [
{
"name": "access_token_trigger",
"type": "timer",
"config": "0 0 * * * * *"
}
]
}
云函數(shù)執(zhí)行代碼
index.js 文件代碼
......
// 云函數(shù)入口函數(shù)
exports.main = async (event, context) => {
// 判斷調(diào)用來源是觸發(fā)器
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' // 如果在測試環(huán)境調(diào)該接口,則線上對應(yīng)的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)
}
}
從數(shù)據(jù)庫中獲取 Access Token,然后調(diào)用接口獲取小程序碼圖片二進制,并上傳到云存儲中
// 生成商戶小程序碼
async function generate_wxcode(event, wxContext) {
try {
// 從數(shù)據(jù)庫中獲取 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, // 參數(shù)名是 check_path ,不是 check_page 。
env_version: 'develop', // 正式版 "release",體驗版 "trial",開發(fā)版 "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)
})
},
// 解析云函數(shù)返回結(jié)果
parseGenerateWxCode(res) {
try {
// 獲取云存儲的商戶小程序碼
let wxacodeCloudPath = res.data.wxacodeCloudPath
this.setData({ wxacodeCloudPath: wxacodeCloudPath })
} catch (error) {
console.error(error)
let title = '提示'
let content = '生成商戶小程序碼發(fā)生異常'
this.popupModalMessage(title, content)
}
},