本文不涉及到 AI 的知識,若是你是衝着 AI 來的,那麼可能會讓你失望了.
前一陣子一個朋友找我,問我能不能搞一個微信自動加好友的軟件,(在普通人眼裏,程序員就是專門寫木馬病毒外掛軟件的三流黑客.不會寫那就連三流都不是.前端
因此爲了證實我是三流黑客,我隨便百度了兩個現成的給他.原本事情到這裏應該結束了的,不過本着探索的精神,想順便了解一下這種外掛的原理,因而百歌谷度了一下,
最終原理沒找到,卻是找到幾個有意思的 github 倉庫,利用網頁版的微信 API 作第三方微信.node
先看個效果?git
<img src="https://raw.githubusercontent...; width="300" />
<img src="https://raw.githubusercontent...; width="300" />程序員
咱們看看大體步驟github
如下爲具體過程,不感興趣的能夠直接拉到末尾查看源碼倉庫web
須要注意的是,每一步的請求所使用的方法(POST/GET) 和 Content-Type 都是不同的,下面我都有標註,若是有請求不通的請參考 gtihub 源碼.
接口地址 https://wx.qq.com/jsloginjson
請求方法 POSTapi
參數類型(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=')
, 期待你一塊兒來稿
事