方便建置基礎的Node.js 微信第三方服務平台。
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 ( )
///
範例程式碼僅供參考,依實際情況調整。
微信開放平台帳號需在微信開放平台註冊,註冊後取得帳號及密碼。 (註冊時提供的郵箱之前未註冊過公眾號碼和小程式)
一個微信開放平台帳號可以創建多個第三方平台,創建後得到第三方平台的appId和appSecret 。也就是程式碼中使用的componentAppId 、 componentAppSecret 。 (第三方平台的數量有上限,客製化開發服務商類型上限是5個、平台型服務商類型上限是5個)
toolkit . on ( EVENT_COMPONENT_VERIFY_TICKET , function ( result ) {
/* {
AppId: "wx304925fbea25bcbe",
CreateTime: "1562424829"
InfoType: "component_verify_ticket",
ComponentVerifyTicket: 'ticket@@@lEHjsBEi_TPDey0IZxw4Zbb7JRYLOtEf9ksvDpSwzkwog3R6xEpdaK0yIee7JOyOXM0V7cp0dpM58GKmb8FSKA'
} */
} )
微信伺服器會每隔10分鐘推送1次,這會導致每次進程重新啟動後,有1至10分鐘服務不可用(因為其他功能全部依賴於component_verify_ticket),解決方法是儲存上一次的推送數據,並且每次啟動時,主動觸發一次相同事件。範例如下:
// !在所有侦听事件绑定完成后,再触发事件
// 从数据库(或其他地方)读取上次缓存的数据,通过事件通知给组件
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])傳回第三方平台授權中介軟體
events()傳回第三方平台授權事件處理中介軟體
message(componentAppId)傳回授權方訊息處理中介軟體
autoTest(componentAppId)傳回全網發布測試案例的中間件
oauth(componentAppId, authorizerAppId, redirectUrl [, scope [, state]])傳回授權方網頁授權中介軟體
getAuthorizerInfo(componentAppId, componentAccessToken, authorizerAppId)取得授權方的帳號基本信息
clearQuota(componentAppId, componentAccessToken)第三方平台對其所有API呼叫次數清零
getJsApiConfig(authorizerAppId, authorizerJsApiTicket, url)取得授權方js sdk 配置
getOauthAccessToken(componentAppId, componentAccessToken, authorizerAppId, code)取得授權方網頁授權access token
getUserInfo(authorizerAccessToken, openId)取得授權方微信使用者基本信息
send(authorizerAccessToken, openId, type, content)發送客服訊息
getAuthorizerOptionInfo(componentAppId, componentAccessToken, authorizerAppId, optionName)取得授權方的選項設定信息
setAuthorizerOption(componentAppId, componentAccessToken, authorizerAppId, optionName, optionValue)設定授權方選項信息
createOpenAccount(authorizerAppId, authorizerAccessToken)建立開放平台帳號並綁定公眾號碼/小程序
bindOpenAccount(openAppId, authorizerAppId, authorizerAccessToken)將公眾號/小程式綁定到開放平台帳號下
unbindOpenAccount(openAppId, authorizerAppId, authorizerAccessToken)將公眾號/小程式從開放平台帳號下解綁
getOpenAccount(authorizerAppId, authorizerAccessToken)取得公眾號/小程式所綁定的開放平台帳號
返回第三方平台授權中間件。
redirectUrl該連結的網域必須和目前服務的網域相同,而且和微信第三方平台配置的網域相同。
authType指定授權時顯示的可選項。 1表示僅展示公眾號、 2表示僅展示小程式、 3表示展示公眾號和小程式。預設為3 。也可以傳入授權方APPID,指定授權方。
pageStyle指定授權頁面的樣式。 1表示PC掃碼授權; 2表示微信瀏覽器開啟。預設值為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 )
返回第三方平台授權事件處理中介軟體。
app . use ( '/wechat/events' , toolkit . events ( ) )
返回授權方訊息處理中介軟體
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'
}
*/
} )
當第三方平台收到授權方使用者訊息時,可以使用被動回覆功能回覆訊息。
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 } ] )
}
} )
傳回全網發布測試案例的中間件。此中間件需要放置在message 中間件後面,以及其他中間件前面。
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 )
} )
返回第三方平台代理微信公眾號網頁授權中間件。
scope 為授權作用域。可能的值為:snsapi_base 和snsapi_userinfo。預設為: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 )
取得授權方的帳號基本信息
let ret = await WechatOpenToolkit . getAuthorizerInfo ( componentAppId , componentAccessToken , authorizerAppId )
取得授權方的js sdk 配置對象
let conf = WechatOpenToolkit . getJsApiConfig ( authorizerAppId , authorizerJsApiTicket , url )
/**
{
appId: '',
timestamp: 158923408,
nonceStr: '292jslk30dk',
signature: '20kjafj20dfhl2j0sjhk2h3f0afjasd2'
}
*/
取得授權方的網頁授權access token
let ret = await WechatOpenToolkit . getOauthAccessToken ( componentAppId , componentAccessToken , authorizerAppId , code )
取得授權方微信使用者的基本訊息
let ret = await WechatOpenToolkit . getUserInfo ( authorizerAccessToken , openId )
發送客服訊息
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' } ) // 发送图文消息
此API用於取得授權方的公眾號或小程式的選項設定訊息,如:地理位置上報,語音辨識開關,多客服開關。
let ret = await WechatOpenToolkit . getAuthorizerOptionInfo ( componentAppId , componentAccessToken , authorizerAppId , optionName )
設定授權方選項
此API用於設定授權方的公眾號或小程式的選項訊息,如:地理位置上報,語音辨識開關,多客服開關。
await WechatOpenToolkit . setAuthorizerOption ( componentAppId , componentAccessToken , authorizerAppId , optionName , optionValue )
第三方平台對其所有API呼叫次數清零
await WechatOpenToolkit . clearQuota ( componentAppId , componentAccessToken )
建立開放平台帳號並綁定公眾號/小程序
let ret = await WechatOpenToolkit . createOpenAccount ( authorizerAppId , authorizerAccessToken )
將公眾號/小程式綁定到開放平台帳號下
await WechatOpenToolkit . bindOpenAccount ( openAppId , authorizerAppId , authorizerAccessToken )
將公眾號/小程式從開放平台帳號下解綁
await WechatOpenToolkit . unbindOpenAccount ( openAppId , authorizerAppId , authorizerAccessToken )
取得公眾號/小程式所綁定的開放平台帳號
let ret = await WechatOpenToolkit . getOpenAccount ( authorizerAppId , authorizerAccessToken )