├── .editorconfig ├── .eslintignore ├── .eslintrc.js ├── .gitignore ├── .vscode └── settings.json ├── CHANGELOG.md ├── README.md ├── define.js ├── demo.js ├── docs └── index.md ├── helper.js ├── index.js ├── log4js.json ├── package.json └── scripts └── docVer.js /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 2 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | test 2 | coverage 3 | node_modules 4 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env : { 4 | node: true, 5 | es6 : true 6 | }, 7 | extends: ['eslint-config-egg'], 8 | globals: { 9 | 'document': true 10 | }, 11 | rules: { 12 | 'semi': 0, 13 | // 数组和对象键值对最后一个逗号, never参数:不能带末尾的逗号, always参数:必须带末尾的逗号, 14 | // always-multiline:多行模式必须带逗号,单行模式不能带逗号 15 | 'comma-dangle': [1, 'always-multiline'], 16 | // 指定数组的元素之间要以空格隔开(, 后面), never参数:[ 之前和 ] 之后不能带空格,always参数:[ 之前和 ] 之后必须带空格 17 | 'array-bracket-spacing': [2, 'never'], 18 | 'no-unused-vars' : 'off', // 未使用变量 19 | // "generator-star-spacing": ["error", { "before": false, "after": true }], 20 | 'valid-jsdoc': ['error', { 21 | // 取消限制注释中必须使用 @return 标签替代 @returns标签 22 | prefer: { 23 | // returns: 'return', 24 | }, 25 | }], 26 | "no-multi-spaces": ["error", { 27 | exceptions: { 28 | "ImportDeclaration" : true, 29 | "VariableDeclarator": true, 30 | "Property" : false, 31 | "ignoreEOLComments" : true 32 | } 33 | }], 34 | //对象字面量中冒号的前后空格 35 | "key-spacing": ["error", { 36 | "beforeColon": true, 37 | "afterColon" : true 38 | }] 39 | }, 40 | 41 | } 42 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | logs/ 2 | npm-debug.log 3 | yarn-error.log 4 | node_modules/ 5 | package-lock.json 6 | yarn.lock 7 | coverage/ 8 | .idea/ 9 | run/ 10 | .DS_Store 11 | *.sw* 12 | *.un~ 13 | *config*.json 14 | qrcode.jpg 15 | exe/ 16 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | // 代码风格自动修正 3 | "eslint.autoFixOnSave": true, 4 | // Turns auto fix on save on or off. 5 | "tslint.autoFixOnSave": true, 6 | // 文件保存时自动格式化 7 | "editor.formatOnSave": true, 8 | //Better Align扩展配置 9 | "alignment.beforeSave": true, 10 | "alignment.exclude": [ 11 | "json" 12 | ], 13 | "alignment.include": [ 14 | "js", 15 | "ts", 16 | "vue", 17 | "css", 18 | "scss" 19 | ], 20 | "alignment.surroundSpace": { 21 | "colon": [ 22 | 0, 23 | 1 24 | ], 25 | "assignment": [ 26 | 1, 27 | 1 28 | ], 29 | "arrow": [ 30 | 1, 31 | 1 32 | ], 33 | "comment": 0 34 | }, 35 | "eslint.options": { 36 | "rules": { 37 | "semi": 0, 38 | // 数组和对象键值对最后一个逗号, never参数:不能带末尾的逗号, always参数:必须带末尾的逗号, 39 | // always-multiline:多行模式必须带逗号,单行模式不能带逗号 40 | "comma-dangle": [ 41 | 1, 42 | "always-multiline" 43 | ], 44 | // 指定数组的元素之间要以空格隔开(, 后面), never参数:[ 之前和 ] 之后不能带空格,always参数:[ 之前和 ] 之后必须带空格 45 | "array-bracket-spacing": [ 46 | 2, 47 | "never" 48 | ], 49 | "no-unused-vars": "off", // 未使用变量 50 | // "generator-star-spacing": ["error", { "before": false, "after": true }], 51 | "valid-jsdoc": [ 52 | "error", 53 | { 54 | // 取消限制注释中必须使用 @return 标签替代 @returns标签 55 | "prefer": { 56 | // returns: "return", 57 | }, 58 | } 59 | ], 60 | "no-multi-spaces": [ 61 | "error", 62 | { 63 | "exceptions": { 64 | "ImportDeclaration": true, 65 | "VariableDeclarator": true, 66 | "Property": false, 67 | "ignoreEOLComments": true 68 | } 69 | } 70 | ], 71 | //对象字面量中冒号的前后空格 72 | "key-spacing": [ 73 | "error", 74 | { 75 | "beforeColon": true, 76 | "afterColon": true 77 | } 78 | ] 79 | }, 80 | }, 81 | } 82 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. 4 | 5 | 6 | ## [0.6.1](https://github.com/binsee/padchat-sdk/compare/v0.5.11...v0.6.1) (2018-11-01) 7 | 8 | 9 | ### Bug Fixes 10 | 11 | * **demo:** 更新demo中断线重连代码 ([fe5b2a6](https://github.com/binsee/padchat-sdk/commit/fe5b2a6)) 12 | * 修复断线重连判断错误 ([3abc799](https://github.com/binsee/padchat-sdk/commit/3abc799)) 13 | 14 | 15 | ### Features 16 | 17 | * 增加自动重连通知事件 ([cc29f3d](https://github.com/binsee/padchat-sdk/commit/cc29f3d)) 18 | * 将推送联系人从push事件中独立出来 ([81d9206](https://github.com/binsee/padchat-sdk/commit/81d9206)) 19 | * 更改cmdId为计数器,减少通讯中cmdId的占用尺寸 ([fd83bfd](https://github.com/binsee/padchat-sdk/commit/fd83bfd)) 20 | * 更改ws通讯中荷载字段名称为payload ([1635b14](https://github.com/binsee/padchat-sdk/commit/1635b14)), closes [#28](https://github.com/binsee/padchat-sdk/issues/28) 21 | * 更改推送机制方案,以优化性能 ([fe22ae0](https://github.com/binsee/padchat-sdk/commit/fe22ae0)) 22 | * 登陆模式的断线重连名称改为 'auto' ([e2461e3](https://github.com/binsee/padchat-sdk/commit/e2461e3)), closes [#29](https://github.com/binsee/padchat-sdk/issues/29) 23 | * **demo:** 可独立开关同步通讯录及消息 ([7d3f0e0](https://github.com/binsee/padchat-sdk/commit/7d3f0e0)) 24 | 25 | 26 | 27 | 28 | # [0.6.0](https://github.com/binsee/padchat-sdk/compare/v0.5.11...v0.6.0) (2018-11-01) 29 | 30 | 31 | ### Bug Fixes 32 | 33 | * **demo:** 更新demo中断线重连代码 ([fe5b2a6](https://github.com/binsee/padchat-sdk/commit/fe5b2a6)) 34 | * 修复断线重连判断错误 ([3abc799](https://github.com/binsee/padchat-sdk/commit/3abc799)) 35 | 36 | 37 | ### Features 38 | 39 | * 增加自动重连通知事件 ([cc29f3d](https://github.com/binsee/padchat-sdk/commit/cc29f3d)) 40 | * 将推送联系人从push事件中独立出来 ([81d9206](https://github.com/binsee/padchat-sdk/commit/81d9206)) 41 | * 更改cmdId为计数器,减少通讯中cmdId的占用尺寸 ([fd83bfd](https://github.com/binsee/padchat-sdk/commit/fd83bfd)) 42 | * 更改ws通讯中荷载字段名称为payload ([1635b14](https://github.com/binsee/padchat-sdk/commit/1635b14)), closes [#28](https://github.com/binsee/padchat-sdk/issues/28) 43 | * 更改推送机制方案,以优化性能 ([fe22ae0](https://github.com/binsee/padchat-sdk/commit/fe22ae0)) 44 | * 登陆模式的断线重连名称改为 'auto' ([e2461e3](https://github.com/binsee/padchat-sdk/commit/e2461e3)), closes [#29](https://github.com/binsee/padchat-sdk/issues/29) 45 | * **demo:** 可独立开关同步通讯录及消息 ([7d3f0e0](https://github.com/binsee/padchat-sdk/commit/7d3f0e0)) 46 | 47 | 48 | 49 | 50 | ## [0.5.13](https://github.com/binsee/padchat-sdk/compare/v0.5.11...v0.5.13) (2018-09-05) 51 | 52 | 53 | 54 | 55 | ## [0.5.12](https://github.com/binsee/padchat-sdk/compare/v0.5.11...v0.5.12) (2018-08-23) 56 | 57 | 58 | 59 | 60 | ## [0.5.11](https://github.com/binsee/padchat-sdk/compare/v0.5.10...v0.5.11) (2018-08-23) 61 | 62 | 63 | ### Bug Fixes 64 | 65 | * 修复使用设备数据登陆后再获取设备数据会无效的问题 ([042eaf1](https://github.com/binsee/padchat-sdk/commit/042eaf1)) 66 | 67 | 68 | 69 | 70 | ## [0.5.10](https://github.com/binsee/padchat-sdk/compare/v0.5.9...v0.5.10) (2018-07-31) 71 | 72 | 73 | ### Bug Fixes 74 | 75 | * 修复群内发送文本消息at成员无效的bug ([27ac206](https://github.com/binsee/padchat-sdk/commit/27ac206)) 76 | 77 | 78 | 79 | 80 | ## [0.5.9](https://github.com/binsee/padchat-sdk/compare/v0.5.8...v0.5.9) (2018-07-20) 81 | 82 | 83 | 84 | 85 | ## [0.5.8](https://github.com/binsee/padchat-sdk/compare/v0.5.7...v0.5.8) (2018-07-20) 86 | 87 | 88 | ### Features 89 | 90 | * 增加支持发送小程序 ([95668ad](https://github.com/binsee/padchat-sdk/commit/95668ad)) 91 | 92 | 93 | 94 | 95 | ## [0.5.7](https://github.com/binsee/padchat-sdk/compare/v0.5.6...v0.5.7) (2018-07-16) 96 | 97 | 98 | ### Features 99 | 100 | * 增加websocket关闭原因参数 ([ac7b14d](https://github.com/binsee/padchat-sdk/commit/ac7b14d)) 101 | 102 | 103 | 104 | 105 | ## [0.5.6](https://github.com/binsee/padchat-sdk/compare/v0.5.5...v0.5.6) (2018-06-13) 106 | 107 | 108 | ### Bug Fixes 109 | 110 | * 修复重连机制可能引发新的异常问题 ([591cb66](https://github.com/binsee/padchat-sdk/commit/591cb66)) 111 | 112 | 113 | 114 | 115 | ## [0.5.5](https://github.com/binsee/padchat-sdk/compare/v0.5.4...v0.5.5) (2018-06-13) 116 | 117 | 118 | ### Bug Fixes 119 | 120 | * 修复warn事件没有正确获得服务器提示信息 ([66f1d7d](https://github.com/binsee/padchat-sdk/commit/66f1d7d)) 121 | 122 | 123 | ### Features 124 | 125 | * 增加start方法来实现更容易的重连 ([231b476](https://github.com/binsee/padchat-sdk/commit/231b476)), closes [#30](https://github.com/binsee/padchat-sdk/issues/30) 126 | 127 | 128 | 129 | 130 | ## [0.5.4](https://github.com/binsee/padchat-sdk/compare/v0.5.3...v0.5.4) (2018-06-09) 131 | 132 | 133 | ### Bug Fixes 134 | 135 | * 断线重连登陆失败后,不需要重新初始化实例! ([099e54f](https://github.com/binsee/padchat-sdk/commit/099e54f)) 136 | 137 | 138 | 139 | 140 | ## [0.5.3](https://github.com/binsee/padchat-sdk/compare/v0.5.2...v0.5.3) (2018-06-08) 141 | 142 | 143 | ### Bug Fixes 144 | 145 | * 修复发送语音显示时间为1秒问题 ([dbb9b24](https://github.com/binsee/padchat-sdk/commit/dbb9b24)) 146 | 147 | 148 | 149 | 150 | ## [0.5.2](https://github.com/binsee/padchat-sdk/compare/v0.5.1...v0.5.2) (2018-06-04) 151 | 152 | 153 | ### Features 154 | 155 | * 增加syncMsg接口,用于手动触发同步消息 ([2c0d488](https://github.com/binsee/padchat-sdk/commit/2c0d488)) 156 | 157 | 158 | 159 | 160 | ## [0.5.1](https://github.com/binsee/padchat-sdk/compare/v0.5.0...v0.5.1) (2018-06-03) 161 | 162 | 163 | ### Features 164 | 165 | * 增加getMyInfo接口,用于获取当前微信号的wxid和uin ([e67fa16](https://github.com/binsee/padchat-sdk/commit/e67fa16)) 166 | 167 | 168 | 169 | 170 | # [0.5.0](https://github.com/binsee/padchat-sdk/compare/v0.4.4...v0.5.0) (2018-05-25) 171 | 172 | 173 | ### Features 174 | 175 | * syncContact增加参数`reset`,明确是否强制同步 ([b298327](https://github.com/binsee/padchat-sdk/commit/b298327)) 176 | * **demo:** 登陆成功后不再自动同步通讯录,根据需要调用syncContact来同步通讯录 ([a28f684](https://github.com/binsee/padchat-sdk/commit/a28f684)) 177 | 178 | 179 | 180 | 181 | ## [0.4.4](https://github.com/binsee/padchat-sdk/compare/v0.4.3...v0.4.4) (2018-05-24) 182 | 183 | 184 | 185 | 186 | ## [0.4.3](https://github.com/binsee/padchat-sdk/compare/v0.4.2...v0.4.3) (2018-05-08) 187 | 188 | 189 | ### Bug Fixes 190 | 191 | * 修复接口名称错误 ([98245fa](https://github.com/binsee/padchat-sdk/commit/98245fa)) 192 | 193 | 194 | 195 | 196 | ## [0.4.2](https://github.com/binsee/padchat-sdk/compare/v0.4.0...v0.4.2) (2018-04-28) 197 | 198 | 199 | ### Bug Fixes 200 | 201 | * 增加解析push联系人事件中的群成员列表 ([8547c97](https://github.com/binsee/padchat-sdk/commit/8547c97)) 202 | 203 | 204 | 205 | 206 | # [0.4.0](https://github.com/binsee/padchat-sdk/compare/v0.3.0...v0.4.0) (2018-04-11) 207 | 208 | 209 | ### Features 210 | 211 | * **demo:** 增加终端中直接生成二维码的示例 ([1681760](https://github.com/binsee/padchat-sdk/commit/1681760)), closes [#6](https://github.com/binsee/padchat-sdk/issues/6) 212 | 213 | 214 | 215 | 216 | # [0.3.0](https://github.com/binsee/padchat-sdk/compare/v0.2.0...v0.3.0) (2018-04-08) 217 | 218 | 219 | ### Bug Fixes 220 | 221 | * 修复demo中输出服务器地址 ([536fe6c](https://github.com/binsee/padchat-sdk/commit/536fe6c)) 222 | * **修复部分需要传递rawMsgData的接口调用失败问题;修复demo中保存设备参数错误:** 1. 增加部分接口返回数据样例 | 2.demo中增加接收转账及红包的示例 ([8d894b9](https://github.com/binsee/padchat-sdk/commit/8d894b9)) 223 | 224 | 225 | ### Features 226 | 227 | * **demo:** 增加通过文本指令执行指定接口的功能 ([45dafd4](https://github.com/binsee/padchat-sdk/commit/45dafd4)) 228 | 229 | 230 | 231 | 232 | # [0.2.0](https://github.com/binsee/padchat-sdk/compare/v0.1.2...v0.2.0) (2018-04-03) 233 | 234 | 235 | ### Features 236 | 237 | * 新增多个接口(配合协议服务v1.4及以上版本);修复部分bug ([602d88b](https://github.com/binsee/padchat-sdk/commit/602d88b)) 238 | 239 | 240 | 241 | 242 | ## [0.1.2](https://github.com/binsee/padchat-sdk/compare/v0.1.1...v0.1.2) (2018-03-27) 243 | 244 | 245 | 246 | 247 | ## [0.1.1](https://github.com/binsee/padchat-sdk/compare/v0.1.0...v0.1.1) (2018-03-26) 248 | 249 | 250 | ### Bug Fixes 251 | 252 | * 修复demo保存设备参数名称错误 ([64f5604](https://github.com/binsee/padchat-sdk/commit/64f5604)) 253 | 254 | 255 | 256 | 257 | # [0.1.0](https://github.com/binsee/padchat-sdk/compare/613b2ae...v0.1.0) (2018-03-20) 258 | 259 | 260 | ### Features 261 | 262 | * v0.1.0 ([613b2ae](https://github.com/binsee/padchat-sdk/commit/613b2ae)) 263 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [飞机群地址](https://t.me/+zPGvjRT-WO8yNGM1) 2 | # Padchat-SDK 3 | 4 | 5 | 6 | - [说明](#说明) 7 | - [接口功能列表](#接口功能列表) 8 | - [通讯约定](#通讯约定) 9 | - [通信协议](#通信协议) 10 | - [连接授权](#连接授权) 11 | - [API请求操作结果(识别异步请求)](#api请求操作结果识别异步请求) 12 | - [数据规则约定](#数据规则约定) 13 | - [API请求结构](#api请求结构) 14 | - [data字段总述](#data字段总述) 15 | - [DEMO](#demo) 16 | - [API文档](#api文档) 17 | 18 | 19 | 20 | ## 说明 21 | 22 | Padchat开发包。通过websocket协议与运行在windows平台上的微信ipad协议服务程序通讯,来登陆与操作微信。 23 | 24 | ## 接口功能列表 25 | 26 | | **接口** | **code** | **备注** | 27 | | ------------------ | :-----------------: | ------------------------------------- | 28 | | **登陆管理** | | 29 | | 初始化实例 | init | 初始化任务实例 | 30 | | 登陆 | login | 登陆账号 | 31 | | 注销登录 | logout | 会退出账号登陆 | 32 | | 关闭实例 | close | 关闭任务实例,不退出账号登陆 | 33 | | 获取设备登陆数据 | getWxData | 固定设备登陆数据 | 34 | | 获取二次登陆数据 | getLoginToken | 可使用二次登陆数据免扫码或免密码登陆 | 35 | | **用户管理** | 36 | | 获取用户信息 | getContact | 获取用户详细信息 | 37 | | 搜索用户 | searchContact | 38 | | 通过好友请求 | acceptUser | 39 | | 添加好友 | addContact | 40 | | 打招呼 | sayHello | | 41 | | 删除好友 | deleteContact | 42 | | 设置好友备注 | setRemark | 43 | | 设置头像 | setHeadImg | 44 | | 主动触发同步消息 | syncMsg | | 45 | | 主动同步通讯录 | syncContact | | 46 | | 获取用户二维码 | getContactQrcode | 用于获取自己的二维码图片 | 47 | | 获取当前用户信息 | getMyInfo | 用于获取当前微信号的wxid和uin | 48 | | **群管理** | 49 | | 创建群 | createRoom | 50 | | 获取群成员 | getRoomMembers | 51 | | 添加群成员 | addRoomMember | 52 | | 邀请好友进群 | inviteRoomMember | 53 | | 删除群成员 | deleteRoomMember | 54 | | 退出群 | quitRoom | 55 | | 设置群公告 | setRoomAnnouncement | 设置群公告会自动@通知群内所有成员 | 56 | | 设置群名称 | setRoomName | 修改微信群名称 | 57 | | 获取进群二维码 | getRoomQrcode | 获取到的进群二维码有效期为7天 | 58 | | **发送消息** | 59 | | 发送文本消息 | sendMsg | 60 | | 发送App消息 | sendAppMsg | 发送图文链接消息 | 61 | | 发送图片消息 | sendImage | 62 | | 发送语音消息 | sendVoice | 语音文件必须是silk格式 | 63 | | 发送名片 | shareCard | 64 | | **获取图片、文件** | 65 | | 获取消息图片原图 | getMsgImage | 获取图片消息的原始图片数据 | 66 | | 获取消息视频数据 | getMsgVideo | 获取小视频消息的视频数据 | 67 | | 获取消息语音数据 | getMsgVoice | 获取语音消息的语音数据 | 68 | | **朋友圈操作** | 69 | | 发朋友圈 | snsSendMoment | 发表文字朋友圈信息 | 70 | | 朋友圈上传图片 | snsUpload | 上传后仅能得到url,而非真正的发朋友圈 | 71 | | 查看用户朋友圈 | snsUserPage | 查看指定用户朋友圈信息 | 72 | | 获取朋友圈动态 | snsTimeline | 查看朋友圈时间轴信息 | 73 | | 获取朋友圈消息详情 | snsGetObject | 74 | | 操作朋友圈 | snsObjectOp | | 75 | | 发表评论 | snsComment | 76 | | 点赞 | snsLike | 77 | | **收藏操作** | 78 | | 同步收藏消息 | syncFav | 79 | | 添加收藏 | addFav | 80 | | 获取收藏消息详情 | getFav | 81 | | 删除收藏 | deleteFav | 82 | | **标签管理** | 83 | | 添加标签 | addLabel | 84 | | 删除标签 | deleteLabel | 85 | | 获取所有标签 | getLabelList | 86 | | 设置用户标签 | setLabel | 87 | | **公众号操作** | 88 | | 搜索公众号 | searchMp | 根据关键字搜索公众号 | 89 | | 获取公众号信息 | getSubscriptionInfo | 90 | | 操作公众号菜单 | operateSubscription | 91 | | 获取公众号网页授权 | getRequestToken | 需要授权才能访问的网页需要先授权 | 92 | | 访问授权页面 | requestUrl | 以授权过的身份访问页面 | 93 | | **小程序相关操作** | | 支持转发分享 | 94 | 95 | 完整接口见**API文档** 96 | 97 | ## 通讯约定 98 | 99 | ### 通信协议 100 | 101 | WebSocket 通信协议 102 | 103 | - [websockets 官方github](https://github.com/websockets) 104 | - [NodeJs 参考](https://github.com/websockets/ws) 105 | 106 | #### 连接授权 107 | 108 | 后续更新。 109 | 110 | #### API请求操作结果(识别异步请求) 111 | 112 | 由于websocket自身是异步操作,未原生支持识别请求返回的结果(即向服务端发送一个请求,服务端返回执行结果,客户端却无法确认是自己这个主动请求的结果,或者是另一个请求的返回结果,或者是服务端主动推送)。因此本服务增加了一个字段`cmdId`,用于标识请求,并在返回操作结果时一块返回。 113 | 114 | 如果希望发送api请求后,能识别服务端执行本次请求后的返回结果,可提供`cmdId`字段,请一定提供随机值,建议使用`uuid`模块随机生成。当收到服务端推送过来的数据中包含`cmdId`字段时,即可确认为之前请求对应的执行结果。 115 | 建议结合使用`Promise`+`Event.once(cmdId)`来实现。 116 | 117 | #### 数据规则约定 118 | 119 | > 在sdk内统一字段命名,统一转换为`小驼峰`写法。 120 | 121 | 微信协议原生接口返回的所有数据字段名称下划线写法(如`user_name`),部分接口(公众号相关接口)返回的混合有大驼峰命名。在sdk内已经全部格式化为`小驼峰`写法。 122 | 123 | 目前仅残留有部分xml结构文本内没有格式化,需自行解析提取与转换。 124 | 125 | 如果遇到接口返回的某个字段是json文本,请发issues告知接口名称、返回数据样本,以便增加对其的解析。 126 | 127 | ### API请求结构 128 | 129 | API请求是以websocket协议发送的json数据,以下为json数据的字段 130 | 131 | | **名称** | **类型** | **描述** | **必选** | 132 | | :------: | :------: | ------------------------------------------------------------- | :------: | 133 | | type | String | 请求类型:`sys`/`user` | 是 | 134 | | cmd | String | API命令 | 是 | 135 | | cmdId | String | 指令id。用于识别API异步操作结果,操作结果会增加此属性推送回来 | 否 | 136 | | data | Object | 取决于是不同的API要求 | 否 | 137 | 138 | #### data字段总述 139 | 140 | 此部分为请求API指令时,需要附加的data数据。根据使用的API不同,需要提供不同的字段及对应数据。 141 | 142 | | 字段名称 | 说明 | 备注 | 143 | | :--------------: | -------------------------- | -------------------------------------------------- | 144 | | **登陆** | 145 | | loginType | 登陆类型 | 支持扫码、帐号密码、手机验证码、二次登陆、断线重连 | 146 | | wxData | 登陆设备数据 | 使用已登陆过的设备数据登录,可避免封号 | 147 | | token | 二次登陆token | 结合`wxData`使用可免扫码、帐号登陆 | 148 | | **发送消息** | | 149 | | toUserName | 目标用户/群id | 群id包含@chatroom部分 | 150 | | content | 文本内容 | 文本消息内容、xml结构体文本、名片自定义标题 | 151 | | | | 添加好友时,为验证信息 | 152 | | file | 文件buffer的base64编码 | 发送图片/语音消息、上传头像、朋友圈上传图片 | 153 | | time | 语音的时间长度(单位为毫秒) | 发送语音消息 | 154 | | atList | `Array`,要at的用户用户 | `["wxid1","wxid2"]` 文本消息时有效 | 155 | | **群及好友管理** | | 156 | | roomName | 群名称 | 157 | | userIds | `Array`,用户id列表数组 | `["wxid1","wxid2"]` 创建群 | 158 | | chatroom | 要操作的群id | 159 | | remark | 备注名称 | 160 | | userId | 用户wxid | 主动添加好友、好友验证、添加/邀请用户进入群 | 161 | | stranger | V1码,相对加密的userId | 接受好友请求(仅限stranger字段) | 162 | | | | 主动添加好友(也可使用`userId`字段) | 163 | | ticket | V2码,好友请求中的ticket | 添加单向好友、接受好友请求 | 164 | | type | `Number`,操作类型 | 添加好友来源、朋友圈操作类型 | 165 | | **朋友圈** | 166 | | momentId | 朋友圈消息id | 167 | | commentId | `Number`,朋友圈评论id | 168 | | commentType | `Number`,朋友圈评论类型 | 169 | | **收藏** | 170 | | favKey | 收藏分页key | 通过分页key来分页拉取收藏 | 171 | | favId | `Number`,收藏id | 172 | | **标签** | 173 | | label | 标签名称 | 174 | | labelId | 标签id | 175 | | **公众号** | 176 | | ghName | 公众号id,`gh_`开头 | 177 | | menuId | `Number`,公众号菜单id | 178 | | menuKey | 公众号菜单key | 179 | | url | 网页url | 180 | | xKey | 网页授权key | 以公众号授权方式访问网页需要提供授权key | 181 | | xUin | 网页授权uin | 以公众号授权方式访问网页需要提供授权uin | 182 | | **其他** | | 183 | | rawMsgData | `Object`,push事件中的data | 用于接收红包、接收转账、获取原始图片 | 184 | 185 | ## DEMO 186 | 187 | 使用DEMO见 [demo.js](./demo.js) 188 | 189 | ## API文档 190 | 191 | SDK完整API文档见:[SDK Api文档](docs/index.md) 192 | -------------------------------------------------------------------------------- /define.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | exports.wsEventType = [ 4 | 'log', 5 | 'cmdRet', 6 | 'userEvent', 7 | 'sysEvent', 8 | ] 9 | 10 | exports.userEvents = [ 11 | 'qrcode', // 登陆二维码 12 | 'scan', // 扫码登陆状态 13 | 'login', // 登陆完成 14 | 'loaded', // 通讯录载入完毕 15 | 'logout', // 注销登录(账户退出) 16 | 'close', // 任务断线 17 | 'warn', // 错误 18 | 'sns', // 朋友圈事件(朋友圈小圆点) 19 | 'notify', // 推送消息通知 20 | 'autoLogin', // 自动重连成功通知 21 | 'push', // 推送消息(系统、好友消息等) 22 | ] 23 | 24 | exports.loginType = { 25 | auto : 'auto', // 断线重连 26 | request: 'request', // 二次登陆 27 | qrcode : 'qrcode', // 扫码登陆 28 | phone : 'phone', // 手机验证码登陆 29 | user : 'user', // 账号密码登陆 30 | } 31 | 32 | exports.blacklist = [ 33 | 'appbrandcustomerservicemsg', 34 | 'blogapp', 35 | 'cardpackage', 36 | 'facebookapp', 37 | 'feedsapp', 38 | 'filehelper', 39 | 'floatbottle', 40 | 'floatbottle', // 漂流瓶 41 | 'fmessage', // 朋友推荐 42 | 'helper_entry', 43 | 'lbsapp', 44 | 'linkedinplugin', 45 | 'masssendapp', 46 | 'medianote', // 语音记事本 47 | 'mphelper', // 公众平台安全助手 48 | 'newsapp', // 腾讯新闻 49 | 'notification_messages', 50 | 'notifymessage', 51 | 'officialaccounts', 52 | 'pc_share', 53 | 'qmessage', // qq离线消息 54 | 'qqfriend', 55 | 'qqmail', 56 | 'qqsync', 57 | 'shakeapp', 58 | 'tmessage', 59 | 'voiceinputapp', 60 | 'voicevoipapp', 61 | 'voipapp', 62 | 'weibo', // 微博-未知 63 | 'weixin', // 腾讯团队 64 | ] 65 | -------------------------------------------------------------------------------- /demo.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const log4js = require('log4js') 4 | const Padchat = require('./index') 5 | const fs = require('fs') 6 | const util = require('util') 7 | const qrcode = require('qrcode-terminal') 8 | 9 | /** 10 | * 创建日志目录 11 | */ 12 | 13 | try { 14 | require('fs').mkdirSync('./logs') 15 | } catch (e) { 16 | if (e.code !== 'EEXIST') { 17 | console.error('Could not set up log directory, error: ', e) 18 | process.exit(1) 19 | } 20 | } 21 | 22 | try { 23 | log4js.configure('./log4js.json') 24 | } catch (e) { 25 | console.error('载入log4js日志输出配置错误: ', e) 26 | process.exit(1); 27 | } 28 | 29 | const logger = log4js.getLogger('app') 30 | const dLog = log4js.getLogger('dev') 31 | 32 | logger.info('demo start!') 33 | 34 | const autoData = { 35 | wxData: '', 36 | token: '', 37 | } 38 | let server = '' 39 | server = 'ws://47.99.211.34:8181/' 40 | // 永久免费使用 41 | 42 | try { 43 | const tmpBuf = fs.readFileSync('./config.json') 44 | const data = JSON.parse(String(tmpBuf)) 45 | autoData.wxData = data.wxData 46 | autoData.token = data.token 47 | logger.info('载入设备参数与自动登陆数据:%o ', autoData) 48 | } catch (e) { 49 | logger.warn('没有在本地发现设备登录参数或解析数据失败!如首次登录请忽略!') 50 | } 51 | 52 | const wx = new Padchat(server) 53 | logger.info('当前连接接口服务器为:', server) 54 | let disconnectCount = 0 // 断开计数 55 | let connected = false // 成功连接标志 56 | 57 | wx 58 | .on('close', (code, msg) => { 59 | // 需要注意关闭代码为3201-3203的错误,重连也用,具体参考文档中`close`事件说明 60 | if (code > 3200) { 61 | logger.warn(`Websocket已关闭!code: ${code} - ${msg}`) 62 | return 63 | } 64 | logger.info(`Websocket已关闭!code: ${code} - ${msg}`) 65 | // 根据是否成功连接过判断本次是未能连接成功还是与服务器连接中断 66 | if (connected) { 67 | connected = false 68 | disconnectCount++ 69 | logger.info(`第 ${disconnectCount} 次与服务器连接断开!现在将重试连接服务器。`) 70 | } else { 71 | logger.debug(`未能连接服务器!将重试连接服务器。`) 72 | } 73 | // 重新启动websocket连接 74 | wx.start() 75 | }) 76 | .on('open', async () => { 77 | let ret 78 | logger.info('连接成功!') 79 | connected = true 80 | 81 | // 非首次登录时最好使用以前成功登录时使用的设备参数, 82 | // 否则可能会被tx服务器怀疑账号被盗,导致手机端被登出 83 | ret = await wx.init() 84 | if (!ret.success) { 85 | logger.error('新建任务失败!', ret) 86 | return 87 | } 88 | logger.info('新建任务成功, json: ', ret) 89 | 90 | //先尝试使用断线重连方式登陆 91 | if (autoData.token) { 92 | ret = await wx.login('auto', autoData) 93 | if (ret.success) { 94 | logger.info('断线重连请求成功!', ret) 95 | return 96 | } 97 | logger.warn('断线重连请求失败!', ret) 98 | 99 | ret = await wx.login('request', autoData) 100 | if (ret.success) { 101 | logger.info('自动登录请求成功!', ret) 102 | return 103 | } 104 | logger.warn('自动登录请求失败!', ret) 105 | } 106 | 107 | ret = await wx.login('qrcode') 108 | if (!ret.success) { 109 | logger.error('使用qrcode登录模式失败!', ret) 110 | return 111 | } 112 | logger.info('使用qrcode登录模式!') 113 | }) 114 | .on('qrcode', data => { 115 | // 如果存在url,则直接在终端中生成二维码并显示 116 | if (data.url) { 117 | logger.info(`登陆二维码内容为: "${data.url}",请使用微信扫描下方二维码登陆!`) 118 | qrcode.generate(data.url, { small: true }) 119 | } else { 120 | logger.error(`未能获得登陆二维码!`) 121 | } 122 | }) 123 | .on('scan', data => { 124 | switch (data.status) { 125 | case 0: 126 | logger.info('等待扫码...', data) 127 | break; 128 | case 1: 129 | // { 130 | // status : 1, 131 | // expiredTime: 239, 132 | // headUrl : 'http://wx.qlogo.cn/mmhead/ver_1/xxxxxxx/0', //头像url 133 | // nickName : '复仇者联盟' //昵称 134 | // } 135 | logger.info('已扫码,请在手机端确认登陆...', data) 136 | break; 137 | case 2: 138 | // { 139 | // password : '***hide***', // 可忽略 140 | // status : 2, 141 | // expiredTime: 238, 142 | // headUrl : 'http://wx.qlogo.cn/mmhead/ver_1/xxxxxxx/0', //头像url 143 | // subStatus : 0 // 登陆操作状态码 144 | // 以下字段仅在登录成功时有效 145 | // external : '1', 146 | // email : '', 147 | // uin : 149806460, // 微信账号uin,全局唯一 148 | // deviceType : 'android', // 登陆的主设备类型 149 | // nickName : '复仇者联盟' //昵称 150 | // userName : 'wxid_xxxxxx', // 微信账号id,全局唯一 151 | // phoneNumber: '18012345678', // 微信账号绑定的手机号 152 | // } 153 | switch (data.subStatus) { 154 | case 0: 155 | logger.info('扫码成功!登陆成功!', data) 156 | break; 157 | case 1: 158 | logger.info('扫码成功!登陆失败!', data) 159 | break; 160 | default: 161 | logger.info('扫码成功!未知状态码!', data) 162 | break; 163 | } 164 | break; 165 | // 如果等待登陆超时或手机上点击了取消登陆,需要重新调用登陆 166 | case 3: 167 | logger.info('二维码已过期!请重新调用登陆接口!', data) 168 | break; 169 | case 4: 170 | logger.info('手机端已取消登陆!请重新调用登陆接口!', data) 171 | break; 172 | default: 173 | logger.warn('未知登陆状态!请重新调用登陆接口!', data) 174 | break; 175 | } 176 | }) 177 | .on('login', async () => { 178 | logger.info('微信账号登陆成功!') 179 | let ret 180 | 181 | ret = await wx.getMyInfo() 182 | logger.info('当前账号信息:', ret.data) 183 | 184 | // 如果不想同步通讯录信息,可关闭同步通讯录 185 | // await wx.setSyncContact(false) 186 | 187 | // 主动同步通讯录 188 | await wx.syncContact() 189 | 190 | await saveAutoData() 191 | }) 192 | .on('autoLogin', async () => { 193 | // 自动重连后需要保存新的自动登陆数据 194 | await saveAutoData() 195 | }) 196 | .on('logout', ({ msg }) => { 197 | logger.info('微信账号已退出!', msg) 198 | }) 199 | .on('over', ({ msg }) => { 200 | logger.info('任务实例已关闭!', msg) 201 | }) 202 | .on('loaded', async () => { 203 | logger.info('通讯录同步完毕!') 204 | 205 | // 主动触发同步消息 206 | await wx.syncMsg() 207 | 208 | const ret = await wx.sendMsg('filehelper', '你登录了!') 209 | logger.info('发送信息结果:', ret) 210 | }) 211 | .on('sns', (data, msg) => { 212 | logger.info('收到朋友圈事件!请查看朋友圈新消息哦!', msg) 213 | }) 214 | 215 | .on('contact', async data => { 216 | logger.info('收到推送联系人:%s - %s\n', data.userName, data.nickName, JSON.stringify(data)) 217 | }) 218 | .on('push', async data => { 219 | // 消息类型 data.mType 220 | // 1 文字消息 221 | // 3 收到图片消息 222 | // 34 语音消息 223 | // 35 用户头像buf 224 | // 37 收到好友请求消息 225 | // 42 名片消息 226 | // 43 视频消息 227 | // 47 表情消息 228 | // 48 定位消息 229 | // 49 APP消息(文件 或者 链接 H5) 230 | // 50 语音通话 231 | // 51 状态通知(如打开与好友/群的聊天界面) 232 | // 52 语音通话通知 233 | // 53 语音通话邀请 234 | // 62 小视频 235 | // 2000 转账消息 236 | // 2001 收到红包消息 237 | // 3000 群邀请 238 | // 9999 系统通知 239 | // 10000 微信通知信息. 微信群信息变更通知,多为群名修改,进群,离群信息,不包含群内聊天信息 240 | // 10002 撤回消息 241 | // -------------------------------- 242 | // 注意,如果是来自微信群的消息,data.content字段中包含发言人的wxid及其发言内容,需要自行提取 243 | // 各类复杂消息,data.content中是xml格式的文本内容,需要自行从中提取各类数据。(如好友请求) 244 | let rawFile 245 | switch (data.mType) { 246 | case 3: 247 | logger.info('收到来自 %s 的图片消息,包含图片数据:%s,xml内容:\n%s', data.fromUser, !!data.data, data.content) 248 | rawFile = data.data || null 249 | logger.info('图片缩略图数据base64尺寸:%d', rawFile.length) 250 | await wx.getMsgImage(data) 251 | .then(ret => { 252 | rawFile = ret.data.image || '' 253 | logger.info('获取消息原始图片结果:%s, 获得图片base64尺寸:%d', ret.success, rawFile.length) 254 | }) 255 | logger.info('图片数据base64尺寸:%d', rawFile.length) 256 | await wx.sendImage('filehelper', rawFile) 257 | .then(ret => { 258 | logger.info('转发图片信息给 %s 结果:', 'filehelper', ret) 259 | }) 260 | .catch(e => { 261 | logger.warn('转发图片信息异常:', e.message) 262 | }) 263 | break 264 | 265 | case 43: 266 | logger.info('收到来自 %s 的视频消息,包含视频数据:%s,xml内容:\n%s', data.fromUser, !!data.data, data.content) 267 | rawFile = data.data || null 268 | if (!rawFile) { 269 | await wx.getMsgVideo(data) 270 | .then(ret => { 271 | rawFile = ret.data.video || '' 272 | logger.info('获取消息原始视频结果:%s, 获得视频base64尺寸:%d', ret.success, rawFile.length) 273 | }) 274 | } 275 | logger.info('视频数据base64尺寸:%d', rawFile.length) 276 | break 277 | 278 | case 1: 279 | if (data.fromUser === 'newsapp') { // 腾讯新闻发的信息太长 280 | break 281 | } 282 | logger.info('收到来自 %s 的文本消息:', data.fromUser, data.description || data.content) 283 | if (/ding/.test(data.content)) { 284 | await wx.sendMsg(data.fromUser, 'dong. receive:' + data.content) 285 | .then(ret => { 286 | logger.info('回复信息给%s 结果:', data.fromUser, ret) 287 | }) 288 | .catch(e => { 289 | logger.warn('回复信息异常:', e.message) 290 | }) 291 | } else if (/^#.*/.test(data.content) || /^[\w]*:\n#.*/.test(data.content)) { 292 | await onMsg(data) 293 | .catch(e => { 294 | logger.warn('处理信息异常:', e) 295 | }) 296 | } 297 | break 298 | 299 | case 34: 300 | logger.info('收到来自 %s 的语音消息,包含语音数据:%s,xml内容:\n%s', data.fromUser, !!data.data, data.content) 301 | // 超过30Kb的语音数据不会包含在推送信息中,需要主动拉取 302 | rawFile = data.data || null 303 | if (!rawFile) { 304 | // BUG: 超过60Kb的语音数据,只能拉取到60Kb,也就是说大约36~40秒以上的语音会丢失后边部分语音内容 305 | await wx.getMsgVoice(data) 306 | .then(ret => { 307 | rawFile = ret.data.voice || '' 308 | logger.info('获取消息原始语音结果:%s, 获得语音base64尺寸:%d,拉取到数据尺寸:%d', ret.success, rawFile.length, ret.data.size) 309 | }) 310 | } 311 | logger.info('语音数据base64尺寸:%d', rawFile.length) 312 | if (rawFile.length > 0) { 313 | let match = data.content.match(/length="(\d+)"/) || [] 314 | const length = match[1] || 0 315 | match = data.content.match(/voicelength="(\d+)"/) || [] 316 | const ms = match[1] || 0 317 | logger.info('语音数据语音长度:%d ms,xml内记录尺寸:%d', ms, length) 318 | 319 | await wx.sendVoice('filehelper', rawFile, ms) 320 | .then(ret => { 321 | logger.info('转发语音信息给 %s 结果:', 'filehelper', ret) 322 | }) 323 | .catch(e => { 324 | logger.warn('转发语音信息异常:', e.message) 325 | }) 326 | } 327 | break 328 | 329 | case 49: 330 | logger.info('收到一条来自 %s 的appmsg富媒体消息:', data.fromUser, data) 331 | break 332 | 333 | case 10002: 334 | if (data.fromUser === 'weixin') { 335 | //每次登陆,会收到一条系统垃圾推送,过滤掉 336 | break 337 | } 338 | logger.info('用户 %s 撤回了一条消息:', data.fromUser, data) 339 | break 340 | 341 | default: 342 | logger.info('收到推送消息:', data) 343 | break 344 | } 345 | }) 346 | .on('error', e => { 347 | logger.error('ws 错误:', e.message) 348 | }) 349 | .on('warn', e => { 350 | logger.error('任务出现错误:', e.message) 351 | }) 352 | 353 | /** 354 | * @description 保存自动登陆数据 355 | */ 356 | async function saveAutoData() { 357 | let ret = await wx.getWxData() 358 | if (!ret.success) { 359 | logger.warn('获取设备参数未成功! json:', ret) 360 | return 361 | } 362 | logger.info('获取设备参数成功, json: ', ret) 363 | Object.assign(autoData, { wxData: ret.data.wxData }) 364 | 365 | ret = await wx.getLoginToken() 366 | if (!ret.success) { 367 | logger.warn('获取自动登陆数据未成功! json:', ret) 368 | return 369 | } 370 | logger.info('获取自动登陆数据成功, json: ', ret) 371 | Object.assign(autoData, { token: ret.data.token }) 372 | 373 | // NOTE: 这里将设备参数保存到本地,以后再次登录此账号时提供相同参数 374 | fs.writeFileSync('./config.json', JSON.stringify(autoData, null, 2)) 375 | logger.info('设备参数已写入到 ./config.json文件') 376 | } 377 | 378 | async function onMsg(data) { 379 | const content = data.content.replace(/^[\w:\n]*#/m, '') 380 | let [cmd, ...args] = content.split('\n') 381 | 382 | args = args.map(str => { 383 | try { 384 | str = JSON.parse(str) 385 | } catch (e) { 386 | } 387 | return str 388 | }) 389 | if (cmd && wx[cmd] && typeof wx[cmd] === 'function') { 390 | logger.info('执行函数 %s,参数:', cmd, args) 391 | await wx[cmd](...args) 392 | .then(ret => { 393 | logger.info('执行函数 %s 结果:%o', cmd, ret) 394 | }) 395 | .catch(e => { 396 | logger.warn('执行函数 %s 异常:', e) 397 | }) 398 | } 399 | } 400 | process.on('uncaughtException', e => { 401 | logger.error('Main', 'uncaughtException:', e) 402 | }) 403 | 404 | process.on('unhandledRejection', e => { 405 | logger.error('Main', 'unhandledRejection:', e) 406 | }) 407 | -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | # Padchat Sdk v0.6.1 Documentation 2 | 3 | 4 | 5 | ## Padchat ⇐ EventEmitter 6 | **Kind**: global class 7 | **Extends**: EventEmitter 8 | 9 | * [Padchat](#Padchat) ⇐ EventEmitter 10 | * [new Padchat()](#new_Padchat_new) 11 | * _instance_ 12 | * [.start()](#Padchat+start) 13 | * [.init()](#Padchat+init) ⇒ Promise.<object> 14 | * [.close()](#Padchat+close) ⇒ Promise.<object> 15 | * [.login(type, data)](#Padchat+login) ⇒ Promise.<object> 16 | * [.getWxData()](#Padchat+getWxData) ⇒ Promise.<object> 17 | * [.getLoginToken()](#Padchat+getLoginToken) ⇒ Promise.<object> 18 | * [.getMyInfo()](#Padchat+getMyInfo) ⇒ Promise.<object> 19 | * [.setSyncContact()](#Padchat+setSyncContact) 20 | * [.setSyncMsg()](#Padchat+setSyncMsg) 21 | * [.syncMsg()](#Padchat+syncMsg) ⇒ Promise.<object> 22 | * [.syncContact([reset])](#Padchat+syncContact) ⇒ Promise.<object> 23 | * [.logout()](#Padchat+logout) ⇒ Promise.<object> 24 | * [.sendMsg(toUserName, content, [atList])](#Padchat+sendMsg) ⇒ Promise.<object> 25 | * ~~[.massMsg([userList], content)](#Padchat+massMsg) ⇒ Promise.<object>~~ 26 | * [.sendAppMsg(toUserName, content, object)](#Padchat+sendAppMsg) ⇒ Promise.<object> 27 | * [.shareCard(toUserName, content, userId)](#Padchat+shareCard) ⇒ Promise.<object> 28 | * [.sendImage(toUserName, file)](#Padchat+sendImage) ⇒ Promise.<object> 29 | * [.sendVoice(toUserName, file, time)](#Padchat+sendVoice) ⇒ Promise.<object> 30 | * [.getMsgImage(rawMsgData)](#Padchat+getMsgImage) ⇒ Promise.<object> 31 | * [.getMsgVideo(rawMsgData)](#Padchat+getMsgVideo) ⇒ Promise.<object> 32 | * [.getMsgVoice(rawMsgData)](#Padchat+getMsgVoice) ⇒ Promise.<object> 33 | * [.createRoom(userList)](#Padchat+createRoom) ⇒ Promise.<object> 34 | * [.getRoomMembers(groupId)](#Padchat+getRoomMembers) ⇒ Promise.<object> 35 | * [.addRoomMember(groupId, userId)](#Padchat+addRoomMember) ⇒ Promise.<object> 36 | * [.inviteRoomMember(groupId, userId)](#Padchat+inviteRoomMember) ⇒ Promise.<object> 37 | * [.deleteRoomMember(groupId, userId)](#Padchat+deleteRoomMember) ⇒ Promise.<object> 38 | * [.quitRoom(groupId)](#Padchat+quitRoom) ⇒ Promise.<object> 39 | * [.setRoomAnnouncement(groupId, content)](#Padchat+setRoomAnnouncement) ⇒ Promise.<object> 40 | * [.setRoomName(groupId, content)](#Padchat+setRoomName) ⇒ Promise.<object> 41 | * [.getRoomQrcode(groupId)](#Padchat+getRoomQrcode) ⇒ Promise.<object> 42 | * [.getContact(userId)](#Padchat+getContact) ⇒ Promise.<object> 43 | * [.searchContact(userId)](#Padchat+searchContact) ⇒ Promise.<object> 44 | * [.deleteContact(userId)](#Padchat+deleteContact) ⇒ Promise.<object> 45 | * [.getContactQrcode(userId, style)](#Padchat+getContactQrcode) ⇒ Promise.<object> 46 | * [.acceptUser(stranger, ticket)](#Padchat+acceptUser) ⇒ Promise.<object> 47 | * [.addContact(stranger, ticket, type, [content])](#Padchat+addContact) ⇒ Promise.<object> 48 | * [.sayHello(stranger, ticket, content)](#Padchat+sayHello) ⇒ Promise.<object> 49 | * [.setRemark(userId, remark)](#Padchat+setRemark) ⇒ Promise.<object> 50 | * [.setHeadImg(file)](#Padchat+setHeadImg) ⇒ Promise.<object> 51 | * [.snsUpload(file)](#Padchat+snsUpload) ⇒ Promise.<object> 52 | * [.snsobjectOp(momentId, type, commentId, commentType)](#Padchat+snsobjectOp) ⇒ Promise.<object> 53 | * [.snsSendMoment(content)](#Padchat+snsSendMoment) ⇒ Promise.<object> 54 | * [.snsUserPage(userId, [momentId])](#Padchat+snsUserPage) ⇒ Promise.<object> 55 | * [.snsTimeline([momentId])](#Padchat+snsTimeline) ⇒ Promise.<object> 56 | * [.snsGetObject(momentId)](#Padchat+snsGetObject) ⇒ Promise.<object> 57 | * [.snsComment(userId, momentId, content)](#Padchat+snsComment) ⇒ Promise.<object> 58 | * [.snsLike(userId, momentId)](#Padchat+snsLike) ⇒ Promise.<object> 59 | * [.syncFav([favKey])](#Padchat+syncFav) ⇒ Promise.<object> 60 | * [.addFav(content)](#Padchat+addFav) ⇒ Promise.<object> 61 | * [.getFav(favId)](#Padchat+getFav) ⇒ Promise.<object> 62 | * [.deleteFav(favId)](#Padchat+deleteFav) ⇒ Promise.<object> 63 | * [.getLabelList()](#Padchat+getLabelList) ⇒ Promise.<object> 64 | * [.addLabel(label)](#Padchat+addLabel) ⇒ Promise.<object> 65 | * [.deleteLabel(labelId)](#Padchat+deleteLabel) ⇒ Promise.<object> 66 | * [.setLabel(userId, labelId)](#Padchat+setLabel) ⇒ Promise.<object> 67 | * [.queryTransfer(rawMsgData)](#Padchat+queryTransfer) ⇒ Promise.<object> 68 | * [.acceptTransfer(rawMsgData)](#Padchat+acceptTransfer) ⇒ Promise.<object> 69 | * [.receiveRedPacket(rawMsgData)](#Padchat+receiveRedPacket) ⇒ Promise.<object> 70 | * [.queryRedPacket(rawMsgData, [index])](#Padchat+queryRedPacket) ⇒ Promise.<object> 71 | * [.openRedPacket(rawMsgData, key)](#Padchat+openRedPacket) ⇒ Promise.<object> 72 | * [.searchMp(content)](#Padchat+searchMp) ⇒ Promise.<object> 73 | * [.getSubscriptionInfo(ghName)](#Padchat+getSubscriptionInfo) ⇒ Promise.<object> 74 | * [.operateSubscription(ghName, menuId, menuKey)](#Padchat+operateSubscription) ⇒ Promise.<object> 75 | * [.getRequestToken(ghName, url)](#Padchat+getRequestToken) ⇒ Promise.<object> 76 | * [.requestUrl(url, xKey, xUin)](#Padchat+requestUrl) ⇒ Promise.<object> 77 | * ["open"](#Padchat+event_open) 78 | * ["close"](#Padchat+event_close) 79 | * ["error"](#Padchat+event_error) 80 | * ["warn"](#Padchat+event_warn) 81 | * ["qrcode"](#Padchat+event_qrcode) 82 | * ["scan"](#Padchat+event_scan) 83 | * ["login"](#Padchat+event_login) 84 | * ["autoLogin"](#Padchat+event_autoLogin) 85 | * ["loaded"](#Padchat+event_loaded) 86 | * ["logout"](#Padchat+event_logout) 87 | * ["over"](#Padchat+event_over) 88 | * ["sns"](#Padchat+event_sns) 89 | * ["push"](#Padchat+event_push) 90 | * ["contact"](#Padchat+event_contact) 91 | * _static_ 92 | * [.Padchat](#Padchat.Padchat) 93 | * [new Padchat([url])](#new_Padchat.Padchat_new) 94 | 95 | 96 | 97 | ### new Padchat() 98 | Padchat模块 99 | 100 | 使用websocket与服务器进行通讯,拥有以下事件 101 | 102 | Event | 说明 103 | ---- | ---- 104 | qrcode | 推送的二维码 105 | scan | 扫码状态 106 | push | 新信息事件 107 | login | 登录 108 | loaded | 通讯录载入完毕 109 | logout | 注销登录 110 | over | 实例注销(账号不退出)(要再登录需要重新调用init) 111 | warn | 错误信息 112 | sns | 朋友圈更新事件 113 | 114 | **接口返回数据结构:** 所有接口均返回以下结构数据: 115 | ``` 116 | { 117 | success: true, // 执行是否成功 118 | err : '', // 错误提示 119 | msg : '', // 附加信息 120 | data : {} // 返回结果 121 | } 122 | ``` 123 | 124 | TODO: 补充各监听事件返回的数据定义 125 | 126 | 127 | 128 | ### padchat.start() 129 | 启动websocket连接 130 | 131 | **Kind**: instance method of [Padchat](#Padchat) 132 | 133 | 134 | ### padchat.init() ⇒ Promise.<object> 135 | 初始化 136 | 137 | **Kind**: instance method of [Padchat](#Padchat) 138 | **Returns**: Promise.<object> - 返回Promise,注意捕捉catch 139 | ``` 140 | { 141 | error : '', 142 | success: true 143 | } 144 | ``` 145 | 146 | 147 | ### padchat.close() ⇒ Promise.<object> 148 | 关闭微信实例(不退出登陆) 149 | 150 | **Kind**: instance method of [Padchat](#Padchat) 151 | **Returns**: Promise.<object> - 返回Promise,注意捕捉catch 152 | 153 | 154 | ### padchat.login(type, data) ⇒ Promise.<object> 155 | 登录账号 156 | 首次登录不需要传入`wxData`,登陆成功后本地保存`wxData`和`token`,以后使用断线重连或二次登陆,可降低封号概率。 157 | 任何登陆方式,使用成功登陆过的`wxData`都可降低封号概率。 158 | 159 | **Kind**: instance method of [Padchat](#Padchat) 160 | **Returns**: Promise.<object> - 返回Promise,注意捕捉catch 161 | ``` 162 | { 163 | error : '', 164 | msg : '请使用手机微信扫码登陆!', 165 | success: true 166 | } 167 | ``` 168 | 169 | | Param | Type | Default | Description | 170 | | --- | --- | --- | --- | 171 | | type | string | "qrcode" | 登录类型,默认为扫码登录
`auto` **断线重连**,用于短时间使用`wxData`和`token`再次登录。`token`有效期很短,如果登陆失败,建议使用二次登陆方式
`request` **二次登陆**。需要提供`wxData`和`token`数据,手机端会弹出确认框,点击后登陆。不容易封号
`qrcode` **扫码登录**(现在此模式已经可以返回二维码内容的url了)
`phone` **手机验证码登录**,建议配合`wxData`使用
`user` **账号密码登录**,建议配合`wxData`使用 | 172 | | data | object | | 附加数据 | 173 | | [data.wxData] | string | | 设备信息数据,登录后使用 `getDeviceInfo` 接口获得。
使用此数据可免设备安全验证,不容易封号 | 174 | | [data.token] | string | | 使用用任意方式登录成功后,使用 `getAutoLoginData` 接口获得。
此token有过期时间,断开登录状态一段时间后会过期。 | 175 | | [data.phone] | string | | 手机号 | 176 | | [data.code] | string | | 手机验证码 | 177 | | [data.username] | string | | 用户名/qq号/手机号 | 178 | | [data.password] | string | | 密码 | 179 | 180 | **Example** *(扫码登陆)* 181 | ```js 182 | const wx = new Padchat() 183 | wx.on('open',()=>{ 184 | await wx.init() 185 | await wx.login('qrcode',{wxData:'xxx'}) 186 | }) 187 | ``` 188 | **Example** *(账号密码登陆)* 189 | ```js 190 | const wx = new Padchat() 191 | wx.on('open',()=>{ 192 | await wx.init() 193 | await wx.login('user',{wxData:'xxx',username:'name',password:'123456'}) 194 | }) 195 | ``` 196 | **Example** *(手机验证码)* 197 | ```js 198 | const wx = new Padchat() 199 | wx.on('open',()=>{ 200 | await wx.init() 201 | await wx.login('phone',{wxData:'xxx',phone:'13512345678',code:'123456'}) 202 | }) 203 | ``` 204 | **Example** *(断线重连)* 205 | ```js 206 | const wx = new Padchat() 207 | wx.on('open',()=>{ 208 | await wx.init() 209 | await wx.login('auto',{wxData:'xxx',token:'xxxxx'}) 210 | }) 211 | ``` 212 | **Example** *(二次登陆)* 213 | ```js 214 | const wx = new Padchat() 215 | wx.on('open',()=>{ 216 | await wx.init() 217 | await wx.login('request',{wxData:'xxx',token:'xxxxx'}) 218 | }) 219 | ``` 220 | 221 | 222 | ### padchat.getWxData() ⇒ Promise.<object> 223 | 获取设备62数据 224 | 225 | 事实上,只要你有一次登陆成功,以后一直用这个62数据,不需要更换。 226 | 227 | **Kind**: instance method of [Padchat](#Padchat) 228 | **Returns**: Promise.<object> - 返回Promise,注意捕捉catch 229 | ``` 230 | { 231 | error: '', success: true, 232 | data : 233 | { 234 | wxData: 'xxxxx' //设备62数据 235 | } 236 | } 237 | ``` 238 | 239 | 240 | ### padchat.getLoginToken() ⇒ Promise.<object> 241 | 获取二次登陆数据 242 | 243 | **Kind**: instance method of [Padchat](#Padchat) 244 | **Returns**: Promise.<object> - 返回Promise,注意捕捉catch 245 | ``` 246 | { 247 | error : '', 248 | success: true, 249 | data : 250 | { 251 | message: '', 252 | status : 0, 253 | token : 'xxxx', //二次登陆token 254 | uin : 14900000 //微信号uin,唯一值 255 | } 256 | } 257 | ``` 258 | 259 | 260 | ### padchat.getMyInfo() ⇒ Promise.<object> 261 | 获取微信号信息 262 | 263 | **Kind**: instance method of [Padchat](#Padchat) 264 | **Returns**: Promise.<object> - 返回Promise,注意捕捉catch 265 | ``` 266 | { 267 | error : '', 268 | success: true, 269 | data: 270 | { 271 | userName: 'wxid_xxxx', //微信号id,注意不一定是微信号,全局唯一 272 | uin : 101234567 //微信号uin,全局唯一 273 | } 274 | } 275 | ``` 276 | 277 | 278 | ### padchat.setSyncContact() 279 | 设置是否同步联系人 280 | 281 | **Kind**: instance method of [Padchat](#Padchat) 282 | 283 | 284 | ### padchat.setSyncMsg() 285 | 设置是否同步消息 286 | 287 | **Kind**: instance method of [Padchat](#Padchat) 288 | 289 | 290 | ### padchat.syncMsg() ⇒ Promise.<object> 291 | 同步消息 292 | 293 | 使用此接口手动触发同步消息,一般用于刚登陆后调用,可立即开始同步消息。 294 | 否则会在有新消息时才开始同步消息。 295 | 296 | **Kind**: instance method of [Padchat](#Padchat) 297 | **Returns**: Promise.<object> - 返回Promise,注意捕捉catch 298 | 299 | 300 | ### padchat.syncContact([reset]) ⇒ Promise.<object> 301 | 同步通讯录 302 | 303 | 使用此接口可以触发同步通讯录,如果设置`reset`为`true`,则在通讯录同步完毕后触发`loaded`事件 304 | 305 | **Kind**: instance method of [Padchat](#Padchat) 306 | **Returns**: Promise.<object> - 返回Promise,注意捕捉catch 307 | 308 | | Param | Type | Default | Description | 309 | | --- | --- | --- | --- | 310 | | [reset] | boolean | false | 是否重置通讯录加载完毕状态 | 311 | 312 | 313 | 314 | ### padchat.logout() ⇒ Promise.<object> 315 | 退出登录 316 | 317 | **Kind**: instance method of [Padchat](#Padchat) 318 | **Returns**: Promise.<object> - 返回Promise,注意捕捉catch 319 | 320 | 321 | ### padchat.sendMsg(toUserName, content, [atList]) ⇒ Promise.<object> 322 | 发送文字信息 323 | 324 | **Kind**: instance method of [Padchat](#Padchat) 325 | **Returns**: Promise.<object> - 返回Promise,注意捕捉catch 326 | ``` 327 | { 328 | error: '', success: true, 329 | data : { 330 | message: '', 331 | msgId : '5172746684759824075', 332 | status : 0 333 | } 334 | } 335 | ``` 336 | 337 | | Param | Type | Default | Description | 338 | | --- | --- | --- | --- | 339 | | toUserName | string | | 接收者的wxid | 340 | | content | string | | 内容文本 | 341 | | [atList] | Array.<string> | [] | 向群内发信息时,要@的用户wxid数组。 内容文本中要有@同样数量的用户昵称,不足时,将自动前缀空白的@符号及换行符 | 342 | 343 | **Example** *(at群成员示例 - content内@了群成员昵称)* 344 | ```js 345 | wx.sendMsg('123456@chatroom','@nickname1 @nickname2 message body',['wxid1','wxid2']) 346 | // 显示内容: 347 | // `@nickname1 @nickname2 message body` 348 | ``` 349 | **Example** *(at群成员示例 - content内遗漏@群成员: )* 350 | ```js 351 | wx.sendMsg('123456@chatroom','@nickname1 message body',['wxid1','wxid2','wxid3']) 352 | // 显示内容: 353 | // `@@ 354 | // @nickname1 message body` 355 | ``` 356 | 357 | 358 | ### ~~padchat.massMsg([userList], content) ⇒ Promise.<object>~~ 359 | ***Deprecated*** 360 | 361 | 群发文字信息 362 | 363 | FIXME: 此接口有问题,暂停使用 364 | 365 | **Kind**: instance method of [Padchat](#Padchat) 366 | **Returns**: Promise.<object> - 返回Promise,注意捕捉catch 367 | 368 | | Param | Type | Default | Description | 369 | | --- | --- | --- | --- | 370 | | [userList] | Array.<string> | [] | 接收者wxid数组 | 371 | | content | string | | 内容文本 | 372 | 373 | 374 | 375 | ### padchat.sendAppMsg(toUserName, content, object) ⇒ Promise.<object> 376 | 发送App消息(含小程序) 377 | 378 | **Kind**: instance method of [Padchat](#Padchat) 379 | **Returns**: Promise.<object> - 返回Promise,注意捕捉catch 380 | ``` 381 | { 382 | error: '', success: true, 383 | data : { 384 | message: '', 385 | msgId : '2195811529497100215', 386 | status : 0 387 | } 388 | } 389 | ``` 390 | 391 | | Param | Type | Description | 392 | | --- | --- | --- | 393 | | toUserName | string | 接收者的wxid | 394 | | content | object \| string | app消息体文本(appmsg xml结构) | 395 | | object | object | app消息体对象(消息体文本和对象二选一) | 396 | | [object.appid] | string | appid,忽略即可 | 397 | | [object.sdkver] | string | sdk版本,忽略即可 | 398 | | [object.title] | string | 标题 | 399 | | [object.des] | string | 描述 | 400 | | [object.url] | string | 链接url | 401 | | [object.thumburl] | string | 缩略图url | 402 | 403 | **Example** *(发送app消息对象)* 404 | ```js 405 | // 直接在第二个参数中传入消息体对象 406 | await wx.sendAppMsg('filehelper',{ 407 | appid = '', //appid,忽略即可 408 | sdkver = '', //sdk版本,忽略即可 409 | title = '', //标题 410 | des = '', //描述 411 | url = '', //链接url 412 | thumburl = '', //缩略图url 413 | }) 414 | ``` 415 | **Example** *(发送app消息体文本)* 416 | ```js 417 | // 如第二个参数传入非空文本,则忽略第三个参数 418 | await wx.sendAppMsg('filehelper','标题描述view50http://wx.qq.comhttp://wx.qq.com/logo.png') 419 | ``` 420 | 421 | 422 | ### padchat.shareCard(toUserName, content, userId) ⇒ Promise.<object> 423 | 分享名片 424 | 425 | **Kind**: instance method of [Padchat](#Padchat) 426 | **Returns**: Promise.<object> - 返回Promise,注意捕捉catch 427 | ``` 428 | { 429 | error: '', success: true, 430 | data : { 431 | message: '', 432 | msgId : '1797099903789182796', 433 | status : 0 434 | } 435 | } 436 | ``` 437 | 438 | | Param | Type | Description | 439 | | --- | --- | --- | 440 | | toUserName | string | 接收者的wxid | 441 | | content | string | 内容文本 | 442 | | userId | string | 被分享人wxid | 443 | 444 | 445 | 446 | ### padchat.sendImage(toUserName, file) ⇒ Promise.<object> 447 | 发送图片消息 448 | 449 | **Kind**: instance method of [Padchat](#Padchat) 450 | **Returns**: Promise.<object> - 返回Promise,注意捕捉catch 451 | ``` 452 | { 453 | error: '', success: true, 454 | data : { 455 | message: '', 456 | msgId : '1797099903789182796', 457 | status : 0 458 | } 459 | } 460 | ``` 461 | 462 | | Param | Type | Description | 463 | | --- | --- | --- | 464 | | toUserName | string | 接收者的wxid | 465 | | file | Buffer \| string | 图片Buffer数据或base64 | 466 | 467 | 468 | 469 | ### padchat.sendVoice(toUserName, file, time) ⇒ Promise.<object> 470 | 发送语音消息 471 | 注意:只能发送silk格式的语音文件 472 | 473 | **Kind**: instance method of [Padchat](#Padchat) 474 | **Returns**: Promise.<object> - 返回Promise,注意捕捉catch 475 | ``` 476 | { 477 | error: '', success: true, 478 | data : { 479 | data : 2490, //语音文件尺寸 480 | message: '', 481 | msgId : '136722815749654341', 482 | size : 0, 483 | status : 0 484 | } 485 | } 486 | ``` 487 | 488 | | Param | Type | Default | Description | 489 | | --- | --- | --- | --- | 490 | | toUserName | string | | 接收者的wxid | 491 | | file | Buffer \| string | | 语音Buffer数据或base64 | 492 | | time | number | 0 | 语音时间,单位为毫秒 | 493 | 494 | 495 | 496 | ### padchat.getMsgImage(rawMsgData) ⇒ Promise.<object> 497 | 获取消息原始图片 498 | 499 | 在push事件中收到的data数据是缩略图图片数据,使用本接口获取原图数据 500 | 501 | **Kind**: instance method of [Padchat](#Padchat) 502 | **Returns**: Promise.<object> - 返回Promise,注意捕捉catch 503 | ``` 504 | { 505 | success: true, 506 | data : 507 | { 508 | image : 'base64_xxxx', //base64编码的原图数据 509 | message: '', 510 | size : 8139, //图片数据尺寸 511 | status : 0 512 | } 513 | } 514 | ``` 515 | 516 | | Param | Type | Description | 517 | | --- | --- | --- | 518 | | rawMsgData | object | 推送的消息结构体,即`push`事件中收到的Object | 519 | 520 | 521 | 522 | ### padchat.getMsgVideo(rawMsgData) ⇒ Promise.<object> 523 | 获取消息原始视频 524 | 525 | 在push事件中只获得推送通知,不包含视频数据,需要使用本接口获取视频文件数据 526 | 527 | **Kind**: instance method of [Padchat](#Padchat) 528 | **Returns**: Promise.<object> - 返回Promise,注意捕捉catch 529 | ``` 530 | { 531 | success: true, 532 | data : 533 | { 534 | message: '', 535 | size : 160036, //视频数据尺寸 536 | status : 0, 537 | video : 'base64_xxxx' //base64编码的视频数据 538 | } 539 | } 540 | ``` 541 | 542 | | Param | Type | Description | 543 | | --- | --- | --- | 544 | | rawMsgData | object | 推送的消息结构体,即`push`事件中收到的Object | 545 | 546 | 547 | 548 | ### padchat.getMsgVoice(rawMsgData) ⇒ Promise.<object> 549 | 获取消息语音数据 550 | 551 | 这个接口获取到的与push事件中接收到的数据一致,是base64编码的silk格式语音数据 552 | 553 | BUG: 超过60Kb的语音数据,只能拉取到60Kb,也就是说大约36~40秒以上的语音会丢失后边部分语音内容 554 | 555 | **Kind**: instance method of [Padchat](#Padchat) 556 | **Returns**: Promise.<object> - 返回Promise,注意捕捉catch 557 | ``` 558 | { 559 | success: true, 560 | data : 561 | { 562 | message: '', 563 | size : 2490, //语音数据尺寸 564 | status : 0, 565 | voice : 'base64_xxxx' //base64编码的语音数据 566 | } 567 | } 568 | ``` 569 | 570 | | Param | Type | Description | 571 | | --- | --- | --- | 572 | | rawMsgData | object | 推送的消息结构体,即`push`事件中收到的Object | 573 | 574 | 575 | 576 | ### padchat.createRoom(userList) ⇒ Promise.<object> 577 | 创建群 578 | 579 | 注意:如果有用户存在问题不能进群,则会建群失败。 580 | 但判断是否成功应以`userName`字段 581 | 582 | **Kind**: instance method of [Padchat](#Padchat) 583 | **Returns**: Promise.<object> - 返回Promise,注意捕捉catch 584 | ``` 585 | { 586 | success: true, 587 | data : 588 | { 589 | message : 'Everything is OK', //操作结果提示,失败为`MemberList are wrong` 590 | status : 0, 591 | userName: '5658541000@chatroom' //如果建群成功,则返回群id 592 | } 593 | } 594 | ``` 595 | 596 | | Param | Type | Description | 597 | | --- | --- | --- | 598 | | userList | Array.<string> | 用户wxid数组 | 599 | 600 | 601 | 602 | ### padchat.getRoomMembers(groupId) ⇒ Promise.<object> 603 | 获取群成员信息 604 | 605 | **Kind**: instance method of [Padchat](#Padchat) 606 | **Returns**: Promise.<object> - 返回Promise,注意捕捉catch 607 | ``` 608 | { 609 | success: true, 610 | data : 611 | { 612 | chatroomId: 700000001, 613 | count : 3, //群成员数量 614 | member : //群成员列表 615 | [{ 616 | bigHead : 'http://wx.qlogo.cn/xxx/0', //大头像url 617 | chatroomNickName: '', //群内昵称 618 | invitedBy : 'binsee', //进群邀请人 619 | nickName : '复仇者联盟', //昵称 620 | smallHead : 'http://wx.qlogo.cn/xxx/132', //小头像url 621 | userName : 'wxid_xxxx' //wxid 622 | }], 623 | message : '', 624 | status : 0, 625 | userName: '5658541000@chatroom' //群id 626 | } 627 | } 628 | ``` 629 | 630 | | Param | Type | Description | 631 | | --- | --- | --- | 632 | | groupId | string | 群id | 633 | 634 | 635 | 636 | ### padchat.addRoomMember(groupId, userId) ⇒ Promise.<object> 637 | 添加群成员 638 | 639 | **Kind**: instance method of [Padchat](#Padchat) 640 | **Returns**: Promise.<object> - 返回Promise,注意捕捉catch 641 | ``` 642 | { 643 | success: true, 644 | data : { 645 | message: 'Everything is OK', //失败为`MemberList are wrong` 646 | status : 0 647 | } 648 | } 649 | ``` 650 | 651 | | Param | Type | Description | 652 | | --- | --- | --- | 653 | | groupId | string | 群id | 654 | | userId | string | 用户wxid | 655 | 656 | 657 | 658 | ### padchat.inviteRoomMember(groupId, userId) ⇒ Promise.<object> 659 | 邀请群成员 660 | 会给对方发送一条邀请消息,无法判断对方是否真的接收到 661 | 662 | **Kind**: instance method of [Padchat](#Padchat) 663 | **Returns**: Promise.<object> - 返回Promise,注意捕捉catch 664 | ``` 665 | { 666 | success: true, 667 | data : { 668 | message: '', 669 | status : 0 670 | } 671 | } 672 | ``` 673 | 674 | | Param | Type | Description | 675 | | --- | --- | --- | 676 | | groupId | string | 群id | 677 | | userId | string | 用户wxid | 678 | 679 | 680 | 681 | ### padchat.deleteRoomMember(groupId, userId) ⇒ Promise.<object> 682 | 删除群成员 683 | 684 | **Kind**: instance method of [Padchat](#Padchat) 685 | **Returns**: Promise.<object> - 返回Promise,注意捕捉catch 686 | ``` 687 | { 688 | success: true, 689 | data : { 690 | message: '', 691 | status : 0 692 | } 693 | } 694 | ``` 695 | 696 | | Param | Type | Description | 697 | | --- | --- | --- | 698 | | groupId | string | 群id | 699 | | userId | string | 用户wxid | 700 | 701 | 702 | 703 | ### padchat.quitRoom(groupId) ⇒ Promise.<object> 704 | 退出群 705 | 706 | **Kind**: instance method of [Padchat](#Padchat) 707 | **Returns**: Promise.<object> - 返回Promise,注意捕捉catch 708 | ``` 709 | { 710 | success: true, 711 | data : { 712 | message: '', 713 | status : 0 714 | } 715 | } 716 | ``` 717 | 718 | | Param | Type | Description | 719 | | --- | --- | --- | 720 | | groupId | string | 群id | 721 | 722 | 723 | 724 | ### padchat.setRoomAnnouncement(groupId, content) ⇒ Promise.<object> 725 | 设置群公告 726 | 727 | **Kind**: instance method of [Padchat](#Padchat) 728 | **Returns**: Promise.<object> - 返回Promise,注意捕捉catch 729 | ``` 730 | { 731 | success: true, 732 | data : { 733 | message: '', 734 | status : 0 735 | } 736 | } 737 | ``` 738 | 739 | | Param | Type | Description | 740 | | --- | --- | --- | 741 | | groupId | string | 群id | 742 | | content | string | 群公告内容 | 743 | 744 | 745 | 746 | ### padchat.setRoomName(groupId, content) ⇒ Promise.<object> 747 | 设置群名称 748 | 749 | **Kind**: instance method of [Padchat](#Padchat) 750 | **Returns**: Promise.<object> - 返回Promise,注意捕捉catch 751 | ``` 752 | { 753 | success: true, 754 | data : { 755 | message: '', 756 | status : 0 757 | } 758 | } 759 | ``` 760 | 761 | | Param | Type | Description | 762 | | --- | --- | --- | 763 | | groupId | string | 群id | 764 | | content | string | 群名称 | 765 | 766 | 767 | 768 | ### padchat.getRoomQrcode(groupId) ⇒ Promise.<object> 769 | 获取微信群二维码 770 | 771 | **Kind**: instance method of [Padchat](#Padchat) 772 | **Returns**: Promise.<object> - 返回Promise,注意捕捉catch 773 | ``` 774 | { 775 | success: true, 776 | data : 777 | { 778 | footer : '该二维码7天内(4月13日前)有效,重新进入将更新', 779 | message: '', 780 | qrCode : '', //进群二维码图片base64 781 | status : 0 782 | } 783 | } 784 | ``` 785 | 786 | | Param | Type | Description | 787 | | --- | --- | --- | 788 | | groupId | string | 群id | 789 | 790 | 791 | 792 | ### padchat.getContact(userId) ⇒ Promise.<object> 793 | 获取用户/群信息 794 | 795 | **Kind**: instance method of [Padchat](#Padchat) 796 | **Returns**: Promise.<object> - 返回Promise,注意捕捉catch 797 | 798 | 微信用户/公众号返回: 799 | 800 | ``` 801 | { 802 | success: true, 803 | data : 804 | { 805 | bigHead : 'http://wx.qlogo.cn/xxx/0', //大头像url 806 | city : 'mesa', //城市 807 | country : 'CN', //国家 808 | intro : '', //简介(公众号主体) 809 | label : '', //(标签) 810 | message : '', 811 | nickName : '复仇者联盟', //昵称 812 | provincia : 'Henan', //省份 813 | pyInitial : 'SM', //昵称拼音简写 814 | quanPin : 'shamu', //昵称拼音 815 | remark : '', //备注 816 | remarkPyInitial: '', //备注拼音简写 817 | remarkQuanPin : '', //备注拼音 818 | sex : 1, //性别:1男2女 819 | signature : '签名', //个性签名 820 | smallHead : 'http://wx.qlogo.cn/xxx/132', //小头像url 821 | status : 0, 822 | stranger : 'v1_xxx@stranger', //用户v1码,从未加过好友则为空 823 | ticket : 'v2_xxx@stranger', //用户v2码,如果非空则为单向好友(非对方好友) 824 | userName : 'binxxx' //用户wxid 825 | } 826 | } 827 | ``` 828 | 829 | 微信群返回: 830 | 831 | ``` 832 | { 833 | success: true, 834 | data : { 835 | city : '', 836 | country : '', 837 | intro : '', 838 | label : '', 839 | member : [], //群成员wxid数组 840 | message : '', 841 | provincia : '', 842 | remark : '', 843 | sex : 0, 844 | signature : '', 845 | status : 0, 846 | stranger : 'v1_xxx@stranger', 847 | ticket : '', 848 | bigHead : '', 849 | chatroomId : 700001234, 850 | chatroomOwner : 'wxid_xxx', 851 | maxMemberCount : 500, //群最大人数 852 | memberCount : 377, //群当前人数 853 | nickName : 'Wechaty Developers\' Home', //群名称 854 | pyInitial : 'WECHATYDEVELOPERSHOME', 855 | quanPin : 'WechatyDevelopersHome', 856 | remarkPyInitial: '', 857 | remarkQuanPin : '', 858 | smallHead : 'http://wx.qlogo.cn/xxx/0', //群头像url 859 | userName : '1234567890@chatroom' 860 | } 861 | } 862 | ``` 863 | 864 | | Param | Type | Description | 865 | | --- | --- | --- | 866 | | userId | string | 用户wxid/群id | 867 | 868 | 869 | 870 | ### padchat.searchContact(userId) ⇒ Promise.<object> 871 | 搜索用户 872 | 可用此接口来判断是否已经加对方为好友 873 | 874 | **Kind**: instance method of [Padchat](#Padchat) 875 | **Returns**: Promise.<object> - 返回Promise,注意捕捉catch 876 | ``` 877 | { 878 | success: true, 879 | data : 880 | { 881 | bigHead : 'http://wx.qlogo.cn/xxx/0', //大头像url 882 | city : 'mesa', //城市 883 | country : 'CN', //国家 884 | message : '', 885 | nickName : '复仇者联盟', //昵称 886 | provincia: 'Henan', //省份 887 | pyInitial: 'SM', //昵称拼音简写 888 | quanPin : 'shamu', //昵称拼音 889 | sex : 1, //性别:1男2女 890 | signature: '签名', //个性签名 891 | smallHead: 'http://wx.qlogo.cn/xxx/132', //小头像url 892 | status : 0, 893 | stranger : 'v1_xxx@stranger', //好友为空,非好友显示v2码 894 | userName : 'binxxx' //是自己好友显示wxid,非好友为v1码 895 | } 896 | } 897 | ``` 898 | 899 | | Param | Type | Description | 900 | | --- | --- | --- | 901 | | userId | string | 用户wxid | 902 | 903 | 904 | 905 | ### padchat.deleteContact(userId) ⇒ Promise.<object> 906 | 删除好友 907 | 908 | **Kind**: instance method of [Padchat](#Padchat) 909 | **Returns**: Promise.<object> - 返回Promise,注意捕捉catch 910 | ``` 911 | { 912 | success: true, 913 | data : { 914 | message: '', 915 | status : 0 916 | } 917 | } 918 | ``` 919 | 920 | | Param | Type | Description | 921 | | --- | --- | --- | 922 | | userId | string | 用户wxid | 923 | 924 | 925 | 926 | ### padchat.getContactQrcode(userId, style) ⇒ Promise.<object> 927 | 获取用户二维码 928 | 仅限获取自己的二维码,无法获取其他人的二维码 929 | 930 | **Kind**: instance method of [Padchat](#Padchat) 931 | **Returns**: Promise.<object> - 返回Promise,注意捕捉catch 932 | ``` 933 | { 934 | success: true, 935 | data : 936 | { 937 | footer : '', 938 | message: '', 939 | qrCode : '', //二维码图片base64 940 | status : 0 941 | } 942 | } 943 | ``` 944 | 945 | | Param | Type | Default | Description | 946 | | --- | --- | --- | --- | 947 | | userId | string | | 用户wxid | 948 | | style | Number | 0 | 二维码风格。可用范围0-3 | 949 | 950 | 951 | 952 | ### padchat.acceptUser(stranger, ticket) ⇒ Promise.<object> 953 | 通过好友验证 954 | 955 | **Kind**: instance method of [Padchat](#Padchat) 956 | **Returns**: Promise.<object> - 返回Promise,注意捕捉catch 957 | ``` 958 | { 959 | success: true, 960 | data : { 961 | message: '', 962 | status : 0 963 | } 964 | } 965 | ``` 966 | 967 | | Param | Type | Description | 968 | | --- | --- | --- | 969 | | stranger | string | 用户stranger数据 | 970 | | ticket | string | 用户ticket数据 | 971 | 972 | 973 | 974 | ### padchat.addContact(stranger, ticket, type, [content]) ⇒ Promise.<object> 975 | 添加好友 976 | 977 | **Kind**: instance method of [Padchat](#Padchat) 978 | **Returns**: Promise.<object> - 返回Promise,注意捕捉catch 979 | ``` 980 | { 981 | success: true, 982 | data : { 983 | message: '', 984 | status : 0 //如果对方设置了验证,会返回-44 985 | } 986 | } 987 | ``` 988 | 989 | | Param | Type | Default | Description | 990 | | --- | --- | --- | --- | 991 | | stranger | string | | 用户stranger数据 | 992 | | ticket | string | | 用户ticket数据 | 993 | | type | Number | 3 | 添加好友途径
`0` : 通过微信号搜索
`1` : 搜索QQ号
`3` : 通过微信号搜索
`4` : 通过QQ好友添加
`8` : 通过群聊
`12`: 来自QQ好友
`14`: 通过群聊
`15`: 通过搜索手机号
`17`: 通过名片分享 //未验证
`22`: 通过摇一摇打招呼方式 //未验证
`25`: 通过漂流瓶 //未验证
`30`: 通过二维码方式 //未验证 | 994 | | [content] | string | "''" | 验证信息 | 995 | 996 | 997 | 998 | ### padchat.sayHello(stranger, ticket, content) ⇒ Promise.<object> 999 | 打招呼 1000 | 如果已经是好友,会收到由系统自动发送,来自对方的一条文本信息 1001 | “xx已通过你的朋友验证请求,现在可以开始聊天了” 1002 | 1003 | **Kind**: instance method of [Padchat](#Padchat) 1004 | **Returns**: Promise.<object> - 返回Promise,注意捕捉catch 1005 | ``` 1006 | { 1007 | success: true, 1008 | data : { 1009 | message: '', 1010 | status : 0 1011 | } 1012 | } 1013 | ``` 1014 | 1015 | | Param | Type | Description | 1016 | | --- | --- | --- | 1017 | | stranger | string | 用户stranger数据 | 1018 | | ticket | string | 用户ticket数据 | 1019 | | content | string | 打招呼内容 | 1020 | 1021 | 1022 | 1023 | ### padchat.setRemark(userId, remark) ⇒ Promise.<object> 1024 | 设置备注 1025 | 1026 | **Kind**: instance method of [Padchat](#Padchat) 1027 | **Returns**: Promise.<object> - 返回Promise,注意捕捉catch 1028 | ``` 1029 | { 1030 | success: true, 1031 | data : { 1032 | message: '', 1033 | status : 0 1034 | } 1035 | } 1036 | ``` 1037 | 1038 | | Param | Type | Description | 1039 | | --- | --- | --- | 1040 | | userId | string | 用户wxid | 1041 | | remark | string | 备注名称 | 1042 | 1043 | 1044 | 1045 | ### padchat.setHeadImg(file) ⇒ Promise.<object> 1046 | 设置头像 1047 | 1048 | **Kind**: instance method of [Padchat](#Padchat) 1049 | **Returns**: Promise.<object> - 返回Promise,注意捕捉catch 1050 | ``` 1051 | { 1052 | success: true, 1053 | data : 1054 | { 1055 | bigHead : 'http://wx.qlogo.cn/mmhead/ver_1/xxx/0', 1056 | data : 1527, //图片文件尺寸 1057 | message : '', 1058 | size : 1527, //图片文件尺寸 1059 | smallHead: 'http://wx.qlogo.cn/mmhead/ver_1/xxx/132', 1060 | status : 0 1061 | } 1062 | } 1063 | ``` 1064 | 1065 | | Param | Type | Description | 1066 | | --- | --- | --- | 1067 | | file | Buffer \| string | 图片Buffer数据或base64 | 1068 | 1069 | 1070 | 1071 | ### padchat.snsUpload(file) ⇒ Promise.<object> 1072 | 上传图片到朋友圈 1073 | NOTE: 此接口只能上传图片,并不会将图片发到朋友圈中 1074 | 1075 | **Kind**: instance method of [Padchat](#Padchat) 1076 | **Returns**: Promise.<object> - 返回Promise,注意捕捉catch 1077 | ``` 1078 | { 1079 | success: true, 1080 | data : 1081 | { 1082 | bigHead : 'http://mmsns.qpic.cn/mmsns/xxx/0', 1083 | data : 1527, //图片文件尺寸 1084 | message : '', 1085 | size : 1527, //图片文件尺寸 1086 | smallHead: 'http://mmsns.qpic.cn/mmsns/xxx/150', 1087 | status : 0 1088 | } 1089 | } 1090 | ``` 1091 | 1092 | | Param | Type | Description | 1093 | | --- | --- | --- | 1094 | | file | Buffer \| string | 图片Buffer数据或base64 | 1095 | 1096 | 1097 | 1098 | ### padchat.snsobjectOp(momentId, type, commentId, commentType) ⇒ Promise.<object> 1099 | 操作朋友圈 1100 | 1101 | **Kind**: instance method of [Padchat](#Padchat) 1102 | **Returns**: Promise.<object> - 返回Promise,注意捕捉catch 1103 | ``` 1104 | { 1105 | success: true, 1106 | data : { 1107 | message: '', 1108 | status : 0 1109 | } 1110 | } 1111 | ``` 1112 | 1113 | | Param | Type | Default | Description | 1114 | | --- | --- | --- | --- | 1115 | | momentId | string | | 朋友圈信息id | 1116 | | type | Number | | 操作类型,1为删除朋友圈,4为删除评论,5为取消赞 | 1117 | | commentId | Number | | 操作类型,当type为4时,对应删除评论的id,其他状态为0 | 1118 | | commentType | Number | 2 | 操作类型,当删除评论时可用,需与评论type字段一致 | 1119 | 1120 | 1121 | 1122 | ### padchat.snsSendMoment(content) ⇒ Promise.<object> 1123 | 发朋友圈 1124 | 1125 | **Kind**: instance method of [Padchat](#Padchat) 1126 | **Returns**: Promise.<object> - 返回Promise,注意捕捉catch 1127 | ``` 1128 | { 1129 | success: true, 1130 | data : 1131 | { 1132 | data: 1133 | { 1134 | create_time: 1523015689, 1135 | description: //朋友圈信息xml结构体文本 1136 | '12775981595019653292wxid_xxx1523015689来自代码发的朋友圈030002', 1137 | id : '12775981595019653292', //朋友圈信息id 1138 | nick_name: '复仇者联盟', 1139 | user_name: 'wxid_xxxx' 1140 | }, 1141 | message: '', 1142 | status : 0 1143 | } 1144 | } 1145 | ``` 1146 | 1147 | | Param | Type | Description | 1148 | | --- | --- | --- | 1149 | | content | string | 文本内容或`Timelineobject`结构体文本 | 1150 | 1151 | 1152 | 1153 | ### padchat.snsUserPage(userId, [momentId]) ⇒ Promise.<object> 1154 | 查看用户朋友圈 1155 | 1156 | **Kind**: instance method of [Padchat](#Padchat) 1157 | **Returns**: Promise.<object> - 返回Promise,注意捕捉catch 1158 | ``` 1159 | { 1160 | success: true, 1161 | data : 1162 | { 1163 | count: 1, 1164 | data : //朋友圈信息结构数组(无评论和点赞数据) 1165 | [{ 1166 | create_time: 1523015689, 1167 | description: '12775981595019653292wxid_xxx1523015689来自代码发的朋友圈030 0 0 2 ', 1168 | id : '12775981595019653292', 1169 | nick_name : '复仇者联盟', 1170 | user_name : 'wxid_xxx' 1171 | }], 1172 | message: '', 1173 | page : '81cb2ad01ebc219f', 1174 | status : 0 1175 | } 1176 | } 1177 | ``` 1178 | 1179 | | Param | Type | Default | Description | 1180 | | --- | --- | --- | --- | 1181 | | userId | string | | 用户wxid | 1182 | | [momentId] | string | "''" | 朋友圈信息id 首次传入空即获取第一页,以后传入上次拉取的最后一条信息id | 1183 | 1184 | 1185 | 1186 | ### padchat.snsTimeline([momentId]) ⇒ Promise.<object> 1187 | 查看朋友圈动态 1188 | 1189 | **Kind**: instance method of [Padchat](#Padchat) 1190 | **Returns**: Promise.<object> - 返回Promise,注意捕捉catch 1191 | ``` 1192 | { 1193 | success: true, 1194 | data : 1195 | { 1196 | count: 1, 1197 | data : //朋友圈信息结构数组(无评论和点赞数据) 1198 | [{ 1199 | create_time: 1523015689, 1200 | description: '12775981595019653292wxid_xxx1523015689来自代码发的朋友圈030 0 0 2 ', 1201 | id : '12775981595019653292', 1202 | nick_name : '复仇者联盟', 1203 | user_name : 'wxid_xxx' 1204 | }], 1205 | message: '', 1206 | page : '81cb2ad01ebc219f', 1207 | status : 0 1208 | } 1209 | } 1210 | ``` 1211 | 1212 | | Param | Type | Default | Description | 1213 | | --- | --- | --- | --- | 1214 | | [momentId] | string | "''" | 朋友圈信息id 首次传入空即获取第一页,以后传入上次拉取的最后一条信息id | 1215 | 1216 | 1217 | 1218 | ### padchat.snsGetObject(momentId) ⇒ Promise.<object> 1219 | 获取朋友圈信息详情 1220 | 1221 | **Kind**: instance method of [Padchat](#Padchat) 1222 | **Returns**: Promise.<object> - 返回Promise,注意捕捉catch 1223 | ``` 1224 | { 1225 | success: true, 1226 | data : { 1227 | data : {}, //朋友圈信息结构 1228 | message: '', 1229 | status : 0 1230 | } 1231 | } 1232 | ``` 1233 | 1234 | | Param | Type | Description | 1235 | | --- | --- | --- | 1236 | | momentId | string | 朋友圈信息id | 1237 | 1238 | 1239 | 1240 | ### padchat.snsComment(userId, momentId, content) ⇒ Promise.<object> 1241 | 评论朋友圈 1242 | 1243 | **Kind**: instance method of [Padchat](#Padchat) 1244 | **Returns**: Promise.<object> - 返回Promise,注意捕捉catch 1245 | ``` 1246 | { 1247 | success: true, 1248 | data : { 1249 | data : {}, //朋友圈信息结构 1250 | message: '', 1251 | status : 0 1252 | } 1253 | } 1254 | ``` 1255 | 1256 | | Param | Type | Description | 1257 | | --- | --- | --- | 1258 | | userId | string | 用户wxid | 1259 | | momentId | string | 朋友圈信息id | 1260 | | content | string | 内容文本 | 1261 | 1262 | 1263 | 1264 | ### padchat.snsLike(userId, momentId) ⇒ Promise.<object> 1265 | 朋友圈点赞 1266 | 1267 | **Kind**: instance method of [Padchat](#Padchat) 1268 | **Returns**: Promise.<object> - 返回Promise,注意捕捉catch 1269 | ``` 1270 | { 1271 | success: true, 1272 | data : { 1273 | data : {}, //朋友圈信息结构 1274 | message: '', 1275 | status : 0 1276 | } 1277 | } 1278 | ``` 1279 | 1280 | | Param | Type | Description | 1281 | | --- | --- | --- | 1282 | | userId | string | 用户wxid | 1283 | | momentId | string | 朋友圈信息id | 1284 | 1285 | 1286 | 1287 | ### padchat.syncFav([favKey]) ⇒ Promise.<object> 1288 | 同步收藏消息 1289 | 1290 | **Kind**: instance method of [Padchat](#Padchat) 1291 | **Returns**: Promise.<object> - 返回Promise,注意捕捉catch 1292 | ``` 1293 | { 1294 | success: true, 1295 | data : 1296 | { 1297 | continue: 0, 1298 | data : //收藏消息列表,如果没有则为null 1299 | [ 1300 | { 1301 | flag: 0, //首次标志,0为有效,1为已取消收藏 1302 | id : 3, //收藏id 1303 | seq : 652265243, //收藏随机值 1304 | time: 1515042008, //收藏时间 1305 | type: 5 //收藏类型:1文本;2图片;3语音;4视频;5图文消息 1306 | } 1307 | ], 1308 | key : 'kzTKsdjD6PM0bbQv+oP7vQ==', //下次的同步key,类似分页 1309 | message: '', 1310 | status : 0 1311 | } 1312 | } 1313 | ``` 1314 | 1315 | | Param | Type | Default | Description | 1316 | | --- | --- | --- | --- | 1317 | | [favKey] | string | "''" | 同步key,首次不用传入 | 1318 | 1319 | 1320 | 1321 | ### padchat.addFav(content) ⇒ Promise.<object> 1322 | 添加收藏 1323 | 1324 | **Kind**: instance method of [Padchat](#Padchat) 1325 | **Returns**: Promise.<object> - 返回Promise,注意捕捉catch 1326 | 1327 | | Param | Type | Description | 1328 | | --- | --- | --- | 1329 | | content | string | 内容文本 | 1330 | 1331 | 1332 | 1333 | ### padchat.getFav(favId) ⇒ Promise.<object> 1334 | 获取收藏消息详情 1335 | 1336 | **Kind**: instance method of [Padchat](#Padchat) 1337 | **Returns**: Promise.<object> - 返回Promise,注意捕捉catch 1338 | ``` 1339 | { 1340 | success: true, 1341 | data : 1342 | { 1343 | data: 1344 | [ 1345 | , { 1346 | flag : 0, //收藏状态:0为有效,1为无效(已删除) 1347 | id : 3, //收藏id,如果为0则为无效收藏 1348 | object: //收藏对象结构体文本 1349 | 'DaoCloud 首席架构师王天青:下一代应用转型之道、术、器gh_4b6a20bcdd8bwxid_xxx5353367357590009973http://mp.weixin.qq.com/s?__biz=MzA5MzA2Njk5OA==&mid=2650096972&idx=1&sn=8707378d0c0bdc0d14d1ac93972c5862&chksm=886266d5bf15efc386050508a2cafb1adb806196f40f4f1bde8e944926c7fb6c6e54a14875c7&scene=0#rdgh_4b6a20bcdd8bDaoCloud 首席架构师王天青:下一代应用转型之道、术、器DaoCloud 受邀出席第13届信息化领袖峰会,立足于 DaoCloud 为传统企业数字化转型旅途中的丰富实践,与大家共话《下一代应用转型之道、术、器》,探讨如何“用新技术原力现代化你的企业应用”。http://mmbiz.qpic.cn/mmbiz_jpg/icGWTH9VkFq315HbKuKtWeWlcVDNPAswdhYA0kIskz0GcEQp6nJetC2aSBNfpibp1wKNHf8kYjUibkCF6SgbMIocw/640?wxtype=jpeg&wxfrom=0http://mmbiz.qpic.cn/mmbiz_jpg/icGWTH9VkFq315HbKuKtWeWlcVDNPAswdhYA0kIskz0GcEQp6nJetC2aSBNfpibp1wKNHf8kYjUibkCF6SgbMIocw/640?wxtype=jpeg&wxfrom=0', 1350 | //文本消息收藏结构 1351 | // '接收到你发送的内容了! 原内容:syncwxid_xxxbinsee5451059336571949850tedhj' 1352 | // 视频 1353 | // 'wxid_xxx4674258153@chatroomwxid_xxx786100356842168336304c02010004453043020100020408eddd7c02030f4fed020419a0360a02045ac9271704206162313437386338616237383833333266336564343335666166363435646331020227110201000400304c02010004453043020100020408eddd7c02030f4fed0204b94c716402045ac9271704203865383031656465633132333661303939346365663837643165316539363663020227110201000400ab1478c8ab788332f3ed435faf645dc18e801edec1236a0994cef87d1e1e966c8e801edec1236a0994cef87d1e1e966c324b6cffbba04142bfabf5cdd0621b4092377ab1478c8ab788332f3ed435faf645dc14fcedfae8fcaa571504c5fd9f2abfa0a5658' 1354 | // 语音 1355 | // 'wxid_xxx4674258153@chatroomwxid_xxx3687245278820959898silk304c02010004453043020100020408eddd7c02030f4fed020419a2360a02045ac92711042030646439623262316234646639366264333838313131366462353338313435370202271102010004000dd9b2b1b4df96bd3881116db538145724650dd9b2b1b4df96bd3881116db5381457d348a2942af6d188100855d48dc753734186' 1356 | seq : 652265243, 1357 | status: 0, //0为有效收藏,1为无效收藏 1358 | time : 1515042008 1359 | } 1360 | ], 1361 | message: '', 1362 | status : 0 1363 | } 1364 | } 1365 | ``` 1366 | 1367 | | Param | Type | Description | 1368 | | --- | --- | --- | 1369 | | favId | Number | 收藏id | 1370 | 1371 | 1372 | 1373 | ### padchat.deleteFav(favId) ⇒ Promise.<object> 1374 | 删除收藏 1375 | 1376 | **Kind**: instance method of [Padchat](#Padchat) 1377 | **Returns**: Promise.<object> - 返回Promise,注意捕捉catch 1378 | ``` 1379 | { 1380 | success: true, 1381 | data : 1382 | { 1383 | data: 1384 | [ 1385 | { 1386 | flag : 0, 1387 | id : 0, 1388 | object: '', 1389 | seq : 0, 1390 | status: 1, //返回删除的收藏id 1391 | time : 0 1392 | }, 1393 | ], 1394 | message: '', 1395 | status : 0 1396 | } 1397 | } 1398 | ``` 1399 | 1400 | | Param | Type | Description | 1401 | | --- | --- | --- | 1402 | | favId | Number | 收藏id | 1403 | 1404 | 1405 | 1406 | ### padchat.getLabelList() ⇒ Promise.<object> 1407 | 获取所有标签 1408 | 1409 | **Kind**: instance method of [Padchat](#Padchat) 1410 | **Returns**: Promise.<object> - 返回Promise,注意捕捉catch 1411 | ``` 1412 | { 1413 | success: true, 1414 | data : 1415 | { 1416 | label: //标签列表 1417 | [{ 1418 | id : 1, //标签id 1419 | name: '测试标签' //标签名称 1420 | }], 1421 | message: '', 1422 | status : 0 1423 | } 1424 | } 1425 | ``` 1426 | 1427 | 1428 | ### padchat.addLabel(label) ⇒ Promise.<object> 1429 | 添加标签 1430 | 1431 | **Kind**: instance method of [Padchat](#Padchat) 1432 | **Returns**: Promise.<object> - 返回Promise,注意捕捉catch 1433 | ``` 1434 | { 1435 | success: true, 1436 | data : { 1437 | message: '', 1438 | status : 0 1439 | } 1440 | } 1441 | ``` 1442 | 1443 | | Param | Type | Description | 1444 | | --- | --- | --- | 1445 | | label | string | 标签名称 | 1446 | 1447 | 1448 | 1449 | ### padchat.deleteLabel(labelId) ⇒ Promise.<object> 1450 | 删除标签 1451 | 1452 | **Kind**: instance method of [Padchat](#Padchat) 1453 | **Returns**: Promise.<object> - 返回Promise,注意捕捉catch 1454 | ``` 1455 | { 1456 | success: true, 1457 | data : { 1458 | message: '', 1459 | status : 0 1460 | } 1461 | } 1462 | ``` 1463 | 1464 | | Param | Type | Description | 1465 | | --- | --- | --- | 1466 | | labelId | string | 标签id,注意是id是string类型 | 1467 | 1468 | 1469 | 1470 | ### padchat.setLabel(userId, labelId) ⇒ Promise.<object> 1471 | 设置用户标签 1472 | 1473 | **Kind**: instance method of [Padchat](#Padchat) 1474 | **Returns**: Promise.<object> - 返回Promise,注意捕捉catch 1475 | ``` 1476 | { 1477 | success: true, 1478 | data : { 1479 | message: '', 1480 | status : 0 1481 | } 1482 | } 1483 | ``` 1484 | 1485 | | Param | Type | Description | 1486 | | --- | --- | --- | 1487 | | userId | string | 用户wxid | 1488 | | labelId | string | 标签id | 1489 | 1490 | 1491 | 1492 | ### padchat.queryTransfer(rawMsgData) ⇒ Promise.<object> 1493 | ***Deprecated*** 1494 | 1495 | 查看转账消息 1496 | 1497 | **Kind**: instance method of [Padchat](#Padchat) 1498 | **Returns**: Promise.<object> - 返回Promise,注意捕捉catch 1499 | ``` 1500 | { 1501 | success: true, 1502 | data : 1503 | { 1504 | external: 1505 | { 1506 | retcode : '0', 1507 | retmsg : 'ok', 1508 | fee : 20, //转账金额(单位为分) 1509 | transStatus : 2000, //状态:2000未收款;2001已收款 1510 | feeType : '1', 1511 | payTime : 1523176700, 1512 | modifyTime : 0, 1513 | refundBankType: 'BANK', 1514 | payerName : 'binsee', 1515 | receiverName : 'wxid_8z66rux8lysr22', 1516 | statusDesc : '待确认收款', //收款描述 1517 | // '已收钱' //已收款 1518 | // '待%s确认收款' //等待对方收款 1519 | // '%s已收钱' //对方已收款 1520 | statusSupplementary: '', //状态补充信息 1521 | // 未领取: 1522 | // '1天内未确认,将退还给对方。<_wc_custom_link_ href="weixin://wcpay/transfer/rebacksendmsg">立即退还', 1523 | delayConfirmFlag: 0, 1524 | // 1525 | // 已领取: 1526 | // '<_wc_custom_link_ href="weixin://wcpay/transfer/watchbalance">查看零钱' 1527 | // 1528 | // 等待对方收款: 1529 | // '1天内朋友未确认,将退还给你。<_wc_custom_link_ href="weixin://wcpay/transfer/retrysendmsg">重发转账消息' 1530 | isPayer: false 1531 | // 1532 | // 对方已收款为空 1533 | }, 1534 | message: '', 1535 | status : 0 1536 | } 1537 | } 1538 | ``` 1539 | 1540 | | Param | Type | Description | 1541 | | --- | --- | --- | 1542 | | rawMsgData | object | 推送的消息结构体,即`push`事件中收到的Object | 1543 | 1544 | 1545 | 1546 | ### padchat.acceptTransfer(rawMsgData) ⇒ Promise.<object> 1547 | ***Deprecated*** 1548 | 1549 | 接受转账 1550 | 1551 | **Kind**: instance method of [Padchat](#Padchat) 1552 | **Returns**: Promise.<object> - 返回Promise,注意捕捉catch 1553 | ``` 1554 | { 1555 | success: true, 1556 | data : 1557 | { 1558 | external: 1559 | { 1560 | fee : 20, //转账金额(单位为分) 1561 | payer : '085exxx', //付款id 1562 | receiver: '085exxx', //接收id 1563 | retcode : '0', 1564 | retmsg : 'ok', 1565 | feeType : '1' 1566 | }, 1567 | message: '', 1568 | status : 0 1569 | } 1570 | } 1571 | ``` 1572 | 1573 | | Param | Type | Description | 1574 | | --- | --- | --- | 1575 | | rawMsgData | object | 推送的消息结构体,即`push`事件中收到的Object | 1576 | 1577 | 1578 | 1579 | ### padchat.receiveRedPacket(rawMsgData) ⇒ Promise.<object> 1580 | ***Deprecated*** 1581 | 1582 | 接收红包 1583 | 1584 | **Kind**: instance method of [Padchat](#Padchat) 1585 | **Returns**: Promise.<object> - 返回Promise,注意捕捉catch 1586 | ``` 1587 | { 1588 | success: true, 1589 | data : 1590 | { 1591 | external: //扩展数据结构 1592 | { 1593 | retcode : 0, 1594 | retmsg : 'ok', 1595 | sendId : '10000xxx', //发送id 1596 | wishing : '发3个红包', //红包祝语 1597 | isSender : 0, //是否自己发送 1598 | receiveStatus : 0, //接收状态:0未接收;2已领取 1599 | hbStatus : 3, //红包状态:3未领取完;4已领取完毕 1600 | statusMess : '发了一个红包,金额随机', // 1601 | hbType : 1, //红包类型 1602 | watermark : '', 1603 | sendUserName : 'binsee', //发送者wxid 1604 | timingIdentifier: 'C6E370xxx', 1605 | agreeDuty : //未知含义,非必然 1606 | { 1607 | title : '', 1608 | serviceProtocolWording: '', 1609 | serviceProtocolUrl : '', 1610 | buttonWording : '', 1611 | delayExpiredTime : 0, 1612 | agreedFlag : 1 1613 | } 1614 | }, 1615 | key : 'C6E370xxx', //红包key,用于领取红包 1616 | message: '', 1617 | status : 0 1618 | } 1619 | } 1620 | ``` 1621 | 1622 | | Param | Type | Description | 1623 | | --- | --- | --- | 1624 | | rawMsgData | object | 推送的消息结构体,即`push`事件中收到的Object | 1625 | 1626 | 1627 | 1628 | ### padchat.queryRedPacket(rawMsgData, [index]) ⇒ Promise.<object> 1629 | ***Deprecated*** 1630 | 1631 | 查看红包信息 1632 | NOTE: 如果是别人发的红包,未领取且未领取完毕时,无法取到红包信息 1633 | 1634 | **Kind**: instance method of [Padchat](#Padchat) 1635 | **Returns**: Promise.<object> - 返回Promise,注意捕捉catch 1636 | 未先接收红包返回结果: 1637 | ``` 1638 | { 1639 | success: true, 1640 | data : 1641 | { 1642 | external: //扩展数据 1643 | { 1644 | retcode : 0, 1645 | retmsg : 'ok', 1646 | operationHeader: [0], 1647 | record : [0] 1648 | }, 1649 | message: '', 1650 | status : 0 1651 | } 1652 | } 1653 | ``` 1654 | 1655 | 接收红包后查询结果: 1656 | ``` 1657 | { 1658 | success: true, 1659 | data : 1660 | { 1661 | external: 1662 | { 1663 | retcode : 0, 1664 | retmsg : 'ok', 1665 | recNum : 2, //已领取数 1666 | totalNum : 2, //红包个数 1667 | totalAmount : 100, //红包总金额(单位为分) 1668 | sendId : '10000xxx', //发送id 1669 | amount : 85, //领取到金额(单位为分) 1670 | wishing : 'Hello!', //红包祝语 1671 | isSender : 1, //是否是自己发送的 1672 | receiveId : '10000xxx', //接收id 1673 | hasWriteAnswer : 1, //是否已写回复 1674 | operationHeader: [], //未知 1675 | hbType : 1, //红包类型 1676 | isContinue : 0, //是否已领取完 1677 | hbStatus : 3, //红包状态:2未领取;3未领取完;4已领取完毕 1678 | // 普通红包或单发红包是2,随机红包是3或4 1679 | receiveStatus: 2, //接收状态:0未接收;2已领取 1680 | statusMess : '成功领到', //状态提示,未领取为空 1681 | headTitle : '', //红包头部标题 1682 | // '已领取1/2个,共0.01/0.02元' //自己发的红包未领取完时 1683 | // '2个红包共1.00元,15秒被抢光' //自己发的红包未领取完时 1684 | // '领取2/3个' //别人发的红包未领取完时 1685 | // '2个红包,42秒被抢光' //别人发的红包未领取完时 1686 | canShare : 0, //是否可分享 1687 | hbKind : 1, //红包种类 1688 | recAmount: 100, //已领取金额(单位为分) 1689 | record : 1690 | [ 1691 | { 1692 | receiveAmount: 85, //领取金额(单位为分) 1693 | receiveTime : '1523169782', //领取时间戳字符串 1694 | answer : '', //领取者留言,仅查询接口有效 1695 | receiveId : '10000xxx', 1696 | state : 1, 1697 | gameTips : '手气最佳', //仅红包领取完毕时,手气最佳者有此字段 1698 | receiveOpenId: '10000xxx', 1699 | userName : 'wxid_xxx' //领取者wxid 1700 | }, 1701 | { 1702 | receiveAmount: 15, 1703 | receiveTime : '1523174612', 1704 | answer : '谢谢红包', 1705 | receiveId : '1000039501001804086017706218338', 1706 | state : 1, 1707 | receiveOpenId: '1000039501001804086017706218338', 1708 | userName : 'binsee' 1709 | }, 1710 | ], 1711 | operationTail: //操作提示:仅自己发的红包有效 1712 | { 1713 | name : '未领取的红包,将于24小时后发起退款', 1714 | type : 'Text', 1715 | content: '', 1716 | enable : 1, 1717 | iconUrl: '', 1718 | ossKey : 4294967295 1719 | }, 1720 | atomicFunc : { enable: 0 }, 1721 | jumpChange : 1, 1722 | changeWording: '已存入零钱,可直接提现', //查询接口返回'已存入零钱,可直接转账' 1723 | sendUserName : 'wxid_xxx' //发送者wxid 1724 | }, 1725 | message: '', 1726 | status : 0 1727 | } 1728 | } 1729 | ``` 1730 | 1731 | | Param | Type | Default | Description | 1732 | | --- | --- | --- | --- | 1733 | | rawMsgData | object | | 推送的消息结构体,即`push`事件中收到的Object | 1734 | | [index] | Number | 0 | 列表索引。 每页11个,查看第二页11,查看第三页22,以此类推 | 1735 | 1736 | 1737 | 1738 | ### padchat.openRedPacket(rawMsgData, key) ⇒ Promise.<object> 1739 | ***Deprecated*** 1740 | 1741 | 领取红包 1742 | 1743 | **Kind**: instance method of [Padchat](#Padchat) 1744 | **Returns**: Promise.<object> - 返回Promise,注意捕捉catch 1745 | 已领取过红包: 1746 | ``` 1747 | { 1748 | success: true, 1749 | data : 1750 | { 1751 | external: { 1752 | retcode: 268502336, 1753 | retmsg : '你已领取过该红包' 1754 | }, 1755 | message: '', 1756 | status : 0 1757 | } 1758 | } 1759 | ``` 1760 | 1761 | 未领取过的红包: 1762 | ``` 1763 | { 1764 | success: true, 1765 | data : 1766 | { 1767 | external: 1768 | { 1769 | retcode : 0, 1770 | retmsg : 'ok', 1771 | sendId : '1000039501201804087013251181768', 1772 | amount : 1, 1773 | recNum : 2, 1774 | recAmount : 2, 1775 | totalNum : 3, 1776 | totalAmount : 4, 1777 | hasWriteAnswer : 0, 1778 | hbType : 1, 1779 | isSender : 0, 1780 | isContinue : 0, 1781 | receiveStatus : 2, 1782 | hbStatus : 3, 1783 | statusMess : '', 1784 | wishing : '发3个红包', 1785 | receiveId : '1000039501001804087013251181768', 1786 | headTitle : '领取2/3个', 1787 | canShare : 0, 1788 | operationHeader: [], 1789 | record : 1790 | [ 1791 | { 1792 | receiveAmount: 1, 1793 | receiveTime : '1523171198', 1794 | answer : '', 1795 | receiveId : '1000039501001804087013251181768', 1796 | state : 1, 1797 | receiveOpenId: '1000039501001804087013251181768', 1798 | userName : 'wxid_xxx' 1799 | }, 1800 | { 1801 | receiveAmount: 1, 1802 | receiveTime : '1523170992', 1803 | answer : '', 1804 | receiveId : '1000039501000804087013251181768', 1805 | state : 1, 1806 | receiveOpenId: '1000039501000804087013251181768', 1807 | userName : 'binsee' 1808 | } 1809 | ], 1810 | watermark : '', 1811 | jumpChange : 1, 1812 | changeWording : '已存入零钱,可直接提现', 1813 | sendUserName : 'binsee', 1814 | SystemMsgContext: //系统消息内容 1815 | ' 你领取了$binsee$的<_wc_custom_link_ color="#FD9931" href="weixin://weixinhongbao/opendetail?sendid=1000039501201804087013251181768&sign=68b9858edbc9ff8a88fb8c8fa987edaad88078b31daf6e7af4dba06e78849e50b29a3c1d10bad4893aff116a0db80c7d8a3aa96a5247e1ed095d88e66983fc6fd9f6f6dc8243411ef97727cf0bc698c3&ver=6">红包', 1816 | sessionUserName: '4674258153@chatroom', //会话wxid/chatroom 1817 | realNameInfo : { guideFlag: 0 } 1818 | }, 1819 | message: '', 1820 | status : 0 1821 | } 1822 | } 1823 | ``` 1824 | 1825 | | Param | Type | Description | 1826 | | --- | --- | --- | 1827 | | rawMsgData | object | 推送的消息结构体,即`push`事件中收到的Object | 1828 | | key | string | 红包的验证key,通过调用 receiveRedPacket 获得 | 1829 | 1830 | 1831 | 1832 | ### padchat.searchMp(content) ⇒ Promise.<object> 1833 | 搜索公众号 1834 | 1835 | **Kind**: instance method of [Padchat](#Padchat) 1836 | **Returns**: Promise.<object> - 返回Promise,注意捕捉catch 1837 | ``` 1838 | { 1839 | success: true, 1840 | data : 1841 | { 1842 | code: 0, 1843 | info: 1844 | { 1845 | continueFlag: 1, //仍有数据标志 1846 | cookies : //cookie数据 1847 | { 1848 | businessType: 1, 1849 | isHomepage : 1, 1850 | query : '"腾讯"', 1851 | scene : 2 1852 | }, 1853 | data: //返回的搜索相关数据 1854 | [{ 1855 | count: 20, 1856 | items: //搜索结果列表 1857 | [{ 1858 | aliasName: 'tencent', 1859 | brandFlag: 2, 1860 | brandInfo: 1861 | { 1862 | urls: 1863 | [{ 1864 | title: '查看历史消息', 1865 | url : 1866 | 'http://mp.weixin.qq.com/mp/getmasssendmsg?__biz=MzA3NDEyMDgzMw==#wechat_webview_type=1&wechat_redirect', 1867 | titleKey: '__mp_wording__brandinfo_history_massmsg' 1868 | }] 1869 | }, 1870 | docID: '3074120833', 1871 | externalInfo: 1872 | { 1873 | Appid: 'wx06441a33a2a67de4', 1874 | BindWxaInfo: 1875 | { 1876 | wxaEntryInfo: 1877 | [{ 1878 | title : '腾讯+', 1879 | username: 'gh_3a5568e1268b@app', 1880 | iconUrl : 'http://mmbiz.qpic.cn/mmbiz_png/xxx/0?wx_fmt=png' 1881 | }] 1882 | }, 1883 | FunctionFlag : 1, 1884 | InteractiveMode : '2', 1885 | IsAgreeProtocol : '1', 1886 | IsHideInputToolbarInMsg: '0', 1887 | IsShowHeadImgInMsg : '1', 1888 | RegisterSource : 1889 | { 1890 | IntroUrl: 1891 | 'http://mp.weixin.qq.com/mp/getverifyinfo?__biz=MzA3NDEyMDgzMw==&type=reg_info#wechat_redirect', 1892 | RegisterBody: '深圳市腾讯计算机系统有限公司' 1893 | }, 1894 | RoleId : '1', 1895 | ScanQRCodeType: 1, 1896 | ServiceType : 0, 1897 | VerifySource : 1898 | { 1899 | Description: '深圳市腾讯计算机系统有限公司', 1900 | IntroUrl : 1901 | 'http://mp.weixin.qq.com/mp/getverifyinfo?__biz=MzA3NDEyMDgzMw==#wechat_webview_type=1&wechat_redirect', 1902 | Type : 0, 1903 | VerifyBizType: 1 1904 | } 1905 | }, 1906 | friendsFollowCount: 0, 1907 | headHDImgUrl : 'http://wx.qlogo.cn/mmhead/xxx/0', 1908 | headImgUrl : 'http://wx.qlogo.cn/mmhead/xxx/132', 1909 | iconUrl : 'http://mmbiz.qpic.cn/mmbiz_png/xxx/0?wx_fmt=png', 1910 | nickName : '腾讯', 1911 | nickNameHighlight : '腾讯', 1912 | segQuery : ' 腾讯', 1913 | signature : '腾讯公司唯一官方帐号。', 1914 | signatureHighlight: '腾讯公司唯一官方帐号。', 1915 | userName : 'gh_88b080670a71', 1916 | verifyFlag : 24 1917 | }], 1918 | keywordList: ['腾讯'], 1919 | resultType : 0, 1920 | title : '公众号', 1921 | totalCount : 1900, 1922 | type : 1 1923 | }], 1924 | direction : 2, 1925 | exposeMs : 500, 1926 | isDivide : 0, 1927 | isExpose : 1, 1928 | isHomePage: 1, 1929 | lang : 'zh_CN', 1930 | monitorMs : 100, 1931 | offset : 20, 1932 | query : '"腾讯"', 1933 | resultType: 0, 1934 | ret : 0, 1935 | searchID : '18232918846508425807' 1936 | }, 1937 | message: '', 1938 | offset : 20, 1939 | status : 0 1940 | } 1941 | } 1942 | ``` 1943 | 1944 | | Param | Type | Description | 1945 | | --- | --- | --- | 1946 | | content | string | 公众号名称等关键字 | 1947 | 1948 | 1949 | 1950 | ### padchat.getSubscriptionInfo(ghName) ⇒ Promise.<object> 1951 | 获取公众号信息 1952 | 1953 | **Kind**: instance method of [Padchat](#Padchat) 1954 | **Returns**: Promise.<object> - 返回Promise,注意捕捉catch 1955 | ``` 1956 | { 1957 | success: true, 1958 | data : 1959 | { 1960 | info: 1961 | { 1962 | alias : 'tencent', 1963 | appid : 'wx06441a33a2a67de4', 1964 | bigHeadImgUrl: 'http://wx.qlogo.cn/mmhead/xxx/0', 1965 | bindKFUin : '0', 1966 | bindWxaInfo : 1967 | { 1968 | wxaEntryInfo: 1969 | [{ 1970 | username: 'gh_3a5568e1268b@app', 1971 | title : '腾讯+', 1972 | iconUrl : 'http://mmbiz.qpic.cn/mmbiz_png/xxx/0?wx_fmt=png' 1973 | }], 1974 | bizEntryInfo: [] 1975 | }, 1976 | bitMask : '4294967295', 1977 | brandIconURL: 'http://mmbiz.qpic.cn/mmbiz_png/xxx/0?wx_fmt=png', 1978 | brandInfo : 1979 | { 1980 | urls: 1981 | [{ 1982 | title : '查看历史消息', 1983 | url : 'http://mp.weixin.qq.com/mp/getmasssendmsg?xxxx', 1984 | titleKey: '__mp_wording__brandinfo_history_massmsg' 1985 | }] 1986 | }, 1987 | functionFlag : '1', 1988 | interactiveMode : '2', 1989 | isAgreeProtocol : '1', 1990 | isHideInputToolbarInMsg: '0', 1991 | isShowHeadImgInMsg : '1', 1992 | mmBizMenu : 1993 | { 1994 | uin : 3074120833, 1995 | version : 425306837, 1996 | interactiveMode: 2, 1997 | updateTime : 1518401098, 1998 | buttonList : 1999 | [ 2000 | { 2001 | id : 425306837, 2002 | type : 0, 2003 | name : '产品体验', 2004 | key : 'rselfmenu_2', 2005 | value: '', 2006 | subButtonList: 2007 | [{ 2008 | id : 425306837, 2009 | type : 2, 2010 | name : '往期内测', 2011 | key : 'rselfmenu_2_1', 2012 | value : 'http://mp.weixin.qq.com/mp/xxxxx', 2013 | subButtonList: [], 2014 | nativeUrl : '' 2015 | }], 2016 | nativeUrl: '' 2017 | }] 2018 | }, 2019 | nickName : '腾讯', 2020 | pyInitial: 'TX', 2021 | quanPin : 'tengxun', 2022 | registerSource: 2023 | { 2024 | registerBody: '深圳市腾讯计算机系统有限公司', 2025 | introUrl : 'http://mp.weixin.qq.com/mp/getverifyinfo?xxxx' 2026 | }, 2027 | roleId : '1', 2028 | scanQRCodeType : '1', 2029 | serviceType : '0', 2030 | signature : '腾讯公司唯一官方帐号。', 2031 | smallHeadImgUrl: 'http://wx.qlogo.cn/mmhead/xxx/132', 2032 | userName : 'gh_88b080670a71', 2033 | verifyFlag : '24', 2034 | verifyInfo : '深圳市腾讯计算机系统有限公司', 2035 | verifySource : 2036 | { 2037 | description : '深圳市腾讯计算机系统有限公司', 2038 | introUrl : 'http://mp.weixin.qq.com/mp/getverifyinfo?xxx', 2039 | type : 0, 2040 | verifyBizType: 1 2041 | } 2042 | }, 2043 | message: ' ', 2044 | status : 0 2045 | } 2046 | } 2047 | ``` 2048 | 2049 | | Param | Type | Description | 2050 | | --- | --- | --- | 2051 | | ghName | string | 公众号gh名称,即`gh_`格式的id | 2052 | 2053 | 2054 | 2055 | ### padchat.operateSubscription(ghName, menuId, menuKey) ⇒ Promise.<object> 2056 | 操作公众号菜单 2057 | 2058 | **Kind**: instance method of [Padchat](#Padchat) 2059 | **Returns**: Promise.<object> - 返回Promise,注意捕捉catch 2060 | ``` 2061 | { 2062 | success: true, 2063 | data : { 2064 | message: '', 2065 | status : 0 2066 | } 2067 | } 2068 | ``` 2069 | 2070 | | Param | Type | Description | 2071 | | --- | --- | --- | 2072 | | ghName | string | 公众号gh名称,即`gh_`格式的id | 2073 | | menuId | Number | 菜单id | 2074 | | menuKey | string | 菜单key | 2075 | 2076 | 2077 | 2078 | ### padchat.getRequestToken(ghName, url) ⇒ Promise.<object> 2079 | 获取网页访问授权 2080 | 2081 | **Kind**: instance method of [Padchat](#Padchat) 2082 | **Returns**: Promise.<object> - 返回Promise,注意捕捉catch 2083 | ``` 2084 | { 2085 | success: true, 2086 | data : 2087 | { 2088 | info: 2089 | { 2090 | 'X-WECHAT-KEY': 'xxxxxxxxxxxx', //授权key 2091 | 'X-WECHAT-UIN': 'MTQ5ODA2NDYw' //授权uin 2092 | }, 2093 | message: '', 2094 | status : 0, 2095 | fullUrl: //完整授权访问url 2096 | 'https://mp.weixin.qq.com/s?__biz=MzA5MDAwOTExMw==&mid=200126214&idx=1&sn=a1e7410ec56de5b6c4810dd7f7db8a47&chksm=1e0b3470297cbd666198666278421aed0a131d775561c08f52db0c82ce0e6a9546aac072a20e&mpshare=1&scene=1&srcid=0408bN3ACxqAH6jyq4vCBP9e&ascene=7&devicetype=iPad+iPhone+OS9.0.2&version=16060125&nettype=WIFI&lang=zh_CN&fontScale=100&pass_ticket=ZQW8EHr9vk%2BPGoWzmON4ev8I0MmliT4mp1ERTPEl8lc%3D&wx_header=1', 2097 | shareUrl: //分享url 2098 | 'http://mp.weixin.qq.com/s/QiB3FPE6fJmV6asvvxIkvA' 2099 | } 2100 | } 2101 | ``` 2102 | 2103 | | Param | Type | Description | 2104 | | --- | --- | --- | 2105 | | ghName | string | 公众号gh名称,即`gh_`格式的id | 2106 | | url | string | 网页url | 2107 | 2108 | 2109 | 2110 | ### padchat.requestUrl(url, xKey, xUin) ⇒ Promise.<object> 2111 | 访问网页 2112 | 2113 | **Kind**: instance method of [Padchat](#Padchat) 2114 | **Returns**: Promise.<object> - 返回Promise,注意捕捉catch 2115 | ``` 2116 | { 2117 | success: true, 2118 | data : 2119 | { 2120 | message : '', 2121 | response: //完整的访问结果原始数据文本(包含http头数据) 2122 | 'HTTP/1.1 200 OK\r\nContent-Security-Policy: script-src \'self\' \'unsafe-inline\' \'unsafe-eval\' http://*.qq.com https://*.qq.com http://*.weishi.com https://*.weishi.com xxxxxxxxxxxxxxxxxxxxxxxxxxx', 2123 | status: 0 2124 | } 2125 | } 2126 | ``` 2127 | 2128 | | Param | Type | Description | 2129 | | --- | --- | --- | 2130 | | url | string | 网页url地址 | 2131 | | xKey | string | 访问Key,用`getRequestToken`获取 | 2132 | | xUin | string | 访问uin,用`getRequestToken`获取 | 2133 | 2134 | 2135 | 2136 | ### "open" 2137 | Open event 2138 | websocket连接打开事件 2139 | 2140 | **Kind**: event emitted by [Padchat](#Padchat) 2141 | **Example** 2142 | ```js 2143 | const wx = new Padchat() 2144 | wx.on('open',()=>{ 2145 | console.log(`连接成功!`) 2146 | }) 2147 | ``` 2148 | 2149 | 2150 | ### "close" 2151 | Close event 2152 | websocket连接关闭事件。可在此事件中调用`Padchat.start()`发起重连 2153 | 2154 | **Kind**: event emitted by [Padchat](#Padchat) 2155 | **Properties** 2156 | 2157 | | Name | Type | Description | 2158 | | --- | --- | --- | 2159 | | code | number | 关闭代码
`3201`: 你的Token是无效的,请联系我们获取有效的Token,以连接padchat-sdk
`3202`: 你的Token已经登录了一个机器人,请不要用同一个Token登录多个机器人
`3203`: 你的Token已经过期了,请联系我们进行续费 | 2160 | | [msg] | string | 关闭说明 | 2161 | 2162 | **Example** 2163 | ```js 2164 | const wx = new Padchat() 2165 | wx.on('close',(code,msg)=>{ 2166 | console.log(`Websocket 已关闭!code: ${code} - ${msg}`) 2167 | wx.start() 2168 | }) 2169 | ``` 2170 | 2171 | 2172 | ### "error" 2173 | Error event 2174 | 错误事件 2175 | 2176 | **Kind**: event emitted by [Padchat](#Padchat) 2177 | **Properties** 2178 | 2179 | | Name | Type | Description | 2180 | | --- | --- | --- | 2181 | | error | error | 报错信息 | 2182 | 2183 | **Example** 2184 | ```js 2185 | const wx = new Padchat() 2186 | wx.on('error',e=>{ 2187 | console.log('Websocket 错误:', e.message) 2188 | }) 2189 | ``` 2190 | 2191 | 2192 | ### "warn" 2193 | Warn event 2194 | 实例错误提示 2195 | 2196 | **Kind**: event emitted by [Padchat](#Padchat) 2197 | **Properties** 2198 | 2199 | | Name | Type | Description | 2200 | | --- | --- | --- | 2201 | | error | error | 报错信息 | 2202 | 2203 | **Example** 2204 | ```js 2205 | const wx = new Padchat() 2206 | wx.on('warn',e=>{ 2207 | console.log('任务出现错误:', e.message) 2208 | }) 2209 | ``` 2210 | 2211 | 2212 | ### "qrcode" 2213 | Qrcode event 2214 | 登陆二维码推送 2215 | 2216 | **Kind**: event emitted by [Padchat](#Padchat) 2217 | **Properties** 2218 | 2219 | | Name | Type | Description | 2220 | | --- | --- | --- | 2221 | | data | object | 二维码信息 | 2222 | | [data.url] | string | 登陆二维码解析后的内容url,可使用此url作为内容生成二维码图片后,使用手机扫码登陆 | 2223 | | msg | string \| null | 附加提示信息 | 2224 | 2225 | **Example** 2226 | ```js 2227 | const wx = new Padchat() 2228 | wx.on('qrcode',data=>{ 2229 | console.log(`登陆二维码内容为: "${data.url}"`) 2230 | // 可使用`qrcode-terminal`库在终端生成二维码 2231 | }) 2232 | ``` 2233 | 2234 | 2235 | ### "scan" 2236 | Scan event 2237 | 扫码状态推送 2238 | 2239 | **Kind**: event emitted by [Padchat](#Padchat) 2240 | **Properties** 2241 | 2242 | | Name | Type | Description | 2243 | | --- | --- | --- | 2244 | | data | object | 扫码状态 | 2245 | | data.status | number | 扫码状态:
`0` 等待扫码
`1` 扫码完成,等待手机端确认登陆
`2` 手机端已确认,等待登陆
`3` 二维码过期
`4` 手机端取消登陆
其他状态未知 | 2246 | | [data.subStatus] | number | 扫码子状态,仅`status`为`2`时有效
`0` 登陆成功
`1` 登陆失败
其他状态未知 | 2247 | | [data.headUrl] | string | 头像url **(扫码后存在)** | 2248 | | [data.deviceType] | string | 主设备类型 **(扫码后存在)** | 2249 | | [data.userName] | string | 账号wxid,全局唯一 **(扫码后存在)** | 2250 | | [data.uin] | number | 账号uin,全局唯一 **(扫码后存在)** | 2251 | | [data.email] | string | 账号绑定的邮箱 **(确认登陆后存在)** | 2252 | | [data.phoneNumber] | string | 账号绑定的手机号 **(确认登陆后存在)** | 2253 | | [data.qq] | number | 账号绑定的QQ号 **(确认登陆后存在)** | 2254 | | [data.nickName] | string | 账号昵称 **(确认登陆后存在)** | 2255 | | [data.external] | number | 是否为扩展设备登陆
`0` 主设备登陆
`1` 扩展设备登录 | 2256 | | msg | string \| null | 附加提示信息 | 2257 | 2258 | **Example** 2259 | ```js 2260 | const wx = new Padchat() 2261 | wx.on('scan',data=>{ 2262 | switch (data.status) { 2263 | case 0: 2264 | case 1: 2265 | case 2: 2266 | case 3: 2267 | case 4: 2268 | default: 2269 | break 2270 | } 2271 | }) 2272 | ``` 2273 | 2274 | 2275 | ### "login" 2276 | Login event 2277 | 登陆成功推送 2278 | 2279 | **Kind**: event emitted by [Padchat](#Padchat) 2280 | **Example** 2281 | ```js 2282 | const wx = new Padchat() 2283 | wx.on('login',()=>{ 2284 | console.log('微信账号登陆成功!') 2285 | }) 2286 | ``` 2287 | 2288 | 2289 | ### "autoLogin" 2290 | AutoLogin event 2291 | 自动重连成功推送 2292 | 2293 | 自动重连后token会变化,可在此时获取新的token,否则使用旧token将不能断线重连,但可以二次登陆(需手机端确认登陆) 2294 | 2295 | **Kind**: event emitted by [Padchat](#Padchat) 2296 | **Example** 2297 | ```js 2298 | const wx = new Padchat() 2299 | wx.on('autoLogin',()=>{ 2300 | wx.getLoginToken() 2301 | console.log('自动重连成功!') 2302 | }) 2303 | ``` 2304 | 2305 | 2306 | ### "loaded" 2307 | Loaded event 2308 | 通讯录同步完毕推送 2309 | 2310 | **Kind**: event emitted by [Padchat](#Padchat) 2311 | **Example** 2312 | ```js 2313 | const wx = new Padchat() 2314 | wx.on('loaded',()=>{ 2315 | console.log('通讯录同步完毕!') 2316 | }) 2317 | ``` 2318 | 2319 | 2320 | ### "logout" 2321 | Logout event 2322 | 微信账号退出推送 2323 | 2324 | **Kind**: event emitted by [Padchat](#Padchat) 2325 | **Properties** 2326 | 2327 | | Name | Type | Description | 2328 | | --- | --- | --- | 2329 | | data | object | | 2330 | | [data.error] | string \| null | 错误提示信息 | 2331 | | [data.msg] | string \| null | 附加提示信息 | 2332 | | [msg] | string \| null | 附加提示信息(同`data.msg`) | 2333 | 2334 | **Example** 2335 | ```js 2336 | const wx = new Padchat() 2337 | wx.on('logout',({error,msg})=>{ 2338 | console.log('微信账号已退出! ',error,msg) 2339 | }) 2340 | ``` 2341 | 2342 | 2343 | ### "over" 2344 | Over event 2345 | 实例关闭推送 2346 | 2347 | **Kind**: event emitted by [Padchat](#Padchat) 2348 | **Properties** 2349 | 2350 | | Name | Type | Description | 2351 | | --- | --- | --- | 2352 | | data | object | | 2353 | | [data.msg] | string \| null | 附加提示信息 | 2354 | | [msg] | string \| null | 附加提示信息(同`data.msg`) | 2355 | 2356 | **Example** 2357 | ```js 2358 | const wx = new Padchat() 2359 | wx.on('over',({msg})=>{ 2360 | console.log('任务实例已关闭!',msg) 2361 | }) 2362 | ``` 2363 | 2364 | 2365 | ### "sns" 2366 | Sns event 2367 | 朋友圈通知 2368 | 2369 | **Kind**: event emitted by [Padchat](#Padchat) 2370 | **Example** 2371 | ```js 2372 | const wx = new Padchat() 2373 | wx.on('sns',()=>{ 2374 | console.log('收到朋友圈事件!') 2375 | }) 2376 | ``` 2377 | 2378 | 2379 | ### "push" 2380 | Push event 2381 | 联系人/消息推送 2382 | 2383 | **Kind**: event emitted by [Padchat](#Padchat) 2384 | **Properties** 2385 | 2386 | | Name | Type | Description | 2387 | | --- | --- | --- | 2388 | | data.mType | number | 推送类型
`1` : 文字消息
`2` : 好友信息推送,包含好友,群,公众号信息
`3` : 收到图片消息
`34` : 语音消息
`35` : 用户头像buf
`37` : 收到好友请求消息
`42` : 名片消息
`43` : 视频消息
`47` : 表情消息
`48` : 定位消息
`49` : APP消息(文件 或者 链接 H5)
`50` : 语音通话
`51` : 状态通知(如打开与好友/群的聊天界面)
`52` : 语音通话通知
`53` : 语音通话邀请
`62` : 小视频
`2000` : 转账消息
`2001` : 收到红包消息
`3000` : 群邀请
`9999` : 系统通知
`10000`: 微信通知信息。微信群信息变更,多为群名修改、进群、离群信息,不包含群内聊天信息
`10002`: 撤回消息 | 2389 | | [data.fromUser] | string | (`mType`非2) 发件人 | 2390 | | [data.toUser] | string | (`mType`非2) 收件人 | 2391 | | [data.content] | string | (`mType`非2) 消息内容。非文本型消息时,此字段可能为xml结构文本 | 2392 | | [data.msgSource] | string | (`mType`非2) | 2393 | | [data.data] | string | 图片、语音、视频等媒体文件base64文本 | 2394 | | [data.description] | string | (部分`mType`非2) 消息描述 | 2395 | | [data.msgId] | string | (`mType`非2) 消息id | 2396 | | [data.timestamp] | string | (`mType`非2) 消息时间戳 | 2397 | | [data.uin] | number | 当前账号uin | 2398 | | [data.*] | string | 其他字段请自行输出查看 | 2399 | 2400 | **Example** 2401 | ```js 2402 | const util = require('util') 2403 | const wx = new Padchat() 2404 | wx.on('push',data=>{ 2405 | console.log('push:',util.inspect(data, { depth: 10 })) 2406 | }) 2407 | ``` 2408 | 2409 | 2410 | ### "contact" 2411 | Contact event 2412 | 联系人/消息推送 2413 | 2414 | **Kind**: event emitted by [Padchat](#Padchat) 2415 | **Properties** 2416 | 2417 | | Name | Type | Description | 2418 | | --- | --- | --- | 2419 | | data.mType | number | 推送类型
`2`: 好友信息推送,包含好友,群,公众号信息 | 2420 | | data.city | string | 城市 | 2421 | | data.country | string | 国家 | 2422 | | data.provincia | string | 省份 | 2423 | | data.intro | string | 公众号主体 | 2424 | | data.stranger | string | 个性签名 | 2425 | | data.label | string | | 2426 | | data.level | number | | 2427 | | data.sex | number | 性别: 1男 2女 0未知 | 2428 | | data.signature | string | v1值 | 2429 | | data.source | number | 联系人添加渠道 | 2430 | | data.uin | number | 当前账号uin (自己微信号的,不是好友的) | 2431 | | data.bigHead | string | 高清头像 | 2432 | | data.smallHead | string | 头像缩略图 | 2433 | | data.bitValue | number | | 2434 | | data.chatroomId | number | 群版本号 | 2435 | | data.chatroomOwner | string | 群主wxid | 2436 | | data.imgFlag | number | | 2437 | | data.maxMemberCount | number | 群成员上限 | 2438 | | data.memberCount | number | 群成员数量 | 2439 | | data.msgType | number | | 2440 | | data.nickName | string | 联系人昵称 | 2441 | | data.pyInitial | string | 昵称拼音简写 | 2442 | | data.quanPin | string | 昵称拼音全拼 | 2443 | | data.remark | string | 备注 | 2444 | | data.remarkPyInitial | string | 备注拼音简写 | 2445 | | data.remarkQuanPin | string | 备注拼音全拼 | 2446 | | data.userName | string | 联系人微信号/wxid | 2447 | 2448 | **Example** 2449 | ```js 2450 | const util = require('util') 2451 | const wx = new Padchat() 2452 | wx.on('push',data=>{ 2453 | console.log('push:',util.inspect(data, { depth: 10 })) 2454 | }) 2455 | ``` 2456 | 2457 | 2458 | ### Padchat.Padchat 2459 | **Kind**: static class of [Padchat](#Padchat) 2460 | 2461 | 2462 | #### new Padchat([url]) 2463 | Creates an instance of Padchat. 2464 | 2465 | 2466 | | Param | Type | Description | 2467 | | --- | --- | --- | 2468 | | [url] | string | 服务器url,后缀你的token:`ws://47.99.211.34:8181/` 有问题联系QQ群:935214596 | 2469 | 2470 | -------------------------------------------------------------------------------- /helper.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | // 将object中的属性名称转换为全驼峰格式 4 | 5 | 6 | module.exports = { 7 | toCamelCase, 8 | toUnderLine, 9 | structureXml, 10 | } 11 | 12 | /** 13 | * 将object中的属性名称从下划线转换为驼峰格式 14 | * (包含子数据的属性名,会遍历转换) 15 | * 16 | * @param {any} obj 要转换的object 17 | * @param {boolean} [big=true] 是否转换为大驼峰格式 18 | * @returns {Object} 转换后的object 19 | */ 20 | function toCamelCase(obj, big = false) { 21 | if (obj instanceof Array) { 22 | return obj.map(item => toCamelCase(item)) 23 | } 24 | if (!(obj instanceof Object)) { 25 | return obj 26 | } 27 | for (const key in obj) { 28 | if (obj.hasOwnProperty(key)) { 29 | let newKey = key.replace(/_(\w)/g, (match, val, offset) => { return val.toUpperCase() }) 30 | if (big) { 31 | newKey = newKey.replace(/^(\w)/, (match, val, offset) => { return val.toUpperCase() }) 32 | } else { 33 | // 将首字母转换为小写(部分字段名称开头两个为大写,比如`PYInitial`/`MMBizMenu`) 34 | // 跳过`X-WECHAT-KEY`和`X-WECHAT-UIN`这种字段 35 | newKey = newKey.replace(/^(\w{2})/, (match, val, offset) => { return val.toLowerCase() }) 36 | } 37 | if ((obj[key] instanceof Array) || (obj[key] instanceof Object)) { 38 | obj[key] = toCamelCase(obj[key]) 39 | } 40 | if (newKey !== key) { 41 | obj[newKey] = obj[key] 42 | delete obj[key] 43 | } 44 | } 45 | } 46 | return obj 47 | } 48 | 49 | /** 50 | * 将object中的属性名称从驼峰转换为下划线格式 51 | * 52 | * @param {any} obj 要转换的object 53 | * @returns {Object} 转换后的object 54 | */ 55 | function toUnderLine(obj) { 56 | const newObj = {} 57 | if (!(obj instanceof Object)) { 58 | return obj 59 | } 60 | for (const key in obj) { 61 | if (obj.hasOwnProperty(key)) { 62 | const newKey = key.replace(/([A-Z])/g, (match, val, offset) => { return (offset ? '_' : '') + val }).toLowerCase() 63 | newObj[newKey] = obj[key] 64 | } 65 | } 66 | return newObj 67 | } 68 | 69 | /** 70 | * 组装appmsg消息体 71 | * 72 | * @param {object} object 消息体参数 73 | * @param {object} [object.appid] - appid,忽略即可 74 | * @param {object} [object.sdkver] - sdk版本,忽略即可 75 | * @param {object} [object.title] - 标题 76 | * @param {object} [object.des] - 描述 77 | * @param {object} [object.url] - 链接url 78 | * @param {object} [object.thumburl] - 缩略图url 79 | * ``` 80 | * { 81 | * appid = '', //appid,忽略即可 82 | * sdkver = '', //sdk版本,忽略即可 83 | * title = '', //标题 84 | * des = '', //描述 85 | * url = '', //链接url 86 | * thumburl = '', //缩略图url 87 | * } 88 | * ``` 89 | * @returns {String} 组装的消息体 90 | */ 91 | function structureXml(object) { 92 | const { appid = '', sdkver = '', title = '', des = '', url = '', thumburl = '' } = object 93 | return ` 94 | ${title} 95 | ${des} 96 | view 97 | 5 98 | 0 99 | 100 | ${url} 101 | ${thumburl} 102 | `.replace(/\n/g, '') 103 | } 104 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const EventEmitter = require('events') 4 | const Websocket = require('ws') 5 | const UUID = require('uuid') 6 | 7 | const Helper = require('./helper') 8 | const { 9 | wsEventType, 10 | loginType, 11 | blacklist, 12 | } = require('./define') 13 | 14 | const server = 'ws://127.0.0.1:7777' 15 | 16 | /** 17 | * Padchat模块 18 | * 19 | * 使用websocket与服务器进行通讯,拥有以下事件 20 | * 21 | * Event | 说明 22 | * ---- | ---- 23 | * qrcode | 推送的二维码 24 | * scan | 扫码状态 25 | * push | 新信息事件 26 | * login | 登录 27 | * loaded | 通讯录载入完毕 28 | * logout | 注销登录 29 | * over | 实例注销(账号不退出)(要再登录需要重新调用init) 30 | * warn | 错误信息 31 | * sns | 朋友圈更新事件 32 | * 33 | * **接口返回数据结构:** 所有接口均返回以下结构数据: 34 | * ``` 35 | { 36 | success: true, // 执行是否成功 37 | err : '', // 错误提示 38 | msg : '', // 附加信息 39 | data : {} // 返回结果 40 | } 41 | * ``` 42 | * 43 | * TODO: 补充各监听事件返回的数据定义 44 | * 45 | * @class Padchat 46 | * @extends {EventEmitter} 47 | */ 48 | class Padchat extends EventEmitter { 49 | /** 50 | * Creates an instance of Padchat. 51 | * @param {string} [url] - 服务器url,后缀你的token:`ws://127.0.0.1:7777/{YourToken}` 52 | * 如:`ws://127.0.0.1:7777/mytoken_123456` 53 | * @memberof Padchat 54 | */ 55 | constructor(url = server) { 56 | super() 57 | this.url = url 58 | this._event = new EventEmitter() 59 | // 向ws服务器提交指令后,返回结果的超时时间,单位毫秒 60 | this.sendTimeout = 10 * 1000 61 | this.connected = false 62 | this._lastStartTime = 0 63 | this.ws = {} 64 | this.openSyncMsg = true //是否同步消息 65 | this.openSyncContact = true //是否同步联系人 66 | this.loaded = false //通讯录载入完毕 67 | this.cmdSeq = 1 68 | this.sendTimeout = 10 * 1000 69 | this.connected = false 70 | this._lastStartTime = 0 71 | this.ws = {} 72 | this.start() 73 | } 74 | 75 | /** 76 | * 启动websocket连接 77 | * 78 | * @memberof Padchat 79 | */ 80 | async start() { 81 | // 限制启动ws连接间隔时间 82 | if (Date.now() - this._lastStartTime < 200) { 83 | throw new Error('建立ws连接时间间隔过短!') 84 | } 85 | this._lastStartTime = Date.now() 86 | if (this.ws instanceof Websocket && this.ws.readyState === this.ws.OPEN) { 87 | this.ws.terminate() 88 | } 89 | this.ws = new Websocket(this.url) 90 | .on('message', (msg) => { 91 | onWsMsg.call(this, msg) 92 | }) 93 | .on('open', () => { 94 | this.connected = true 95 | /** 96 | * Open event 97 | * websocket连接打开事件 98 | * 99 | * @event Padchat#open 100 | * @example 101 | * const wx = new Padchat() 102 | * wx.on('open',()=>{ 103 | * console.log(`连接成功!`) 104 | * }) 105 | * 106 | * @memberof Padchat 107 | */ 108 | this.emit('open') 109 | }) 110 | .on('close', (code = 0, msg = '') => { 111 | this.connected = false 112 | /** 113 | * Close event 114 | * websocket连接关闭事件。可在此事件中调用`Padchat.start()`发起重连 115 | * 116 | * @event Padchat#close 117 | * @property {number} code - 关闭代码 118 | *
`3201`: 你的Token是无效的,请联系我们获取有效的Token,以连接padchat-sdk 119 | *
`3202`: 你的Token已经登录了一个机器人,请不要用同一个Token登录多个机器人 120 | *
`3203`: 你的Token已经过期了,请联系我们进行续费 121 | * @property {string} [msg] - 关闭说明 122 | * @example 123 | * const wx = new Padchat() 124 | * wx.on('close',(code,msg)=>{ 125 | * console.log(`Websocket 已关闭!code: ${code} - ${msg}`) 126 | * wx.start() 127 | * }) 128 | * 129 | * @memberof Padchat 130 | */ 131 | this.emit('close', code, msg) 132 | }) 133 | .on('error', (e) => { 134 | /** 135 | * Error event 136 | * 错误事件 137 | * 138 | * @event Padchat#error 139 | * @property {error} error - 报错信息 140 | * @example 141 | * const wx = new Padchat() 142 | * wx.on('error',e=>{ 143 | * console.log('Websocket 错误:', e.message) 144 | * }) 145 | * 146 | * @memberof Padchat 147 | */ 148 | this.emit('error', e) 149 | }) 150 | } 151 | 152 | /** 153 | * ws发送数据 154 | * 155 | * @param {object} data - 数据 156 | * @returns {Promise} 返回ws处理结果 157 | * @private 158 | * @memberof Padchat 159 | */ 160 | async _send(data) { 161 | return new Promise((resolve, reject) => { 162 | if (!this.connected || !(this.ws instanceof Websocket)) { 163 | reject('websocket未连接!') 164 | } 165 | this.ws.send(JSON.stringify(data), e => { 166 | if (e) { 167 | reject(new Error(`ws发送数据失败! err: ${e.message}`)) 168 | } else { 169 | resolve(true) 170 | } 171 | }) 172 | }) 173 | } 174 | 175 | /** 176 | * 包装ws发送数据 177 | * 178 | * @param {object} data - 要发送的数据 179 | * @param {number} timeout - 发送超时时间 180 | * @returns {Promise} 返回ws处理结果 181 | * @private 182 | * @memberof Padchat 183 | */ 184 | async asyncSend(data, timeout = 30000) { 185 | if (!data.cmdId) { 186 | data.cmdId = '' + this.cmdSeq++ 187 | if (this.cmdSeq >= 0xffffff00) { 188 | this.cmdSeq = 1 189 | } 190 | } 191 | return new Promise((res, rej) => { 192 | try { 193 | getCmdRecv.call(this, data.cmdId, timeout) 194 | .then(data => { 195 | // console.info('getCmdRecv ret data:', data) 196 | res(data.payload) 197 | }) 198 | this._send(data) 199 | .then(async ret => { 200 | // console.info('asyncSend ret: %s', ret) 201 | return ret 202 | }) 203 | } catch (e) { 204 | rej(e) 205 | } 206 | }) 207 | } 208 | 209 | /** 210 | * 包装ws发送指令数据包 211 | * 212 | * @param {string} cmd - 要操作的接口 213 | * @param {object} data - 要发送的数据 214 | * @returns {Promise} 返回ws处理结果 215 | * @private 216 | * @memberof Padchat 217 | */ 218 | async sendCmd(cmd, data = {}) { 219 | if (data.rawMsgData) { 220 | // 清洗掉无用而占空间的字段 221 | data.rawMsgData = clearRawMsg(data.rawMsgData) 222 | data.rawMsgData = Helper.toUnderLine(data.rawMsgData) 223 | } 224 | 225 | return await this.asyncSend({ 226 | type: 'user', 227 | cmd, 228 | payload: data, 229 | }) 230 | .then(ret => { 231 | // 用于抓取操作接口对应的返回数据,便于写入文档 232 | this.emit('cmdRet', cmd, ret) 233 | return ret 234 | }) 235 | .catch(e => { 236 | throw e 237 | }) 238 | } 239 | 240 | /** 241 | * 初始化 242 | * 243 | * @returns {Promise} 返回Promise,注意捕捉catch 244 | * ``` 245 | { 246 | error : '', 247 | success: true 248 | } 249 | * ``` 250 | * @memberof Padchat 251 | */ 252 | async init() { 253 | return await this.sendCmd('init') 254 | } 255 | 256 | /** 257 | * 关闭微信实例(不退出登陆) 258 | * 259 | * @returns {Promise} 返回Promise,注意捕捉catch 260 | * @memberof Padchat 261 | */ 262 | async close() { 263 | return await this.sendCmd('close') 264 | } 265 | 266 | /** 267 | * 登录账号 268 | * 首次登录不需要传入`wxData`,登陆成功后本地保存`wxData`和`token`,以后使用断线重连或二次登陆,可降低封号概率。 269 | * 任何登陆方式,使用成功登陆过的`wxData`都可降低封号概率。 270 | * 271 | * @param {string} type - 登录类型,默认为扫码登录 272 | *
`auto` **断线重连**,用于短时间使用`wxData`和`token`再次登录。`token`有效期很短,如果登陆失败,建议使用二次登陆方式 273 | *
`request` **二次登陆**。需要提供`wxData`和`token`数据,手机端会弹出确认框,点击后登陆。不容易封号 274 | *
`qrcode` **扫码登录**(现在此模式已经可以返回二维码内容的url了) 275 | *
`phone` **手机验证码登录**,建议配合`wxData`使用 276 | *
`user` **账号密码登录**,建议配合`wxData`使用 277 | * 278 | * @param {object} data - 附加数据 279 | * @param {string} [data.wxData] - 设备信息数据,登录后使用 `getDeviceInfo` 接口获得。
使用此数据可免设备安全验证,不容易封号 280 | * @param {string} [data.token] - 使用用任意方式登录成功后,使用 `getAutoLoginData` 接口获得。
此token有过期时间,断开登录状态一段时间后会过期。 281 | * @param {string} [data.phone] - 手机号 282 | * @param {string} [data.code] - 手机验证码 283 | * @param {string} [data.username] - 用户名/qq号/手机号 284 | * @param {string} [data.password] - 密码 285 | * 286 | * @example 扫码登陆 287 | * const wx = new Padchat() 288 | * wx.on('open',()=>{ 289 | * await wx.init() 290 | * await wx.login('qrcode',{wxData:'xxx'}) 291 | * }) 292 | * 293 | * @example 账号密码登陆 294 | * const wx = new Padchat() 295 | * wx.on('open',()=>{ 296 | * await wx.init() 297 | * await wx.login('user',{wxData:'xxx',username:'name',password:'123456'}) 298 | * }) 299 | * 300 | * @example 手机验证码 301 | * const wx = new Padchat() 302 | * wx.on('open',()=>{ 303 | * await wx.init() 304 | * await wx.login('phone',{wxData:'xxx',phone:'13512345678',code:'123456'}) 305 | * }) 306 | * 307 | * @example 断线重连 308 | * const wx = new Padchat() 309 | * wx.on('open',()=>{ 310 | * await wx.init() 311 | * await wx.login('auto',{wxData:'xxx',token:'xxxxx'}) 312 | * }) 313 | * 314 | * @example 二次登陆 315 | * const wx = new Padchat() 316 | * wx.on('open',()=>{ 317 | * await wx.init() 318 | * await wx.login('request',{wxData:'xxx',token:'xxxxx'}) 319 | * }) 320 | * 321 | * @returns {Promise} 返回Promise,注意捕捉catch 322 | * ``` 323 | { 324 | error : '', 325 | msg : '请使用手机微信扫码登陆!', 326 | success: true 327 | } 328 | * ``` 329 | * @memberof Padchat 330 | */ 331 | async login(type = 'qrcode', data = {}) { 332 | const _data = { 333 | loginType: '', 334 | wxData: data.wxData || null, 335 | } 336 | if (!loginType[type]) { 337 | throw new Error('login type error!') 338 | } 339 | 340 | switch (type) { 341 | case loginType.auto: 342 | case loginType.request: 343 | if (!data.token || !data.wxData) { 344 | throw new Error('login data error!') 345 | } 346 | _data.token = data.token || null 347 | break 348 | case loginType.phone: 349 | if (!data.phone) { 350 | // code 351 | throw new Error('login data error!') 352 | } 353 | _data.phone = data.phone 354 | _data.code = data.code 355 | break 356 | case loginType.user: 357 | if (!data.username || !data.password) { 358 | throw new Error('login data error!') 359 | } 360 | _data.username = data.username 361 | _data.password = data.password 362 | break 363 | default: 364 | break 365 | } 366 | _data.loginType = loginType[type] 367 | return await this.sendCmd('login', _data) 368 | } 369 | 370 | /** 371 | * 获取设备62数据 372 | * 373 | * 事实上,只要你有一次登陆成功,以后一直用这个62数据,不需要更换。 374 | * 375 | * @returns {Promise} 返回Promise,注意捕捉catch 376 | * ``` 377 | { 378 | error: '', success: true, 379 | data : 380 | { 381 | wxData: 'xxxxx' //设备62数据 382 | } 383 | } 384 | * ``` 385 | * @memberof Padchat 386 | */ 387 | async getWxData() { 388 | return await this.sendCmd('getWxData', {}) 389 | } 390 | 391 | /** 392 | * 获取二次登陆数据 393 | * 394 | * @returns {Promise} 返回Promise,注意捕捉catch 395 | * ``` 396 | { 397 | error : '', 398 | success: true, 399 | data : 400 | { 401 | message: '', 402 | status : 0, 403 | token : 'xxxx', //二次登陆token 404 | uin : 14900000 //微信号uin,唯一值 405 | } 406 | } 407 | * ``` 408 | * @memberof Padchat 409 | */ 410 | async getLoginToken() { 411 | return await this.sendCmd('getLoginToken', {}) 412 | } 413 | 414 | /** 415 | * 获取微信号信息 416 | * 417 | * @returns {Promise} 返回Promise,注意捕捉catch 418 | * ``` 419 | { 420 | error : '', 421 | success: true, 422 | data: 423 | { 424 | userName: 'wxid_xxxx', //微信号id,注意不一定是微信号,全局唯一 425 | uin : 101234567 //微信号uin,全局唯一 426 | } 427 | } 428 | * ``` 429 | * @memberof Padchat 430 | */ 431 | async getMyInfo() { 432 | return await this.sendCmd('getMyInfo') 433 | } 434 | 435 | /** 436 | * 设置是否同步联系人 437 | * 438 | * @memberof Padchat 439 | */ 440 | setSyncContact(open) { 441 | this.openSyncContact = !!open 442 | } 443 | 444 | /** 445 | * 设置是否同步消息 446 | * 447 | * @memberof Padchat 448 | */ 449 | setSyncMsg(open) { 450 | this.openSyncMsg = !!open 451 | } 452 | 453 | /** 454 | * 同步消息 455 | * 456 | * 使用此接口手动触发同步消息,一般用于刚登陆后调用,可立即开始同步消息。 457 | * 否则会在有新消息时才开始同步消息。 458 | * 459 | * @returns {Promise} 返回Promise,注意捕捉catch 460 | * @memberof Padchat 461 | */ 462 | async syncMsg() { 463 | return await this.sendCmd('syncMsg') 464 | } 465 | 466 | /** 467 | * 同步通讯录 468 | * 469 | * 使用此接口可以触发同步通讯录,如果设置`reset`为`true`,则在通讯录同步完毕后触发`loaded`事件 470 | * 471 | * @param {boolean} [reset=false] 是否重置通讯录加载完毕状态 472 | * @returns {Promise} 返回Promise,注意捕捉catch 473 | * @memberof Padchat 474 | */ 475 | async syncContact(reset = false) { 476 | if (reset) { 477 | this.loaded = false 478 | } 479 | return await this.sendCmd('syncContact') 480 | } 481 | 482 | /** 483 | * 退出登录 484 | * 485 | * @returns {Promise} 返回Promise,注意捕捉catch 486 | * @memberof Padchat 487 | */ 488 | async logout() { 489 | return await this.sendCmd('logout', {}) 490 | } 491 | 492 | /** 493 | * 关闭推送 494 | * 495 | * @description 仅用于开发调试,不需要使用 496 | * @private 497 | * @returns {Promise} 返回Promise,注意捕捉catch 498 | * @memberof Padchat 499 | */ 500 | async closePush() { 501 | return await this.sendCmd('closePush', {}) 502 | } 503 | 504 | /** 505 | * 启动心跳 506 | * 507 | * @description 仅用于开发调试,不需要使用 508 | * @private 509 | * @returns {Promise} 返回Promise,注意捕捉catch 510 | * @memberof Padchat 511 | */ 512 | async heartBeat() { 513 | return await this.sendCmd('heartBeat', {}) 514 | } 515 | 516 | /** 517 | * 发送文字信息 518 | * 519 | * @param {string} toUserName - 接收者的wxid 520 | * @param {string} content - 内容文本 521 | * @param {Array} [atList=[]] - 向群内发信息时,要@的用户wxid数组。 522 | * 内容文本中要有@同样数量的用户昵称,不足时,将自动前缀空白的@符号及换行符 523 | * 524 | * @example at群成员示例 - content内@了群成员昵称 525 | * wx.sendMsg('123456@chatroom','@nickname1 @nickname2 message body',['wxid1','wxid2']) 526 | * // 显示内容: 527 | * // `@nickname1 @nickname2 message body` 528 | * 529 | * @example at群成员示例 - content内遗漏@群成员: 530 | * wx.sendMsg('123456@chatroom','@nickname1 message body',['wxid1','wxid2','wxid3']) 531 | * // 显示内容: 532 | * // `@@ 533 | * // @nickname1 message body` 534 | * 535 | * @returns {Promise} 返回Promise,注意捕捉catch 536 | * ``` 537 | { 538 | error: '', success: true, 539 | data : { 540 | message: '', 541 | msgId : '5172746684759824075', 542 | status : 0 543 | } 544 | } 545 | * ``` 546 | * @memberof Padchat 547 | */ 548 | async sendMsg(toUserName, content, atList = []) { 549 | if (Array.isArray(atList) && atList.length > 0) { 550 | const arr = content.match(/@/g) 551 | const num = Array.isArray(arr) ? arr.length : 0 552 | if (num < atList.length) { 553 | content = '@'.repeat(atList.length - num) + '\n' + content 554 | } 555 | } 556 | return await this.sendCmd('sendMsg', { 557 | toUserName, 558 | content, 559 | atList, 560 | }) 561 | } 562 | 563 | /** 564 | * 群发文字信息 565 | * 566 | * FIXME: 此接口有问题,暂停使用 567 | * 568 | * @param {Array} [userList=[]] - 接收者wxid数组 569 | * @param {string} content - 内容文本 570 | * @returns {Promise} 返回Promise,注意捕捉catch 571 | * @deprecated 572 | * @memberof Padchat 573 | */ 574 | async massMsg(userList = [], content) { 575 | return new Error('此接口存在问题,停用!') 576 | // return await this.sendCmd('massMsg', { 577 | // userList, 578 | // content, 579 | // }) 580 | } 581 | 582 | /** 583 | * 发送App消息(含小程序) 584 | * 585 | * @param {string} toUserName - 接收者的wxid 586 | * @param {object|string} content - app消息体文本(appmsg xml结构) 587 | * @param {object} object - app消息体对象(消息体文本和对象二选一) 588 | * @param {string} [object.appid] - appid,忽略即可 589 | * @param {string} [object.sdkver] - sdk版本,忽略即可 590 | * @param {string} [object.title] - 标题 591 | * @param {string} [object.des] - 描述 592 | * @param {string} [object.url] - 链接url 593 | * @param {string} [object.thumburl] - 缩略图url 594 | * 595 | * @example 发送app消息对象 596 | * // 直接在第二个参数中传入消息体对象 597 | * await wx.sendAppMsg('filehelper',{ 598 | appid = '', //appid,忽略即可 599 | sdkver = '', //sdk版本,忽略即可 600 | title = '', //标题 601 | des = '', //描述 602 | url = '', //链接url 603 | thumburl = '', //缩略图url 604 | }) 605 | * 606 | * @example 发送app消息体文本 607 | * // 如第二个参数传入非空文本,则忽略第三个参数 608 | * await wx.sendAppMsg('filehelper','标题描述view50http://wx.qq.comhttp://wx.qq.com/logo.png') 609 | * 610 | * @returns {Promise} 返回Promise,注意捕捉catch 611 | * ``` 612 | { 613 | error: '', success: true, 614 | data : { 615 | message: '', 616 | msgId : '2195811529497100215', 617 | status : 0 618 | } 619 | } 620 | * ``` 621 | * @memberof Padchat 622 | */ 623 | async sendAppMsg(toUserName, content, object = {}) { 624 | if (!content) { 625 | content = object 626 | } 627 | if (typeof (content) === 'object') { 628 | content = Helper.structureXml(content) 629 | } 630 | return await this.sendCmd('sendAppMsg', { 631 | toUserName, 632 | content, 633 | }) 634 | } 635 | 636 | /** 637 | * 分享名片 638 | * 639 | * @param {string} toUserName - 接收者的wxid 640 | * @param {string} content - 内容文本 641 | * @param {string} userId - 被分享人wxid 642 | * @returns {Promise} 返回Promise,注意捕捉catch 643 | * ``` 644 | { 645 | error: '', success: true, 646 | data : { 647 | message: '', 648 | msgId : '1797099903789182796', 649 | status : 0 650 | } 651 | } 652 | * ``` 653 | * @memberof Padchat 654 | */ 655 | async shareCard(toUserName, content, userId) { 656 | return await this.sendCmd('shareCard', { 657 | toUserName, 658 | content, 659 | userId, 660 | }) 661 | } 662 | 663 | /** 664 | * @returns {Promise} 返回Promise,注意捕捉catch 665 | * @private 666 | * @memberof Padchat 667 | */ 668 | async dumpWxuser() { 669 | return await this.sendCmd('dumpWxuser', { 670 | }) 671 | } 672 | 673 | /** 674 | * 发送图片消息 675 | * 676 | * @param {string} toUserName - 接收者的wxid 677 | * @param {Buffer|string} file - 图片Buffer数据或base64 678 | * @returns {Promise} 返回Promise,注意捕捉catch 679 | * ``` 680 | { 681 | error: '', success: true, 682 | data : { 683 | message: '', 684 | msgId : '1797099903789182796', 685 | status : 0 686 | } 687 | } 688 | * ``` 689 | * @memberof Padchat 690 | */ 691 | async sendImage(toUserName, file) { 692 | if (file instanceof Buffer) { 693 | file = file.toString('base64') 694 | } 695 | return await this.sendCmd('sendImage', { 696 | toUserName, 697 | file, 698 | }) 699 | } 700 | 701 | /** 702 | * 发送语音消息 703 | * 注意:只能发送silk格式的语音文件 704 | * 705 | * @param {string} toUserName - 接收者的wxid 706 | * @param {Buffer|string} file - 语音Buffer数据或base64 707 | * @param {number} time - 语音时间,单位为毫秒 708 | * @returns {Promise} 返回Promise,注意捕捉catch 709 | * ``` 710 | { 711 | error: '', success: true, 712 | data : { 713 | data : 2490, //语音文件尺寸 714 | message: '', 715 | msgId : '136722815749654341', 716 | size : 0, 717 | status : 0 718 | } 719 | } 720 | * ``` 721 | * @memberof Padchat 722 | */ 723 | async sendVoice(toUserName, file, time = 0) { 724 | if (file instanceof Buffer) { 725 | file = file.toString('base64') 726 | } 727 | return await this.sendCmd('sendVoice', { 728 | toUserName, 729 | file, 730 | time: time * 1 731 | }) 732 | } 733 | 734 | /** 735 | * 获取消息原始图片 736 | * 737 | * 在push事件中收到的data数据是缩略图图片数据,使用本接口获取原图数据 738 | * 739 | * @param {object} rawMsgData - 推送的消息结构体,即`push`事件中收到的Object 740 | * @returns {Promise} 返回Promise,注意捕捉catch 741 | * ``` 742 | { 743 | success: true, 744 | data : 745 | { 746 | image : 'base64_xxxx', //base64编码的原图数据 747 | message: '', 748 | size : 8139, //图片数据尺寸 749 | status : 0 750 | } 751 | } 752 | * ``` 753 | * @memberof Padchat 754 | */ 755 | async getMsgImage(rawMsgData) { 756 | return await this.sendCmd('getMsgImage', { 757 | rawMsgData, 758 | }) 759 | } 760 | 761 | /** 762 | * 获取消息原始视频 763 | * 764 | * 在push事件中只获得推送通知,不包含视频数据,需要使用本接口获取视频文件数据 765 | * 766 | * @param {object} rawMsgData - 推送的消息结构体,即`push`事件中收到的Object 767 | * @returns {Promise} 返回Promise,注意捕捉catch 768 | * ``` 769 | { 770 | success: true, 771 | data : 772 | { 773 | message: '', 774 | size : 160036, //视频数据尺寸 775 | status : 0, 776 | video : 'base64_xxxx' //base64编码的视频数据 777 | } 778 | } 779 | * ``` 780 | * @memberof Padchat 781 | */ 782 | 783 | async getMsgVideo(rawMsgData) { 784 | return await this.sendCmd('getMsgVideo', { 785 | rawMsgData, 786 | }) 787 | } 788 | 789 | /** 790 | * 获取消息语音数据 791 | * 792 | * 这个接口获取到的与push事件中接收到的数据一致,是base64编码的silk格式语音数据 793 | * 794 | * BUG: 超过60Kb的语音数据,只能拉取到60Kb,也就是说大约36~40秒以上的语音会丢失后边部分语音内容 795 | * 796 | * @param {object} rawMsgData - 推送的消息结构体,即`push`事件中收到的Object 797 | * @returns {Promise} 返回Promise,注意捕捉catch 798 | * ``` 799 | { 800 | success: true, 801 | data : 802 | { 803 | message: '', 804 | size : 2490, //语音数据尺寸 805 | status : 0, 806 | voice : 'base64_xxxx' //base64编码的语音数据 807 | } 808 | } 809 | * ``` 810 | * @memberof Padchat 811 | */ 812 | async getMsgVoice(rawMsgData) { 813 | return await this.sendCmd('getMsgVoice', { 814 | rawMsgData, 815 | }) 816 | } 817 | 818 | /** 819 | * 创建群 820 | * 821 | * 注意:如果有用户存在问题不能进群,则会建群失败。 822 | * 但判断是否成功应以`userName`字段 823 | * 824 | * @param {string[]} userList - 用户wxid数组 825 | * @returns {Promise} 返回Promise,注意捕捉catch 826 | * ``` 827 | { 828 | success: true, 829 | data : 830 | { 831 | message : 'Everything is OK', //操作结果提示,失败为`MemberList are wrong` 832 | status : 0, 833 | userName: '5658541000@chatroom' //如果建群成功,则返回群id 834 | } 835 | } 836 | * ``` 837 | * @memberof Padchat 838 | */ 839 | async createRoom(userList) { 840 | return await this.sendCmd('createRoom', { 841 | userList, 842 | }) 843 | } 844 | 845 | /** 846 | * 获取群成员信息 847 | * 848 | * @param {string} groupId - 群id 849 | * @returns {Promise} 返回Promise,注意捕捉catch 850 | * ``` 851 | { 852 | success: true, 853 | data : 854 | { 855 | chatroomId: 700000001, 856 | count : 3, //群成员数量 857 | member : //群成员列表 858 | [{ 859 | bigHead : 'http://wx.qlogo.cn/xxx/0', //大头像url 860 | chatroomNickName: '', //群内昵称 861 | invitedBy : 'binsee', //进群邀请人 862 | nickName : '复仇者联盟', //昵称 863 | smallHead : 'http://wx.qlogo.cn/xxx/132', //小头像url 864 | userName : 'wxid_xxxx' //wxid 865 | }], 866 | message : '', 867 | status : 0, 868 | userName: '5658541000@chatroom' //群id 869 | } 870 | } 871 | * ``` 872 | * @memberof Padchat 873 | */ 874 | async getRoomMembers(groupId) { 875 | return await this.sendCmd('getRoomMembers', { 876 | groupId, 877 | }) 878 | } 879 | 880 | /** 881 | * 添加群成员 882 | * 883 | * @param {string} groupId - 群id 884 | * @param {string} userId - 用户wxid 885 | * @returns {Promise} 返回Promise,注意捕捉catch 886 | * ``` 887 | { 888 | success: true, 889 | data : { 890 | message: 'Everything is OK', //失败为`MemberList are wrong` 891 | status : 0 892 | } 893 | } 894 | * ``` 895 | * @memberof Padchat 896 | */ 897 | async addRoomMember(groupId, userId) { 898 | return await this.sendCmd('addRoomMember', { 899 | groupId, 900 | userId, 901 | }) 902 | } 903 | 904 | /** 905 | * 邀请群成员 906 | * 会给对方发送一条邀请消息,无法判断对方是否真的接收到 907 | * 908 | * @param {string} groupId - 群id 909 | * @param {string} userId - 用户wxid 910 | * @returns {Promise} 返回Promise,注意捕捉catch 911 | * ``` 912 | { 913 | success: true, 914 | data : { 915 | message: '', 916 | status : 0 917 | } 918 | } 919 | * ``` 920 | * @memberof Padchat 921 | */ 922 | async inviteRoomMember(groupId, userId) { 923 | return await this.sendCmd('inviteRoomMember', { 924 | groupId, 925 | userId, 926 | }) 927 | } 928 | 929 | /** 930 | * 删除群成员 931 | * 932 | * @param {string} groupId - 群id 933 | * @param {string} userId - 用户wxid 934 | * @returns {Promise} 返回Promise,注意捕捉catch 935 | * ``` 936 | { 937 | success: true, 938 | data : { 939 | message: '', 940 | status : 0 941 | } 942 | } 943 | * ``` 944 | * @memberof Padchat 945 | */ 946 | async deleteRoomMember(groupId, userId) { 947 | return await this.sendCmd('deleteRoomMember', { 948 | groupId, 949 | userId, 950 | }) 951 | } 952 | 953 | /** 954 | * 退出群 955 | * 956 | * @param {string} groupId - 群id 957 | * @returns {Promise} 返回Promise,注意捕捉catch 958 | * ``` 959 | { 960 | success: true, 961 | data : { 962 | message: '', 963 | status : 0 964 | } 965 | } 966 | * ``` 967 | * @memberof Padchat 968 | */ 969 | async quitRoom(groupId) { 970 | return await this.sendCmd('quitRoom', { 971 | groupId, 972 | }) 973 | } 974 | 975 | /** 976 | * 设置群公告 977 | * 978 | * @param {string} groupId - 群id 979 | * @param {string} content - 群公告内容 980 | * @returns {Promise} 返回Promise,注意捕捉catch 981 | * ``` 982 | { 983 | success: true, 984 | data : { 985 | message: '', 986 | status : 0 987 | } 988 | } 989 | * ``` 990 | * @memberof Padchat 991 | */ 992 | async setRoomAnnouncement(groupId, content) { 993 | return await this.sendCmd('setRoomAnnouncement', { 994 | groupId, 995 | content, 996 | }) 997 | } 998 | 999 | /** 1000 | * 设置群名称 1001 | * 1002 | * @param {string} groupId - 群id 1003 | * @param {string} content - 群名称 1004 | * @returns {Promise} 返回Promise,注意捕捉catch 1005 | * ``` 1006 | { 1007 | success: true, 1008 | data : { 1009 | message: '', 1010 | status : 0 1011 | } 1012 | } 1013 | * ``` 1014 | * @memberof Padchat 1015 | */ 1016 | async setRoomName(groupId, content) { 1017 | return await this.sendCmd('setRoomName', { 1018 | groupId, 1019 | content, 1020 | }) 1021 | } 1022 | 1023 | /** 1024 | * 获取微信群二维码 1025 | * 1026 | * @param {string} groupId - 群id 1027 | * @returns {Promise} 返回Promise,注意捕捉catch 1028 | * ``` 1029 | { 1030 | success: true, 1031 | data : 1032 | { 1033 | footer : '该二维码7天内(4月13日前)有效,重新进入将更新', 1034 | message: '', 1035 | qrCode : '', //进群二维码图片base64 1036 | status : 0 1037 | } 1038 | } 1039 | * ``` 1040 | * @memberof Padchat 1041 | */ 1042 | async getRoomQrcode(groupId) { 1043 | return await this.sendCmd('getRoomQrcode', { 1044 | groupId, 1045 | style: 0, 1046 | }) 1047 | } 1048 | 1049 | /** 1050 | * 获取用户/群信息 1051 | * 1052 | * @param {string} userId - 用户wxid/群id 1053 | * @returns {Promise} 返回Promise,注意捕捉catch 1054 | * 1055 | * 微信用户/公众号返回: 1056 | * 1057 | * ``` 1058 | { 1059 | success: true, 1060 | data : 1061 | { 1062 | bigHead : 'http://wx.qlogo.cn/xxx/0', //大头像url 1063 | city : 'mesa', //城市 1064 | country : 'CN', //国家 1065 | intro : '', //简介(公众号主体) 1066 | label : '', //(标签) 1067 | message : '', 1068 | nickName : '复仇者联盟', //昵称 1069 | provincia : 'Henan', //省份 1070 | pyInitial : 'SM', //昵称拼音简写 1071 | quanPin : 'shamu', //昵称拼音 1072 | remark : '', //备注 1073 | remarkPyInitial: '', //备注拼音简写 1074 | remarkQuanPin : '', //备注拼音 1075 | sex : 1, //性别:1男2女 1076 | signature : '签名', //个性签名 1077 | smallHead : 'http://wx.qlogo.cn/xxx/132', //小头像url 1078 | status : 0, 1079 | stranger : 'v1_xxx@stranger', //用户v1码,从未加过好友则为空 1080 | ticket : 'v2_xxx@stranger', //用户v2码,如果非空则为单向好友(非对方好友) 1081 | userName : 'binxxx' //用户wxid 1082 | } 1083 | } 1084 | * ``` 1085 | * 1086 | * 微信群返回: 1087 | * 1088 | * ``` 1089 | { 1090 | success: true, 1091 | data : { 1092 | city : '', 1093 | country : '', 1094 | intro : '', 1095 | label : '', 1096 | member : [], //群成员wxid数组 1097 | message : '', 1098 | provincia : '', 1099 | remark : '', 1100 | sex : 0, 1101 | signature : '', 1102 | status : 0, 1103 | stranger : 'v1_xxx@stranger', 1104 | ticket : '', 1105 | bigHead : '', 1106 | chatroomId : 700001234, 1107 | chatroomOwner : 'wxid_xxx', 1108 | maxMemberCount : 500, //群最大人数 1109 | memberCount : 377, //群当前人数 1110 | nickName : 'Wechaty Developers\' Home', //群名称 1111 | pyInitial : 'WECHATYDEVELOPERSHOME', 1112 | quanPin : 'WechatyDevelopersHome', 1113 | remarkPyInitial: '', 1114 | remarkQuanPin : '', 1115 | smallHead : 'http://wx.qlogo.cn/xxx/0', //群头像url 1116 | userName : '1234567890@chatroom' 1117 | } 1118 | } 1119 | * ``` 1120 | * @memberof Padchat 1121 | */ 1122 | async getContact(userId) { 1123 | return await this.sendCmd('getContact', { 1124 | userId, 1125 | }) 1126 | } 1127 | 1128 | /** 1129 | * 搜索用户 1130 | * 可用此接口来判断是否已经加对方为好友 1131 | * 1132 | * @param {string} userId - 用户wxid 1133 | * @returns {Promise} 返回Promise,注意捕捉catch 1134 | * ``` 1135 | { 1136 | success: true, 1137 | data : 1138 | { 1139 | bigHead : 'http://wx.qlogo.cn/xxx/0', //大头像url 1140 | city : 'mesa', //城市 1141 | country : 'CN', //国家 1142 | message : '', 1143 | nickName : '复仇者联盟', //昵称 1144 | provincia: 'Henan', //省份 1145 | pyInitial: 'SM', //昵称拼音简写 1146 | quanPin : 'shamu', //昵称拼音 1147 | sex : 1, //性别:1男2女 1148 | signature: '签名', //个性签名 1149 | smallHead: 'http://wx.qlogo.cn/xxx/132', //小头像url 1150 | status : 0, 1151 | stranger : 'v1_xxx@stranger', //好友为空,非好友显示v2码 1152 | userName : 'binxxx' //是自己好友显示wxid,非好友为v1码 1153 | } 1154 | } 1155 | * ``` 1156 | * @memberof Padchat 1157 | */ 1158 | async searchContact(userId) { 1159 | return await this.sendCmd('searchContact', { 1160 | userId, 1161 | }) 1162 | } 1163 | 1164 | /** 1165 | * 删除好友 1166 | * 1167 | * @param {string} userId - 用户wxid 1168 | * @returns {Promise} 返回Promise,注意捕捉catch 1169 | * ``` 1170 | { 1171 | success: true, 1172 | data : { 1173 | message: '', 1174 | status : 0 1175 | } 1176 | } 1177 | * ``` 1178 | * @memberof Padchat 1179 | */ 1180 | async deleteContact(userId) { 1181 | return await this.sendCmd('deleteContact', { 1182 | userId, 1183 | }) 1184 | } 1185 | 1186 | /** 1187 | * 获取用户二维码 1188 | * 仅限获取自己的二维码,无法获取其他人的二维码 1189 | * 1190 | * @param {string} userId - 用户wxid 1191 | * @param {Number} style - 二维码风格。可用范围0-3 1192 | * @returns {Promise} 返回Promise,注意捕捉catch 1193 | * ``` 1194 | { 1195 | success: true, 1196 | data : 1197 | { 1198 | footer : '', 1199 | message: '', 1200 | qrCode : '', //二维码图片base64 1201 | status : 0 1202 | } 1203 | } 1204 | * ``` 1205 | * @memberof Padchat 1206 | */ 1207 | async getContactQrcode(userId, style = 0) { 1208 | return await this.sendCmd('getUserQrcode', { 1209 | userId, 1210 | style, 1211 | }) 1212 | } 1213 | 1214 | /** 1215 | * 通过好友验证 1216 | * 1217 | * @param {string} stranger - 用户stranger数据 1218 | * @param {string} ticket - 用户ticket数据 1219 | * @returns {Promise} 返回Promise,注意捕捉catch 1220 | * ``` 1221 | { 1222 | success: true, 1223 | data : { 1224 | message: '', 1225 | status : 0 1226 | } 1227 | } 1228 | * ``` 1229 | * @memberof Padchat 1230 | */ 1231 | async acceptUser(stranger, ticket) { 1232 | return await this.sendCmd('acceptUser', { 1233 | stranger, 1234 | ticket, 1235 | }) 1236 | } 1237 | 1238 | /** 1239 | * 添加好友 1240 | * 1241 | * @param {string} stranger - 用户stranger数据 1242 | * @param {string} ticket - 用户ticket数据 1243 | * @param {Number} type - 添加好友途径 1244 |
`0` : 通过微信号搜索 1245 |
`1` : 搜索QQ号 1246 |
`3` : 通过微信号搜索 1247 |
`4` : 通过QQ好友添加 1248 |
`8` : 通过群聊 1249 |
`12`: 来自QQ好友 1250 |
`14`: 通过群聊 1251 |
`15`: 通过搜索手机号 1252 |
`17`: 通过名片分享 //未验证 1253 |
`22`: 通过摇一摇打招呼方式 //未验证 1254 |
`25`: 通过漂流瓶 //未验证 1255 |
`30`: 通过二维码方式 //未验证 1256 | * @param {string} [content=''] - 验证信息 1257 | * @returns {Promise} 返回Promise,注意捕捉catch 1258 | * ``` 1259 | { 1260 | success: true, 1261 | data : { 1262 | message: '', 1263 | status : 0 //如果对方设置了验证,会返回-44 1264 | } 1265 | } 1266 | * ``` 1267 | * @memberof Padchat 1268 | */ 1269 | async addContact(stranger, ticket, type = 3, content = '') { 1270 | return await this.sendCmd('addContact', { 1271 | stranger, 1272 | ticket, 1273 | type, 1274 | content, 1275 | }) 1276 | } 1277 | 1278 | /** 1279 | * 打招呼 1280 | * 如果已经是好友,会收到由系统自动发送,来自对方的一条文本信息 1281 | * “xx已通过你的朋友验证请求,现在可以开始聊天了” 1282 | * 1283 | * @param {string} stranger - 用户stranger数据 1284 | * @param {string} ticket - 用户ticket数据 1285 | * @param {string} content - 打招呼内容 1286 | * @returns {Promise} 返回Promise,注意捕捉catch 1287 | * ``` 1288 | { 1289 | success: true, 1290 | data : { 1291 | message: '', 1292 | status : 0 1293 | } 1294 | } 1295 | * ``` 1296 | * @memberof Padchat 1297 | */ 1298 | async sayHello(stranger, ticket, content = '') { 1299 | return await this.sendCmd('sayHello', { 1300 | stranger, 1301 | ticket, 1302 | content, 1303 | }) 1304 | } 1305 | 1306 | /** 1307 | * 设置备注 1308 | * 1309 | * @param {string} userId - 用户wxid 1310 | * @param {string} remark - 备注名称 1311 | * @returns {Promise} 返回Promise,注意捕捉catch 1312 | * ``` 1313 | { 1314 | success: true, 1315 | data : { 1316 | message: '', 1317 | status : 0 1318 | } 1319 | } 1320 | * ``` 1321 | * @memberof Padchat 1322 | */ 1323 | async setRemark(userId, remark) { 1324 | return await this.sendCmd('setRemark', { 1325 | userId, 1326 | remark, 1327 | }) 1328 | } 1329 | 1330 | /** 1331 | * 设置头像 1332 | * 1333 | * @param {Buffer|string} file - 图片Buffer数据或base64 1334 | * @returns {Promise} 返回Promise,注意捕捉catch 1335 | * ``` 1336 | { 1337 | success: true, 1338 | data : 1339 | { 1340 | bigHead : 'http://wx.qlogo.cn/mmhead/ver_1/xxx/0', 1341 | data : 1527, //图片文件尺寸 1342 | message : '', 1343 | size : 1527, //图片文件尺寸 1344 | smallHead: 'http://wx.qlogo.cn/mmhead/ver_1/xxx/132', 1345 | status : 0 1346 | } 1347 | } 1348 | * ``` 1349 | * @memberof Padchat 1350 | */ 1351 | async setHeadImg(file) { 1352 | if (file instanceof Buffer) { 1353 | file = file.toString('base64') 1354 | } 1355 | return await this.sendCmd('setHeadImg', { 1356 | file, 1357 | }) 1358 | } 1359 | 1360 | /** 朋友圈系列接口 */ 1361 | 1362 | /** 1363 | * 上传图片到朋友圈 1364 | * NOTE: 此接口只能上传图片,并不会将图片发到朋友圈中 1365 | * 1366 | * @param {Buffer|string} file - 图片Buffer数据或base64 1367 | * @returns {Promise} 返回Promise,注意捕捉catch 1368 | * ``` 1369 | { 1370 | success: true, 1371 | data : 1372 | { 1373 | bigHead : 'http://mmsns.qpic.cn/mmsns/xxx/0', 1374 | data : 1527, //图片文件尺寸 1375 | message : '', 1376 | size : 1527, //图片文件尺寸 1377 | smallHead: 'http://mmsns.qpic.cn/mmsns/xxx/150', 1378 | status : 0 1379 | } 1380 | } 1381 | * ``` 1382 | * @memberof Padchat 1383 | */ 1384 | async snsUpload(file) { 1385 | if (file instanceof Buffer) { 1386 | file = file.toString('base64') 1387 | } 1388 | return await this.sendCmd('snsUpload', { 1389 | file, 1390 | }) 1391 | } 1392 | 1393 | /** 1394 | * 操作朋友圈 1395 | * 1396 | * @param {string} momentId - 朋友圈信息id 1397 | * @param {Number} type - 操作类型,1为删除朋友圈,4为删除评论,5为取消赞 1398 | * @param {Number} commentId - 操作类型,当type为4时,对应删除评论的id,其他状态为0 1399 | * @param {Number} commentType - 操作类型,当删除评论时可用,需与评论type字段一致 1400 | * @returns {Promise} 返回Promise,注意捕捉catch 1401 | * ``` 1402 | { 1403 | success: true, 1404 | data : { 1405 | message: '', 1406 | status : 0 1407 | } 1408 | } 1409 | * ``` 1410 | * @memberof Padchat 1411 | */ 1412 | async snsobjectOp(momentId, type, commentId, commentType = 2) { 1413 | return await this.sendCmd('snsobjectOp', { 1414 | momentId, 1415 | type, 1416 | commentId, 1417 | commentType, 1418 | }) 1419 | } 1420 | 1421 | /** 1422 | * 发朋友圈 1423 | * 1424 | * @param {string} content - 文本内容或`Timelineobject`结构体文本 1425 | * @returns {Promise} 返回Promise,注意捕捉catch 1426 | * ``` 1427 | { 1428 | success: true, 1429 | data : 1430 | { 1431 | data: 1432 | { 1433 | create_time: 1523015689, 1434 | description: //朋友圈信息xml结构体文本 1435 | '12775981595019653292wxid_xxx1523015689来自代码发的朋友圈030002', 1436 | id : '12775981595019653292', //朋友圈信息id 1437 | nick_name: '复仇者联盟', 1438 | user_name: 'wxid_xxxx' 1439 | }, 1440 | message: '', 1441 | status : 0 1442 | } 1443 | } 1444 | * ``` 1445 | * @memberof Padchat 1446 | */ 1447 | async snsSendMoment(content) { 1448 | return await this.sendCmd('snsSendMoment', { 1449 | content, 1450 | }) 1451 | } 1452 | 1453 | /** 1454 | * 查看用户朋友圈 1455 | * 1456 | * @param {string} userId - 用户wxid 1457 | * @param {string} [momentId=''] - 朋友圈信息id 1458 | * 首次传入空即获取第一页,以后传入上次拉取的最后一条信息id 1459 | * @returns {Promise} 返回Promise,注意捕捉catch 1460 | * ``` 1461 | { 1462 | success: true, 1463 | data : 1464 | { 1465 | count: 1, 1466 | data : //朋友圈信息结构数组(无评论和点赞数据) 1467 | [{ 1468 | create_time: 1523015689, 1469 | description: '12775981595019653292wxid_xxx1523015689来自代码发的朋友圈030 0 0 2 ', 1470 | id : '12775981595019653292', 1471 | nick_name : '复仇者联盟', 1472 | user_name : 'wxid_xxx' 1473 | }], 1474 | message: '', 1475 | page : '81cb2ad01ebc219f', 1476 | status : 0 1477 | } 1478 | } 1479 | * ``` 1480 | * @memberof Padchat 1481 | */ 1482 | async snsUserPage(userId, momentId = '') { 1483 | return await this.sendCmd('snsUserPage', { 1484 | userId, 1485 | momentId, 1486 | }) 1487 | } 1488 | 1489 | /** 1490 | * 查看朋友圈动态 1491 | * 1492 | * @param {string} [momentId=''] - 朋友圈信息id 1493 | * 首次传入空即获取第一页,以后传入上次拉取的最后一条信息id 1494 | * @returns {Promise} 返回Promise,注意捕捉catch 1495 | * ``` 1496 | { 1497 | success: true, 1498 | data : 1499 | { 1500 | count: 1, 1501 | data : //朋友圈信息结构数组(无评论和点赞数据) 1502 | [{ 1503 | create_time: 1523015689, 1504 | description: '12775981595019653292wxid_xxx1523015689来自代码发的朋友圈030 0 0 2 ', 1505 | id : '12775981595019653292', 1506 | nick_name : '复仇者联盟', 1507 | user_name : 'wxid_xxx' 1508 | }], 1509 | message: '', 1510 | page : '81cb2ad01ebc219f', 1511 | status : 0 1512 | } 1513 | } 1514 | * ``` 1515 | * @memberof Padchat 1516 | */ 1517 | async snsTimeline(momentId = '') { 1518 | return await this.sendCmd('snsTimeline', { 1519 | momentId, 1520 | }) 1521 | } 1522 | 1523 | /** 1524 | * 获取朋友圈信息详情 1525 | * 1526 | * @param {string} momentId - 朋友圈信息id 1527 | * @returns {Promise} 返回Promise,注意捕捉catch 1528 | * ``` 1529 | { 1530 | success: true, 1531 | data : { 1532 | data : {}, //朋友圈信息结构 1533 | message: '', 1534 | status : 0 1535 | } 1536 | } 1537 | * ``` 1538 | * @memberof Padchat 1539 | */ 1540 | async snsGetObject(momentId) { 1541 | return await this.sendCmd('snsGetObject', { 1542 | momentId, 1543 | }) 1544 | } 1545 | 1546 | /** 1547 | * 评论朋友圈 1548 | * 1549 | * @param {string} userId - 用户wxid 1550 | * @param {string} momentId - 朋友圈信息id 1551 | * @param {string} content - 内容文本 1552 | * @returns {Promise} 返回Promise,注意捕捉catch 1553 | * ``` 1554 | { 1555 | success: true, 1556 | data : { 1557 | data : {}, //朋友圈信息结构 1558 | message: '', 1559 | status : 0 1560 | } 1561 | } 1562 | * ``` 1563 | * @memberof Padchat 1564 | */ 1565 | 1566 | async snsComment(userId, momentId, content) { 1567 | return await this.sendCmd('snsComment', { 1568 | userId, 1569 | momentId, 1570 | content, 1571 | }) 1572 | } 1573 | 1574 | /** 1575 | * 朋友圈点赞 1576 | * 1577 | * @param {string} userId - 用户wxid 1578 | * @param {string} momentId - 朋友圈信息id 1579 | * @returns {Promise} 返回Promise,注意捕捉catch 1580 | * ``` 1581 | { 1582 | success: true, 1583 | data : { 1584 | data : {}, //朋友圈信息结构 1585 | message: '', 1586 | status : 0 1587 | } 1588 | } 1589 | * ``` 1590 | * @memberof Padchat 1591 | */ 1592 | async snsLike(userId, momentId) { 1593 | return await this.sendCmd('snsLike', { 1594 | userId, 1595 | momentId, 1596 | }) 1597 | } 1598 | 1599 | /** 收藏系列接口 */ 1600 | 1601 | /** 1602 | * 同步收藏消息 1603 | * 1604 | * @param {string} [favKey=''] - 同步key,首次不用传入 1605 | * @returns {Promise} 返回Promise,注意捕捉catch 1606 | * ``` 1607 | { 1608 | success: true, 1609 | data : 1610 | { 1611 | continue: 0, 1612 | data : //收藏消息列表,如果没有则为null 1613 | [ 1614 | { 1615 | flag: 0, //首次标志,0为有效,1为已取消收藏 1616 | id : 3, //收藏id 1617 | seq : 652265243, //收藏随机值 1618 | time: 1515042008, //收藏时间 1619 | type: 5 //收藏类型:1文本;2图片;3语音;4视频;5图文消息 1620 | } 1621 | ], 1622 | key : 'kzTKsdjD6PM0bbQv+oP7vQ==', //下次的同步key,类似分页 1623 | message: '', 1624 | status : 0 1625 | } 1626 | } 1627 | * ``` 1628 | * @memberof Padchat 1629 | */ 1630 | async syncFav(favKey = '') { 1631 | return await this.sendCmd('syncFav', { 1632 | favKey, 1633 | }) 1634 | } 1635 | 1636 | /** 1637 | * 添加收藏 1638 | * 1639 | * @param {string} content - 内容文本 1640 | * @returns {Promise} 返回Promise,注意捕捉catch 1641 | * @memberof Padchat 1642 | */ 1643 | async addFav(content) { 1644 | return await this.sendCmd('addFav', { 1645 | content, 1646 | }) 1647 | } 1648 | 1649 | /** 1650 | * 获取收藏消息详情 1651 | * 1652 | * @param {Number} favId - 收藏id 1653 | * @returns {Promise} 返回Promise,注意捕捉catch 1654 | * ``` 1655 | { 1656 | success: true, 1657 | data : 1658 | { 1659 | data: 1660 | [ 1661 | , { 1662 | flag : 0, //收藏状态:0为有效,1为无效(已删除) 1663 | id : 3, //收藏id,如果为0则为无效收藏 1664 | object: //收藏对象结构体文本 1665 | 'DaoCloud 首席架构师王天青:下一代应用转型之道、术、器gh_4b6a20bcdd8bwxid_xxx5353367357590009973http://mp.weixin.qq.com/s?__biz=MzA5MzA2Njk5OA==&mid=2650096972&idx=1&sn=8707378d0c0bdc0d14d1ac93972c5862&chksm=886266d5bf15efc386050508a2cafb1adb806196f40f4f1bde8e944926c7fb6c6e54a14875c7&scene=0#rdgh_4b6a20bcdd8bDaoCloud 首席架构师王天青:下一代应用转型之道、术、器DaoCloud 受邀出席第13届信息化领袖峰会,立足于 DaoCloud 为传统企业数字化转型旅途中的丰富实践,与大家共话《下一代应用转型之道、术、器》,探讨如何“用新技术原力现代化你的企业应用”。http://mmbiz.qpic.cn/mmbiz_jpg/icGWTH9VkFq315HbKuKtWeWlcVDNPAswdhYA0kIskz0GcEQp6nJetC2aSBNfpibp1wKNHf8kYjUibkCF6SgbMIocw/640?wxtype=jpeg&wxfrom=0http://mmbiz.qpic.cn/mmbiz_jpg/icGWTH9VkFq315HbKuKtWeWlcVDNPAswdhYA0kIskz0GcEQp6nJetC2aSBNfpibp1wKNHf8kYjUibkCF6SgbMIocw/640?wxtype=jpeg&wxfrom=0', 1666 | //文本消息收藏结构 1667 | // '接收到你发送的内容了! 原内容:syncwxid_xxxbinsee5451059336571949850tedhj' 1668 | // 视频 1669 | // 'wxid_xxx4674258153@chatroomwxid_xxx786100356842168336304c02010004453043020100020408eddd7c02030f4fed020419a0360a02045ac9271704206162313437386338616237383833333266336564343335666166363435646331020227110201000400304c02010004453043020100020408eddd7c02030f4fed0204b94c716402045ac9271704203865383031656465633132333661303939346365663837643165316539363663020227110201000400ab1478c8ab788332f3ed435faf645dc18e801edec1236a0994cef87d1e1e966c8e801edec1236a0994cef87d1e1e966c324b6cffbba04142bfabf5cdd0621b4092377ab1478c8ab788332f3ed435faf645dc14fcedfae8fcaa571504c5fd9f2abfa0a5658' 1670 | // 语音 1671 | // 'wxid_xxx4674258153@chatroomwxid_xxx3687245278820959898silk304c02010004453043020100020408eddd7c02030f4fed020419a2360a02045ac92711042030646439623262316234646639366264333838313131366462353338313435370202271102010004000dd9b2b1b4df96bd3881116db538145724650dd9b2b1b4df96bd3881116db5381457d348a2942af6d188100855d48dc753734186' 1672 | seq : 652265243, 1673 | status: 0, //0为有效收藏,1为无效收藏 1674 | time : 1515042008 1675 | } 1676 | ], 1677 | message: '', 1678 | status : 0 1679 | } 1680 | } 1681 | * ``` 1682 | * @memberof Padchat 1683 | */ 1684 | async getFav(favId) { 1685 | return await this.sendCmd('getFav', { 1686 | favId, 1687 | }) 1688 | } 1689 | 1690 | /** 1691 | * 删除收藏 1692 | * 1693 | * @param {Number} favId - 收藏id 1694 | * @returns {Promise} 返回Promise,注意捕捉catch 1695 | * ``` 1696 | { 1697 | success: true, 1698 | data : 1699 | { 1700 | data: 1701 | [ 1702 | { 1703 | flag : 0, 1704 | id : 0, 1705 | object: '', 1706 | seq : 0, 1707 | status: 1, //返回删除的收藏id 1708 | time : 0 1709 | }, 1710 | ], 1711 | message: '', 1712 | status : 0 1713 | } 1714 | } 1715 | * ``` 1716 | * @memberof Padchat 1717 | */ 1718 | async deleteFav(favId) { 1719 | return await this.sendCmd('deleteFav', { 1720 | favId, 1721 | }) 1722 | } 1723 | 1724 | /** 标签系列接口 */ 1725 | 1726 | /** 1727 | * 获取所有标签 1728 | * 1729 | * @returns {Promise} 返回Promise,注意捕捉catch 1730 | * ``` 1731 | { 1732 | success: true, 1733 | data : 1734 | { 1735 | label: //标签列表 1736 | [{ 1737 | id : 1, //标签id 1738 | name: '测试标签' //标签名称 1739 | }], 1740 | message: '', 1741 | status : 0 1742 | } 1743 | } 1744 | * ``` 1745 | * @memberof Padchat 1746 | */ 1747 | async getLabelList() { 1748 | return await this.sendCmd('getLabelList', {}) 1749 | } 1750 | 1751 | /** 1752 | * 添加标签 1753 | * 1754 | * @param {string} label - 标签名称 1755 | * @returns {Promise} 返回Promise,注意捕捉catch 1756 | * ``` 1757 | { 1758 | success: true, 1759 | data : { 1760 | message: '', 1761 | status : 0 1762 | } 1763 | } 1764 | * ``` 1765 | * @memberof Padchat 1766 | */ 1767 | async addLabel(label) { 1768 | return await this.sendCmd('addLabel', { 1769 | label, 1770 | }) 1771 | } 1772 | 1773 | /** 1774 | * 删除标签 1775 | * 1776 | * @param {string} labelId - 标签id,注意是id是string类型 1777 | * @returns {Promise} 返回Promise,注意捕捉catch 1778 | * ``` 1779 | { 1780 | success: true, 1781 | data : { 1782 | message: '', 1783 | status : 0 1784 | } 1785 | } 1786 | * ``` 1787 | * @memberof Padchat 1788 | */ 1789 | async deleteLabel(labelId) { 1790 | return await this.sendCmd('deleteLabel', { 1791 | labelId, 1792 | }) 1793 | } 1794 | 1795 | /** 1796 | * 设置用户标签 1797 | * 1798 | * @param {string} userId - 用户wxid 1799 | * @param {string} labelId - 标签id 1800 | * @returns {Promise} 返回Promise,注意捕捉catch 1801 | * ``` 1802 | { 1803 | success: true, 1804 | data : { 1805 | message: '', 1806 | status : 0 1807 | } 1808 | } 1809 | * ``` 1810 | * @memberof Padchat 1811 | */ 1812 | async setLabel(userId, labelId) { 1813 | return await this.sendCmd('setLabel', { 1814 | userId, 1815 | labelId, 1816 | }) 1817 | } 1818 | 1819 | /** 转账及红包接口 */ 1820 | 1821 | /** 1822 | * 查看转账消息 1823 | * 1824 | * @param {object} rawMsgData - 推送的消息结构体,即`push`事件中收到的Object 1825 | * @returns {Promise} 返回Promise,注意捕捉catch 1826 | * ``` 1827 | { 1828 | success: true, 1829 | data : 1830 | { 1831 | external: 1832 | { 1833 | retcode : '0', 1834 | retmsg : 'ok', 1835 | fee : 20, //转账金额(单位为分) 1836 | transStatus : 2000, //状态:2000未收款;2001已收款 1837 | feeType : '1', 1838 | payTime : 1523176700, 1839 | modifyTime : 0, 1840 | refundBankType: 'BANK', 1841 | payerName : 'binsee', 1842 | receiverName : 'wxid_8z66rux8lysr22', 1843 | statusDesc : '待确认收款', //收款描述 1844 | // '已收钱' //已收款 1845 | // '待%s确认收款' //等待对方收款 1846 | // '%s已收钱' //对方已收款 1847 | statusSupplementary: '', //状态补充信息 1848 | // 未领取: 1849 | // '1天内未确认,将退还给对方。<_wc_custom_link_ href="weixin://wcpay/transfer/rebacksendmsg">立即退还', 1850 | delayConfirmFlag: 0, 1851 | // 1852 | // 已领取: 1853 | // '<_wc_custom_link_ href="weixin://wcpay/transfer/watchbalance">查看零钱' 1854 | // 1855 | // 等待对方收款: 1856 | // '1天内朋友未确认,将退还给你。<_wc_custom_link_ href="weixin://wcpay/transfer/retrysendmsg">重发转账消息' 1857 | isPayer: false 1858 | // 1859 | // 对方已收款为空 1860 | }, 1861 | message: '', 1862 | status : 0 1863 | } 1864 | } 1865 | * ``` 1866 | * @deprecated 1867 | * @memberof Padchat 1868 | */ 1869 | async queryTransfer(rawMsgData) { 1870 | return await this.sendCmd('queryTransfer', { 1871 | rawMsgData, 1872 | }) 1873 | } 1874 | 1875 | /** 1876 | * 接受转账 1877 | * 1878 | * @param {object} rawMsgData - 推送的消息结构体,即`push`事件中收到的Object 1879 | * @returns {Promise} 返回Promise,注意捕捉catch 1880 | * ``` 1881 | { 1882 | success: true, 1883 | data : 1884 | { 1885 | external: 1886 | { 1887 | fee : 20, //转账金额(单位为分) 1888 | payer : '085exxx', //付款id 1889 | receiver: '085exxx', //接收id 1890 | retcode : '0', 1891 | retmsg : 'ok', 1892 | feeType : '1' 1893 | }, 1894 | message: '', 1895 | status : 0 1896 | } 1897 | } 1898 | * ``` 1899 | * @deprecated 1900 | * @memberof Padchat 1901 | */ 1902 | async acceptTransfer(rawMsgData) { 1903 | return await this.sendCmd('acceptTransfer', { 1904 | rawMsgData, 1905 | }) 1906 | } 1907 | 1908 | /** 1909 | * 接收红包 1910 | * 1911 | * @param {object} rawMsgData - 推送的消息结构体,即`push`事件中收到的Object 1912 | * @returns {Promise} 返回Promise,注意捕捉catch 1913 | * ``` 1914 | { 1915 | success: true, 1916 | data : 1917 | { 1918 | external: //扩展数据结构 1919 | { 1920 | retcode : 0, 1921 | retmsg : 'ok', 1922 | sendId : '10000xxx', //发送id 1923 | wishing : '发3个红包', //红包祝语 1924 | isSender : 0, //是否自己发送 1925 | receiveStatus : 0, //接收状态:0未接收;2已领取 1926 | hbStatus : 3, //红包状态:3未领取完;4已领取完毕 1927 | statusMess : '发了一个红包,金额随机', // 1928 | hbType : 1, //红包类型 1929 | watermark : '', 1930 | sendUserName : 'binsee', //发送者wxid 1931 | timingIdentifier: 'C6E370xxx', 1932 | agreeDuty : //未知含义,非必然 1933 | { 1934 | title : '', 1935 | serviceProtocolWording: '', 1936 | serviceProtocolUrl : '', 1937 | buttonWording : '', 1938 | delayExpiredTime : 0, 1939 | agreedFlag : 1 1940 | } 1941 | }, 1942 | key : 'C6E370xxx', //红包key,用于领取红包 1943 | message: '', 1944 | status : 0 1945 | } 1946 | } 1947 | * ``` 1948 | * @deprecated 1949 | * @memberof Padchat 1950 | */ 1951 | async receiveRedPacket(rawMsgData) { 1952 | return await this.sendCmd('receiveRedPacket', { 1953 | rawMsgData, 1954 | }) 1955 | } 1956 | 1957 | /** 1958 | * 查看红包信息 1959 | * NOTE: 如果是别人发的红包,未领取且未领取完毕时,无法取到红包信息 1960 | * 1961 | * @param {object} rawMsgData - 推送的消息结构体,即`push`事件中收到的Object 1962 | * @param {Number} [index=0] - 列表索引。 1963 | * 每页11个,查看第二页11,查看第三页22,以此类推 1964 | * @returns {Promise} 返回Promise,注意捕捉catch 1965 | * 未先接收红包返回结果: 1966 | * ``` 1967 | { 1968 | success: true, 1969 | data : 1970 | { 1971 | external: //扩展数据 1972 | { 1973 | retcode : 0, 1974 | retmsg : 'ok', 1975 | operationHeader: [0], 1976 | record : [0] 1977 | }, 1978 | message: '', 1979 | status : 0 1980 | } 1981 | } 1982 | * ``` 1983 | * 1984 | * 接收红包后查询结果: 1985 | * ``` 1986 | { 1987 | success: true, 1988 | data : 1989 | { 1990 | external: 1991 | { 1992 | retcode : 0, 1993 | retmsg : 'ok', 1994 | recNum : 2, //已领取数 1995 | totalNum : 2, //红包个数 1996 | totalAmount : 100, //红包总金额(单位为分) 1997 | sendId : '10000xxx', //发送id 1998 | amount : 85, //领取到金额(单位为分) 1999 | wishing : 'Hello!', //红包祝语 2000 | isSender : 1, //是否是自己发送的 2001 | receiveId : '10000xxx', //接收id 2002 | hasWriteAnswer : 1, //是否已写回复 2003 | operationHeader: [], //未知 2004 | hbType : 1, //红包类型 2005 | isContinue : 0, //是否已领取完 2006 | hbStatus : 3, //红包状态:2未领取;3未领取完;4已领取完毕 2007 | // 普通红包或单发红包是2,随机红包是3或4 2008 | receiveStatus: 2, //接收状态:0未接收;2已领取 2009 | statusMess : '成功领到', //状态提示,未领取为空 2010 | headTitle : '', //红包头部标题 2011 | // '已领取1/2个,共0.01/0.02元' //自己发的红包未领取完时 2012 | // '2个红包共1.00元,15秒被抢光' //自己发的红包未领取完时 2013 | // '领取2/3个' //别人发的红包未领取完时 2014 | // '2个红包,42秒被抢光' //别人发的红包未领取完时 2015 | canShare : 0, //是否可分享 2016 | hbKind : 1, //红包种类 2017 | recAmount: 100, //已领取金额(单位为分) 2018 | record : 2019 | [ 2020 | { 2021 | receiveAmount: 85, //领取金额(单位为分) 2022 | receiveTime : '1523169782', //领取时间戳字符串 2023 | answer : '', //领取者留言,仅查询接口有效 2024 | receiveId : '10000xxx', 2025 | state : 1, 2026 | gameTips : '手气最佳', //仅红包领取完毕时,手气最佳者有此字段 2027 | receiveOpenId: '10000xxx', 2028 | userName : 'wxid_xxx' //领取者wxid 2029 | }, 2030 | { 2031 | receiveAmount: 15, 2032 | receiveTime : '1523174612', 2033 | answer : '谢谢红包', 2034 | receiveId : '1000039501001804086017706218338', 2035 | state : 1, 2036 | receiveOpenId: '1000039501001804086017706218338', 2037 | userName : 'binsee' 2038 | }, 2039 | ], 2040 | operationTail: //操作提示:仅自己发的红包有效 2041 | { 2042 | name : '未领取的红包,将于24小时后发起退款', 2043 | type : 'Text', 2044 | content: '', 2045 | enable : 1, 2046 | iconUrl: '', 2047 | ossKey : 4294967295 2048 | }, 2049 | atomicFunc : { enable: 0 }, 2050 | jumpChange : 1, 2051 | changeWording: '已存入零钱,可直接提现', //查询接口返回'已存入零钱,可直接转账' 2052 | sendUserName : 'wxid_xxx' //发送者wxid 2053 | }, 2054 | message: '', 2055 | status : 0 2056 | } 2057 | } 2058 | * ``` 2059 | * @deprecated 2060 | * @memberof Padchat 2061 | */ 2062 | async queryRedPacket(rawMsgData, index = 0) { 2063 | return await this.sendCmd('queryRedPacket', { 2064 | rawMsgData, 2065 | index, 2066 | }) 2067 | } 2068 | 2069 | /** 2070 | * 领取红包 2071 | * 2072 | * @param {object} rawMsgData - 推送的消息结构体,即`push`事件中收到的Object 2073 | * @param {string} key - 红包的验证key,通过调用 receiveRedPacket 获得 2074 | * @returns {Promise} 返回Promise,注意捕捉catch 2075 | * 已领取过红包: 2076 | * ``` 2077 | { 2078 | success: true, 2079 | data : 2080 | { 2081 | external: { 2082 | retcode: 268502336, 2083 | retmsg : '你已领取过该红包' 2084 | }, 2085 | message: '', 2086 | status : 0 2087 | } 2088 | } 2089 | * ``` 2090 | * 2091 | * 未领取过的红包: 2092 | * ``` 2093 | { 2094 | success: true, 2095 | data : 2096 | { 2097 | external: 2098 | { 2099 | retcode : 0, 2100 | retmsg : 'ok', 2101 | sendId : '1000039501201804087013251181768', 2102 | amount : 1, 2103 | recNum : 2, 2104 | recAmount : 2, 2105 | totalNum : 3, 2106 | totalAmount : 4, 2107 | hasWriteAnswer : 0, 2108 | hbType : 1, 2109 | isSender : 0, 2110 | isContinue : 0, 2111 | receiveStatus : 2, 2112 | hbStatus : 3, 2113 | statusMess : '', 2114 | wishing : '发3个红包', 2115 | receiveId : '1000039501001804087013251181768', 2116 | headTitle : '领取2/3个', 2117 | canShare : 0, 2118 | operationHeader: [], 2119 | record : 2120 | [ 2121 | { 2122 | receiveAmount: 1, 2123 | receiveTime : '1523171198', 2124 | answer : '', 2125 | receiveId : '1000039501001804087013251181768', 2126 | state : 1, 2127 | receiveOpenId: '1000039501001804087013251181768', 2128 | userName : 'wxid_xxx' 2129 | }, 2130 | { 2131 | receiveAmount: 1, 2132 | receiveTime : '1523170992', 2133 | answer : '', 2134 | receiveId : '1000039501000804087013251181768', 2135 | state : 1, 2136 | receiveOpenId: '1000039501000804087013251181768', 2137 | userName : 'binsee' 2138 | } 2139 | ], 2140 | watermark : '', 2141 | jumpChange : 1, 2142 | changeWording : '已存入零钱,可直接提现', 2143 | sendUserName : 'binsee', 2144 | SystemMsgContext: //系统消息内容 2145 | ' 你领取了$binsee$的<_wc_custom_link_ color="#FD9931" href="weixin://weixinhongbao/opendetail?sendid=1000039501201804087013251181768&sign=68b9858edbc9ff8a88fb8c8fa987edaad88078b31daf6e7af4dba06e78849e50b29a3c1d10bad4893aff116a0db80c7d8a3aa96a5247e1ed095d88e66983fc6fd9f6f6dc8243411ef97727cf0bc698c3&ver=6">红包', 2146 | sessionUserName: '4674258153@chatroom', //会话wxid/chatroom 2147 | realNameInfo : { guideFlag: 0 } 2148 | }, 2149 | message: '', 2150 | status : 0 2151 | } 2152 | } 2153 | * ``` 2154 | * @deprecated 2155 | * @memberof Padchat 2156 | */ 2157 | async openRedPacket(rawMsgData, key) { 2158 | return await this.sendCmd('openRedPacket', { 2159 | rawMsgData, 2160 | key, 2161 | }) 2162 | } 2163 | 2164 | /** 公众号系列接口 */ 2165 | 2166 | /** 2167 | * 搜索公众号 2168 | * 2169 | * @param {string} content - 公众号名称等关键字 2170 | * @returns {Promise} 返回Promise,注意捕捉catch 2171 | * ``` 2172 | { 2173 | success: true, 2174 | data : 2175 | { 2176 | code: 0, 2177 | info: 2178 | { 2179 | continueFlag: 1, //仍有数据标志 2180 | cookies : //cookie数据 2181 | { 2182 | businessType: 1, 2183 | isHomepage : 1, 2184 | query : '"腾讯"', 2185 | scene : 2 2186 | }, 2187 | data: //返回的搜索相关数据 2188 | [{ 2189 | count: 20, 2190 | items: //搜索结果列表 2191 | [{ 2192 | aliasName: 'tencent', 2193 | brandFlag: 2, 2194 | brandInfo: 2195 | { 2196 | urls: 2197 | [{ 2198 | title: '查看历史消息', 2199 | url : 2200 | 'http://mp.weixin.qq.com/mp/getmasssendmsg?__biz=MzA3NDEyMDgzMw==#wechat_webview_type=1&wechat_redirect', 2201 | titleKey: '__mp_wording__brandinfo_history_massmsg' 2202 | }] 2203 | }, 2204 | docID: '3074120833', 2205 | externalInfo: 2206 | { 2207 | Appid: 'wx06441a33a2a67de4', 2208 | BindWxaInfo: 2209 | { 2210 | wxaEntryInfo: 2211 | [{ 2212 | title : '腾讯+', 2213 | username: 'gh_3a5568e1268b@app', 2214 | iconUrl : 'http://mmbiz.qpic.cn/mmbiz_png/xxx/0?wx_fmt=png' 2215 | }] 2216 | }, 2217 | FunctionFlag : 1, 2218 | InteractiveMode : '2', 2219 | IsAgreeProtocol : '1', 2220 | IsHideInputToolbarInMsg: '0', 2221 | IsShowHeadImgInMsg : '1', 2222 | RegisterSource : 2223 | { 2224 | IntroUrl: 2225 | 'http://mp.weixin.qq.com/mp/getverifyinfo?__biz=MzA3NDEyMDgzMw==&type=reg_info#wechat_redirect', 2226 | RegisterBody: '深圳市腾讯计算机系统有限公司' 2227 | }, 2228 | RoleId : '1', 2229 | ScanQRCodeType: 1, 2230 | ServiceType : 0, 2231 | VerifySource : 2232 | { 2233 | Description: '深圳市腾讯计算机系统有限公司', 2234 | IntroUrl : 2235 | 'http://mp.weixin.qq.com/mp/getverifyinfo?__biz=MzA3NDEyMDgzMw==#wechat_webview_type=1&wechat_redirect', 2236 | Type : 0, 2237 | VerifyBizType: 1 2238 | } 2239 | }, 2240 | friendsFollowCount: 0, 2241 | headHDImgUrl : 'http://wx.qlogo.cn/mmhead/xxx/0', 2242 | headImgUrl : 'http://wx.qlogo.cn/mmhead/xxx/132', 2243 | iconUrl : 'http://mmbiz.qpic.cn/mmbiz_png/xxx/0?wx_fmt=png', 2244 | nickName : '腾讯', 2245 | nickNameHighlight : '腾讯', 2246 | segQuery : ' 腾讯', 2247 | signature : '腾讯公司唯一官方帐号。', 2248 | signatureHighlight: '腾讯公司唯一官方帐号。', 2249 | userName : 'gh_88b080670a71', 2250 | verifyFlag : 24 2251 | }], 2252 | keywordList: ['腾讯'], 2253 | resultType : 0, 2254 | title : '公众号', 2255 | totalCount : 1900, 2256 | type : 1 2257 | }], 2258 | direction : 2, 2259 | exposeMs : 500, 2260 | isDivide : 0, 2261 | isExpose : 1, 2262 | isHomePage: 1, 2263 | lang : 'zh_CN', 2264 | monitorMs : 100, 2265 | offset : 20, 2266 | query : '"腾讯"', 2267 | resultType: 0, 2268 | ret : 0, 2269 | searchID : '18232918846508425807' 2270 | }, 2271 | message: '', 2272 | offset : 20, 2273 | status : 0 2274 | } 2275 | } 2276 | * ``` 2277 | * @memberof Padchat 2278 | */ 2279 | async searchMp(content) { 2280 | return await this.sendCmd('searchMp', { 2281 | content, 2282 | }) 2283 | } 2284 | 2285 | /** 2286 | * 获取公众号信息 2287 | * 2288 | * @param {string} ghName - 公众号gh名称,即`gh_`格式的id 2289 | * @returns {Promise} 返回Promise,注意捕捉catch 2290 | * ``` 2291 | { 2292 | success: true, 2293 | data : 2294 | { 2295 | info: 2296 | { 2297 | alias : 'tencent', 2298 | appid : 'wx06441a33a2a67de4', 2299 | bigHeadImgUrl: 'http://wx.qlogo.cn/mmhead/xxx/0', 2300 | bindKFUin : '0', 2301 | bindWxaInfo : 2302 | { 2303 | wxaEntryInfo: 2304 | [{ 2305 | username: 'gh_3a5568e1268b@app', 2306 | title : '腾讯+', 2307 | iconUrl : 'http://mmbiz.qpic.cn/mmbiz_png/xxx/0?wx_fmt=png' 2308 | }], 2309 | bizEntryInfo: [] 2310 | }, 2311 | bitMask : '4294967295', 2312 | brandIconURL: 'http://mmbiz.qpic.cn/mmbiz_png/xxx/0?wx_fmt=png', 2313 | brandInfo : 2314 | { 2315 | urls: 2316 | [{ 2317 | title : '查看历史消息', 2318 | url : 'http://mp.weixin.qq.com/mp/getmasssendmsg?xxxx', 2319 | titleKey: '__mp_wording__brandinfo_history_massmsg' 2320 | }] 2321 | }, 2322 | functionFlag : '1', 2323 | interactiveMode : '2', 2324 | isAgreeProtocol : '1', 2325 | isHideInputToolbarInMsg: '0', 2326 | isShowHeadImgInMsg : '1', 2327 | mmBizMenu : 2328 | { 2329 | uin : 3074120833, 2330 | version : 425306837, 2331 | interactiveMode: 2, 2332 | updateTime : 1518401098, 2333 | buttonList : 2334 | [ 2335 | { 2336 | id : 425306837, 2337 | type : 0, 2338 | name : '产品体验', 2339 | key : 'rselfmenu_2', 2340 | value: '', 2341 | subButtonList: 2342 | [{ 2343 | id : 425306837, 2344 | type : 2, 2345 | name : '往期内测', 2346 | key : 'rselfmenu_2_1', 2347 | value : 'http://mp.weixin.qq.com/mp/xxxxx', 2348 | subButtonList: [], 2349 | nativeUrl : '' 2350 | }], 2351 | nativeUrl: '' 2352 | }] 2353 | }, 2354 | nickName : '腾讯', 2355 | pyInitial: 'TX', 2356 | quanPin : 'tengxun', 2357 | registerSource: 2358 | { 2359 | registerBody: '深圳市腾讯计算机系统有限公司', 2360 | introUrl : 'http://mp.weixin.qq.com/mp/getverifyinfo?xxxx' 2361 | }, 2362 | roleId : '1', 2363 | scanQRCodeType : '1', 2364 | serviceType : '0', 2365 | signature : '腾讯公司唯一官方帐号。', 2366 | smallHeadImgUrl: 'http://wx.qlogo.cn/mmhead/xxx/132', 2367 | userName : 'gh_88b080670a71', 2368 | verifyFlag : '24', 2369 | verifyInfo : '深圳市腾讯计算机系统有限公司', 2370 | verifySource : 2371 | { 2372 | description : '深圳市腾讯计算机系统有限公司', 2373 | introUrl : 'http://mp.weixin.qq.com/mp/getverifyinfo?xxx', 2374 | type : 0, 2375 | verifyBizType: 1 2376 | } 2377 | }, 2378 | message: ' ', 2379 | status : 0 2380 | } 2381 | } 2382 | * ``` 2383 | * @memberof Padchat 2384 | */ 2385 | async getSubscriptionInfo(ghName) { 2386 | return await this.sendCmd('getSubscriptionInfo', { 2387 | ghName, 2388 | }) 2389 | } 2390 | 2391 | /** 2392 | * 操作公众号菜单 2393 | * 2394 | * @param {string} ghName - 公众号gh名称,即`gh_`格式的id 2395 | * @param {Number} menuId - 菜单id 2396 | * @param {string} menuKey - 菜单key 2397 | * @returns {Promise} 返回Promise,注意捕捉catch 2398 | * ``` 2399 | { 2400 | success: true, 2401 | data : { 2402 | message: '', 2403 | status : 0 2404 | } 2405 | } 2406 | * ``` 2407 | * @memberof Padchat 2408 | */ 2409 | async operateSubscription(ghName, menuId, menuKey) { 2410 | return await this.sendCmd('operateSubscription', { 2411 | ghName, 2412 | menuId, 2413 | menuKey, 2414 | }) 2415 | } 2416 | 2417 | /** 2418 | * 获取网页访问授权 2419 | * 2420 | * @param {string} ghName - 公众号gh名称,即`gh_`格式的id 2421 | * @param {string} url - 网页url 2422 | * @returns {Promise} 返回Promise,注意捕捉catch 2423 | * ``` 2424 | { 2425 | success: true, 2426 | data : 2427 | { 2428 | info: 2429 | { 2430 | 'X-WECHAT-KEY': 'xxxxxxxxxxxx', //授权key 2431 | 'X-WECHAT-UIN': 'MTQ5ODA2NDYw' //授权uin 2432 | }, 2433 | message: '', 2434 | status : 0, 2435 | fullUrl: //完整授权访问url 2436 | 'https://mp.weixin.qq.com/s?__biz=MzA5MDAwOTExMw==&mid=200126214&idx=1&sn=a1e7410ec56de5b6c4810dd7f7db8a47&chksm=1e0b3470297cbd666198666278421aed0a131d775561c08f52db0c82ce0e6a9546aac072a20e&mpshare=1&scene=1&srcid=0408bN3ACxqAH6jyq4vCBP9e&ascene=7&devicetype=iPad+iPhone+OS9.0.2&version=16060125&nettype=WIFI&lang=zh_CN&fontScale=100&pass_ticket=ZQW8EHr9vk%2BPGoWzmON4ev8I0MmliT4mp1ERTPEl8lc%3D&wx_header=1', 2437 | shareUrl: //分享url 2438 | 'http://mp.weixin.qq.com/s/QiB3FPE6fJmV6asvvxIkvA' 2439 | } 2440 | } 2441 | * ``` 2442 | * @memberof Padchat 2443 | */ 2444 | async getRequestToken(ghName, url) { 2445 | return await this.sendCmd('getRequestToken', { 2446 | ghName, 2447 | url, 2448 | }) 2449 | } 2450 | 2451 | /** 2452 | * 访问网页 2453 | * 2454 | * @param {string} url - 网页url地址 2455 | * @param {string} xKey - 访问Key,用`getRequestToken`获取 2456 | * @param {string} xUin - 访问uin,用`getRequestToken`获取 2457 | * @returns {Promise} 返回Promise,注意捕捉catch 2458 | * ``` 2459 | { 2460 | success: true, 2461 | data : 2462 | { 2463 | message : '', 2464 | response: //完整的访问结果原始数据文本(包含http头数据) 2465 | 'HTTP/1.1 200 OK\r\nContent-Security-Policy: script-src \'self\' \'unsafe-inline\' \'unsafe-eval\' http://*.qq.com https://*.qq.com http://*.weishi.com https://*.weishi.com xxxxxxxxxxxxxxxxxxxxxxxxxxx', 2466 | status: 0 2467 | } 2468 | } 2469 | * ``` 2470 | * @memberof Padchat 2471 | */ 2472 | async requestUrl(url, xKey, xUin) { 2473 | return await this.sendCmd('requestUrl', { 2474 | url, 2475 | xKey, 2476 | xUin, 2477 | }) 2478 | } 2479 | } 2480 | /** 2481 | * 等待指定cmdId返回 2482 | * 2483 | * @param {string} cmdId - 要监听的cmdId 2484 | * @param {number} [timeout=3000] 超时时间默认为3秒 2485 | * @private 2486 | * @returns {Promise} 2487 | */ 2488 | async function getCmdRecv(cmdId, timeout = 3000) { 2489 | if (!cmdId) { 2490 | throw new Error('未指定cmdID!') 2491 | } 2492 | cmdId = 'RET#' + cmdId 2493 | // console.log('进入 getCmdRecv,应该监听: %s', cmdId) 2494 | 2495 | return new Promise((res, rej) => { 2496 | // 如果某操作超过指定时间没有返回结果,则认为是操作超时 2497 | const timeOutHandle = setTimeout(() => { 2498 | this.removeAllListeners(cmdId) 2499 | rej(new Error('等待指令操作结果超时!当前超时时间为:' + timeout * 1000)) 2500 | }, timeout * 1000) 2501 | 2502 | this.once(cmdId, data => { 2503 | // console.log('监听到 %s 事件', cmdId, data) 2504 | clearTimeout(timeOutHandle) 2505 | res(data) 2506 | }) 2507 | }) 2508 | } 2509 | 2510 | /** 2511 | * 加工处理ws接收到的数据 2512 | * 2513 | * @param {string} msg - ws连接接收到的文本消息 2514 | * @private 2515 | */ 2516 | function onWsMsg(msg) { 2517 | let data 2518 | // console.log('进入 onWsMsg', msg) 2519 | try { 2520 | if (typeof msg === 'string') { 2521 | data = JSON.parse(msg) 2522 | } else { 2523 | throw new Error('ws传输的数据不是字符串格式!') 2524 | } 2525 | } catch (e) { 2526 | this.emit('error', new Error('解析msg数据失败: ' + e.message)) 2527 | return 2528 | } 2529 | 2530 | if (data.payload) { 2531 | if (data.payload.data) { 2532 | // 解析扩展数据的json文本 2533 | 2534 | if (data.payload.data.external) { 2535 | try { 2536 | //解析红包及转账接口返回数据 2537 | data.payload.data.external = JSON.parse(data.payload.data.external) 2538 | } catch (e) { } 2539 | } 2540 | 2541 | if (data.payload.data.info) { 2542 | try { 2543 | //解析公众号接口返回数据 2544 | data.payload.data.info = JSON.parse(data.payload.data.info) 2545 | 2546 | const info = data.payload.data.info 2547 | const fields = [ 2548 | 'BrandInfo', 2549 | 'externalInfo', 2550 | 'MMBizMenu', 2551 | 'RegisterSource', 2552 | 'VerifySource', 2553 | 'Location', 2554 | 'cookies', 2555 | 'brandInfo', 2556 | 'BindWxaInfo', 2557 | ] 2558 | 2559 | // 解析`getSubscriptionInfo`接口返回数据字段 2560 | fields.forEach(field => { 2561 | if (!info[field]) { return } 2562 | try { 2563 | info[field] = JSON.parse(info[field]) 2564 | } catch (e) { } 2565 | }) 2566 | 2567 | //解析`searchMp`接口返回数据字段 2568 | info.data.forEach((d_item, d_index) => { 2569 | //第一层数组 2570 | if (!d_item.items) { return } 2571 | const _item = info.data[d_index] 2572 | 2573 | _item.items.forEach((item, index) => { 2574 | //第二层数组,即真实的搜索结果列表 2575 | const _item2 = _item.items[index] 2576 | fields.forEach(field => { 2577 | if (!_item2[field]) { return } 2578 | try { 2579 | _item2[field] = JSON.parse(_item2[field]) 2580 | } catch (e) { } 2581 | }) 2582 | }) 2583 | }) 2584 | } catch (e) { } 2585 | } 2586 | 2587 | if (data.payload.data.member) { 2588 | try { 2589 | //解析获取群成员接口返回数据 2590 | data.payload.data.member = JSON.parse(data.payload.data.member) 2591 | } catch (e) { } 2592 | } 2593 | } 2594 | // 转小驼峰 2595 | data.payload = Helper.toCamelCase(data.payload) 2596 | } 2597 | 2598 | this.emit('msg', data) 2599 | // TODO: 补充push数据格式 2600 | 2601 | /** 2602 | * 返回数据结果: 2603 | data = { 2604 | type : 'cmdRet', //返回数据包类型 2605 | cmdId : 'b61eb250-3770-11e8-b00f-595f9d4f3df0', //请求id 2606 | taskId : '5', //服务端返回当前实例的任务ID 2607 | payload: //荷载数据(以下字段名称为转换为小驼峰后的,原始数据为下划线分隔) 2608 | { 2609 | error : '', //错误提示 2610 | msg : '', //其他提示信息 2611 | success: true, //接口执行是否成功 2612 | data : //接口执行结果数据,`push`类型无 2613 | { 2614 | message: '', 2615 | msgId : '1284778244346778513', 2616 | status : 0 2617 | }, 2618 | list: // 仅`push`类型拥有,包含多个push结构数据 2619 | [ 2620 | { 2621 | content : '信息内容', //消息内容或xml结构体内容 2622 | continue : 1, 2623 | description: '复仇者联盟 : 信息内容', //描述内容 2624 | fromUser : 'wxid_001', //发信人 2625 | msgId : '4032724472820776289', //消息id 2626 | msgSource : '', 2627 | msgType : 5, //消息主类型,类型为5时则用子类型判断 2628 | status : 1, 2629 | subType : 1, //消息子类型 2630 | timestamp : 1522921008, //消息时间戳 2631 | toUser : 'wxid_002', //收件人 2632 | uin : 149801234, //用户uin,全局唯一 2633 | mType : 1 //消息类型。等同msgType,当msgType为5时,等同于subType 2634 | } 2635 | ], 2636 | }, 2637 | } 2638 | */ 2639 | 2640 | let hasOn 2641 | switch (data.type) { 2642 | case 'cmdRet': 2643 | if (data.type === 'cmdRet' && data.cmdId) { 2644 | hasOn = this.emit('RET#' + data.cmdId, data) 2645 | if (!hasOn) { 2646 | this.emit('warn', new Error(`返回执行结果没有被监听!指令ID:${data.cmdId}`)) 2647 | } 2648 | } 2649 | break; 2650 | 2651 | case 'userEvent': 2652 | switch (data.event) { 2653 | case 'warn': 2654 | /** 2655 | * Warn event 2656 | * 实例错误提示 2657 | * 2658 | * @event Padchat#warn 2659 | * @property {error} error - 报错信息 2660 | * @example 2661 | * const wx = new Padchat() 2662 | * wx.on('warn',e=>{ 2663 | * console.log('任务出现错误:', e.message) 2664 | * }) 2665 | * 2666 | * @memberof Padchat 2667 | */ 2668 | // 如果success字段为true,则为不严重的问题 2669 | this.emit('warn', new Error('服务器返回错误提示:' + data.payload.error), data.success) 2670 | break 2671 | case 'qrcode': // 微信扫码登陆,推送二维码 2672 | /** 2673 | * Qrcode event 2674 | * 登陆二维码推送 2675 | * 2676 | * @event Padchat#qrcode 2677 | * @property {object} data - 二维码信息 2678 | * @property {string} [data.url] - 登陆二维码解析后的内容url,可使用此url作为内容生成二维码图片后,使用手机扫码登陆 2679 | * @property {string|null} msg - 附加提示信息 2680 | * @example 2681 | * const wx = new Padchat() 2682 | * wx.on('qrcode',data=>{ 2683 | * console.log(`登陆二维码内容为: "${data.url}"`) 2684 | * // 可使用`qrcode-terminal`库在终端生成二维码 2685 | * }) 2686 | * 2687 | * @memberof Padchat 2688 | */ 2689 | case 'scan': // 微信账号扫码事件 2690 | /** 2691 | * Scan event 2692 | * 扫码状态推送 2693 | * 2694 | * @event Padchat#scan 2695 | * @property {object} data - 扫码状态 2696 | * @property {number} data.status - 扫码状态: 2697 | *
`0` 等待扫码 2698 | *
`1` 扫码完成,等待手机端确认登陆 2699 | *
`2` 手机端已确认,等待登陆 2700 | *
`3` 二维码过期 2701 | *
`4` 手机端取消登陆 2702 | *
其他状态未知 2703 | * @property {number} [data.subStatus] - 扫码子状态,仅`status`为`2`时有效 2704 | *
`0` 登陆成功 2705 | *
`1` 登陆失败 2706 | *
其他状态未知 2707 | * @property {string} [data.headUrl] - 头像url **(扫码后存在)** 2708 | * @property {string} [data.deviceType] - 主设备类型 **(扫码后存在)** 2709 | * @property {string} [data.userName] - 账号wxid,全局唯一 **(扫码后存在)** 2710 | * @property {number} [data.uin] - 账号uin,全局唯一 **(扫码后存在)** 2711 | * @property {string} [data.email] - 账号绑定的邮箱 **(确认登陆后存在)** 2712 | * @property {string} [data.phoneNumber] - 账号绑定的手机号 **(确认登陆后存在)** 2713 | * @property {number} [data.qq] - 账号绑定的QQ号 **(确认登陆后存在)** 2714 | * @property {string} [data.nickName] - 账号昵称 **(确认登陆后存在)** 2715 | * @property {number} [data.external] - 是否为扩展设备登陆 2716 | *
`0` 主设备登陆 2717 | *
`1` 扩展设备登录 2718 | * @property {string|null} msg - 附加提示信息 2719 | * @example 2720 | * const wx = new Padchat() 2721 | * wx.on('scan',data=>{ 2722 | * switch (data.status) { 2723 | * case 0: 2724 | * case 1: 2725 | * case 2: 2726 | * case 3: 2727 | * case 4: 2728 | * default: 2729 | * break 2730 | * } 2731 | * }) 2732 | * 2733 | * @memberof Padchat 2734 | */ 2735 | case 'login': // 微信账号登陆成功 2736 | /** 2737 | * Login event 2738 | * 登陆成功推送 2739 | * 2740 | * @example 2741 | * const wx = new Padchat() 2742 | * wx.on('login',()=>{ 2743 | * console.log('微信账号登陆成功!') 2744 | * }) 2745 | * 2746 | * @event Padchat#login 2747 | */ 2748 | case 'autoLogin': // 自动重连成功 2749 | /** 2750 | * AutoLogin event 2751 | * 自动重连成功推送 2752 | * 2753 | * 自动重连后token会变化,可在此时获取新的token,否则使用旧token将不能断线重连,但可以二次登陆(需手机端确认登陆) 2754 | * 2755 | * @example 2756 | * const wx = new Padchat() 2757 | * wx.on('autoLogin',()=>{ 2758 | * wx.getLoginToken() 2759 | * console.log('自动重连成功!') 2760 | * }) 2761 | * 2762 | * @event Padchat#autoLogin 2763 | */ 2764 | case 'loaded': // 通讯录载入完毕 2765 | /** 2766 | * Loaded event 2767 | * 通讯录同步完毕推送 2768 | * 2769 | * @example 2770 | * const wx = new Padchat() 2771 | * wx.on('loaded',()=>{ 2772 | * console.log('通讯录同步完毕!') 2773 | * }) 2774 | * 2775 | * @event Padchat#loaded 2776 | */ 2777 | case 'logout': // 微信账号退出 2778 | /** 2779 | * Logout event 2780 | * 微信账号退出推送 2781 | * 2782 | * @example 2783 | * const wx = new Padchat() 2784 | * wx.on('logout',({error,msg})=>{ 2785 | * console.log('微信账号已退出! ',error,msg) 2786 | * }) 2787 | * 2788 | * @event Padchat#logout 2789 | * @property {object} data 2790 | * @property {string|null} [data.error] - 错误提示信息 2791 | * @property {string|null} [data.msg] - 附加提示信息 2792 | * @property {string|null} [msg] - 附加提示信息(同`data.msg`) 2793 | */ 2794 | case 'over': // 实例注销(账号不退出) 2795 | /** 2796 | * Over event 2797 | * 实例关闭推送 2798 | * 2799 | * @event Padchat#over 2800 | * @property {object} data 2801 | * @property {string|null} [data.msg] - 附加提示信息 2802 | * @property {string|null} [msg] - 附加提示信息(同`data.msg`) 2803 | * 2804 | * @example 2805 | * const wx = new Padchat() 2806 | * wx.on('over',({msg})=>{ 2807 | * console.log('任务实例已关闭!',msg) 2808 | * }) 2809 | * 2810 | */ 2811 | case 'sns': // 朋友圈事件:新评论 2812 | /** 2813 | * Sns event 2814 | * 朋友圈通知 2815 | * 2816 | * @event Padchat#sns 2817 | * @example 2818 | * const wx = new Padchat() 2819 | * wx.on('sns',()=>{ 2820 | * console.log('收到朋友圈事件!') 2821 | * }) 2822 | * 2823 | */ 2824 | this.emit(data.event, data.payload || {}, data.payload.msg) 2825 | break 2826 | 2827 | case 'notify': // 推送通知 2828 | if (data.payload.type === 4) { 2829 | if (this.openSyncContact) { 2830 | this.syncContact() 2831 | } 2832 | } else { 2833 | if (this.openSyncMsg) { 2834 | this.syncMsg() 2835 | } 2836 | } 2837 | break 2838 | case 'push': 2839 | if (data.payload && Array.isArray(data.payload.list)) { 2840 | const pushContact = data.payload.type === 4 2841 | const event = pushContact ? 'contact' : 'push' 2842 | let loaded = false 2843 | data.payload.list.forEach(item => { 2844 | const type = item.msgType 2845 | if (type === 32768 && item.continue === 0) { 2846 | //通讯录同步完毕 2847 | loaded = true 2848 | } 2849 | // 过滤无意义的2048和32768类型数据 2850 | if (type === undefined || type === 2048 || type === 32768) { 2851 | return null 2852 | } 2853 | // 当msg_type为5时,即表示推送的信息类型要用sub_type进行判断 2854 | // 另外增加一个属性来存储好了 2855 | item.mType = item.msgType === 5 ? item.subType : item.msgType 2856 | // 解析群成员列表 2857 | if (item.member) { 2858 | try { 2859 | item.member = JSON.parse(item.member) || [] 2860 | } catch (e) { 2861 | } 2862 | } 2863 | /** 2864 | * Push event 2865 | * 联系人/消息推送 2866 | * 2867 | * @event Padchat#push 2868 | * @property {number} data.mType - 推送类型 2869 |
`1` : 文字消息 2870 |
`2` : 好友信息推送,包含好友,群,公众号信息 2871 |
`3` : 收到图片消息 2872 |
`34` : 语音消息 2873 |
`35` : 用户头像buf 2874 |
`37` : 收到好友请求消息 2875 |
`42` : 名片消息 2876 |
`43` : 视频消息 2877 |
`47` : 表情消息 2878 |
`48` : 定位消息 2879 |
`49` : APP消息(文件 或者 链接 H5) 2880 |
`50` : 语音通话 2881 |
`51` : 状态通知(如打开与好友/群的聊天界面) 2882 |
`52` : 语音通话通知 2883 |
`53` : 语音通话邀请 2884 |
`62` : 小视频 2885 |
`2000` : 转账消息 2886 |
`2001` : 收到红包消息 2887 |
`3000` : 群邀请 2888 |
`9999` : 系统通知 2889 |
`10000`: 微信通知信息。微信群信息变更,多为群名修改、进群、离群信息,不包含群内聊天信息 2890 |
`10002`: 撤回消息 2891 | * @property {string} [data.fromUser] - (`mType`非2) 发件人 2892 | * @property {string} [data.toUser] - (`mType`非2) 收件人 2893 | * @property {string} [data.content] - (`mType`非2) 消息内容。非文本型消息时,此字段可能为xml结构文本 2894 | * @property {string} [data.msgSource] - (`mType`非2) 2895 | * @property {string} [data.data] - 图片、语音、视频等媒体文件base64文本 2896 | * @property {string} [data.description] - (部分`mType`非2) 消息描述 2897 | * @property {string} [data.msgId] - (`mType`非2) 消息id 2898 | * @property {string} [data.timestamp] - (`mType`非2) 消息时间戳 2899 | * @property {number} [data.uin] - 当前账号uin 2900 | * @property {string} [data.*] - 其他字段请自行输出查看 2901 | * @example 2902 | * const util = require('util') 2903 | * const wx = new Padchat() 2904 | * wx.on('push',data=>{ 2905 | * console.log('push:',util.inspect(data, { depth: 10 })) 2906 | * }) 2907 | */ 2908 | 2909 | /** 2910 | * Contact event 2911 | * 联系人/消息推送 2912 | * 2913 | * @event Padchat#contact 2914 | * @property {number} data.mType - 推送类型 2915 |
`2`: 好友信息推送,包含好友,群,公众号信息 2916 | * @property {string} data.city 城市 2917 | * @property {string} data.country 国家 2918 | * @property {string} data.provincia 省份 2919 | * @property {string} data.intro 公众号主体 2920 | * @property {string} data.stranger 个性签名 2921 | * @property {string} data.label 2922 | * @property {number} data.level 2923 | * @property {number} data.sex 性别: 1男 2女 0未知 2924 | * @property {string} data.signature v1值 2925 | * @property {number} data.source 联系人添加渠道 2926 | * @property {number} data.uin 当前账号uin (自己微信号的,不是好友的) 2927 | * @property {string} data.bigHead 高清头像 2928 | * @property {string} data.smallHead 头像缩略图 2929 | * @property {number} data.bitValue 2930 | * @property {number} data.chatroomId 群版本号 2931 | * @property {string} data.chatroomOwner 群主wxid 2932 | * @property {number} data.imgFlag 2933 | * @property {number} data.maxMemberCount 群成员上限 2934 | * @property {number} data.memberCount 群成员数量 2935 | * @property {number} data.msgType 2936 | * @property {string} data.nickName 联系人昵称 2937 | * @property {string} data.pyInitial 昵称拼音简写 2938 | * @property {string} data.quanPin 昵称拼音全拼 2939 | * @property {string} data.remark 备注 2940 | * @property {string} data.remarkPyInitial 备注拼音简写 2941 | * @property {string} data.remarkQuanPin 备注拼音全拼 2942 | * @property {string} data.userName 联系人微信号/wxid 2943 | * @example 2944 | * const util = require('util') 2945 | * const wx = new Padchat() 2946 | * wx.on('push',data=>{ 2947 | * console.log('push:',util.inspect(data, { depth: 10 })) 2948 | * }) 2949 | */ 2950 | this.emit(event, item) 2951 | }) 2952 | if (pushContact) { 2953 | if (!loaded && this.openSyncContact) { 2954 | this.syncContact() 2955 | } 2956 | if (loaded && !this.loaded) { 2957 | this.loaded = true 2958 | this.emit('loaded') 2959 | } 2960 | } 2961 | } 2962 | break 2963 | default: 2964 | this.emit('other', data) 2965 | break 2966 | } 2967 | break 2968 | default: 2969 | this.emit('other', data) 2970 | break; 2971 | } 2972 | } 2973 | 2974 | /** 2975 | * 清除消息结构中多余字段 2976 | * 2977 | * @param {object} obj - 要处理的数据结构 2978 | * @private 2979 | * @returns {object} 2980 | */ 2981 | function clearRawMsg(obj) { 2982 | if (typeof obj === 'object') { 2983 | delete obj.data 2984 | } 2985 | return obj 2986 | } 2987 | 2988 | 2989 | Padchat.loginType = loginType 2990 | Padchat.blacklist = blacklist 2991 | module.exports = Padchat 2992 | -------------------------------------------------------------------------------- /log4js.json: -------------------------------------------------------------------------------- 1 | { 2 | "appenders": { 3 | "console": { 4 | "type": "console" 5 | }, 6 | "rule-app": { 7 | "type": "dateFile", 8 | "filename": "logs/app.log", 9 | "maxLogSize": 10485760, 10 | "numBackups": 10, 11 | "keepFileExt": true 12 | }, 13 | "dev": { 14 | "type": "dateFile", 15 | "filename": "logs/dev.log", 16 | "maxLogSize": 10485760, 17 | "keepFileExt": true 18 | }, 19 | "error": { 20 | "type": "dateFile", 21 | "filename": "logs/error.log", 22 | "maxLogSize": 10485760, 23 | "keepFileExt": true 24 | }, 25 | "rule-error": { 26 | "type": "logLevelFilter", 27 | "level": "warn", 28 | "appender": "error" 29 | } 30 | }, 31 | "categories": { 32 | "default": { 33 | "appenders": [ 34 | "rule-app", 35 | "rule-error", 36 | "console" 37 | ], 38 | "level": "all" 39 | }, 40 | "dev": { 41 | "appenders": [ 42 | "dev" 43 | ], 44 | "level": "all" 45 | } 46 | }, 47 | "level": "debug" 48 | } 49 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "padchat-sdk", 3 | "version": "0.6.1", 4 | "description": "padchat开发包", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "node demo", 8 | "doc": "node scripts/docVer.js >nul && jsdoc2md index.js >> docs/index.md", 9 | "eslint": "eslint {define,helper,index,demo}.js", 10 | "release": "standard-version -a --scripts.postbump \"npm run doc && git add docs/index.md\"", 11 | "release:major": "npm run release -- -r major", 12 | "release:minor": "npm run release -- -r minor", 13 | "release:patch": "npm run release -- -r patch", 14 | "changelog": "conventional-changelog -p angular -i CHANGELOG.md -s -r 0" 15 | }, 16 | "author": "binsee", 17 | "license": "ISC", 18 | "dependencies": { 19 | "uuid": "^3.2.1", 20 | "ws": "^5.1.1" 21 | }, 22 | "devDependencies": { 23 | "@types/eslint": "^4.16.0", 24 | "@types/log4js": "^2.3.5", 25 | "@types/uuid": "^3.4.3", 26 | "@types/ws": "^4.0.2", 27 | "eslint": "^4.19.1", 28 | "eslint-config-egg": "^7.0.0", 29 | "jsdoc-to-markdown": "^4.0.1", 30 | "log4js": "^2.5.3", 31 | "qrcode-terminal": "^0.12.0" 32 | }, 33 | "repository": { 34 | "type": "git", 35 | "url": "git+https://github.com/binsee/padchat-sdk.git" 36 | }, 37 | "bugs": { 38 | "url": "https://github.com/binsee/padchat-sdk/issues" 39 | }, 40 | "homepage": "https://github.com/binsee/padchat-sdk#readme", 41 | "files": [ 42 | "README.md", 43 | "docs/index.md", 44 | "package.json", 45 | "define.js", 46 | "helper.js", 47 | "index.js" 48 | ], 49 | "standard-version": { 50 | "skip": { 51 | "tag": true 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /scripts/docVer.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const fs = require('fs') 4 | 5 | const tpl = `# Padchat Sdk $ver$ Documentation 6 | 7 | ` 8 | 9 | console.log(`args: ${process.argv}`) 10 | 11 | try { 12 | const tmpBuf = fs.readFileSync('./package.json') 13 | const data = JSON.parse(String(tmpBuf)) 14 | const ver = String(data.version || '') 15 | const str = tpl.replace('$ver$', `v${ver}` || 'Unknown version') 16 | 17 | fs.writeFileSync('docs/index.md', str) 18 | } catch (e) { 19 | console.error(e) 20 | process.exit(-1) 21 | } 22 | 23 | --------------------------------------------------------------------------------