评论

省钱有道之 云开发环境共享小结

总结一下云开发环境共享一些注意点以及适配方法

#前言

最近为了节省一点小程序的运营成本,一些没啥流量的小程序如果每个月也要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;


到此也就大功告成。为了省钱也是够折腾的[哭笑]


最后一次编辑于  2023-08-28  
点赞 8
收藏
评论

3 个评论

  • Y.Boy
    Y.Boy
    08-11


    请问博主,为什么没有 wx.cloud.Cloud 这个类的?

    08-11
    赞同
    回复 2
    • showms
      showms
      08-12
      这是什么工具,可能只是不会自动提示吧
      08-12
      回复
    • Y.Boy
      Y.Boy
      08-12回复showms
      这是微信开发者工具,在写代码时没有自动提示。虽然硬写也不会报错。
      08-12
      回复
  • 源远流长
    源远流长
    05-29

    博主你好,未开通云开发能共享被共享环境的存储里的文件吗?

    05-29
    赞同
    回复 1
    • showms
      showms
      05-29
      可以
      05-29
      1
      回复
  • 一束光-
    一束光-
    发表于小程序端
    2023-09-17

    博主你好,我想请问一下调用方的初始化是不是不需要在云函数里面初始化啊?

    2023-09-17
    赞同
    回复 3
    • showms
      showms
      2023-09-17
      调用方都没有云开发环境,自然也就没有在云函数里面初始化的说法了
      2023-09-17
      回复
    • 一束光-
      一束光-
      发表于小程序端
      2023-09-17回复showms

      Ha

      2023-09-17
      回复
    • 一束光-
      一束光-
      发表于小程序端
      2023-09-17回复showms

      好的,谢谢

      2023-09-17
      回复
登录 后发表内容