资讯专栏INFORMATION COLUMN

利用网页版微信API做一个微信机器人

caspar / 2508人阅读

摘要:本文不涉及到的知识如果你是冲着来的那么可能会让你失望了前一阵子一个朋友找我问我能不能搞一个微信自动加好友的软件在普通人眼里程序员就是专门写木马病毒外挂软件的三流黑客不会写那就连三流都不是所以为了证明我是三流黑客我随便百度了两个现成的给他本来

本文不涉及到 AI 的知识,如果你是冲着 AI 来的,那么可能会让你失望了.

前一阵子一个朋友找我,问我能不能搞一个微信自动加好友的软件,(在普通人眼里,程序员就是专门写木马病毒外挂软件的三流黑客.不会写那就连三流都不是.

所以为了证明我是三流黑客,我随便百度了两个现成的给他.本来事情到这里应该结束了的,不过本着探索的精神,想顺便了解一下这种外挂的原理,于是百歌谷度了一下,
最终原理没找到,倒是找到几个有意思的 github 仓库,利用网页版的微信 API 做第三方微信.

先看个效果?


步骤

我们看看大致步骤

获取 UUID

根据 UUID 获取二维码

扫码登陆, 获取登陆信息

拿登陆信息换初始化数据

拿数据初始化

获取好友列表和消息列表

发送消息

以下为具体过程,不感兴趣的可以直接拉到末尾查看源码仓库

需要注意的是,每一步的请求所使用的方法(POST/GET) 和 Content-Type 都是不一样的,下面我都有标注,如果有请求不通的请参考 gtihub 源码.
一、获取 UUID

接口地址 https://wx.qq.com/jslogin

请求方法 POST

参数类型(content-type) application/x-www-form-urlencoded

参数

{
    appid: "wx782c26e4c19acffb",
    fun: "new",
    lang: "zh_CN",
     _: new Date().valueOf()
}

除了最后一个当前时间戳不是固定的,其他的3个参数都是写死的,照抄即可,调用成功的话,会到一个字符串 window.QRLogin.code = 200; window.QRLogin.uuid = "obizONtqZA==";, 需要自己想办法截取到 window.QRLogin.uuid = 后面的那串字符,即 UUID.

二、获取二维码

这一步很简单,有了 UUID 后,我们可以直接请求 "https://wx.qq.com/qrcode/" + UUID 获取到二维码. 获取到二维码以后,先别急着去扫描二维码,因为我们要先去监听二维码的扫描状态,这样我们才能知道什么时候被登陆.

请求方式 GET 无需参数

三、监听二维码的扫描结果

接口地址 https://wx.qq.com/cgi-bin/mmw...

请求方法 GET

参数类型(content-type) application/x-www-form-urlencoded

参数

{
    tip: 0,
    uuid: "obizONtqZA==",
    _: new Date().valueOf(),
    loginicon: true
}

tip 取值 0 或 1, 监听分2个阶段,第一阶段,监听用户是否扫码,tip 为 0,第二阶段,监听用户是否在微信上点确认登陆,tip 为 1.

uuid 就是第一步获取到的那个 UUID

_ 当前时间戳

loginicon 我猜应该是否扫码完返回用户头像,都填 true 即可.

返回结果,当你扫描二维码的时候,接口会返回你一个这样的对象

{
    "window.code": 201,
    "window.userAvatar": 头像的 base64 地址
}

得到的 code 是 201, 说明已扫码,但并不代表已登陆,还需要继续监听是否在手机微信上点击 确认登陆 按钮(重复上面步骤,把 参数里的 tip 改为 1 即可)

这步如果成功的话,会返回一个如下对象

{
    "window.code": "200",
    "window.redirect_uri": "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxnewloginpage?ticket=ARD37_ikx-Kakd2i0W-f-E7q@qrticket_0&uuid=4f6yOkV4AA==&lang=zh_CN&scan=1548300672" }
}
四、获取初始化数据(敏感数据)

上一步获取到的数据里面的 window.redirect_uri 里包含了一个 url 和一些 查询参数,直接请求这个地址好像没办法成功,需要将 url 和 参数拆分,然后加入其他参数

