#前言
最近为了节省一点小程序的运营成本,一些没啥流量的小程序如果每个月也要19块略微有些肉疼(主要还是穷),研究了一下云环境共享,在这里简单做一下总结。
这里有官方的小程序环境共享文档需提前了解一下,具体共享步骤按官方文档操作即可。
https://developers.weixin.qq.com/miniprogram/dev/wxcloud/guide/resource-sharing/introduce.html
#注意点
共享环境有几个注意点大致如下:
1、必须是相同主体
2、开通了云开发环境的小程序可以共享给同主体的小程序、公众号,被共享方无需开通云开发环境
3、一个云开发环境最多可以共享给10个小程序/公众号
4、共享后双发均可主动解除
5、按官方文档要求,资源方需有云函数cloudbase_auth,测试时发现没有这个云函数其实也能正常运行,可能我验证的场景还不够多
6、云能力初始化的方式不同,资源方按传统的云环境初始化方式即可,也就是
wx.cloud.init({
env: env.activeEnv,
traceUser: true
});
而调用方的初始化方式有所不同
const cloud = new wx.cloud.Cloud({
//资源方AppID
resourceAppid,
//资源方环境ID
resourceEnv,
})
// 跨账号调用,必须等待 init 完成
// init 过程中,资源方小程序对应环境下的 cloudbase_auth 函数会被调用,并需返回协议字段(见下)来确认允许访问、并可自定义安全规则
const initRes = await cloud.init();
后续调用资源方的云函数就用这个cloud就行了:cloud.callFunction({...});
7、调用方有操作到云存储文件的api也需要用6步骤中的cloud
8、云存储fileId需要用cloud.getTempFileURL转换成临时/永久链接,否则在调用方无法展示
9、一些api的云调用方式也有变化,需指明具体的appid。比如A小程序授权给了B小程序,想给B小程序推送客服消息需要写成
await cloud.openapi({appid:B小程序appid}).customerServiceMessage.send({...});
10、获取调用方的appid/openid/unionid也有所不同
// 跨账号调用时,由此拿到来源方小程序/公众号 AppID
console.log(wxContext.FROM_APPID)
// 跨账号调用时,由此拿到来源方小程序/公众号的用户 OpenID
console.log(wxContext.FROM_OPENID)
// 跨账号调用、且满足 unionid 获取条件时,由此拿到同主体下的用户 UnionID
console.log(wxContext.FROM_UNIONID)
#适配
基于以上注意点,开始进行适配,由于我是一套代码部署N个小程序,然后一个云环境共享给其他小程序,希望通过配置决定哪个小程序作为资源方,哪些作为调用方
首先是云开发环境的初始化:
1、env.js 环境配置:
//云开发环境
const cloudBase = {
//使用共享云环境资源,资源方=false,调用方=true
useShareResource: false,
//资源方AppID
resourceAppid: "wx9d2xxxxxxxx0088",
//资源方环境ID
resourceEnv: "prod-9gxqvi3qb3c257ef",
//云环境ID
prod: "prod-9gxqvi3qb3c257ef"
}
2、api.js 操作模块
const env = require('../env.js');
let cloud;
/**
* 初始化云能力
* @returns {Promise}
*/
const wxCloudInit = async function () {
const {cloudBase} = env;
if (!wx.cloud) {
console.error('请使用 2.2.3 或以上的基础库以使用云能力')
} else if (cloudBase.useShareResource) {
const {resourceAppid, resourceEnv} = cloudBase;
// 声明新的 cloud 实例
cloud = new wx.cloud.Cloud({
//资源方AppID
resourceAppid,
//资源方环境ID
resourceEnv,
})
// 跨账号调用,必须等待 init 完成
// init 过程中,资源方小程序对应环境下的 cloudbase_auth 函数会被调用,并需返回协议字段(见下)来确认允许访问、并可自定义安全规则
const initRes = await cloud.init();
console.log("初始化云能力完毕:", initRes, "资源方appid:", resourceAppid, "资源方环境ID:", resourceEnv);
} else {
wx.cloud.init({
env: env.activeEnv,
traceUser: true
});
console.log("初始化云能力完毕,当前环境:", env.activeEnv);
cloud = wx.cloud;
}
this.cloud = cloud;
}
/**
* 云函数调用
* @param name
* @param data
* @param success
* @param fail
* @param complete
*/
const callCloudFunction = function (name, data, success, fail, complete) {
//执行云函数
cloud.callFunction({
// 云函数名称
name: name,
// 传给云函数的参数
data: Object.assign({}, data, {env: env.activeEnv})
}).then(res => {
typeof success == 'function' && success(res);
}).catch(res => {
typeof fail == 'function' && fail(res);
}).then(res => {
typeof complete == 'function' && complete(res);
});
};
3、在app.js中初始化云环境,后续有用到wx.cloud的都需要改成api.cloud
const api = require('utils/api.js');
App({
onLaunch: async function (options) {
await api.wxCloudInit();
}
});
其次是资源方的获取用户信息调整
每次都要判断wxContext.FROM_OPENID是否为空,不为空则是调用方的用户信息,为空则是资源方的用户信息,略微繁琐,干脆封装了一个npm包wx-server-inherit-sdk,改造了一下getWxContext函数,源码如下,引入这个包后也就可以不用引入官方的wx-server-sdk
const cloud = require('wx-server-sdk');
// 保存原始getWXContext方法到另一个变量
const originalGetWXContext = cloud.getWXContext;
cloud.getWXContext = function () {
//调用原始getWXContext方法
const wxContext = originalGetWXContext.call(this);
const {FROM_APPID, FROM_OPENID} = wxContext;
//云开发环境共享时获取到的APPID会替换成源方APPID
if (FROM_APPID) {
Object.assign(wxContext, {APPID: FROM_APPID});
}
//云开发环境共享时获取到的OPENID会替换成源方OPENID
if (FROM_OPENID) {
Object.assign(wxContext, {OPENID: FROM_OPENID});
}
return wxContext;
}
module.exports = cloud;
到此也就大功告成。为了省钱也是够折腾的[哭笑]
请问博主,为什么没有 wx.cloud.Cloud 这个类的?
博主你好,未开通云开发能共享被共享环境的存储里的文件吗?
博主你好,我想请问一下调用方的初始化是不是不需要在云函数里面初始化啊?
Ha
好的,谢谢