WeChat Pay V3 version applet payment php signature, signature verification, data decryption code sharing
WeChat Pay v3 version php decryption code
Required for data decryption Most PHP versions to expand to Sodium need to install
The certificate serial number can be viewed here https://myssl.com/cert_decode.html
The PHP7.4 version I use
Go directly to the code:
//微信原生支付 class Wxpay { /* * 支付(小程序支付) * @param type $sn 訂單編號 * @param type $money 金額 * @param type $openid 用戶小程序openid * @return type */ public static function getPayParam($sn, $money, $openid) { $url = 'https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi'; $notify_url = url('/api/weixin/notify'); $data = []; $data['appid'] = Action::config(CONFIG_WXXCX, 'app_id'); $data['mchid'] = Action::config(CONFIG_WXXCX, 'mchid'); //商戶號 $data['description'] = 'xxx'; //描述? $data['out_trade_no'] = $sn; //商戶系統(tǒng)內(nèi)部訂單號 $data['time_expire'] = date('Y-m-d') . 'T' . date('H:i:s', (time() + 1800)) . '+08:00'; //訂單失效時間2018-06-08T10:34:56+08:00 $data['notify_url'] = $notify_url; //異步通知接口地址 $data['amount'] = ['total' => $money * 100, 'currency' => 'CNY']; //金額 $data['payer'] = ['openid' => $openid]; //用戶 $re = self::wxCurl($url, $data, 'POST'); if (!isset($re['prepay_id'])) { api_fail('參數(shù)獲取失敗'); } $result = []; $result['appId'] = Action::config(CONFIG_WXXCX, 'app_id'); $result['timeStamp'] = (string)time(); $result['nonceStr'] = uniqid(); $result['package'] = 'prepay_id=' . $re['prepay_id']; $result['signType'] = 'RSA'; $result['paySign'] = self::getPaySign($result); return $result; } /** * 查詢訂單 * @param type $sn */ public static function select($sn, $return = false) { $mchid = Action::config(CONFIG_WXXCX, 'mchid'); //商戶號 $url = 'https://api.mch.weixin.qq.com/v3/pay/transactions/out-trade-no/' . $sn . '?mchid=' . $mchid; $re = self::wxCurl($url, [], 'GET'); if ($return) { return $re; } if (isset($re['trade_state']) && $re['trade_state'] == 'SUCCESS') { return true; } return false; } /** * 關(guān)閉訂單 * @param type $sn */ public static function close($sn) { $mchid = Action::config(CONFIG_WXXCX, 'mchid'); //商戶號 $url = 'https://api.mch.weixin.qq.com/v3/pay/transactions/out-trade-no/' . $sn . '/close'; $re = self::wxCurl($url, ['mchid'=>$mchid], 'POST'); return true; } /** * 退款 * @param type $sn */ public static function refund($order_sn,$refund_sn,$total,$refund,$msg='退款') { $url='https://api.mch.weixin.qq.com/v3/refund/domestic/refunds'; $data=[]; $data['notify_url']=url('ag/weixin/notify_refund'); $data['out_trade_no']=$order_sn;//訂單號 $data['out_refund_no']=$refund_sn;//退款單號 $data['reason']=$msg; $data['amount']=['refund'=>$refund*100,'total'=>$total*100,'currency'=>'CNY']; $re = self::wxCurl($url, $data, 'POST'); return $re; } //請求 public static function wxCurl($url, $data = [], $method = 'GET') { $Authorization = self::getReSign($url, $data, $method); $header = [ 'Content-Type: application/json', 'Accept: application/json', 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36 Edg/89.0.774.63', 'Authorization: ' . $Authorization ]; $redata = $data ? json_encode($data) : ''; $res = reCurl($url, $redata, $header); return $res ? json_decode($res, true) : []; } //后端請求簽名 public static function getReSign($url, $data, $method = 'GET') { $url_parts = parse_url($url); $canonical_url = ($url_parts['path'] . (!empty($url_parts['query']) ? "?${url_parts['query']}" : "")); $http_method = $method; $timestamp = time(); $nonce = uniqid(); $body = $data ? json_encode($data) : ''; $mchid = Action::config(CONFIG_WXXCX, 'mchid'); //商戶id $serial_no = Action::config(CONFIG_WXXCX, 'serial_no'); //證書編號 $private_key = self::getPrivateKey(BASE_PATH . 'cert/apiclient_key.pem'); //商戶私鑰 $message = $http_method . "\n" . $canonical_url . "\n" . $timestamp . "\n" . $nonce . "\n" . $body . "\n"; openssl_sign($message, $raw_sign, $private_key, 'sha256WithRSAEncryption'); $sign = base64_encode($raw_sign); $token = sprintf('mchid="%s",nonce_str="%s",timestamp="%d",serial_no="%s",signature="%s"', $mchid, $nonce, $timestamp, $serial_no, $sign); return 'WECHATPAY2-SHA256-RSA2048 ' . $token; } //前端小程序簽名 public static function getPaySign($result) { $private_key = self::getPrivateKey(BASE_PATH . 'cert/apiclient_key.pem'); //商戶私鑰 $message = $result['appId'] . "\n" . $result['timeStamp'] . "\n" . $result['nonceStr'] . "\n" . $result['package'] . "\n"; openssl_sign($message, $raw_sign, $private_key, 'sha256WithRSAEncryption'); $sign = base64_encode($raw_sign); return $sign; } //驗(yàn)證簽名 public static function checkSign() { $header = Context::get('header'); $serial_no = $header['wechatpay-serial'] ?? ''; //微信平臺序列號 $timeStamp = $header['wechatpay-timestamp'] ?? ''; $nonce = $header['wechatpay-nonce'] ?? ''; $body = Context::get('raw'); $wx_sign = $header['wechatpay-signature'] ?? ''; $wx_serial_no = Action::config(CONFIG_WXXCX, 'wx_serial_no');//保存的序列號 if (!$serial_no || $wx_serial_no != $serial_no) { \sff\Log::write('簽名過期'); return false; } $message = $timeStamp . "\n" . $nonce . "\n" . $body . "\n"; $wx_sign = base64_decode($wx_sign); $public_key = self::getPublicKey(BASE_PATH . 'cert/wx_public_cert.pem'); //平臺公鑰 $res = openssl_verify($message, $wx_sign, $public_key, OPENSSL_ALGO_SHA256); if ($res == 1) { return true; } \sff\Log::write('驗(yàn)簽失敗'); return false; } //獲取私鑰 public static function getPrivateKey($filepath) { return openssl_get_privatekey(file_get_contents($filepath)); } //獲取公鑰 public static function getPublicKey($filepath) { return openssl_pkey_get_public(file_get_contents($filepath)); } //加密數(shù)據(jù) public static function getEncrypt($str) { //$str是待加密字符串 $public_key_path = BASE_PATH . 'cert/wx_public_cert.pem'; //'平臺證書路徑'; $public_key = file_get_contents($public_key_path); $encrypted = ''; if (openssl_public_encrypt($str, $encrypted, $public_key, OPENSSL_PKCS1_OAEP_PADDING)) { //base64編碼 $sign = base64_encode($encrypted); } else { throw new Exception('encrypt failed'); } return $sign; } //解密數(shù)據(jù) public static function decryptToString($ciphertext, $associatedData, $nonceStr) { $aesKey = Action::config(CONFIG_WXXCX, 'mch_keyv3'); //商戶apiv3密鑰解密 $str = base64_decode($ciphertext); if (strlen($str) <= 16) { return ''; } // ext-sodium (default installed on >= PHP 7.2) return \sodium_crypto_aead_aes256gcm_decrypt($str, $associatedData, $nonceStr, $aesKey); } //下載平臺證書 public static function downCert() { $url = 'https://api.mch.weixin.qq.com/v3/certificates'; $re = self::wxCurl($url, [], 'GET'); if (!isset($re['data'])) { api_fail('獲取證書失敗'); } $ciphertext = $re['data'][0]['encrypt_certificate']['ciphertext']; $associatedData = $re['data'][0]['encrypt_certificate']['associated_data']; $nonceStr = $re['data'][0]['encrypt_certificate']['nonce']; $data = self::decryptToString($ciphertext, $associatedData, $nonceStr); if (!$data) { api_fail('獲取證書解密失敗'); } file_put_contents(BASE_PATH . '/cert/wx_public_cert.pem', $data); return $data; } }
The above is the detailed content of Share WeChat payment v3 version php decryption code. For more information, please follow other related articles on the PHP Chinese website!

Hot AI Tools

Undress AI Tool
Undress images for free

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)
