监听与输入企业微信登录验证码
监听与输入企业微信登录验证码
近期,企业微信在一些账号首次登录设备时,会要求输入验证码。形式如下:
为了尽快适配此功能,我们在 @juzi/wechaty 包中率先实现了验证码事件和输入验证码的方法。我们也会接下来推动这一方法在社区版实现。需要注意的是,我们目前只能保证 node 版 wechaty 的使用体验,暂时没有多余的人手推动其他版本的迭代,为了更好的使用 token ,请尽量使用 node 版本的 wechaty。 ( @juzi/wechaty 只提供了 node 版本)
依赖版本
@juzi/[email protected]
@juzi/[email protected]
@juzi/[email protected]
类型定义
export enum VerifyCodeStatus {
UNKNOWN = 0,
WAITING = 1, // 待输入
EXPIRED = 2, // 过期,尚未实装,目前应该根据接口返回抛错来判断是否过期
}
export enum VerifyCodeScene {
UNKNOWN = 0,
LOGIN = 1, // 登录验证码
}
type WechatyEventListenerVerifyCode = (
id: string, // 验证码 id ,在登录场景下,与登录链接中的 key 对应
message: string, // 验证码附带文字消息,目前固定为 请输入企业微信手机端展示的验证码,以继续登录
scene: PUPPET.types.VerifyCodeScene, // 验证码场景,目前只有 登录
status: PUPPET.types.VerifyCodeStatus // 验证码状态,目前只实现了 待输入
) => void | Promise<void>
// 监听事件
bot.on('verify-code', async (id: string, message: string, scene: types.VerifyCodeScene, status: types.VerifyCodeStatus) => {
// code here
})
相关方法
async enterVerifyCode (
id: string,
code: string,
): Promise<void> // 输入验证码
async cancelVerifyCode (
id: string,
): Promise<void> // 取消验证码 (会导致二维码刷新)
async refreshQrCode (): Promise<void> // 强制刷新二维码
使用说明
在验证码事件 verify-code 推送的过程中,扫码事件 scan 也会继续推送 ( status 为 4 Confirmed )。bot 开发者应该关注 verify-code 事件的 id 字段,并将其与 scan 事件的 qrcode 字段进行比较。qrcode 字段是形式如 https://wx.work.weixin.qq.com/cgi-bin/crtx_auth?key=${qrcodeKey}&wx=1 的字符串,我们应该比较其中的 qrcodeKey 和 verify-code 事件的 id,如果两个不相同,说明出了新的二维码,需要重新扫码。
示例
输入验证码
const store = {}
bot.on('scan', (qrcode: string, status: types.ScanStatus) => {
if (status === types.ScanStatus.Waiting) {
// 新二维码
store.qrcodeKey= getQrcodeKey(qrcode)
}
}).on('verify-code', async (id: string, message: string, scene: types.VerifyCodeScene, status: types.VerifyCodeStatus) => {
if (status === types.VerifyCodeStatus.WAITING && scene === types.VerifyCodeScene.LOGIN && id === store.qrcodeKey) {
const verifyCode = await getVerifyCode() // 通过一些途径输入验证码
try {
await bot.enterVerifyCode(id, verifyCode) // 如果没抛错,则说明输入成功,会推送登录事件
return
} catch (e) {
console.log(e.message)
// 如果抛错,请根据 message 处理,目前发现可以输错3次,超过3次错误需要重新扫码。
// 错误关键词: 验证码错误输入错误,请重新输入
// 错误关键词:验证码错误次数超过阈值,请重新扫码'
// 目前不会推送 EXPIRED 事件,需要根据错误内容判断
}
}
})
刷新验证码
await bot.cancelVerifyCode(store.qrcodeKey) // 根据 key 取消验证码 (需要重新扫码,不是更换验证码),但必须要在等待验证码状态才可以使用。
await bot.refreshQrCode() // 刷新二维码,任何情况都可使用
其他
请注意,相关文档可能会变化,但此 Issue 不一定能即时更新。请关注相关飞书文档,后期在我们的 token 自助系统上线后也会有 @juzi/wechaty 包的文档。
可运行实例
请使用这个 codespace
示例代码
请查看这个 repo workpro-getting-started.
@hcfw007 请问,调用 bot.enterVerifyCode(id, verifyCode) 时出现 this.puppet.enterVerifyCode is not a function 报错是为何引起的?
以下是我调用时的部分代码
export async function submitLoginVerifyCode(verifyCode: string) {
log.info("提交登录验证码 ->", `qrcodeKey: ${loginStore.qrcodeKey}; verifyCode: ${verifyCode}`);
await getBot().enterVerifyCode(loginStore.qrcodeKey, verifyCode);
}
输出日志为
11:02:05 INFO 提交登录验证码 -> qrcodeKey: B3DB5551B3DAD4A096485981A62F3BDD; verifyCode: 459209
error -> TypeError: this.puppet.enterVerifyCode is not a function
at WechatyImpl.enterVerifyCode (D:\Projects\xxx-puppet\node_modules\@juzi\wechaty\dist\cjs\src\wechaty\wechaty-base.js:255:28)
at D:\Projects\xxx-puppet\dist\src\bot\bot.js:80:24
at Generator.next (<anonymous>)
at D:\Projects\xxx-puppet\dist\src\bot\bot.js:8:71
at new Promise (<anonymous>)
at __awaiter (D:\Projects\xxx-puppet\dist\src\bot\bot.js:4:12)
at submitLoginVerifyCode (D:\Projects\xxx-puppet\dist\src\bot\bot.js:78:12)
at D:\Projects\xxx-puppet\dist\src\bot\botProcess.js:60:51
at Generator.next (<anonymous>)
at D:\Projects\xxx-puppet\dist\src\bot\botProcess.js:8:71
依赖版本
"@juzi/wechaty": "^1.0.65",
"@juzi/wechaty-puppet": "^1.0.61",
"@juzi/wechaty-puppet-service": "^1.0.69",
建议你们最好能提供一个最小的能运行的最新版本的example,比提供一些没有context的代码片段强多了
@hcfw007 请问,调用
bot.enterVerifyCode(id, verifyCode)时出现this.puppet.enterVerifyCode is not a function报错是为何引起的?以下是我调用时的部分代码
export async function submitLoginVerifyCode(verifyCode: string) { log.info("提交登录验证码 ->", `qrcodeKey: ${loginStore.qrcodeKey}; verifyCode: ${verifyCode}`); await getBot().enterVerifyCode(loginStore.qrcodeKey, verifyCode); }输出日志为
11:02:05 INFO 提交登录验证码 -> qrcodeKey: B3DB5551B3DAD4A096485981A62F3BDD; verifyCode: 459209 error -> TypeError: this.puppet.enterVerifyCode is not a function at WechatyImpl.enterVerifyCode (D:\Projects\xxx-puppet\node_modules\@juzi\wechaty\dist\cjs\src\wechaty\wechaty-base.js:255:28) at D:\Projects\xxx-puppet\dist\src\bot\bot.js:80:24 at Generator.next (<anonymous>) at D:\Projects\xxx-puppet\dist\src\bot\bot.js:8:71 at new Promise (<anonymous>) at __awaiter (D:\Projects\xxx-puppet\dist\src\bot\bot.js:4:12) at submitLoginVerifyCode (D:\Projects\xxx-puppet\dist\src\bot\bot.js:78:12) at D:\Projects\xxx-puppet\dist\src\bot\botProcess.js:60:51 at Generator.next (<anonymous>) at D:\Projects\xxx-puppet\dist\src\bot\botProcess.js:8:71依赖版本
"@juzi/wechaty": "^1.0.65", "@juzi/wechaty-puppet": "^1.0.61", "@juzi/wechaty-puppet-service": "^1.0.69",
我觉得最大的可能是bot build的时候没有引用@juzi/wechaty-puppet-service
@KroMiose package.json里把之前旧的依赖删除,引入@hcfw007提供的就可以
感谢解答!问题已解决,引用的依赖都是@juzi/wechaty没错,在 WechatyBuilder.build 参数中传入的 puppet 改为 puppet: "@juzi/wechaty-puppet-service" 即可
嗯,你把旧的依赖删了这里会报错的,比较容易找到问题
@hcfw007 请问,调用
bot.enterVerifyCode(id, verifyCode)时出现this.puppet.enterVerifyCode is not a function报错是为何引起的? 以下是我调用时的部分代码export async function submitLoginVerifyCode(verifyCode: string) { log.info("提交登录验证码 ->", `qrcodeKey: ${loginStore.qrcodeKey}; verifyCode: ${verifyCode}`); await getBot().enterVerifyCode(loginStore.qrcodeKey, verifyCode); }输出日志为
11:02:05 INFO 提交登录验证码 -> qrcodeKey: B3DB5551B3DAD4A096485981A62F3BDD; verifyCode: 459209 error -> TypeError: this.puppet.enterVerifyCode is not a function at WechatyImpl.enterVerifyCode (D:\Projects\xxx-puppet\node_modules\@juzi\wechaty\dist\cjs\src\wechaty\wechaty-base.js:255:28) at D:\Projects\xxx-puppet\dist\src\bot\bot.js:80:24 at Generator.next (<anonymous>) at D:\Projects\xxx-puppet\dist\src\bot\bot.js:8:71 at new Promise (<anonymous>) at __awaiter (D:\Projects\xxx-puppet\dist\src\bot\bot.js:4:12) at submitLoginVerifyCode (D:\Projects\xxx-puppet\dist\src\bot\bot.js:78:12) at D:\Projects\xxx-puppet\dist\src\bot\botProcess.js:60:51 at Generator.next (<anonymous>) at D:\Projects\xxx-puppet\dist\src\bot\botProcess.js:8:71依赖版本
"@juzi/wechaty": "^1.0.65", "@juzi/wechaty-puppet": "^1.0.61", "@juzi/wechaty-puppet-service": "^1.0.69",我觉得最大的可能是bot build的时候没有引用@juzi/wechaty-puppet-service
你们这个依赖的版本需要替换以前package.json的哪几个依赖吗?我的verify-code监听事件不奏效呢
目前我安装的依赖
不生效的最大可能是你只是安装了依赖,但在代码中创建实例时仍然使用了旧的依赖。
let verifyCode = fs.readFileSync(conf.wxVerifyCodeFile).toString();
console.log(`bot.config id:${id}, verifyCode: ${verifyCode}`)
try {
await bot.enterVerifyCode(id, verifyCode) // 如果没抛错,则说明输入成功,会推送登录事件
return
} catch (e) {
console.log(`enterVerifyCode error : ${JSON.stringify(e)}`)
}
错误信息如下,是什么原因呢? {"code":13,"details":"Invalid verify code!","metadata":{"content-type":["application/grpc+proto"],"date":["Wed, 20 Sep 2023 09:02:10 GMT"],"authorization":["Wechaty undefined"]}}
let verifyCode = fs.readFileSync(conf.wxVerifyCodeFile).toString(); console.log(`bot.config id:${id}, verifyCode: ${verifyCode}`) try { await bot.enterVerifyCode(id, verifyCode) // 如果没抛错,则说明输入成功,会推送登录事件 return } catch (e) { console.log(`enterVerifyCode error : ${JSON.stringify(e)}`) }错误信息如下,是什么原因呢? {"code":13,"details":"Invalid verify code!","metadata":{"content-type":["application/grpc+proto"],"date":["Wed, 20 Sep 2023 09:02:10 GMT"],"authorization":["Wechaty undefined"]}}
就是错误码有误。请注意是否包含了空格、换行、不可显字符等特殊字符。
let verifyCode = fs.readFileSync(conf.wxVerifyCodeFile).toString(); console.log(`bot.config id:${id}, verifyCode: ${verifyCode}`) try { await bot.enterVerifyCode(id, verifyCode) // 如果没抛错,则说明输入成功,会推送登录事件 return } catch (e) { console.log(`enterVerifyCode error : ${JSON.stringify(e)}`) }错误信息如下,是什么原因呢? {"code":13,"details":"Invalid verify code!","metadata":{"content-type":["application/grpc+proto"],"date":["Wed, 20 Sep 2023 09:02:10 GMT"],"authorization":["Wechaty undefined"]}}
相同的问题解决了,验证码要字符串类型不是数字,同时使用text.replace(/\s+/g, '')去除空格和字符串,已经登录,有问题可以联系我v:jitasanshao
启动报错 08:59:53 INFO PuppetSkeleton start() 08:59:53 INFO PuppetService start() instanciating GrpcManager ... 08:59:53 INFO PuppetService start() instanciating GrpcManager ... done 08:59:53 INFO PuppetService start() setting up bridge grpc event stream ... 08:59:53 INFO PuppetService start() setting up bridge grpc event stream ... done 08:59:53 INFO PuppetService start() starting grpc manager... 08:59:53 WARN last event was 1708995593.491 seconds ago, will not request event cache 08:59:53 WARN GrpcManager initClient() TLS: disabled (INSECURE) 08:59:53 INFO GrpcManager startStream() connecting event stream with account undefined and seq undefined /home/test2/workpro-getting-started-latest-features/node_modules/@grpc/grpc-js/src/subchannel-address.ts:40 return 'port' in address; ^ TypeError: Cannot use 'in' operator to search for 'port' in undefined at isTcpSubchannelAddress (/home/test2/workpro-getting-started-latest-features/node_modules/@grpc/grpc-js/src/subchannel-address.ts:40:16) at interleaveAddressFamilies (/home/test2/workpro-getting-started-latest-features/node_modules/@grpc/grpc-js/src/load-balancer-pick-first.ts:145:27) at PickFirstLoadBalancer.updateAddressList (/home/test2/workpro-getting-started-latest-features/node_modules/@grpc/grpc-js/src/load-balancer-pick-first.ts:520:25) at ChildLoadBalancerHandler.updateAddressList (/home/test2/workpro-getting-started-latest-features/node_modules/@grpc/grpc-js/src/load-balancer-child-handler.ts:137:19) at onSuccessfulResolution (/home/test2/workpro-getting-started-latest-features/node_modules/@grpc/grpc-js/src/resolving-load-balancer.ts:298:34) at processTicksAndRejections (node:internal/process/task_queues:86:22)
TypeError: Cannot use 'in' operator to search for 'port' in undefined
@15638192475 参考这个issue: https://github.com/wechaty/puppet-supports/issues/364#issuecomment-1952270004
ps:我这个能算贡献者吗
@petrichor112321 额,这个不太行。
无法监听到verify-code事件 是什么原因?
无法监听到verify-code事件 是什么原因?
检查下依赖版本?
@hcfw007 store.qrcodeKey= getQrcodeKey(qrcode)和 const verifyCode = await getVerifyCode()的getQrcodeKey、getVerifyCode是怎么来的?是后端写的还是某一个依赖里面自带的?
为什么监听不到verify-code这个事件,扫码登录后,监听验证码事件没有响应
@hcfw007 store.qrcodeKey= getQrcodeKey(qrcode)和 const verifyCode = await getVerifyCode()的getQrcodeKey、getVerifyCode是怎么来的?是后端写的还是某一个依赖里面自带的?
自行编码获取。
为什么监听不到verify-code这个事件,扫码登录后,监听验证码事件没有响应
请确保使用@juzi的依赖包