From 7936a68cd409bfe72d04da1bcda11bfb4fddfa16 Mon Sep 17 00:00:00 2001 From: Devil Date: Mon, 11 Oct 2021 14:32:10 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=AF=E4=BB=98=E5=AE=9D=E8=AF=81=E4=B9=A6?= =?UTF-8?q?=E9=80=9A=E4=BF=A1=E6=94=AF=E4=BB=98=E6=96=B9=E5=BC=8F=E8=BF=94?= =?UTF-8?q?=E5=9B=9E=E5=A2=9E=E5=8A=A0=E7=AD=BE=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- extend/payment/AlipayCert.php | 139 +++++++++++++++++++++++++++------- 1 file changed, 111 insertions(+), 28 deletions(-) diff --git a/extend/payment/AlipayCert.php b/extend/payment/AlipayCert.php index b6d5a94b1..c600132c6 100644 --- a/extend/payment/AlipayCert.php +++ b/extend/payment/AlipayCert.php @@ -345,43 +345,55 @@ class AlipayCert */ public function Respond($params = []) { - // 请求参数 $data = empty($_POST) ? $_GET : array_merge($_GET, $_POST); + ksort($data); - // 查询订单参数 - $parameter = array( - 'app_id' => $this->config['appid'], - 'method' => 'alipay.trade.query', - 'format' => 'JSON', - 'charset' => 'utf-8', - 'sign_type' => 'RSA2', - 'timestamp' => date('Y-m-d H:i:s'), - 'version' => '1.0', - 'app_cert_sn' => $this->GetCertSNFromContent($this->config['cert_content']), - 'alipay_root_cert_sn' => $this->GetRootCertSNFromContent($this->config['out_root_cert_content']), - ); - $biz_content = array( - 'out_trade_no' => $data['out_trade_no'], - 'trade_no' => $data['trade_no'], - ); - $parameter['biz_content'] = json_encode($biz_content, JSON_UNESCAPED_UNICODE); + // 参数字符串 + $prestr = ''; + foreach($data AS $key=>$val) + { + if ($key != 'sign' && $key != 'sign_type' && $key != 'code') + { + $prestr .= "$key=$val&"; + } + } + $prestr = substr($prestr, 0, -1); - // 生成签名参数+签名 - $parameter['sign'] = $this->MyRsaSign($this->GetSignContent($parameter)); + // 签名 + if(!$this->OutRsaVerify($prestr, $data['sign'])) + { + return DataReturn('签名校验失败', -1); + } - // 执行请求 - $result = $this->HttpRequest('https://openapi.alipay.com/gateway.do', $parameter); - $key = str_replace('.', '_', $parameter['method']).'_response'; - if(isset($result[$key]['code']) && $result[$key]['code'] == 10000) + // 支付状态 + if(!empty($data['trade_no']) && isset($data['total_amount']) && $data['total_amount'] > 0) { - if(in_array($result[$key]['trade_status'], ['TRADE_SUCCESS'])) + $status = false; + if(isset($data['trade_status'])) { - return DataReturn('支付成功', 0, $this->ReturnData($data)); + if(in_array($data['trade_status'], ['TRADE_SUCCESS', 'TRADE_FINISHED'])) + { + $status = true; + } } else { - return DataReturn('支付失败、状态'.'['.$result[$key]['trade_status'].']', -1); + switch($data['method']) + { + // pc、h5 + case 'alipay.trade.wap.pay.return' : + case 'alipay.trade.page.pay.return' : + if(isset($data['seller_id'])) + { + $status = true; + } + break; + } + } + if($status) + { + return DataReturn('支付成功', 0, $this->ReturnData($data)); } } - return DataReturn($result[$key]['sub_msg'].'['.$result[$key]['sub_code'].']', -1000); + return DataReturn('处理异常错误', -100); } /** @@ -468,6 +480,13 @@ class AlipayCert // 执行请求 $result = $this->HttpRequest('https://openapi.alipay.com/gateway.do', $parameter); $key = str_replace('.', '_', $parameter['method']).'_response'; + // 验证签名 + if(!$this->SyncRsaVerify($result, $key)) + { + return DataReturn('签名验证错误', -1); + } + + // 状态 if(isset($result[$key]['code']) && $result[$key]['code'] == 10000) { // 统一返回格式 @@ -705,5 +724,69 @@ class AlipayCert } return $dec; } + + /** + * 从证书中提取公钥 + * @author Devil + * @blog http://gong.gg/ + * @version 1.0.0 + * @date 2021-10-11 + * @desc description + * @return [string] [公钥] + */ + public function GetPublicKey() + { + $pkey = openssl_pkey_get_public($this->config['out_cert_content']); + $keyData = openssl_pkey_get_details($pkey); + $public_key = str_replace('-----BEGIN PUBLIC KEY-----', '', $keyData['key']); + $public_key = trim(str_replace('-----END PUBLIC KEY-----', '', $public_key)); + return $public_key; + } + + /** + * 支付宝验证签名 + * @author Devil + * @blog http://gong.gg/ + * @version 1.0.0 + * @datetime 2017-09-24T08:39:50+0800 + * @param [string] $prestr [需要签名的字符串] + * @param [string] $sign [签名结果] + * @return [boolean] [正确true, 错误false] + */ + private function OutRsaVerify($prestr, $sign) + { + $public_key = $this->GetPublicKey(); + if(stripos($public_key, '-----') === false) + { + $res = "-----BEGIN PUBLIC KEY-----\n"; + $res .= wordwrap($public_key, 64, "\n", true); + $res .= "\n-----END PUBLIC KEY-----"; + } else { + $res = $public_key; + } + $pkeyid = openssl_pkey_get_public($res); + $sign = base64_decode($sign); + if($pkeyid) + { + $verify = openssl_verify($prestr, $sign, $pkeyid, OPENSSL_ALGO_SHA256); + openssl_free_key($pkeyid); + } + return (isset($verify) && $verify == 1) ? true : false; + } + + /** + * [SyncRsaVerify 同步返回签名验证] + * @author Devil + * @blog http://gong.gg/ + * @version 1.0.0 + * @datetime 2017-09-25T13:13:39+0800 + * @param [array] $data [返回数据] + * @param [boolean] $key [数据key] + */ + private function SyncRsaVerify($data, $key) + { + $string = json_encode($data[$key], JSON_UNESCAPED_UNICODE); + return $this->OutRsaVerify($string, $data['sign']); + } } ?> \ No newline at end of file -- GitLab