This article doesn’t cover AI, so if you’re looking for AI, you might be disappointed.

A while ago a friend look for me, ask me to be able to make a micro letter automatically add friend’s software,(in the eyes of ordinary people, programmer is specialized in writing Trojan virus plug-in software third-rate hacker. If you can’t write, you’re not even third-rate.

So to prove that I was a third-rate hacker, I randomly googled two ready-made ones for him. Originally things should be over here, but in the spirit of exploration, want to incidentally understand the principle of this plug-in, so 100 Google degree, the final principle did not find, but found a few interesting Github warehouse, using the webpage version of wechat API to do third-party wechat.

Let’s see what happens first, okay?


steps

Let’s look at the general process

  1. Get UUID
  2. Obtain the QR code based on the UUID
  3. Scan code login, access to login information
  4. Exchange login information for initialization data
  5. Get data to initialize
  6. Gets a list of friends and messages
  7. Send a message

The following is the detailed process, those who are not interested can just drag to the end to view the source repository

It should be noted that the methods (POST/GET) and content-Type used in each step of the request are different. I have marked them below. If any request fails, please refer to the source code of GtiHub.

Obtain the UUID

Interface address wx.qq.com/jslogin

Request method POST

Content-type Application/X-www-form-urlencoded

parameter

{
    appid: 'wx782c26e4c19acffb',
    fun: 'new',
    lang: 'zh_CN',
     _: new Date().valueOf()
}
Copy the code

Qrlogin. code = 200; window.qrlogin. code = 200; window.qrlogin. code = 200; window.QRLogin.uuid = “obizONtqZA==”; Uuid = (window. Qrlogin. uuid =);

2. Obtain the QR code

This step is very simple, after a UUID, we can directly ask ‘https://wx.qq.com/qrcode/’ + UUID for the qr code. After obtaining the TWO-DIMENSIONAL code, don’t rush to scan the two-dimensional code, because we have to monitor the scanning state of the two-dimensional code first, so that we can know when to be logged in.

Request mode GET requires no parameters

Three, monitor the scanning results of the TWO-DIMENSIONAL code

Interface address wx.qq.com/cgi-bin/mmw…

Request method GET

Content-type Application/X-www-form-urlencoded

parameter

{
    tip: 0,
    uuid: 'obizONtqZA==',
    _: new Date().valueOf(),
    loginicon: true
}
Copy the code

Tip takes the value of 0 or 1. The monitoring can be divided into two stages. In the first stage, whether the monitoring user scans codes,tip is 0; in the second stage, whether the monitoring user clicks on wechat to confirm login,tip is 1.

The UUID is the one obtained in the first step

_ Current timestamp

Loginicon I guess whether to scan the code to return to the user’s avatar, both fill in true.

Return the result, when you scan the QR code, the interface will return you one of these objects

{
    'window.code': 201,
    'window.userAvatar': Base64 address of avatar}Copy the code

The obtained code is 201, indicating that the code has been scanned, but it does not mean that the user has logged in. It is still necessary to monitor whether to click the login confirmation button on wechat of the mobile phone (repeat the above steps and change the tip in the parameter to 1).

This step, if successful, returns the following object

{
    '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==&la ng=zh_CN&scan=1548300672'}}Copy the code

4. Obtain initialization data (sensitive data)

The window. Redirect_uri contains a URL and some query parameters. It is not possible to request the url directly, so you need to split the URL and parameters and add other parameters

The interface address is the url above

Request method GET

Content-type Application/X-www-form-urlencoded

parameter

