PHP实现对微信支付v3版本回调数据的解密

本文详细介绍了如何使用PHP处理微信支付V3版本的回调数据解密,基于微信官方提供的示例代码进行了解析,并针对代码中的注意事项进行了说明。文章中展示了解密前后的JSON数据格式,帮助读者理解解密过程,特别指出需要PHP 7.1及以上版本运行,以及在实际应用中不需要将数据写入文件。

PS:本文使用了微信官方给出的demo来实现对回调数据的解密,本文主要对微信官方给出的demo如何使用作出部分个人讲解,以及对解密前后数据的格式进行展示

PHP类:这是微信官方给出的demo

<?php

class AesUtil
{
    /**
     * AES key
     *
     * @var string
     */
    public $aesKey = '此处填写你的APIv3密钥';

    const KEY_LENGTH_BYTE = 32;
    const AUTH_TAG_LENGTH_BYTE = 16;

    /**
     * Constructor
     */
    public
    function __construct()
    {
        $aesKey = '此处填写你的APIv3密钥';
        if (strlen($aesKey) != self::KEY_LENGTH_BYTE) {
            throw new InvalidArgumentException('无效的ApiV3Key,长度应为32个字节');
        }
        $this->aesKey = $aesKey;
    }

    /**
     * Decrypt AEAD_AES_256_GCM ciphertext
     *
     * @param string $associatedData AES GCM additional authentication data
     * @param string $nonceStr AES GCM nonce
     * @param string $ciphertext AES GCM cipher text
     *
     * @return string|bool      Decrypted string on success or FALSE on failure
     */
    public
    function decryptToString($associatedData, $nonceStr, $ciphertext)
    {
        $ciphertext = \base64_decode($ciphertext);
        if (strlen($ciphertext) <= self::AUTH_TAG_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, $this->aesKey);
        }

        // 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, $this->aesKey);
        }

        // 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', $this->aesKey, \OPENSSL_RAW_DATA, $nonceStr,
                $authTag, $associatedData);
        }

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

PS:值得注意的是,在微信官方给出的代码中,有很大一部分的$this-> XXX(),这一段代码中,横岗与大于号之间有一个空格,需要进行删除,在这篇文章中的代码,我删除了部分的关于抛出错误的代码(注:有些导致错误的信息发生的概率实在是太小了,这边选择了删除)
还需要注意的是,微信官方给出的代码需要PHP版本至少是7.1以上才能够运行

以下是调用的PHP代码:

<?php
require_once('./v3OrderCallBack.php');

$getCallBackData = file_get_contents('php://input'); //接收来自微信的回调数据

file_put_contents('./callBack.json',$getCallBackData."\n\r",FILE_APPEND); //将接收到的数据存入callBack.json文件中

$getData = new AesUtil;

$getReturnData = file_get_contents('./callBack.json');  //将返回的json数据赋值给变量
$disposeReturnData = json_decode($getReturnData, true);  //将变量由json类型数据转换为数组

$associatedData = $disposeReturnData['resource']['associated_data'];  //获取associated_data数据,附加数据
$nonceStr = $disposeReturnData['resource']['nonce'];                  //获取nonce数据,加密使用的随机串
$ciphertext = $disposeReturnData['resource']['ciphertext'];           //获取ciphertext数据,base64编码后的数据密文

$result = $getData -> decryptToString($associatedData,$nonceStr,$ciphertext); //调用微信官方给出的方法将解密后的数据赋值给变量

$array_data = json_decode($result,true);  //将解密后的数据转换为数组

file_put_contents('./decryptReturnData.json',$result); //将数据以JSON格式储存到decryptReturnData.json文件中

注:在调用的PHP代码中我将接收到的数据与解密后的数据全部使用file_put_contents将其存入到了向桂英的json文件中,在实际操作中是不必要的,这里只是展示一下,获取到的json数据的格式

微信回调返回的json数据展示:

{
  "id": "2dd87d80-2478-5ab0-852c-6d20084f8175",
  "create_time": "2022-07-26T17:07:28+08:00",
  "resource_type": "encrypt-resource",
  "event_type": "TRANSACTION.SUCCESS",
  "summary": "支付成功",
  "resource": {
    "original_type": "transaction",
    "algorithm": "AEAD_AES_256_GCM",
    "ciphertext": "此处显示很长一段的密文,就是我们需要解密的内容,应为隐私的原因,这边就不展示了",
    "associated_data": "transaction",
    "nonce": "8oAAd7fCPvpO"
  }
}

对回调数据解密后的数据展示:

{
  "mchid": "显示你的商户号",
  "appid": "显示你的appid",
  "out_trade_no": "20220726165882643607854",  此处显示的是商户订单号,你自己定义
  "transaction_id": "此处显示微信支付订单好",
  "trade_type": "JSAPI",
  "trade_state": "SUCCESS",
  "trade_state_desc": "支付成功",
  "bank_type": "OTHERS",
  "attach": "",
  "success_time": "2022-07-26T17:07:28+08:00",
  "payer": {
    "openid": "小程序用户的openid"
  },
  "amount": {
    "total": 1,
    "payer_total": 1,
    "currency": "CNY",
    "payer_currency": "CNY"
  }
}

注:部分涉及到隐私的数据我已经隐去,不影响你对整个json数据结构的理解


本篇文章由优快云用户: 缱绻淡蓝海 原创,代码具有时效性,作者会不定时进行修改

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值