PHP
PHP对接支付宝APP支付
PHP对接支付宝APP支付
这两天接了一个需求,就是对接支付宝的APP支付,看了下支付宝文档,结合之前写的支付宝sign篇,最终决定不用支付宝SDK,在这里跟大家分享下代码,我这里是用thinkphp开发。
一、支付宝类
我们先创建一个支付宝的类,命名为AliPay,代码如下
<?php /** * Created by PhpStorm. * User: zhangw * Date: 2024-03-01 * Time: 17:22 */ namespace app\service; /** * 支付宝付款 * Class AliPay * @package app\service */ class AliPay { /** * 获取支付宝APP支付参数 * @param string $outOrderSn * @param int $totalAmount * @param string $notifyUrl * @return string */ function aliPayOrder($outOrderSn = "", $totalAmount = 0, $notifyUrl = "") { #获取配置参数 $appId = Config('appConfig.ali_pay_app_id'); $rsaPrivateKey = Config('appConfig.ali_pay_private_key'); #获取时间 $outTime = time() + 2 *60; #非公共参数 $requestData = [ 'total_amount' => $totalAmount, // 订单总金额(元) 'product_code' => 'QUICK_MSECURITY_PAY', // 销售产品码 'subject' => "商品标题", // 商品标题 'out_trade_no' => $outOrderSn, // 订单号 'time_expire'=> date("Y-m-d H:i:s",$outTime), // 超时时间 ]; #公共参数 $commonData = array( 'app_id' => $appId, 'method' => 'alipay.trade.app.pay', 'charset' => 'UTF-8', 'sign_type' => 'RSA2', 'timestamp' => date('Y-m-d H:i:s', time()), 'version' => '1.0', 'notify_url' => $notifyUrl, 'biz_content' => json_encode($requestData) ); #拼接成字符串 $signString = self::getSignContent($commonData); #待请求字符串加密获取sign $sign = self::alonersaSign($signString, $rsaPrivateKey, "RSA2"); #将sign带入数组 $commonData["sign"] = $sign; #请求链接编码及转换 $url = self::getSignContentUrlencode($commonData); #返回支付链接给前端 return $url; } /////////////////////////////////////发起支付公共方法///////////////////////////////////// /** * 链接拼接 * @param $params * @return string */ function getSignContentUrlEncode($params) { ksort($params); $stringToBeSigned = ""; $i = 0; foreach ($params as $k => $v) { if (false === self::checkEmpty($v) && "@" != substr($v, 0, 1)) { // 转换成目标字符集 $v = self::charaCet($v, "UTF-8"); if ($i == 0) { $stringToBeSigned .= "$k" . "=" . urlencode($v); } else { $stringToBeSigned .= "&" . "$k" . "=" . urlencode($v); } $i++; } } unset ($k, $v); return $stringToBeSigned; } /** * 请求参数加密获取sign * @param $data * @param $privateKey * @param string $signType * @param bool $keyFromFile * @return string */ function aloneRsaSign($data, $privateKey, $signType = "RSA", $keyFromFile = false) { if (!$keyFromFile) { $priKey = $privateKey; $res = "-----BEGIN RSA PRIVATE KEY-----\n" . wordwrap($priKey, 64, "\n", true) . "\n-----END RSA PRIVATE KEY-----"; } else { $priKey = file_get_contents($privateKey); $res = openssl_get_privatekey($priKey); } ($res) or die('您使用的私钥格式错误,请检查RSA私钥配置'); if ("RSA2" == $signType) { openssl_sign($data, $sign, $res, OPENSSL_ALGO_SHA256); } else { openssl_sign($data, $sign, $res); } if ($keyFromFile) { openssl_free_key($res); } $sign = base64_encode($sign); return $sign; } /** * 数组转成字符串 * @param $params * @return string */ function getSignContent($params) { ksort($params); $stringToBeSigned = ""; $i = 0; foreach ($params as $k => $v) { if (false === self::checkEmpty($v) && "@" != substr($v, 0, 1)) { // 转换成目标字符集 $v = self::charaCet($v, "UTF-8"); if ($i == 0) { $stringToBeSigned .= "$k" . "=" . "$v"; } else { $stringToBeSigned .= "&" . "$k" . "=" . "$v"; } $i++; } } unset ($k, $v); return $stringToBeSigned; } /** * 判断参数值是否为空 * @param $value * @return bool */ function checkEmpty($value) { if (!isset($value)) return true; if ($value === null) return true; if (trim($value) === "") return true; return false; } /** * 转换成目标字符集 * @param $data * @param $targetCharset * @return string */ function charaCet($data, $targetCharset) { if (!empty($data)) { $fileType = "UTF-8"; if (strcasecmp($fileType, $targetCharset) != 0) { $data = mb_convert_encoding($data, $targetCharset, $fileType); } } return $data; } /** * 支付宝回调验签 * @param $params * @param $ali_pay_public_key * @param string $sign_type * @return bool */ function verifySign($params,$ali_pay_public_key,$sign_type='RSA2') { $ori_sign=$params['sign']; unset($params['sign']); unset($params['sign_type']); ksort($params); $data=''; foreach($params as $k => $v){ $data.=$k.'='.$v.'&'; } $data=substr($data,0,-1); $public_content="-----BEGIN PUBLIC KEY-----\n" . wordwrap($ali_pay_public_key, 64, "\n", true) . "\n-----END PUBLIC KEY-----"; $public_key=openssl_get_publickey($public_content); if($public_key){ if($sign_type=='RSA2') { $result = (bool)openssl_verify($data, base64_decode($ori_sign), $public_key, OPENSSL_ALGO_SHA256); } else { $result = (bool)openssl_verify($data, base64_decode($ori_sign), $public_key); } openssl_free_key($public_key); return $result; }else{ return false; } } }
二、新增配置
我这里是放在thinkphp的config下的appConfig.php文件下,分别是
'ali_pay_app_id' => '支付宝appId', 'ali_pay_private_key' => '支付宝私钥' 'ali_pay_public_key'=>'支付宝平台应用公钥【非自己的的支付宝公钥】'
三、获取前端需要支付参数
我们直接在我们的接口直接调用该函数,获取前端所需的支付参数
#初始化支付宝类 $aliPay = new AliPay(); #初始化参数 $order_sn = time(); $total_money = 0.01; $notify_url = ""; #获取支付参数 $aliPayUrl = $aliPay->aliPayOrder($order_sn,$total_money,$notify_url);
这样我们就可以获得前端所需支付参数。
四、回调处理
我们同样新增一个接口来处理回调,代码如下
#获取用户参数 $signData = request()->post(); #记录请求参数 Log::write("支付宝回调",json_encode($signData)); #检查回调参数是否正确 if (!isset($signData['sign']) && !isset($signData['trade_status'])){ echo "false"; die; } #获取配置 $aliPayPublicKey = Config('appConfig.ali_pay_public_key'); #初始化支付宝 $aliPay = new AliPay(); #格式化公钥【支付宝平台公钥】 $verifyRes = $aliPay->verifySign($signData,$aliPayPublicKey); #验签 if (!$verifyRes){ echo "false"; die; }; #判断是否是支付成功 if($signData['trade_status']!="TRADE_SUCCESS"){ echo "false"; die; } #提取参数 $buyerId = isset($signData["buyer_id"])?$signData["buyer_id"]:""; $tradeNo = isset($signData["trade_no"])?$signData["trade_no"]:NULL; $outTradeNo = isset($signData["out_trade_no"])?$signData["out_trade_no"]:""; $gmtPayment = isset($signData["gmt_payment"])?$signData["gmt_payment"]:time();
以上是部分片段,这部分代码基本可以直接复制,下面的就是各自业务处理逻辑,我这里就不放上去了,仅供大家参考
以上就是thinkphp不通过支付宝SDK,进行支付宝APP支付以及回调处理。
0条评论