{ticket: ticket obtained above, uuid: uUID obtained above, lang:'zh_CN', // fix scan: get scan above, fun:'new'/ / fixed}Copy the code

In this step, you’re going to have a cookie in the header that you’re going to have to store, and then you’re going to have to store that cookie in the request header, and then you’re going to have to store sensitive information in XML.

XML formats can be converted to JSON using XML2JS.

5. Initialization

At this point, finally close to login success, just call the following interface, initialize the following

Interface address https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxinit?r=${~(new Date().valueof ())}

Request method POST

Parameter Type (Content-type) Application /json

parameter

{
    BaseRequest: {
        DeviceID: 'e747337466044216'Sid: wxsid, U from the previous stepin: wxuin obtained in the previous step, Skey: Skey obtained in the previous step}}Copy the code

The first is that the address is followed by a timestamp, which is reversed by bit, and the second is that the request parameters are placed under the BaseRequest instead of the object’s first level properties.

Data. SyncKey and res.data.user. UserName are the ckey parameters that need to be saved

Now that you’ve logged in, if you don’t need a friend list, you can receive messages directly

Detect new messages

Interface address webpush.wx.qq.com/cgi-bin/mmw…

Request method GET

Parameter Type (Content-type) Application /json

parameter

let time = new Date().getTime()

let synckey = ' '

letSk = data. SyncKey. List | | [] / / data SyncKey is step on to get to thatfor (let i = 0; i < sk.length; i++) {
    synckey += `${sk[i].Key}_${sk[i].Val}`
    if(i ! == sk.length - 1) synckey +='|'} // pass parameters {r: time, sid: wxSID, uin: wxuin, skey: skey, deviceid:'e747337466044216', // Synckey: synckey, _: time}Copy the code

The data returned contains the following contents

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

If selector is 2, there’s a new message, so go to the next step and get the message content

Seven, get the message content

Interface address wx.qq.com/cgi-bin/mmw…

Request method POST

Parameter Type (Content-type) Application /json

parameter

{
    BaseRequest: {
        UinWxuin, Sid: wxSID, Skey: DeviceID: wxuin, Sid: Skey: DeviceID:'e747337466044216', // SyncKey: data.SyncKey, // Remember when we had to transform this material? Rr: ~(new Date().valueof ())}Copy the code

AddMsgList is the list of messages, and Data. SyncCheckKey is SyncKey for the next request, which changes each time.

AddMsgList is an array, which may contain multiple messages, messages are more automatic, I do not have to explain, here are two more important fields, other fields are interested in printing out their own look.

FromUserName is the wechat name of the other party. In fact, it is an internal ID that starts with @ or @@, which is completely unreadable. According to my guess, @ should start with ordinary friends, while @@ should start with group or public account

Content Message Content

Given the content of the message, and the person who sent it, we can reply to each other, but to what? Of course, it is impossible to write a lot of if else or switch cases to adapt to various situations, why not search online for ai code worth 100 million hahaha

8. Get the auto-reply content

Here I’m using the Turing robot API address, but you can use other ones as well.

The interface address openapi.tuling123.com/openapi/api…

Request method POST

Parameter Type (Content-type) Application /json

parameter

Perception: {perception: {inputText: {text: ‘message to be replied’}}, userInfo: {apiKey: tulingApiKey, // Apply userId on Turing’s official web site: TulingUserId}

If you’re too lazy to apply, you can copy it in my project, In SRC /global.js, data. Results [0].values.text (results is an array, multiple responses can be returned at once).

9. Reply to messages

Once we get an automatic reply, we just send it to your friends, completing an automatic conversation.

Interface address wx.qq.com/cgi-bin/mmw…

Request method POST

Parameter Type (Content-type) Application /json

parameter

let timeStamp = new Date().getTime() + ' ' + (9000 * Math.random() + 1000)
{
    BaseRequest: {
      UinSkey: Skey: Skey: Skey: Skey: Skey: Skey: Skey: Skey: Skey: Skey: Skey: Skey: Skey: Skey: Skey: Skey: Skey: Skey: Skey: Skey: Skey: Skey: Skey'Content of reply',
      FromUserName: 'Your username, got in step 5.',
      ToUserName: 'FromUserName in step 7',
      LocalID: timeStamp,
      ClientMsgId: timeStamp
}
Copy the code

If the message is sent successfully, the following information is displayed

{
    BaseResponse: { Ret: 0, ErrMsg: ' ' },
    MsgID: '2033517278669301361',
    LocalID: ' '
}
Copy the code

Okay, so we’re done with one of our auto-reply robots. The full code is here

AD time

Our 40-person front end team is always recruiting, those in Xiamen and those who want to come to Xiamen, don’t spare your resume, hard hit the mailbox: ATOB (‘bnVveWFAZ2FvZGluZy5jb20=’), look forward to your contribution

If you have any comments or suggestions on this article, please make an issue on Github. Recently, you have been busy and do not visit the community much