介绍

微信公众号接口对接,主要涉及以下几个方面:

  1. 模块Config
  2. 消息推送
  3. 网页登录
  4. 网页前端JSSDK
  5. 微信网页布局
  6. 微信API调用

1. 模块Config

我们可以通过在项目Config文件中覆盖模块Config中的参数,从而配置与微信公众号有关的信息

关于如何覆盖模块Config,请参见:Config

a-wechat/backend/src/config/config.js

  // account.public
  config.account.public = {
    appID: '',
    appSecret: '',
    token: appInfo.name,
    encodingAESKey: '',
    message: {
      reply: {
        default: 'You are welcome!',
        subscribe: 'You are subscribed!',
      },
    },
  };

2. 消息推送

模块a-wechat已经对消息推送的通讯机制进行了封装,并且通过event机制进行扩展。如果我们要对用户发送的消息进行定制化的回复,可以这样操作:

关于event机制,请参见:后端事件

2.0 消息推送配置

名称 说明
服务器地址(URL) https://xxx.yyy.com/api/a/wechat/message/index
令牌(Token) 随机值
消息加解密密钥(EncodingAESKey) 随机值
消息加解密方式 安全模式(推荐)

2.1 meta

test-wechat/backend/src/meta.js

event: {
      implementations: {
        'a-wechat:wechatMessage': 'event/wechatMessage',
    },

声明一个event实现,通过api路由event/wechatMessage来响应事件a-wechat:wechatMessage,从而实现自定义的消息响应逻辑

2.2 路由

test-wechat/backend/src/routes.js

{ method: 'post', path: 'event/wechatMessage', controller: event, middlewares: 'inner,wechat', meta: { auth: { enable: false } } },
名称 说明
middlewares: inner 声明该api只能被内部调用
middlewares: wechat 注入wechat api对象,便于通过ctx.meta.wechat来调用微信api接口
auth: { enable: false } 由于是内部调用,所以禁用中间件auth,从而不需要对ctx.user进行处理

2.3 Controller

test-wechat/backend/src/controller/event.js

    async wechatMessage() {
      const res = await this.service.event.wechatMessage({
        event: this.ctx.request.body.event,
        data: this.ctx.request.body.data,
      });
      this.ctx.success(res);
    }

2.4 Service

test-wechat/backend/src/service/event.js

    async wechatMessage({ event, data }) {
      const message = data.message;
      if (message.MsgType === 'text') {
        event.break = true;
        return {
          ToUserName: message.FromUserName,
          FromUserName: message.ToUserName,
          CreateTime: new Date().getTime(),
          MsgType: 'text',
          Content: `${this.ctx.text.locale('zh-cn', 'Reply')}: ${message.Content}`,
        };
      }
    }
名称 说明
event.break=true 由于同一个事件可以有多个模块进行订阅,并提供自定义的逻辑。如果想阻止后续的订阅响应,可以通过event.break=true进行终止

3. 网页登录

模块a-wechat自动判断,如果当前网页处于微信app中,会自动转向微信登录,然后自动进行微信用户注册

4. 网页前端JSSDK

模块a-wechat提供了便捷的组件,可以自动注入微信JSSDK,并且自动进行config配置

测试模块test-wechat演示了如何调用微信的二维码扫描操作:

test-wechat/front/src/pages/test/index.vue

  created() {
    const action = {
      actionModule: 'a-wechat',
      actionComponent: 'jssdk',
      name: 'config',
    };
    this.$meta.util.performAction({ ctx: this, action }).then(res => {
      this.wx = res && res.wx;
    }).catch(e => {
      this.$view.toast.show({ text: e.errMsg });
    })
  },
  methods: {
    onPerformScanQRCode() {
      this.wx.scanQRCode({
        needResult: 1,
        scanType: ['qrCode', 'barCode'],
        success: (res) => {
          this.$view.toast.show({ text: res.resultStr });
        }
      });
    }
  }
  1. 先通过this.$meta.util.performAction调用模块a-wechat提供的组件,返回wx对象
  2. 调用wx对象执行扫描二维码的微信接口

5. 微信网页布局

CabloyJS可以一站式开发PC端和移动端的网页,此外,CabloyJS通过event机制可以灵活定制不同场景下前端页面的布局组合

测试模块test-wechat演示了如何定制微信公号场景下的前端布局:

5.1 meta

test-wechat/backend/src/meta.js

event: {
      implementations: {
        'a-base:loginInfo': 'event/loginInfo',
    },

5.2 路由

test-wechat/backend/src/routes.js

{ method: 'post', path: 'event/loginInfo', controller: event, middlewares: 'inner', meta: { auth: { enable: false } } },

5.3 Controller

test-wechat/backend/src/controller/event.js

    async loginInfo() {
      const res = await this.service.event.loginInfo({
        event: this.ctx.request.body.event,
        data: this.ctx.request.body.data,
      });
      this.ctx.success(res);
    }

5.4 Service

test-wechat/backend/src/service/event.js

    async loginInfo({ /* event,*/ data }) {
      const info = data.info;
      const provider = info.user && info.user.provider;
      if (provider && provider.module === 'a-wechat' && provider.providerName === 'wechat') {
        info.config = extend(true, info.config, {
          modules: {
            'a-layoutmobile': {
              layout: {
                login: '/a/login/login',
                loginOnStart: true,
                toolbar: {
                  tabbar: true, labels: true, bottomMd: true,
                },
                tabs: [
                  { name: 'Test', tabLinkActive: true, iconMaterial: 'group_work', url: '/test/wechat/test/index' },
                  { name: 'Home', tabLinkActive: false, iconMaterial: 'home', url: '/a/base/menu/list' },
                  { name: 'Mine', tabLinkActive: false, iconMaterial: 'person', url: '/a/user/user/mine' },
                ],
              },
            },
          },
        });
      }
    }

判断info.user.provider,如果是通过微信公众号登录的账户,就提供自定义的前端布局参数

6. 微信API调用

模块a-wechat通过中间件机制提供了一个中间件wechat,如果要在后端API接口中访问微信API,只需要在API接口路由中指定中间件wechat即可。然后按如下方式调用微信API

this.ctx.meta.wechat.app

微信API基于node-webot/co-wechat-api。为了便于更灵活的添加新API,CabloyJS对主仓库发起了一个新分支,详细的API清单请参见:co-wechat-api

下面以JSSDK Config为例:

6.1 路由

a-wechat/backend/src/routes.js

{ method: 'post', path: 'jssdk/jsconfig', controller: jssdk, middlewares: 'wechat' },

6.2 Controller

a-wechat/backend/src/controller/jssdk.js

    async jsconfig() {
      const res = await this.service.jssdk.jsconfig({
        url: this.ctx.request.body.url,
      });
      this.ctx.success(res);
    }

6.3 Service

a-wechat/backend/src/service/jssdk.js

    async jsconfig({ url }) {
      // config
      const config = this.ctx.config.account.public;
      // params
      const params = {
        debug: config.jssdk.debug,
        jsApiList: config.jssdk.jsApiList,
        url,
      };
      return await this.ctx.meta.wechat.app.getJsConfig(params);
    }

直接通过this.ctx.meta.wechat.app访问相应的微信API

7. 如何判断是否在微信公众号

由于CabloyJS后端架构的普适性,我们有时候需要判断当前是否在微信公众号中,从而做出相应的处理

7.1 通过中间件判断

可以通过中间件inWechat来判断该api接口是否被微信公众号调用,如果不是则自动阻止后续逻辑的执行

src/module/test-wechat/backend/src/routes.js

  { method: 'post', path: 'test/getOpenid', controller: test, middlewares: 'inWechat',
      meta: {
        inWechat: {
          scene: 'wechat',
        },
      },
    },
名称 说明
meta.inWechat 指定中间件inWechat的参数
scene 如果指定wechat,表示该api只能被微信公众号调用

scene支持以下值:

名称 说明
空字符串 默认为wechat,代表微信公众号
wechatweb 代表微信Web应用
wechatmini 代表微信小程序
wechatmini${scene} 指定更明确的某个小程序,如wechatminidefault
wechat,wechatweb,wechatmini 该api可被任何一个指定的场景调用

7.2 通过代码判断

可以直接通过代码进行判断

this.ctx.meta.wechat.util.in(scene)

名称 说明
scene 场景名,如wechat