📜 ⬆️ ⬇️

WeChat. Serialize the object - get SMS

Previous article .
In continuation of the topic WeChat. In this article we will show how objects are serialized and deserialized, as well as encrypt the message and get an SMS with a confirmation code. In addition, we will provide all the necessary PHP code so you can try and make sure everything works.



The application uses the ProtoBuf library.

There is a base object WXPBGeneratedMessage, all the others are inherited from it.
Initially, Protobuf can only serialize simple types (strings and numbers). To serialize complex objects, a field is created for each object, which we call classInfo. It stores the names and descriptions of all fields.
')
To request an SMS, you need to create a BindOpMobileRequest object.

public function __construct() { $this->classInfo = new \wechat\PBClassInfo(); $this->classInfo->nameProperty[] = 'baseRequest'; $this->classInfo->objectDefinition[] = new \wechat\ObjectDefinition(0x1, 0x2, 0xB, 0x0, 0x0, 'BaseRequest'); $this->classInfo->nameProperty[] = 'userName'; $this->classInfo->objectDefinition[] = new \wechat\ObjectDefinition(0x2, 0x1, 0x9, 0x0, 0x0, ''); $this->classInfo->nameProperty[] = 'mobile'; $this->classInfo->objectDefinition[] = new \wechat\ObjectDefinition(0x3, 0x1, 0x9, 0x0, 0x0, ''); $this->classInfo->nameProperty[] = 'opcode'; $this->classInfo->objectDefinition[] = new \wechat\ObjectDefinition(0x4, 0x2, 0x5, 0x0, 0x0, ''); $this->classInfo->nameProperty[] = 'verifycode'; $this->classInfo->objectDefinition[] = new \wechat\ObjectDefinition(0x5, 0x1, 0x9, 0x0, 0x0, ''); $this->classInfo->nameProperty[] = 'dialFlag'; $this->classInfo->objectDefinition[] = new \wechat\ObjectDefinition(0x6, 0x1, 0x5, 0x0, 0x0, ''); $this->classInfo->nameProperty[] = 'dialLang'; $this->classInfo->objectDefinition[] = new \wechat\ObjectDefinition(0x7, 0x1, 0x9, 0x0, 0x0, ''); $this->classInfo->nameProperty[] = 'authTicket'; $this->classInfo->objectDefinition[] = new \wechat\ObjectDefinition(0x8, 0x1, 0x9, 0x0, 0x0, ''); $this->classInfo->nameProperty[] = 'forceReg'; $this->classInfo->objectDefinition[] = new \wechat\ObjectDefinition(0x9, 0x1, 0xD, 0x0, 0x0, ''); $this->classInfo->nameProperty[] = 'safeDeviceName'; $this->classInfo->objectDefinition[] = new \wechat\ObjectDefinition(0xA, 0x1, 0x9, 0x0, 0x0, ''); $this->classInfo->nameProperty[] = 'safeDeviceType'; $this->classInfo->objectDefinition[] = new \wechat\ObjectDefinition(0xB, 0x1, 0x9, 0x0, 0x0, ''); $this->classInfo->nameProperty[] = 'randomEncryKey'; $this->classInfo->objectDefinition[] = new \wechat\ObjectDefinition(0xC, 0x1, 0xB, 0x0, 0x0, 'SKBuiltinBuffer_t'); $this->classInfo->nameProperty[] = 'language'; $this->classInfo->objectDefinition[] = new \wechat\ObjectDefinition(0xD, 0x1, 0x9, 0x0, 0x0, ''); $this->classInfo->nameProperty[] = 'inputMobileRetrys'; $this->classInfo->objectDefinition[] = new \wechat\ObjectDefinition(0xE, 0x1, 0xD, 0x0, 0x0, ''); $this->classInfo->nameProperty[] = 'adjustRet'; $this->classInfo->objectDefinition[] = new \wechat\ObjectDefinition(0xF, 0x1, 0xD, 0x0, 0x0, ''); $this->classInfo->nameProperty[] = 'clientSeqId'; $this->classInfo->objectDefinition[] = new \wechat\ObjectDefinition(0x10, 0x1, 0x9, 0x0, 0x0, ''); parent::__construct(); } 

As you can see, classInfo consists of two arrays (field names and their descriptions). ObjectDefinition consists of five numbers and a string:

  1. Field number
  2. Array ID. Set to three if the field is an array. In other cases, does not affect anything
  3. Field type (for example, 0x9 - string, 0x8 - bool, 0x7 - unsigned int, 0xB - object, etc.)
  4. Used when serializing arrays together with the second item, otherwise equal to zero
  5. The purpose of this number remains a mystery (it is always zero and is not used anywhere)
  6. If the field is an object, the type of the object is indicated; otherwise, an empty string is specified.

The object is serialized recursively using the direct depth traversal algorithm. Before each field, first put a tag that is calculated (using the dictionary) as follows:

 $FieldTypeDictionary = array(-1, 1, 5, 0, 0, 0, 1, 5, 0, 2, 3, 2, 2, 0, 0, 5, 1, 0, 0); $fieldType = $FieldTypeDictionary[$fieldType]; $tag = $fieldNumber << 3 | $fieldType; 

If the field is an object, then after the tag its length is set.

Preparing a message to send to the server


Create the BindOpMobileRequest object, fill in the fields and serialize:

  public function getVerifyCode() { $bindOpMobileRequest = new \wechat\Request\BindOpMobileRequest(); $baseRequest = $this->createBaseRequest(); $this->aesKey = random_bytes(0x10); $baseRequest->sessionKey = ''; $baseRequest->scene = 0; $bindOpMobileRequest->baseRequest = $baseRequest; $bindOpMobileRequest->mobile = $this->phoneNumber; $bindOpMobileRequest->opcode = 14; $bindOpMobileRequest->safeDeviceName = $this->deviceName; $bindOpMobileRequest->safeDeviceType = 'iPhone'; $bindOpMobileRequest->randomEncryKey = new \wechat\Object\SKBuiltinBuffer_t(); $bindOpMobileRequest->randomEncryKey->iLen = strlen($this->aesKey); $bindOpMobileRequest->randomEncryKey->buffer = $this->aesKey; $bindOpMobileRequest->language = $this->language; $bindOpMobileRequest->inputMobileRetrys = 5; $bindOpMobileRequest->adjustRet = 0; $bindOpMobileRequest->clientSeqId = $this->clientSeqId; $serializedData = $bindOpMobileRequest->serializedData(); } 

The result is:



Now it remains to make a header, encrypt the data and send to the server.

 $header = $this->computeHeader($serializedData, 0x91, 2); $dataToSend = $header . $this->client->RSAEncrypt($serializedData); $response = $this->client->request($this, $dataToSend, 'bindopmobileforreg'); 

If everything is done correctly, the server will send us the answer, which needs to be decrypted with the AES-key transmitted in the request and deserialized:

 $response = deleteHeaderFromResponse($response); $response = $this->client->AESDecrypt($response, $this->aesKey); $bindOpMobileResponse = new \wechat\Response\BindOpMobileResponse(); $bindOpMobileResponse->mergeFromData($response); 

You must deserialize into a BindOpMobileResponse object.
Here is the php code that implements all of the above. Dare ...

Ps. SMS does not come to the numbers of one "buzzing" company. Inexplicably…

Source: https://habr.com/ru/post/339772/


All Articles