PHP 微信支付V3接口---微信加签

微信支付平台证书下载后,下载器会用获得的平台证书对返回的消息进行验签。下载器同时开启了 Guzzledebug => true 参数,方便查询请求/响应消息的基础调试信息。

composer exec CertificateDownloader.php -- -k ${apiV3key} -m ${mchId} -f ${mchPrivateKeyFilePath} -s ${mchSerialNo} -o ${outputFilePath}

先获取微信平台的公钥证书,商户的公钥/秘钥,v3接口秘钥可以在微信商户平台下载,保存到服务器

/**
     * [createAuthorization 获取接口授权header头信息]
     * @param  [type] $url    [请求地址]
     * @param array $data [请求参数]
     * @param string $method [请求方式]
     * @return [type]         [description]
     */
    //生成v3 Authorization
    protected static function createAuthorization($url, $data = [], $method = 'POST') {
        $config = self::$config;
        //商户号
        $mchid = $config['mchid'];
        // 证书序列号
        $serial_no = $config['serial_no'];
        // 解析url地址
        $url_parts = parse_url($url);
        //生成签名
        $body = [
            'method' => $method,
            'url' => ($url_parts['path'] . (!empty($url_parts['query']) ? "?${url_parts['query']}" : '')),
            'time' => time(), // 当前时间戳
            'nonce' => self::get_rand_str(32, 0, 1), // 随机32位字符串
            'data' => ((strtolower($method) == 'post' || strtolower($method) == 'patch') ? json_encode($data,JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) : ''), // POST请求时 需要 转JSON字符串
        ];
        
        $sign = self::makeSign($body);


        //Authorization 类型
        $schema = 'WECHATPAY2-SHA256-RSA2048';
        //生成token
        $token = sprintf('mchid="%s",nonce_str="%s",timestamp="%d",serial_no="%s",signature="%s"', $mchid, $body['nonce'], $body['time'], $serial_no, $sign);

        $header = [
            'Content-Type:application/json',
            'Accept:application/json',
            //'User-Agent:*/*',
            'Authorization: ' . $schema . ' ' . $token
        ];
        return $header;
    }

/**
     * [makeSign 生成签名]
     * @param  [type] $data [加密数据]
     * @return [type]       [description]
     */
    public static function makeSign($data) {
        $config = self::$config;
        if(!in_array('sha256WithRSAEncryption', \openssl_get_md_methods(true))) {
            throw new \RuntimeException('当前PHP环境不支持SHA256withRSA');
        }

        // 拼接生成签名所需的字符串
        $message = '';
        foreach($data as $value) {
            $message .= $value . "\n";
        }
        
        // 获取商户私钥
        $private_key = self::getPrivateKey($config['cert_key']);
        // 生成签名
        openssl_sign($message, $sign, $private_key, 'sha256WithRSAEncryption');
        return  base64_encode($sign);
    }

//获取私钥
    public static function getPrivateKey($filepath) {
        return openssl_pkey_get_private(file_get_contents($filepath));
    }

以上介绍的是微信支付加签的代码。

下面在介绍一下微信支付回调的解密的方法,微信回调的时候,会返回associated_data, nonceStr, ciphertext三个报文,下面我们来看看支付解密的代码:

/**
     * [decryptToString 证书和回调报文解密]
     * @param  [type] $associatedData [附加数据包(可能为空)]
     * @param  [type] $nonceStr       [加密使用的随机串初始化向量]
     * @param  [type] $ciphertext     [Base64编码后的密文]
     * @return [type]                 [description]
     */
    public static function decryptToString($associatedData, $nonceStr, $ciphertext) {
        $config = self::$config;
        $privateKey = $config['api_cert_key'];
        $ciphertext = \base64_decode($ciphertext);
        if(strlen($ciphertext) <= self::KEY_LENGTH_BYTE) {
            return false;
        }

        // ext-sodium (default installed on >= PHP 7.2)
        if(function_exists('\sodium_crypto_aead_aes256gcm_is_available') &&
            \sodium_crypto_aead_aes256gcm_is_available()) {
            return \sodium_crypto_aead_aes256gcm_decrypt($ciphertext, $associatedData, $nonceStr, $privateKey);
        }

        // ext-libsodium (need install libsodium-php 1.x via pecl)
        if(function_exists('\Sodium\crypto_aead_aes256gcm_is_available') &&
            \Sodium\crypto_aead_aes256gcm_is_available()) {
            return \Sodium\crypto_aead_aes256gcm_decrypt($ciphertext, $associatedData, $nonceStr, $privateKey);
        }

        // openssl (PHP >= 7.1 support AEAD)
        if(PHP_VERSION_ID >= 70100 && in_array('aes-256-gcm', \openssl_get_cipher_methods())) {
            $ctext = substr($ciphertext, 0, -self::AUTH_TAG_LENGTH_BYTE);
            $authTag = substr($ciphertext, -self::AUTH_TAG_LENGTH_BYTE);
            return \openssl_decrypt($ctext, 'aes-256-gcm', $privateKey, \OPENSSL_RAW_DATA, $nonceStr,
                $authTag, $associatedData);
        }

        throw new \RuntimeException('AEAD_AES_256_GCM需要PHP 7.1以上或者安装libsodium-php');
    }

微信回调响应的数据如下:

{"id":"7a91137f-898f-5c29-a564-5309206c5423","create_time":"2022-10-09T10:21:18+08:00","resource_type":"encrypt-resource","event_type":"TRANSACTION.SUCCESS","summary":"\u652f\u4ed8\u6210","resource":{"original_type":"transaction","algorithm":"AEAD_AES_256_GCM","ciphertext":"rssdf1IXDjcdD5JJysq4VnjxTC0sFIac4HQBXQvVeBc64pCLpOmNQgtreP+9xiJwZ9wwfQjpxbduT+xHirFtndbD1DOD3mHqfbhLdMhrFAe0QD+3w9xhNH0YpXFL5tX2+l8zcooZVz3xv\/dJoRxINO8P4CAhBHZap7VYf9RoxrCfqpl2Ayr5wk02d9t1Qn27JE7MYAPXj3uHLL6yy0zY+MfvHCgX5efBwKDQ13N0f8F+90keDvtviqprx2koktzkrSBkycUBSLdJkEaZcuKBf0p601ozujedFqR0peEiNcFS7JPTur0qVkU2nX\/D5GKBBkwPrqKL6gbzckfxu9fKXnNpOrLpSB\/o4jh\/JmRcBN1lIJqUiiZs83qAzPp8tHwZD9+kSpkFcyTmDi4tuibtSD5bc0PNSN3XZIP9acqm07RJbZQ5DInVV3gl17DVQpL72BMDKDjOwEbcMRAx\/4b0UuHgpgELMjJq4FEaBFukIXJOqGkt\/8rshiGQznunUn3l2ulLkohJfF1BOXcwD","associated_data":"transaction","nonce":"p7u0zWPEaNKa"}}

解密之后得到:

{"OrderNo":"SHOP8888888888888888","transaction_id":"4200006668888888888888888","trade_type":"MWEB","trade_state":"SUCCESS","success_time":"2022-05-10T09:18:51+08:00","appid":"wx8888888888c","mchid":"888888888888","payer_total":8888}

以上就是微信v3接口的加密和解密

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值