Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

监听与输入企业微信登录验证码 #267

Open
hcfw007 opened this issue Aug 31, 2023 · 21 comments
Open

监听与输入企业微信登录验证码 #267

hcfw007 opened this issue Aug 31, 2023 · 21 comments

Comments

@hcfw007
Copy link
Member

hcfw007 commented Aug 31, 2023

监听与输入企业微信登录验证码

近期,企业微信在一些账号首次登录设备时,会要求输入验证码。形式如下:

image

为了尽快适配此功能,我们在 @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 的字符串,我们应该比较其中的 qrcodeKeyverify-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.

@KroMiose
Copy link

KroMiose commented Sep 1, 2023

@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",

@LLSean
Copy link

LLSean commented Sep 1, 2023

建议你们最好能提供一个最小的能运行的最新版本的example,比提供一些没有context的代码片段强多了

@hcfw007
Copy link
Member Author

hcfw007 commented Sep 1, 2023

@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

@LLSean
Copy link

LLSean commented Sep 1, 2023

@KroMiose package.json里把之前旧的依赖删除,引入@hcfw007提供的就可以

@KroMiose
Copy link

KroMiose commented Sep 1, 2023

感谢解答!问题已解决,引用的依赖都是@juzi/wechaty没错,在 WechatyBuilder.build 参数中传入的 puppet 改为 puppet: "@juzi/wechaty-puppet-service" 即可

@LLSean
Copy link

LLSean commented Sep 1, 2023

嗯,你把旧的依赖删了这里会报错的,比较容易找到问题

@charleyCC
Copy link

@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

image
你们这个依赖的版本需要替换以前package.json的哪几个依赖吗?我的verify-code监听事件不奏效呢
目前我安装的依赖
image

@hcfw007
Copy link
Member Author

hcfw007 commented Sep 20, 2023

不生效的最大可能是你只是安装了依赖,但在代码中创建实例时仍然使用了旧的依赖。

@xronghui
Copy link

        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"]}}

@su-chang su-chang reopened this Sep 27, 2023
@hcfw007
Copy link
Member Author

hcfw007 commented Sep 27, 2023

        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"]}}

就是错误码有误。请注意是否包含了空格、换行、不可显字符等特殊字符。

@myllq
Copy link

myllq commented Dec 14, 2023

        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

@15638192475
Copy link

启动报错
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)

@su-chang
Copy link
Member

TypeError: Cannot use 'in' operator to search for 'port' in undefined

@15638192475 参考这个issue: #364 (comment)

@petrichor112321
Copy link

我写了一个md汇总了会遇到的问题及解决方案,包括怎么实现输入验证码 @hcfw007 Wework Bot问题汇总,有帮助的话点个star

ps:我这个能算贡献者吗

@su-chang
Copy link
Member

su-chang commented Apr 2, 2024

ps:我这个能算贡献者吗

@petrichor112321 额,这个不太行。

@Lyq0055
Copy link

Lyq0055 commented May 16, 2024

无法监听到verify-code事件 是什么原因?

@hcfw007
Copy link
Member Author

hcfw007 commented May 16, 2024

无法监听到verify-code事件 是什么原因?

检查下依赖版本?

@GiockL
Copy link

GiockL commented Aug 15, 2024

@hcfw007 store.qrcodeKey= getQrcodeKey(qrcode)和 const verifyCode = await getVerifyCode()的getQrcodeKey、getVerifyCode是怎么来的?是后端写的还是某一个依赖里面自带的?

@18075717849
Copy link

为什么监听不到verify-code这个事件,扫码登录后,监听验证码事件没有响应

@hcfw007
Copy link
Member Author

hcfw007 commented Aug 24, 2024

@hcfw007 store.qrcodeKey= getQrcodeKey(qrcode)和 const verifyCode = await getVerifyCode()的getQrcodeKey、getVerifyCode是怎么来的?是后端写的还是某一个依赖里面自带的?

自行编码获取。

@hcfw007
Copy link
Member Author

hcfw007 commented Aug 24, 2024

为什么监听不到verify-code这个事件,扫码登录后,监听验证码事件没有响应

请确保使用@juzi的依赖包

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests