当前位置:   article > 正文

公众号第三方平台开发流程详解_微信公众号 第三方平台的 开发流程 详细

微信公众号 第三方平台的 开发流程 详细

准备工作

1. 注册申请


访问https://open.weixin.qq.com 根据指引进行注册申请,申请流程相对比较麻烦,需要耐心等待审核

2. 创建第三方平台


进入‘管理中心->创建第三方平台’
这里写图片描述

2.1. 输入基本信息


!基本信息将显示在授权页被用户看到,请认真填写
修改平台审核成功后,仅对测试公众号生效,届时再提交“覆盖现网全网发布状态”并审核成功后,才可影响现网

这里写图片描述

2.2. 选择权限


根据第三方平台需要的接口权限进行选择,需要注意:

  1. 修改平台审核成功后,仅对测试公众号生效,届时再提交“覆盖现网全网发布状态”并审核成功后,才可影响现网;
  2. 在修改平台时,若有权限的增加,则视为一次平台升级,已授权用户使用老权限不受任何影响,但使用新权限需要用户再次进行授权页进行升级授权,此时注意引导用户重新授权

这里写图片描述

2.3. 填写开发资料


授权流程相关
这里写图片描述

授权发起页:即引导用户进入授权页面的入口页面的域名(后面开发部分会详细介绍)
授权测试公众号列表:要填写公众号的原始ID,‘微信公众平台->公众号设置->原始ID’
授权事件接收URL:用于接收微信的各种通知,包括授权成功、取消授权、授权更新以及每十分钟推送的component_verify_ticket(后面开发部分会详细介绍)


授权后代公众号实现业务
这里写图片描述

如果有过公众号开发经验这部分就相对比较容易理解了,基本上与公众号开发的配置相同(‘微信公众平台->基本配置->服务器配置’),可以参考公众号开发准备这篇文章。
公众号消息与事件接收URL 这一项要配置一个通配符$APPID$,不同的公众号事件推送时,这个通配符会自动替换为对应的公众号的AppID


其它
这里写图片描述

这个IP列表要填写公网IP,我使用的是阿里云ESC云服务器


开发

使用 Node.js进行的服务端开发,数据库使用 MysqlES7语法,使用Koa2框架。具体框架结构参考使用Koa2搭建web项目这篇文章(一定要看,不然后面的代码会看不懂)。下面会按流程逐步完成第三方平台后台的开发

为了篇幅工整,所有的工具类(XXXUtil.js)均放在最后列举


1. 授权事件接收

<完成本文2.3中的 授权事件接收URL 的开发>
在公众号第三方平台创建审核通过后,微信服务器会向其“授权事件接收URL”每隔10分钟定时推送component_verify_ticket(重要字段类似于密码)。将字段存入数据库定期刷新,component_verify_ticket、component_access_token以及component_auth_code存储在同一个表中,数据表component结构如下:

id component_ticket component_access_token component_auth_code

【component.js】

const xmlUtil = require("./../utils/xmlUtil.js");
const componentService = require('./../service/componentService.js');

//Be called every 10 minutes to refresh component_verify_ticket by wechat
//Be called when authorized
//Be called when unauthorized
//Be called when refresh
var handleComponentMessage = async (ctx, next) => {
    let requestString = ctx.data;
    let requestMessage = xmlUtil.formatMessage(requestString.xml);

    let query = ctx.query;
    /**
    * Checking whether access_token and pre_auth_code 
    * need to be refreshed according to component_verify_ticket 
    * access_token need to be refreshed every 2 hours
    * pre_auth_code need to be refreshed every 30 minutes
    */
    let result = await componentService.handleComponentMessage(requestMessage, query);

    ctx.response.body = 'success';
}

... ...

module.exports = {
    'POST /handleComponentMessage' :handleComponentMessage
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

【componentService.js】

const xml2js = require('xml2js');
const xmlUtil = require("./../utils/xmlUtil.js");
const wechatCrypto = require('./../utils/cryptoUtil.js');
const http = require('./../utils/httpUtils.js');
//analyze the decrypted message (xml => json)
var resolveMessage = messageXML => {
    var message = new Promise((resolve, reject) => {
            xml2js.parseString(messageXML, {trim: true}, (err, result) => {
            var message = xmlUtil.formatMessage(result.xml);
            resolve(message);
        });
    }).then(function(message) {
        return message;
    });

    return message;
};

var handleComponentMessage = async (requestMessage, query) => {
    let signature = query.msg_signature;
    let timestamp = query.timestamp;
    let nonce = query.nonce;
    logger.debug("Receive messasge from weixin \nsignature: " + signature + "\ntimestamp: " + timestamp + "\nnonce: " + nonce);

    //Create cryptor object for decrypt message
    let cryptor = new wechatCrypto(真实的token, 真实的encodingAESKey, 真实的第三方平台appID);
    let encryptMessage = requestMessage.Encrypt;
    let decryptMessage = cryptor.decrypt(encryptMessage);

    logger.debug('Receive messasge from weixin decrypted :' + JSON.stringify(decryptMessage));

    var message = await resolveMessage(decryptMessage.message);
    let infoType = message.InfoType;
    if(infoType == 'component_verify_ticket') {
        let ticket = message.ComponentVerifyTicket;
         //query the component_verify_ticket, component_access_token and component_auth_code
        ... ...
        //TODO 将拿到的ticket更新存储到数据表component中
    } else if(infoType == 'authorized') {
        //TODO authorized
    } else if(infoType == 'unauthorized') {
        //TODO unauthorized
    } else if(infoType == 'refresh') {
        //TODO refresh
    }

    return '';
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48

2. 获取component_access_token和pre_auth_code

由于两个属性都需要定期刷新,所以我做了一个定时任务,定时刷新这两个字段并存入数据表component


【refresh.js】

const schedule = require('node-schedule');
const http = require('./../utils/httpUtils.js');

//refresh component_access_token every 1 hour
var refreshComponentAccessToken = async function() {
   
    var component = 读取表component;
    var ticket = component.component_ticket;

    if(ticket == null || ticket == undefined || ticket == '') {
        return;
    }
    var access_token = component.component_access_token;
    var auth_code = component.component_auth_code;

    var componentTokenPostData = {
        component_appid : 第三方appID,
        component_appsecret : 第三方appSecret,
        component_verify_ticket : ticket
    };
    var https_options = {
        hostname : 'api.weixin.qq.com',
        path : '/cgi-bin/component/api_component_token',
        method : 'post'
    };

    var component_access_token_result = await http.doHttps_withdata(https_options, componentTokenPostData);
    var access_token_json = JSON.parse(component_access_token_result);
    logger.debug('Refresh component_access_token result: ' + component_access_token_result);

    if(access_token_json.errcode != undefined) {
        return;
    }

    access_token = access_token_json.component_access_token;

    //TODO 将拿到的access_token 更新存储到数据表component中
}

//refresh pre_auth_code every 20 minutes
var refreshComponentAuthCode = async function() {
   
    var component = 读取表component;
    var ticket = component.component_ticket;
    var access_token = component.component_access_token;

    if(access_token == null || access_token == undefined || access_token == '') {
        return;
    }

    var access_token_times = component.component_access_token_times;
    var auth_code = component.component_auth_code;
    var auth_code_times = component.component_auth_code_times;

    var componentAuthCodePostData = {
        component_appid : config.component.appID
    };
    var https_options = {
        hostname : 'api
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/280773
推荐阅读
相关标签
  

闽ICP备14008679号