接口地址 就是上面的 url

请求方法 GET

参数类型(content-type) application/x-www-form-urlencoded

参数

{
    ticket: 上面得到的 ticket,
    uuid: 上面得到的 uuid,
    lang: "zh_CN",  // 固定
    scan: 上面得到的 scan,
    fun: "new" // 固定
}

这一步的返回的头部里面,会有个 cookie ,需要存起来,接来来得到请求头里面要带上这个 cookie,另外就是一个 xml 格式的 敏感的信息,也是要存起来.

tip: xml 格式可以用 xml2js 转换成 json.
五、初始化

呼,到这一步,终于接近登陆成功了,只需再调用以下接口,初始化以下

接口地址 https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxinit?r=${~(new Date().valueOf())}

请求方法 POST

参数类型(content-type) application/json

参数

{
    BaseRequest: {
        DeviceID: "e747337466044216", // 这个好像随便填都可以
        Sid: 上一步获取到的 wxsid,
        Uin: 上一步获取到的 wxuin,
        Skey: 上一步获取到的 skey
    }
}

这里有 2 个地方跟之前不同的,第一是地址后面要跟一个时间戳,而且这个时间戳还要按位取反,第二个是请求参数是放在 BaseRequest 下面,而不是对象的一级属性下面.

返回的数据里面有 2 个数据需要保存起来,一个是 data.SyncKey, 一个是 res.data.User.UserName,后面都会用到

到此才真正完成登陆,下面如果你不需要好友列表的话,可以直接收取消息了

六、检测新消息

接口地址 https://webpush.wx.qq.com/cgi...

请求方法 GET

参数类型(content-type) application/json

参数

let time = new Date().getTime()

let synckey = ""

let sk = data.SyncKey.List || []   // data.SyncKey 就是上一步获取到的那个

for (let i = 0; i < sk.length; i++) {
    synckey += `${sk[i].Key}_${sk[i].Val}`
    if (i !== sk.length - 1) synckey += "|"
}

// 传递的参数
{
    r: time,
    sid: 第四步拿到的 wxsid,
    uin: 第四步拿到的 wxuin,
    skey: 第四步拿到的 skey,
    deviceid: "e747337466044216", // 同上一步
    synckey: synckey,
    _: time
}

返回内容的 data 里面 包含如下内容

window.synccheck={retcode:"0",selector:"2"}

如果 selector 是 2, 说明有新消息,走下一步,获取消息内容

七、获取消息内容

接口地址 https://wx.qq.com/cgi-bin/mmw...

请求方法 POST

参数类型(content-type) application/json

参数

{
    BaseRequest: {
        Uin: 第四步拿到的 wxuin,
        Sid: 第四步拿到的 wxsid,
        Skey: 第四步拿到的 skey,
        DeviceID: "e747337466044216", // 同上一步
    },
    SyncKey: data.SyncKey, // 还记得上一步我们费尽千辛万苦转换这个数据吗? 你没看错,这里不需要转换,就是这么神奇
    rr: ~(new Date().valueOf())
}

返回结果里面有个 data.AddMsgList 就是消息列表了,还有个 data.SyncCheckKey 就是下次请求的时候用的 SyncKey, 每次都会变的.

AddMsgList 是一个数组,里面可能包含多条消息,消息的自动比较多,就不一一说明了,这里说说 2 个比较重要的字段,其他的字段有兴趣的可以自己打印出来看一下.

FromUserName 对方的微信名,说是微信名,其实是一个 @ 或 @@ 开头的内部的id, 完全不可读,据我猜测 @ 开头的应该是普通好友, @@ 开头的是群或者公众号之类的

Content 消息内容

有了消息内容,和发消息的人,我们就可以回复对方,不过回复什么? 当然不可能写一大堆 if else 或者 switch case 去适应各种情况,不妨网上搜索一下 价值一个亿的ai代码 哈哈哈

八、获取自动回复内容

这边我用的是图灵机器人的 API 地址,当然你也可以用其他的.

接口地址 http://openapi.tuling123.com/...

请求方法 POST

参数类型(content-type) application/json

参数

