WeChat. We serialize the object - we get SMS
Continuing the theme of WeChat. In this article we will show how objects are serialized and deserialized, as well as encrypt the message and receive an SMS with a confirmation code. In addition, we will provide all the necessary PHP code so that you can try and make sure that everything works
The application uses the ProtoBuf library.
There is a basic object WXPBGeneratedMessage, all the rest 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 called classInfo. It stores the names and descriptions of all fields.
To request 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:
- Field serial number
- Array identifier. Set to three if the field is an array. In other cases, it does not affect anything.
- Field type (for example, 0x9 - string, 0x8 - bool, 0x7 - unsigned int, 0xB - object, etc.)
- It is used when serializing arrays together with the second item; in other cases it is equal to zero
- The purpose of this number remains a mystery (it is always equal to zero and is not used anywhere)
- If the field is an object, the type of the object is indicated, otherwise an empty string is indicated.
An object is serialized recursively using the direct tree traversal algorithm in depth. Before each field, first put a tag, which 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 it is placed after the tag.
Preparing a message to send to the server
Create a 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();
}
As a result, we get: Now it remains to compose a header, encrypt the data and send it 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 an answer that needs to be decrypted with the AES key passed in the request and deserialized:
$response = deleteHeaderFromResponse($response);
$response = $this->client->AESDecrypt($response, $this->aesKey);
$bindOpMobileResponse = new \wechat\Response\BindOpMobileResponse();
$bindOpMobileResponse->mergeFromData($response);Deserialize to a BindOpMobileResponse object.
Here is the php code that implements all of the above. Go ahead ...
PS. SMS messages do not come to the numbers of one buzzing company. Inexplicably…