Conveniently build a basic Node.js WeChat third-party service platform.
npm install wechat-open-toolkit
const express = require ( 'express' )
const app = express ( )
const WechatOpenToolkit = require ( 'wechat-open-toolkit' )
const {
EVENT_COMPONENT_VERIFY_TICKET , EVENT_AUTHORIZED , EVENT_UPDATE_AUTHORIZED ,
EVENT_UNAUTHORIZED , EVENT_COMPONENT_ACCESS_TOKEN , EVENT_AUTHORIZER_ACCESS_TOKEN ,
EVENT_AUTHORIZER_JSAPI_TICKET
} = WechatOpenToolkit
// 微信第三方平台列表
let list = [
{
componentAppId : '' , // 微信第三方平台 appId
componentAppSecret : '' , // 微信第三方平台 appSecret
token : '' , // 消息校验 Token
encodingAESKey : '' // 消息加解密 key
}
]
let toolkit = new WechatOpenToolkit ( { list } )
// 绑定全部事件
toolkit . on ( EVENT_COMPONENT_VERIFY_TICKET , ret => {
console . log ( ret )
} )
toolkit . on ( EVENT_AUTHORIZED , ret => {
console . log ( ret )
} )
toolkit . on ( EVENT_UPDATE_AUTHORIZED , ret => {
console . log ( ret )
} )
toolkit . on ( EVENT_UNAUTHORIZED , ret => {
console . log ( ret )
} )
toolkit . on ( EVENT_COMPONENT_ACCESS_TOKEN , ret => {
console . log ( ret )
} )
toolkit . on ( EVENT_AUTHORIZER_ACCESS_TOKEN , ret => {
console . log ( ret )
} )
toolkit . on ( EVENT_AUTHORIZER_JSAPI_TICKET , ret => {
console . log ( ret )
} )
toolkit . on ( 'error' , err => {
console . error ( err )
} )
// 通常需要绑定5个中间件
app . use ( '/wechat/events' , toolkit . events ( ) ) // 第三方平台事件接收中间件
list . forEach ( ( { componentAppId } ) => {
let authMiddleware = toolkit . auth ( componentAppId , 'https://domain.com/' ) // 第三方平台网页授权中间件
let msgMiddleware = toolkit . message ( componentAppId ) // 授权方用户消息接收中间件
let autoTestMiddleware = toolkit . autoTest ( componentAppId ) // 第三方平台全网发布测试中间件
app . get ( `/wechat/auth/ ${ componentAppId } ` , authMiddleware )
app . post ( `/wechat/message/ ${ componentAppId } /:authorizerAppId` , msgMiddleware , autoTestMiddleware , ( req , res ) => {
res . end ( 'success' )
console . log ( req . wechat )
} )
app . get ( `/wechat/oauth/ ${ componentAppId } /:authorizerAppId` , ( req , res ) => {
let { authorizerAppId } = req . params
let oauthMiddleware = toolkit . oauth ( componentAppId , authorizerAppId , 'https://domain.com/' ) // 授权方网页授权中间件
oauthMiddleware ( req , res )
} )
} )
app . listen ( 3000 )
console . log ( 'server start at 3000' )
const CoWechatApi = require ( 'co-wechat-api' )
const WechatApi = require ( 'wechat-api' )
let store = { } // 缓存数据
let componentAppId = 'test app id'
let authorizerAppId = 'test app id'
let api = new WechatApi ( '' , '' , callback => {
// 每次调用 api.方法(),都会从 store 对象取 access token
callback ( null , {
accessToken : store [ ` ${ componentAppId } / ${ authorizerAppId } ` ] ,
expireTime : Date . now ( ) + 1000 * 60
}
} )
let coApi = new CoWechatApi ( '' , '' , async ( ) => {
// 每次调用 api.方法(),都会从 store 对象取 access token
return {
accessToken : store [ ` ${ componentAppId } / ${ authorizerAppId } ` ] ,
expireTime : Date . now ( ) + 1000 * 60
}
} )
// 每次授权方 access token 更新时,同步更新缓存数据
toolkit . on ( EVENT_AUTHORIZER_ACCESS_TOKEN , function ( ret ) {
let { AppId , authorizer_appid , authorizer_access_token } = ret
store [ ` ${ AppID } / ${ authorizer_appid } ` ] = authorizer_access_token // 更新
} )
// 该功能需等到 access token 首次更新后,才能调用
api . sendText ( )
await coApi . sendText ( )
///
The sample code is for reference only and should be adjusted according to the actual situation.
The WeChat Open Platform account needs to be registered on the WeChat Open Platform. After registration, you will get the account number and password. (The email address provided during registration has not been registered for public accounts and mini programs before)
A WeChat open platform account can create multiple third-party platforms. After creation, the appId and appSecret of the third-party platform will be obtained. That is, componentAppId and componentAppSecret used in the code. (There is an upper limit on the number of third-party platforms, the upper limit of customized development service provider types is 5 , and the upper limit of platform service provider types is 5 )
toolkit . on ( EVENT_COMPONENT_VERIFY_TICKET , function ( result ) {
/* {
AppId: "wx304925fbea25bcbe",
CreateTime: "1562424829"
InfoType: "component_verify_ticket",
ComponentVerifyTicket: 'ticket@@@lEHjsBEi_TPDey0IZxw4Zbb7JRYLOtEf9ksvDpSwzkwog3R6xEpdaK0yIee7JOyOXM0V7cp0dpM58GKmb8FSKA'
} */
} )
The WeChat server will push every 10 minutes, which will cause the service to be unavailable for 1 to 10 minutes after each process restart (because all other functions depend on component_verify_ticket). The solution is to store the last push data, and Each time it is started, the same event is actively triggered. Examples are as follows:
// !在所有侦听事件绑定完成后,再触发事件
// 从数据库(或其他地方)读取上次缓存的数据,通过事件通知给组件
toolkit . emit ( EVENT_COMPONENT_VERIFY_TICKET , {
AppId : "wx52ffab2939ad" ,
CreateTime : "142345003"
InfoType : "component_verify_ticket" ,
ComponentVerifyTicket : 'ticket@@@lEHjsBEi_TPDey0IZxw4Zbb7JRYLOtEf9ksvDpSwzkwog3R6xEpdaK0yIee7JOyOXM0V7cp0dpM58GKmb8FSKA'
} )
toolkit . on ( EVENT_COMPONENT_ACCESS_TOKEN , function ( result ) {
/* {
component_access_token: 'M5CvflZyL5fkV29gU6MhQIoNsvzPEGBjYgmgA7yxnI_l8sblqm0QUULiMHoWY3gXPOnenZs3-42x_EenE1DEAg2F1K3X_fOI44h_eqxrV_7b0K7yc3pEGf_qTZl8HOlyCTSiAHAVML',
expires_in: 7200,
componentAppId: 'componentAppId'
} */
} )
toolkit . on ( EVENT_AUTHORIZER_ACCESS_TOKEN , function ( result ) {
/**
{
AppId: 'wx304925fbea25bcbe',
authorizer_appid: 'wxc736b9251b3c6c41',
authorizer_access_token: 'j7mR_dvcCAmUq5Iw-MuzE4sBT0unN-ukg7LR8EqZEQ1wZ7oyw0rs1Idk40d7uxriOubE3795JiFa3e5jDGdofRpTemXd2HLLV6p_i_Uwy7m2Rp-qv1k1ld-T9iCCDcVeQONdALDFDC',
authorizer_refresh_token: 'refreshtoken@@@6Esz0GgFsth_vRPtqjQd_aIQcCBcJ4iuzQFf3akLwgg',
expires_in: 7200
}
*/
} )
toolkit . on ( EVENT_AUTHORIZER_JSAPI_TICKET , function ( result ) {
/* {
errcode: 0,
errmsg: 'ok',
ticket: 'Zqqmael1_O_ddyFwCE14BtflzySMrtVpp086SHhK3P07xXnhjii2MTmKAGQHBwPOg8GsEtR9HG_dHUngs22ayQ',
expires_in: 7200,
componentAppId: 'wx304925fbea25bcbe',
authorizerAppId: 'wxc736b9251b3c6c41'
} */
} )
toolkit . on ( EVENT_AUTHORIZED , function ( result ) {
/* {
AppId: 'wx304925fbea25bcbe',
CreateTime: '1562428385',
InfoType: 'authorized',
AuthorizerAppid: 'wxc736b9251b3c6c41',
AuthorizationCode: 'queryauthcode@@@SozCwT_ve8WQI6Poum-qdGrrBrnQoX2rApglrUIMF0e308IQY7w_tCfAkndxzUth_YwHDto8DUsIeNrX4atetA',
AuthorizationCodeExpiredTime: '1562431985',
PreAuthCode: 'preauthcode@@@c4Uh5vOCS3wu9Bbx4tJWxplzkn5swwVHQc9xGtF57C1lfk_UeW50INZsh2flrwxh'
} */
} )
toolkit . on ( EVENT_UPDATE_AUTHORIZED , function ( result ) {
/* {
AppId: 'wx304925fbea25bcbe',
CreateTime: '1562426956',
InfoType: 'updateauthorized',
AuthorizerAppid: 'wxc736b9251b3c6c41',
AuthorizationCode: 'queryauthcode@@@SozCwT_ve8WQI6Poum-qdG_rFKaepJCyhL-zx1OkvsxmmJkbZadF78t3U9lh20IaWFqb2DcLne7MGVICr5eRfQ',
AuthorizationCodeExpiredTime: '1562430556',
PreAuthCode: 'preauthcode@@@ivkKNYhiXXsDFLBmH2ccOCg6doXsD_RdQOS7Cxw5GoILrdQktfx_glIzmhWQrMyT'
} */
} )
toolkit . on ( EVENT_UNAUTHORIZED , function ( result ) {
/* {
AppId: 'wx304925fbea25bcbe',
CreateTime: '1562428154',
InfoType: 'unauthorized',
AuthorizerAppid: 'wxc736b9251b3c6c41'
} */
} )
toolkit . on ( 'error' , function ( err ) {
console . error ( err )
} )
auth(componentAppId, redirectUrl [, authType]) returns the third-party platform authorization middleware
events() returns the third-party platform authorization event processing middleware
message(componentAppId) returns the authorizing party message processing middleware
autoTest(componentAppId) returns the middleware for publishing test cases across the entire network
oauth(componentAppId, authorizerAppId, redirectUrl [, scope [, state]]) returns the authorizer web page authorization middleware
getAuthorizerInfo(componentAppId, componentAccessToken, authorizerAppId) obtains the authorizer’s basic account information
clearQuota(componentAppId, componentAccessToken) The third-party platform clears all API calls to zero
getJsApiConfig(authorizerAppId, authorizerJsApiTicket, url) gets the authorizer js sdk configuration
getOauthAccessToken(componentAppId, componentAccessToken, authorizerAppId, code) obtains the authorizer's webpage authorization access token
getUserInfo(authorizerAccessToken, openId) obtains the basic information of the authorizer WeChat user
send(authorizerAccessToken, openId, type, content) Send customer service message
getAuthorizerOptionInfo(componentAppId, componentAccessToken, authorizerAppId, optionName) gets the authorizer’s option setting information
setAuthorizerOption(componentAppId, componentAccessToken, authorizerAppId, optionName, optionValue) sets the authorizer option information
createOpenAccount(authorizerAppId, authorizerAccessToken) creates an open platform account and binds the official account/mini program
bindOpenAccount(openAppId, authorizerAppId, authorizerAccessToken) binds the official account/mini program to the open platform account
unbindOpenAccount(openAppId, authorizerAppId, authorizerAccessToken) unbinds the official account/mini program from the open platform account
getOpenAccount(authorizerAppId, authorizerAccessToken) Gets the open platform account bound to the official account/mini program
Returns the third-party platform authorization middleware.
The domain name of the redirectUrl link must be the same as the domain name of the current service and the domain name configured by the WeChat third-party platform.
authType specifies the optional options displayed during authorization. 1 means only display official accounts, 2 means only display mini programs, and 3 means display official accounts and mini programs. Default is 3 . You can also pass in the authorizer APPID to specify the authorizer.
pageStyle specifies the style of the authorization page. 1 means PC scan code for authorization; 2 means WeChat browser is opened. The default value is 1 .
const { AUTH_TYPE_BOTH , PAGE_STYLE_PC } = require ( 'wechat-open-toolkit' )
let componentAppId = 'wx52ffab2939ad'
let redirectUrl = 'https://domain.com/authorized'
let authMiddleware = toolkit . auth ( componentAppId , redirectUrl , AUTH_TYPE_BOTH , PAGE_STYLE_PC )
// 浏览器打开该路由即可扫码授权
app . get ( `/wechat/auth/ ${ componentAppId } ` , authMiddleware )
Returns the third-party platform authorization event processing middleware.
app . use ( '/wechat/events' , toolkit . events ( ) )
Returns the authorizing party message processing middleware
const componentAppId = 'wx52ffab2939ad'
let msgMiddleware = toolkit . message ( componentAppId ) // 用户消息中间件
app . post ( `/wechat/message/ ${ componentAppId } /:authorizerAppId` , msgMiddleware , ( req , res ) => {
console . log ( req . wechat )
/**
{
ToUserName: 'gh_2a33e5f5a9b0',
FromUserName: 'oVtjJv5NEub-fbE7E6_P2_jCLMXo',
CreateTime: '1508406464',
MsgType: 'text',
Content: 'hello world',
MsgId: '6478556432393017916'
}
*/
} )
When the third-party platform receives a message from the authorized party user, it can use the passive reply function to reply to the message.
let componentAppId = 'wx52ffab2939ad' // 第三方平台APPID
let msgMiddleware = toolkit . message ( componentAppId ) // 用户消息中间件
app . post ( `/wechat/message/ ${ componentAppId } /:authorizerAppId` , msgMiddleware , ( req , res ) => {
let { MsgType , Content , MediaId , Label , Title , Description , Url } = req . wechat
switch ( MsgType ) {
case 'text' :
res . text ( Content ) // 被动回复文本消息
break ;
case 'image' :
res . image ( MediaId ) // 被动回复图片消息
break ;
case 'voice' :
res . voice ( MediaId ) // 被动回复语音消息
break ;
case 'video' :
res . video ( MediaId ) // 被动回复视频消息
break ;
case 'location' :
res . text ( Label )
break ;
case 'link' :
res . news ( [ { Title , Description , Url } ] )
}
} )
Returns the middleware for publishing test cases across the entire network. This middleware needs to be placed behind the message middleware and before other middleware.
let componentAppId = 'wx52ffab2939ad'
let msgMiddleware = toolkit . message ( componentAppId ) // 用户消息中间件
let testMiddleware = toolkit . autoTest ( componentAppId ) // 全网发布测试中间件
app . post ( `/wechat/message/ ${ componentAppId } /:authorizerAppId` , msgMiddleware , testMiddleware , ( req , res ) => {
res . end ( 'success' ) // 响应微信服务器
console . log ( req . wechat )
} )
Return to the third-party platform agent WeChat official account web page authorization middleware.
scope is the authorization scope. Possible values are: snsapi_base and snsapi_userinfo. Default: snsapi_base
const { OAUTH_TYPE_USERINFO } = require ( 'wechat-open-toolkit' )
let componentAppId = 'wx304925fbea25bcbe'
let authorizerAppId = 'wxc736b9251b3c6c41'
let redirectUrl = 'https://domain.com/authorized'
let oauthMiddleware = toolkit . oauth ( componentAppId , authorizerAppId , redirectUrl , OAUTH_TYPE_USERINFO )
app . get ( `/wechat/oauth/ ${ componentAppId } / ${ authorizerAppId } ` , oauthMiddleware )
Obtain the basic account information of the authorized party
let ret = await WechatOpenToolkit . getAuthorizerInfo ( componentAppId , componentAccessToken , authorizerAppId )
Get the js sdk configuration object of the authorizer
let conf = WechatOpenToolkit . getJsApiConfig ( authorizerAppId , authorizerJsApiTicket , url )
/**
{
appId: '',
timestamp: 158923408,
nonceStr: '292jslk30dk',
signature: '20kjafj20dfhl2j0sjhk2h3f0afjasd2'
}
*/
Obtain the authorizer's webpage authorization access token
let ret = await WechatOpenToolkit . getOauthAccessToken ( componentAppId , componentAccessToken , authorizerAppId , code )
Obtain the basic information of the authorized WeChat user
let ret = await WechatOpenToolkit . getUserInfo ( authorizerAccessToken , openId )
Send customer service message
await WechatOpenToolkit . send ( authorizerAccessToken , openId , 'text' , { content : '消息内容' } ) // 发送文本消息
await WechatOpenToolkit . send ( authorizerAccessToken , openId , 'image' , { media_id : 'MEDIA_ID' } ) // 发送图片消息
await WechatOpenToolkit . send ( authorizerAccessToken , openId , 'voice' , { media_id : 'MEDIA_ID' } ) // 发送语音消息
await WechatOpenToolkit . send ( authorizerAccessToken , openId , 'video' , {
media_id : 'MEDIA_ID' ,
thumb_media_id : 'MEDIA_ID' ,
title : 'TITLE' ,
description : 'DESCRIPTION'
} ) // 发送视频消息
await WechatOpenToolkit . send ( authorizerAccessToken , openId , 'music' , {
title : 'TITLE' ,
description : 'DESCRIPTION' ,
musicurl : 'MUSIC_URL' ,
hqmusicurl : 'HQ_MUSIC_URL' ,
thumb_media_id : 'MEDIA_ID'
} ) // 发送音乐消息
await WechatOpenToolkit . send ( authorizerAccessToken , openId , 'news' , {
articles : [ {
title : 'TITLE' ,
description : 'DESCRIPTION' ,
url : 'URL' ,
picurl : 'PIC_URL'
} ]
} ) // 发送图文消息
await WechatOpenToolkit . send ( authorizerAccessToken , openId , 'mpnews' , { media_id : 'MEDIA_ID' } ) // 发送图文消息
This API is used to obtain the option setting information of the authorized party's official account or mini program, such as: geographical location reporting, voice recognition switch, and multi-customer service switch.
let ret = await WechatOpenToolkit . getAuthorizerOptionInfo ( componentAppId , componentAccessToken , authorizerAppId , optionName )
Set authorizer options
This API is used to set the option information of the authorized party's official account or mini program, such as: geographical location reporting, voice recognition switch, and multi-customer service switch.
await WechatOpenToolkit . setAuthorizerOption ( componentAppId , componentAccessToken , authorizerAppId , optionName , optionValue )
The third-party platform clears all API call times
await WechatOpenToolkit . clearQuota ( componentAppId , componentAccessToken )
Create an open platform account and bind official account/mini program
let ret = await WechatOpenToolkit . createOpenAccount ( authorizerAppId , authorizerAccessToken )
Bind the official account/mini program to the open platform account
await WechatOpenToolkit . bindOpenAccount ( openAppId , authorizerAppId , authorizerAccessToken )
Unbind the official account/mini program from the open platform account
await WechatOpenToolkit . unbindOpenAccount ( openAppId , authorizerAppId , authorizerAccessToken )
Obtain the open platform account bound to the official account/mini program
let ret = await WechatOpenToolkit . getOpenAccount ( authorizerAppId , authorizerAccessToken )