{

perception: {
    inputText: {
        text: "待回复的消息"
    }
},
userInfo: {
    apiKey: tulingApiKey,  // 在图灵官网申请
    userId: tulingUserId   // 同上

}

你要是懒得去申请的话,可以在我的项目里面复制, 在 src/global.js 里面,在返回的内容里面 data.results[0].values.text 下面可以看到图灵给你生成的自动回复内容(results是一个数组,支持一次回复多条)

九、回复消息

拿到自动回复以后,我们只需要把它发给你的好友,即完成一次自动对话.

接口地址 https://wx.qq.com/cgi-bin/mmw...

请求方法 POST

参数类型(content-type) application/json

参数

let timeStamp = new Date().getTime() + "" + (9000 * Math.random() + 1000)
{
    BaseRequest: {
      Uin: 同上,
      Sid: 同上,
      Skey: 同上,
      DeviceID: 同上
    },
    Msg: {
      Type: 1,  // 消息类型 1 是文字消息,其他的暂时没用过
      Content: "回复的内容",
      FromUserName: "你的用户名,在第五步有拿到",
      ToUserName: "对方的微信名 第七步的 FromUserName",
      LocalID: timeStamp,
      ClientMsgId: timeStamp
}

发送成功的话,会返回如下内容

{
    BaseResponse: { Ret: 0, ErrMsg: "" },
    MsgID: "2033517278669301361",
    LocalID: ""
}

好了,这样我们的一个自动回复机器人就完成了.完整的代码在这里

广告时间

我们40人的前端团队常年招兵买马中,在厦门的和想来厦门的童鞋们,不要吝惜你的简历,使劲砸过来 邮箱:atob("bnVveWFAZ2FvZGluZy5jb20="), 期待你一起来稿

对本文有意见或者建议,请尽量在 github 上提 issue, 最近比较忙,比较不怎么逛社区

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/53614.html

相关文章

  • 利用网页微信API一个微信器人

    摘要:本文不涉及到的知识如果你是冲着来的那么可能会让你失望了前一阵子一个朋友找我问我能不能搞一个微信自动加好友的软件在普通人眼里程序员就是专门写木马病毒外挂软件的三流黑客不会写那就连三流都不是所以为了证明我是三流黑客我随便百度了两个现成的给他本来 本文不涉及到 AI 的知识,如果你是冲着 AI 来的,那么可能会让你失望了. 前一阵子一个朋友找我,问我能不能搞一个微信自动加好友的软件,(在普通...

    crelaber 评论0 收藏0
  • js微信聊天器人——wechat-robot

    摘要:基于和端微信开发的聊天机器人。使用的微信账号即充当机器人的账号为个人账号,可自定义指令。关闭玫瑰感谢您的使用玫瑰闪电需要开启请在控制台启动程序闪电微信发出关闭口令,程序退出。 Github: https://github.com/doterlin/wechat-robot showImg(https://segmentfault.com/img/remote/1460000010601...

    Darkgel 评论0 收藏0
  • 手把手教你扩展个人微信号(2)(微信控制器、群发助手、好友删除检测)

    摘要:本文为教程的第二部分,主要以微信控制器群发助手好友删除检测为例演示如何调用微信。教程流程简介这一系列教程从如何分析微信协议开始,第一部分教你如何从零开始获取并模拟扩展个人微信号所需要的协议。 现在的日常生活已经离不开微信,本文将会抛砖引玉演示如何使用Python调用微信API做一些有意思的东西。 看完这一系列教程,你就能从头开始实现自己关于微信的想法。 本文为教程的第二部分,主要以微信...

    LeanCloud 评论0 收藏0
  • 手把手教你扩展个人微信号(1)

    摘要:关于本教程有任何建议或者疑问,都欢迎邮件与我联系,或者在上提出教程流程简介教程将会从如何分析微信协议开始,第一部分将教你如何从零开始获取并模拟扩展个人微信号所需要的协议。 现在的日常生活已经离不开微信,难免会生出微信有没有什么API可以使用的想法。 那样就可以拿自己微信做个消息聚合、开个投票什么的,可以显然没有这种东西。 不过还好,有网页版微信不就等于有了API么,这个项目就是出于这个...

    siberiawolf 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<