微信消息消息加解密 PHP版

449 阅读1分钟

public function __construct()
{
    $this->aesKey = base64_decode(config('wechat.app.aes_key') . '=');
    $this->iv = substr($this->aesKey, 0, 16);

}

public function decrypt(string $encrypted): string
{
    $encrypted = base64_decode($encrypted, true);
    $randMsg = openssl_decrypt($encrypted, "aes-256-cbc", $this->aesKey, OPENSSL_RAW_DATA | OPENSSL_NO_PADDING ,$this->iv);
    $decrypted = $this->decode($randMsg);
    if (strlen($decrypted) < 16) {
        Log::info('wechat decrypt error, result is ' . $decrypted);
        return '';
    }
    $content = substr($decrypted, 16, strlen($decrypted));
    $len_list = unpack("N", substr($content, 0, 4));
    $xml_len = $len_list[1];
    $result = substr($content, 4, $xml_len);
    $formAppId = substr($content, $xml_len + 4);
    if ($formAppId != config('wechat.app.aiadartifact.app_id')) {
        Log::info('wechat decrypt error, appid is wrong '. $formAppId);
        return '';
    }
    return $result;
}

/**
 * 对解密后的明文进行补位删除
 * @param $text
 * @return string
 */
private function decode($text)
{
    $pad = ord(substr($text, -1));
    if ($pad < 1 || $pad > 32) {
        $pad = 0;
    }
    return substr($text, 0, (strlen($text) - $pad));
}


private function getAccessToken(): string
{
    $accessToken = Redis::get(RedisKey::WECHAT_ACCESS_TOKEN);
    if ($accessToken) {
        return $accessToken;
    }

    $resp = HttpClientFactory::factory()->request(
        'GET', WechatCustomMessage::ACCESS_TOKEN_URL,
        [
            'query' => [
                'grant_type' => 'client_credential',
                'appid'      =>  $this->appId,
                'secret'     =>  $this->appSecret
            ],
        ]
    );
    $body = json_decode($resp->getBody()->getContents(), true);
    Log::info('get access token from wechat result:' . json_encode($body));
    if (isset($body['errcode'])) {
        Log::info('get access token from wechat result error: ' . json_encode($body));
        return '';
    }
    Redis::set(RedisKey::WECHAT_ACCESS_TOKEN, $body['access_token']);
    Redis::expire(RedisKey::WECHAT_ACCESS_TOKEN, 2 * 60 * 60);
    return $body['access_token'];
}

/**
 * 发送消息给用户
 * @param string $receiveUser
 */
public function sendMsgToUser(string $receiveUser): void
{
    $accessToken = $this->getAccessToken();

    $execTime = ExecTime::record();
    $resp = HttpClientFactory::factory()->request(
        'POST', WechatCustomMessage::SEND_MSG_TO_USER,
        [
            RequestOptions::QUERY => ['access_token' => $accessToken],
            RequestOptions::JSON  => [
                'msgtype' => 'text',
                'touser' => $receiveUser,
                'text' => [
                    'content' => 'hello world'
                ],
            ],
        ]
    );
    $body = $resp->getBody();
    Log::info('send wechat message after result:', [
        'headers' => $resp->getHeaders(),
        'body' => $body,
        'exec_time'  => $execTime->end(),
    ]);
}