{"id":42759730,"url":"https://github.com/pengng/wechat-open-toolkit","last_synced_at":"2026-01-29T20:31:35.006Z","repository":{"id":65472287,"uuid":"107247610","full_name":"pengng/wechat-open-toolkit","owner":"pengng","description":"微信开放平台工具套件。方便搭建基础的 Node.js 微信第三方服务平台。","archived":false,"fork":false,"pushed_at":"2023-04-10T20:56:07.000Z","size":164,"stargazers_count":46,"open_issues_count":2,"forks_count":9,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-09-20T02:39:24.028Z","etag":null,"topics":["access","oauth","open","ticket","token","verify","wechat"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pengng.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-10-17T09:35:13.000Z","updated_at":"2025-04-29T15:20:19.000Z","dependencies_parsed_at":"2023-01-25T01:45:22.693Z","dependency_job_id":null,"html_url":"https://github.com/pengng/wechat-open-toolkit","commit_stats":null,"previous_names":[],"tags_count":16,"template":false,"template_full_name":null,"purl":"pkg:github/pengng/wechat-open-toolkit","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pengng%2Fwechat-open-toolkit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pengng%2Fwechat-open-toolkit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pengng%2Fwechat-open-toolkit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pengng%2Fwechat-open-toolkit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pengng","download_url":"https://codeload.github.com/pengng/wechat-open-toolkit/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pengng%2Fwechat-open-toolkit/sbom","scorecard":{"id":727097,"data":{"date":"2025-08-11","repo":{"name":"github.com/pengng/wechat-open-toolkit","commit":"0f664c2395b23729a75c574b5b1462c3d38a4742"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":2.5,"checks":[{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Code-Review","score":0,"reason":"Found 0/30 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":0,"reason":"license file not detected","details":["Warn: project does not have a license file"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Vulnerabilities","score":9,"reason":"1 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-776f-qx25-q3cc"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-22T13:08:47.386Z","repository_id":65472287,"created_at":"2025-08-22T13:08:47.386Z","updated_at":"2025-08-22T13:08:47.386Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28884291,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-29T19:55:09.949Z","status":"ssl_error","status_checked_at":"2026-01-29T19:55:08.490Z","response_time":59,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["access","oauth","open","ticket","token","verify","wechat"],"created_at":"2026-01-29T20:31:34.185Z","updated_at":"2026-01-29T20:31:34.997Z","avatar_url":"https://github.com/pengng.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# wechat-open-toolkit 微信开放平台工具套件\n\n**方便搭建基础的 Node.js 微信第三方服务平台。**\n\n### 示例代码\n\n```shell\nnpm install wechat-open-toolkit\n```\n\n```javascript\nconst express = require('express')\nconst app = express()\nconst WechatOpenToolkit = require('wechat-open-toolkit')\nconst {\n    EVENT_COMPONENT_VERIFY_TICKET, EVENT_AUTHORIZED, EVENT_UPDATE_AUTHORIZED,\n    EVENT_UNAUTHORIZED, EVENT_COMPONENT_ACCESS_TOKEN, EVENT_AUTHORIZER_ACCESS_TOKEN, \n    EVENT_AUTHORIZER_JSAPI_TICKET\n} = WechatOpenToolkit\n\n// 微信第三方平台列表\nlet list = [\n    {\n        componentAppId: '', // 微信第三方平台 appId\n        componentAppSecret: '', // 微信第三方平台 appSecret\n        token: '', // 消息校验 Token\n        encodingAESKey: '' // 消息加解密 key\n    }\n]\n\nlet toolkit = new WechatOpenToolkit({ list })\n\n// 绑定全部事件\ntoolkit.on(EVENT_COMPONENT_VERIFY_TICKET, ret =\u003e {\n    console.log(ret)\n})\ntoolkit.on(EVENT_AUTHORIZED, ret =\u003e {\n    console.log(ret)\n})\ntoolkit.on(EVENT_UPDATE_AUTHORIZED, ret =\u003e {\n    console.log(ret)\n})\ntoolkit.on(EVENT_UNAUTHORIZED, ret =\u003e {\n    console.log(ret)\n})\ntoolkit.on(EVENT_COMPONENT_ACCESS_TOKEN, ret =\u003e {\n    console.log(ret)\n})\ntoolkit.on(EVENT_AUTHORIZER_ACCESS_TOKEN, ret =\u003e {\n    console.log(ret)\n})\ntoolkit.on(EVENT_AUTHORIZER_JSAPI_TICKET, ret =\u003e {\n    console.log(ret)\n})\ntoolkit.on('error', err =\u003e {\n    console.error(err)\n})\n\n// 通常需要绑定5个中间件\napp.use('/wechat/events', toolkit.events()) // 第三方平台事件接收中间件\n\nlist.forEach(({ componentAppId }) =\u003e {\n\n    let authMiddleware = toolkit.auth(componentAppId, 'https://domain.com/') // 第三方平台网页授权中间件\n    let msgMiddleware = toolkit.message(componentAppId) // 授权方用户消息接收中间件\n    let autoTestMiddleware = toolkit.autoTest(componentAppId) // 第三方平台全网发布测试中间件\n\n    app.get(`/wechat/auth/${componentAppId}`, authMiddleware)\n  \n    app.post(`/wechat/message/${componentAppId}/:authorizerAppId`, msgMiddleware, autoTestMiddleware, (req, res) =\u003e {\n        res.end('success')\n        console.log(req.wechat)\n    })\n\n    app.get(`/wechat/oauth/${componentAppId}/:authorizerAppId`, (req, res) =\u003e {\n        let { authorizerAppId } = req.params\n        let oauthMiddleware = toolkit.oauth(componentAppId, authorizerAppId, 'https://domain.com/') // 授权方网页授权中间件\n        oauthMiddleware(req, res)\n    })\n})\n\napp.listen(3000)\nconsole.log('server start at 3000')\n```\n\n\n### 接入 co-wechat-api 和 wechat-api 示例代码\n\n```javascript\nconst CoWechatApi = require('co-wechat-api')\nconst WechatApi = require('wechat-api')\n\nlet store = {} // 缓存数据\n\nlet componentAppId = 'test app id'\nlet authorizerAppId = 'test app id'\n\nlet api = new WechatApi('', '', callback =\u003e {\n    // 每次调用 api.方法()，都会从 store 对象取 access token\n    callback(null, {\n        accessToken: store[`${componentAppId}/${authorizerAppId}`],\n        expireTime: Date.now() + 1000 * 60\n    }\n})\n\nlet coApi = new CoWechatApi('', '', async () =\u003e {\n    // 每次调用 api.方法()，都会从 store 对象取 access token\n    return {\n        accessToken: store[`${componentAppId}/${authorizerAppId}`],\n        expireTime: Date.now() + 1000 * 60\n    }\n})\n\n// 每次授权方 access token 更新时，同步更新缓存数据\ntoolkit.on(EVENT_AUTHORIZER_ACCESS_TOKEN, function (ret) {\n    let { AppId, authorizer_appid, authorizer_access_token } = ret\n    store[`${AppID}/${authorizer_appid}`] = authorizer_access_token // 更新\n})\n\n// 该功能需等到 access token 首次更新后，才能调用\napi.sendText()\nawait coApi.sendText()\n///\n```\n\n**示例代码仅供参考，根据实际情况调整。**\n\n### 微信第三方平台要求配置2个URL，分别推送第三方平台事件和公众号事件，列表整理如下：\n\n- **授权事件接收URL**\n  - **component_verity_ticket 当微信服务器推送 component_verity_ticket 时触发**\n  - **authorized 当有新的公众号授权给第三方平台时触发**\n  - **updateauthorized 当已授权公众号修改授权给第三方平台的权限时触发**\n  - **unauthorized 当已授权公众号取消授权时触发**\n- **公众号消息接收URL**\n  - **推送用户与公众号的消息**\n  - **用户点击底部菜单、关注、取消关注、扫码事件**\n\n### 微信开放平台 和 微信第三方平台\n\n微信开放平台账号需要在 [微信开放平台](https://open.weixin.qq.com/) 注册，注册后得到账号和密码。(注册时提供的邮箱之前未注册过公众号和小程序)\n\n一个微信开放平台账号可以创建多个第三方平台，创建后得到第三方平台的 **appId** 和 **appSecret**。也就是代码中使用的**componentAppId**、**componentAppSecret** 。(第三方平台的数量有上限，定制化开发服务商类型上限是**5个**、平台型服务商类型上限是**5个**)\n\n### 当收到微信推送的 component_verify_ticket 时触发 component_verify_ticket 事件\n\n```javascript\ntoolkit.on(EVENT_COMPONENT_VERIFY_TICKET, function (result) {\n/* {\n    AppId: \"wx304925fbea25bcbe\",\n    CreateTime: \"1562424829\"\n    InfoType: \"component_verify_ticket\",\n    ComponentVerifyTicket: 'ticket@@@lEHjsBEi_TPDey0IZxw4Zbb7JRYLOtEf9ksvDpSwzkwog3R6xEpdaK0yIee7JOyOXM0V7cp0dpM58GKmb8FSKA'\n} */\n})\n```\n\n\u003e **微信服务器会每隔10分钟推送1次，这会导致每次进程重新启动后，有1至10分钟服务不可用（因为其他功能全部依赖于 component_verify_ticket），解决方法是存储上一次的推送数据，并且每次启动时，主动触发一次相同事件。示例如下：**\n\n```javascript\n// ！在所有侦听事件绑定完成后，再触发事件\n// 从数据库（或其他地方）读取上次缓存的数据，通过事件通知给组件\ntoolkit.emit(EVENT_COMPONENT_VERIFY_TICKET, {\n    AppId: \"wx52ffab2939ad\",\n    CreateTime: \"142345003\"\n    InfoType: \"component_verify_ticket\",\n    ComponentVerifyTicket: 'ticket@@@lEHjsBEi_TPDey0IZxw4Zbb7JRYLOtEf9ksvDpSwzkwog3R6xEpdaK0yIee7JOyOXM0V7cp0dpM58GKmb8FSKA'\n})\n```\n\n### 当刷新第三方平台 access token 时触发 component_access_token 事件\n\n```javascript\ntoolkit.on(EVENT_COMPONENT_ACCESS_TOKEN, function (result) {\n/* {\n    component_access_token: 'M5CvflZyL5fkV29gU6MhQIoNsvzPEGBjYgmgA7yxnI_l8sblqm0QUULiMHoWY3gXPOnenZs3-42x_EenE1DEAg2F1K3X_fOI44h_eqxrV_7b0K7yc3pEGf_qTZl8HOlyCTSiAHAVML',\n    expires_in: 7200,\n    componentAppId: 'componentAppId'\n} */\n})\n```\n\n### 当刷新授权方 access token 时触发 authorizer_access_token 事件\n\n```javascript\ntoolkit.on(EVENT_AUTHORIZER_ACCESS_TOKEN, function (result) {\n/**\n{\n    AppId: 'wx304925fbea25bcbe',\n    authorizer_appid: 'wxc736b9251b3c6c41',\n    authorizer_access_token: 'j7mR_dvcCAmUq5Iw-MuzE4sBT0unN-ukg7LR8EqZEQ1wZ7oyw0rs1Idk40d7uxriOubE3795JiFa3e5jDGdofRpTemXd2HLLV6p_i_Uwy7m2Rp-qv1k1ld-T9iCCDcVeQONdALDFDC',\n    authorizer_refresh_token: 'refreshtoken@@@6Esz0GgFsth_vRPtqjQd_aIQcCBcJ4iuzQFf3akLwgg',\n    expires_in: 7200\n}\n*/\n})\n```\n\n### 当刷新授权方 jsapi_ticket 时触发 authorizer_jsapi_ticket 事件\n\n```javascript\ntoolkit.on(EVENT_AUTHORIZER_JSAPI_TICKET, function (result) {\n/* {\n    errcode: 0,\n    errmsg: 'ok',\n    ticket: 'Zqqmael1_O_ddyFwCE14BtflzySMrtVpp086SHhK3P07xXnhjii2MTmKAGQHBwPOg8GsEtR9HG_dHUngs22ayQ',\n    expires_in: 7200,\n    componentAppId: 'wx304925fbea25bcbe',\n    authorizerAppId: 'wxc736b9251b3c6c41'\n} */\n})\n```\n\n### 当新的公众号授权成功时触发 authorized 事件\n\n```javascript\ntoolkit.on(EVENT_AUTHORIZED, function (result) {\n/* {\n    AppId: 'wx304925fbea25bcbe',\n    CreateTime: '1562428385',\n    InfoType: 'authorized',\n    AuthorizerAppid: 'wxc736b9251b3c6c41',\n    AuthorizationCode: 'queryauthcode@@@SozCwT_ve8WQI6Poum-qdGrrBrnQoX2rApglrUIMF0e308IQY7w_tCfAkndxzUth_YwHDto8DUsIeNrX4atetA',\n    AuthorizationCodeExpiredTime: '1562431985',\n    PreAuthCode: 'preauthcode@@@c4Uh5vOCS3wu9Bbx4tJWxplzkn5swwVHQc9xGtF57C1lfk_UeW50INZsh2flrwxh'\n} */\n})\n```\n\n### 当已授权公众号更新权限时触发 updateauthorized 事件\n\n```javascript\ntoolkit.on(EVENT_UPDATE_AUTHORIZED, function (result) {\n/* {\n    AppId: 'wx304925fbea25bcbe',\n    CreateTime: '1562426956',\n    InfoType: 'updateauthorized',\n    AuthorizerAppid: 'wxc736b9251b3c6c41',\n    AuthorizationCode: 'queryauthcode@@@SozCwT_ve8WQI6Poum-qdG_rFKaepJCyhL-zx1OkvsxmmJkbZadF78t3U9lh20IaWFqb2DcLne7MGVICr5eRfQ',\n    AuthorizationCodeExpiredTime: '1562430556',\n    PreAuthCode: 'preauthcode@@@ivkKNYhiXXsDFLBmH2ccOCg6doXsD_RdQOS7Cxw5GoILrdQktfx_glIzmhWQrMyT'\n} */\n})\n```\n\n### 当已授权公众号取消授权时触发 unauthorized 事件\n\n```javascript\ntoolkit.on(EVENT_UNAUTHORIZED, function (result) {\n/* {\n    AppId: 'wx304925fbea25bcbe',\n    CreateTime: '1562428154',\n    InfoType: 'unauthorized',\n    AuthorizerAppid: 'wxc736b9251b3c6c41'\n} */\n})\n```\n\n### 当有错误时触发 error 事件\n\n```Javascript\ntoolkit.on('error', function (err) {\n    console.error(err)\n})\n```\n\n### 实例方法：\n\n- **auth(componentAppId, redirectUrl [, authType])** [返回第三方平台授权中间件](#auth)\n\n- **events()** [返回第三方平台授权事件处理中间件](#events)\n\n- **message(componentAppId)** [返回授权方消息处理中间件](#message)\n\n- **autoTest(componentAppId)** [返回全网发布测试用例的中间件](#autoTest)\n\n- **oauth(componentAppId, authorizerAppId, redirectUrl [, scope [, state]])** [返回授权方网页授权中间件](#oauth)\n\n### 类方法：\n\n- **getAuthorizerInfo(componentAppId, componentAccessToken, authorizerAppId)** [获取授权方的账号基本信息](#getauthorizerinfo)\n\n- **clearQuota(componentAppId, componentAccessToken)** [第三方平台对其所有API调用次数清零](#clearquota)\n\n- **getJsApiConfig(authorizerAppId, authorizerJsApiTicket, url)** [获取授权方 js sdk 配置](#getjsapiconfig)\n\n- **getOauthAccessToken(componentAppId, componentAccessToken, authorizerAppId, code)** [获取授权方网页授权 access token](#getoauthaccesstoken)\n\n- **getUserInfo(authorizerAccessToken, openId)** [获取授权方微信用户基本信息](#getuserinfo)\n\n- **send(authorizerAccessToken, openId, type, content)** [发送客服消息](#send)\n\n- **getAuthorizerOptionInfo(componentAppId, componentAccessToken, authorizerAppId, optionName)** [获取授权方的选项设置信息](#getauthorizeroptioninfo)\n\n- **setAuthorizerOption(componentAppId, componentAccessToken, authorizerAppId, optionName, optionValue)** [设置授权方选项信息](#setauthorizeroption)\n\n- **createOpenAccount(authorizerAppId, authorizerAccessToken)** [创建开放平台帐号并绑定公众号/小程序](#createopenaccount)\n\n- **bindOpenAccount(openAppId, authorizerAppId, authorizerAccessToken)** [将公众号/小程序绑定到开放平台帐号下](#bindopenaccount)\n\n- **unbindOpenAccount(openAppId, authorizerAppId, authorizerAccessToken)** [将公众号/小程序从开放平台帐号下解绑](#unbindopenaccount)\n\n- **getOpenAccount(authorizerAppId, authorizerAccessToken)** [获取公众号/小程序所绑定的开放平台帐号](#getopenaccount)\n\n### auth\n\n返回第三方平台授权中间件。\n\n- **componentAppId** \\\u003cstring\\\u003e 第三方平台APPID\n- **redirectUrl** \\\u003cstring\\\u003e 授权成功后重定向的URL\n- **authType** \\\u003cnumber|string\\\u003e 授权的类型\n- **pageStyle** \\\u003cnumber\\\u003e 页面样式\n\n**redirectUrl** 该链接的域名必须和当前服务的域名相同，而且和微信第三方平台配置的域名相同。\n\n**authType** 指定授权时显示的可选项。**1** 表示仅展示公众号、**2** 表示仅展示小程序、**3** 表示展示公众号和小程序。默认为 **3** 。也可以传入授权方 APPID，指定授权方。\n\n**pageStyle** 指定授权页面的样式。**1** 表示PC扫码授权；**2** 表示微信浏览器打开。默认值为 **1**。\n\n```javascript\nconst { AUTH_TYPE_BOTH, PAGE_STYLE_PC } = require('wechat-open-toolkit')\nlet componentAppId = 'wx52ffab2939ad'\nlet redirectUrl = 'https://domain.com/authorized'\nlet authMiddleware = toolkit.auth(componentAppId, redirectUrl, AUTH_TYPE_BOTH, PAGE_STYLE_PC)\n\n// 浏览器打开该路由即可扫码授权\napp.get(`/wechat/auth/${componentAppId}`, authMiddleware)\n```\n\n### events\n\n返回第三方平台授权事件处理中间件。\n\n```javascript\napp.use('/wechat/events', toolkit.events())\n```\n\n### message\n\n返回授权方消息处理中间件\n\n- **componentAppId** \\\u003cstring\\\u003e 第三方平台appId\n\n```javascript\nconst componentAppId = 'wx52ffab2939ad'\nlet msgMiddleware = toolkit.message(componentAppId) // 用户消息中间件\n\napp.post(`/wechat/message/${componentAppId}/:authorizerAppId`, msgMiddleware, (req, res) =\u003e {\n    console.log(req.wechat)\n    /**\n    {\n        ToUserName: 'gh_2a33e5f5a9b0',\n        FromUserName: 'oVtjJv5NEub-fbE7E6_P2_jCLMXo',\n        CreateTime: '1508406464',\n        MsgType: 'text',\n        Content: 'hello world',\n        MsgId: '6478556432393017916'\n    }\n    */\n})\n```\n\n### 被动回复消息功能\n\n当第三方平台收到授权方用户消息时，可以使用被动回复功能回复消息。\n\n- **res.text(content)** 回复文本消息\n- **res.image(mediaId)** 回复图片\n- **res.voice(mediaId)** 回复语音\n- **res.video(mediaId [, title [, description]])** 回复视频\n- **res.music(thumbMediaId [, HQMusicUrl [, musicUrl [, title [, description]]]])** 回复音乐\n- **res.news(articles)** 回复图文\n  - **Title** 标题\n  - **Description** 描述\n  - **Url** 跳转链接\n  - **PicUrl** 缩略图链接\n\n```javascript\nlet componentAppId = 'wx52ffab2939ad' // 第三方平台APPID\nlet msgMiddleware = toolkit.message(componentAppId) // 用户消息中间件\n\napp.post(`/wechat/message/${componentAppId}/:authorizerAppId`, msgMiddleware, (req, res) =\u003e {\n    let { MsgType, Content, MediaId, Label, Title, Description, Url} = req.wechat\n    switch (MsgType) {\n        case 'text':\n            res.text(Content) // 被动回复文本消息\n            break;\n        case 'image':\n            res.image(MediaId) // 被动回复图片消息\n            break;\n        case 'voice':\n            res.voice(MediaId) // 被动回复语音消息\n            break;\n        case 'video':\n            res.video(MediaId) // 被动回复视频消息\n            break;\n        case 'location':\n            res.text(Label)\n            break;\n        case 'link':\n            res.news([{ Title, Description, Url }])\n    }\n})\n```\n\n### autoTest\n\n返回全网发布测试用例的中间件。该中间件需要放置在 [message](#message) 中间件后面，以及其他中间件前面。\n\n- **componentAppId** \\\u003cstring\\\u003e 第三方平台APPID\n\n```javascript\nlet componentAppId = 'wx52ffab2939ad'\nlet msgMiddleware = toolkit.message(componentAppId) // 用户消息中间件\nlet testMiddleware = toolkit.autoTest(componentAppId) // 全网发布测试中间件\n\napp.post(`/wechat/message/${componentAppId}/:authorizerAppId`, msgMiddleware, testMiddleware, (req, res) =\u003e {\n    res.end('success') // 响应微信服务器\n    console.log(req.wechat)\n})\n```\n\n### oauth\n\n返回第三方平台代理微信公众号网页授权中间件。\n\n- **componentAppId** \\\u003cstring\\\u003e 第三方平台APPID\n- **authorizerAppId** \\\u003cstring\\\u003e 授权方APPID\n- **redirectUrl** \\\u003cstring\\\u003e 授权成功后的重定向URL\n- **scope** \\\u003cstring\\\u003e 网页授权的类型。可选\n- **state** \\\u003cstring\\\u003e 授权的附带值。可选\n\n**scope 为授权作用域。可能的值为：snsapi_base 和 snsapi_userinfo。默认为：snsapi_base**\n\n```javascript\nconst { OAUTH_TYPE_USERINFO } = require('wechat-open-toolkit')\nlet componentAppId = 'wx304925fbea25bcbe'\nlet authorizerAppId = 'wxc736b9251b3c6c41'\nlet redirectUrl = 'https://domain.com/authorized'\nlet oauthMiddleware = toolkit.oauth(componentAppId, authorizerAppId, redirectUrl, OAUTH_TYPE_USERINFO)\n\napp.get(`/wechat/oauth/${componentAppId}/${authorizerAppId}`, oauthMiddleware)\n```\n\n### getAuthorizerInfo\n\n获取授权方的账号基本信息\n\n```javascript\nlet ret = await WechatOpenToolkit.getAuthorizerInfo(componentAppId, componentAccessToken, authorizerAppId)\n```\n\n### getJsApiConfig\n\n获取授权方的 js sdk 配置对象\n\n- **authorizerAppId** \\\u003cstring\\\u003e 授权方APPID\n- **authorizerJsApiTicket** \\\u003cstring\\\u003e 授权方 JsApi Ticket\n- **url** \\\u003cstring\\\u003e 要配置的网页链接\n\n```javascript\nlet conf = WechatOpenToolkit.getJsApiConfig(authorizerAppId, authorizerJsApiTicket, url)\n/**\n{\n    appId: '',\n    timestamp: 158923408,\n    nonceStr: '292jslk30dk',\n    signature: '20kjafj20dfhl2j0sjhk2h3f0afjasd2'\n}\n*/\n```\n\n### getOauthAccessToken\n\n获取授权方的网页授权 access token\n\n- **componentAppId** \\\u003cstring\\\u003e 第三方平台APPID\n- **componentAccessToken** \\\u003cstring\\\u003e\n- **authorizerAppId** \\\u003cstring\\\u003e 授权方APPID\n- **code** \\\u003cstring\\\u003e 网页授权后得到的临时 code\n\n```javascript\nlet ret = await WechatOpenToolkit.getOauthAccessToken(componentAppId, componentAccessToken, authorizerAppId, code)\n```\n\n### getUserInfo\n\n获取授权方微信用户的基本信息\n\n- **authorizerAccessToken** \\\u003cstring\\\u003e 授权方网页授权得到的 access token\n- **openId** \\\u003cstring\\\u003e 授权方微信用户的openId\n\n```javascript\nlet ret = await WechatOpenToolkit.getUserInfo(authorizerAccessToken, openId)\n```\n\n### send\n\n发送客服消息\n\n- **authorizerAccessToken** \\\u003cstring\\\u003e 授权方 access token\n- **openId** \\\u003cstring\\\u003e 微信用户 openId\n- **type** \\\u003cstring\\\u003e 消息类型\n- **content** \\\u003cstring\\\u003e 消息主体\n\n```javascript\nawait WechatOpenToolkit.send(authorizerAccessToken, openId, 'text', { content: '消息内容' }) // 发送文本消息\nawait WechatOpenToolkit.send(authorizerAccessToken, openId, 'image', { media_id: 'MEDIA_ID' }) // 发送图片消息\nawait WechatOpenToolkit.send(authorizerAccessToken, openId, 'voice', { media_id: 'MEDIA_ID' }) // 发送语音消息\n\nawait WechatOpenToolkit.send(authorizerAccessToken, openId, 'video', {\n    media_id: 'MEDIA_ID',\n    thumb_media_id: 'MEDIA_ID',\n    title: 'TITLE',\n    description: 'DESCRIPTION'\n}) // 发送视频消息\n\nawait WechatOpenToolkit.send(authorizerAccessToken, openId, 'music', {\n    title: 'TITLE',\n    description: 'DESCRIPTION',\n    musicurl: 'MUSIC_URL',\n    hqmusicurl: 'HQ_MUSIC_URL',\n    thumb_media_id: 'MEDIA_ID'\n}) // 发送音乐消息\n\nawait WechatOpenToolkit.send(authorizerAccessToken, openId, 'news', {\n    articles: [{\n        title: 'TITLE',\n        description: 'DESCRIPTION',\n        url: 'URL',\n        picurl: 'PIC_URL'\n    }]\n}) // 发送图文消息\n\nawait WechatOpenToolkit.send(authorizerAccessToken, openId, 'mpnews', { media_id: 'MEDIA_ID' }) // 发送图文消息\n```\n\n### getAuthorizerOptionInfo\n\n该API用于获取授权方的公众号或小程序的选项设置信息，如：地理位置上报，语音识别开关，多客服开关。\n\n- **componentAppId**\n- **componentAccessToken**\n- **authorizerAppId**\n- **optionName**\n\n```javascript\nlet ret = await WechatOpenToolkit.getAuthorizerOptionInfo(componentAppId, componentAccessToken, authorizerAppId, optionName)\n```\n\n### setAuthorizerOption\n\n设置授权方选项\n\n- **componentAppId** \\\u003cstring\\\u003e 第三方平台APPID\n- **componentAccessToken** \\\u003cstring\\\u003e\n- **authorizerAppId** \\\u003cstring\\\u003e 授权方平台APPID\n- **optionName** \\\u003cstring\\\u003e\n- **optionValue** \\\u003cnumber\\\u003e\n\n**该API用于设置授权方的公众号或小程序的选项信息，如：地理位置上报，语音识别开关，多客服开关。**\n\n```javascript\nawait WechatOpenToolkit.setAuthorizerOption(componentAppId, componentAccessToken, authorizerAppId, optionName, optionValue)\n```\n\n### clearQuota\n\n第三方平台对其所有API调用次数清零\n\n- **componentAppId** \\\u003cstring\\\u003e 第三方平台APPID\n- **componentAccessToken** \\\u003cstring\\\u003e\n\n```javascript\nawait WechatOpenToolkit.clearQuota(componentAppId, componentAccessToken)\n```\n\n### createOpenAccount\n\n创建开放平台帐号并绑定公众号/小程序\n\n- **authorizerAppId** \\\u003cstring\\\u003e 授权方APPID\n- **authorizerAccessToken** \\\u003cstring\\\u003e\n\n```javascript\nlet ret = await WechatOpenToolkit.createOpenAccount(authorizerAppId, authorizerAccessToken)\n```\n\n### bindOpenAccount\n\n将公众号/小程序绑定到开放平台帐号下\n\n- **openAppId** \\\u003cstring\\\u003e\n- **authorizerAppId** \\\u003cstring\\\u003e\n- **authorizerAccessToken** \\\u003cstring\\\u003e\n\n```javascript\nawait WechatOpenToolkit.bindOpenAccount(openAppId, authorizerAppId, authorizerAccessToken)\n```\n\n### unbindOpenAccount\n\n将公众号/小程序从开放平台帐号下解绑\n\n- **openAppId** \\\u003cstring\\\u003e\n- **authorizerAppId** \\\u003cstring\\\u003e\n- **authorizerAccessToken** \\\u003cstring\\\u003e\n\n```javascript\nawait WechatOpenToolkit.unbindOpenAccount(openAppId, authorizerAppId, authorizerAccessToken)\n```\n\n### getOpenAccount\n\n获取公众号/小程序所绑定的开放平台帐号\n\n- **authorizerAppId** \\\u003cstring\\\u003e\n- **authorizerAccessToken** \\\u003cstring\\\u003e\n\n```javascript\nlet ret = await WechatOpenToolkit.getOpenAccount(authorizerAppId, authorizerAccessToken)\n```\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpengng%2Fwechat-open-toolkit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpengng%2Fwechat-open-toolkit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpengng%2Fwechat-open-toolkit/lists"}