最近在寫支付 , 遇到了一些支付寶的坑,這里也記錄分享一下
首先必須在螞蟻金服上面有一個應用 , 並且把商戶私鑰 , 支付寶公鑰等都設置好
然后下載支付寶php的SDK , 鏈接如下
https://docs.open.alipay.com/270/106291/
我用的是TP5框架
這里把SDK下好解壓之后放到TP的extend目錄下
首先我們需要在自己的數據庫中保存以下內容 :
1.subject //訂單標題 2.total_amount //需付款金額 3.body //商品描述, 可空 4.out_trade_no //訂單號, 需自己生成 5.user_id //這個不用傳給支付寶
這里附上我的生成訂單號代碼
//生成訂單號
$osn = date('YmdHis').substr(implode(NULL, array_map('ord', str_split(substr(uniqid(), 7, 13), 1))), 0, 8);
以上都完成之后 , 就可以使用SDK了
這里我遇到了第一個問題 , 第三方類的引用. 由於支付寶SDK無法使用composer下載 , 導致了整個包里面的
類都沒有命名空間 .
引用的時候總是報錯文件不存在或類不存在
查閱了許多資料之后 , 終於找到了解決方法 :
使用Loader加載
Loader::import('alipay.pagepay.service.AlipayTradeService');
Loader::import('alipay.pagepay.buildermodel.AlipayTradePagePayContentBuilder');
這樣的話即使第三方類庫沒有命名空間 , 也能完美引用
我把SDK之中的pagepay.php 寫到了我的class之中
//以下是簡化過后的代碼
public function payment ()
{
$data = $this->request->param();
$user_id = $this->userInfo['id'];
//生成唯一訂單號
$osn = date('YmdHis').substr(implode(NULL, array_map('ord', str_split(substr(uniqid(), 7, 13), 1))), 0, 8);
//保存訂單
$res = Db::name('order')->insert([
'title' => $data['subject'], //訂單標題
'type' => $data['type'], //訂單類型
'number' => $osn, //訂單編號
'money' => $data['total_amount'],
'user_id'=> $user_id,
'create_time'=>time(),
]);
if($res){
//訂單信息保存成功
Loader::import('alipay.pagepay.service.AlipayTradeService');
Loader::import('alipay.pagepay.buildermodel.AlipayTradePagePayContentBuilder');
$payRequestBuilder = new \AlipayTradePagePayContentBuilder();
$payRequestBuilder->setBody($data['body']);
$payRequestBuilder->setSubject($data['subject']);
$payRequestBuilder->setTotalAmount($data['total_amount']);
$payRequestBuilder->setOutTradeNo($osn);
$aop = new \AlipayTradeService(config('alipay'));
/**
* pagePay 電腦網站支付請求
* @param $builder 業務參數,使用buildmodel中的對象生成。
* @param $return_url 同步跳轉地址,公網可以訪問
* @param $notify_url 異步通知地址,公網可以訪問
* @return $response 支付寶返回的信息
*/
$response = $aop->pagePay($payRequestBuilder,config('alipay')['return_url'],config('alipay')['notify_url']);
}
echo $osn; //2018070499495653
}
這里的config函數是我提前就在application目錄下的config.php文件中部署好的
//在你application目錄下的config文件之后加上支付寶的一些配置信息
// 之后就可以直接使用config('alipay')調用此數組
//一定要確保這些數據沒有任何問題
'alipay'=>[
//應用ID,您的APPID。
'app_id' => "",
//商戶私鑰
'merchant_private_key' => "",
//異步通知地址
'notify_url' => "",
//同步跳轉
'return_url' => "",
//編碼格式
'charset' => "UTF-8",
//簽名方式
'sign_type'=>"RSA2",
//支付寶網關
'gatewayUrl' => "https://openapi.alipay.com/gateway.do",
//支付寶公鑰
'alipay_public_key' => "",
],
至此 , 調用了pagepay之后 , 就會出現付款界面了
付款成功 , 接下來是支付寶的支付結果異步通知
此通知是支付寶單方面訪問你的接口 , 你需要在此接口之中處理商戶的業務邏輯
成功之后返回 “success” 即可
注意 ! 請不要把支付寶的異步請求的接口放在繼承了登陸等判斷的class之中 , 因為如果加了這些判斷 ,
則支付寶無法正常請求我們的接口
此接口必須放在服務器上 ,如果在本地則支付寶服務器無法請求
/**
* 支付寶異步回調接口
*/
public function notify_url ()
{
Loader::import('alipay.pagepay.service.AlipayTradeService');
$arr=$_POST;
$alipaySevice = new \AlipayTradeService(config('alipay'));
$alipaySevice->writeLog(var_export($_POST,true));
$result = $alipaySevice->check($arr); //這一步驗簽
if($result) {//驗證成功
//商戶訂單號
$out_trade_no = $_POST['out_trade_no'];
//訂單金額
$total_amount = $_POST['total_amount'];
//支付寶交易號
$trade_no = $_POST['trade_no'];
//交易狀態
$trade_status = $_POST['trade_status'];
if($_POST['trade_status'] == 'TRADE_FINISHED') {
//--交易結束執行的業務邏輯--
}else if ($_POST['trade_status'] == 'TRADE_SUCCESS') {
//--交易支付成功執行的業務邏輯--
}
//——請根據您的業務邏輯來編寫程序(以上代碼僅作參考)——
echo "success"; //請不要修改或刪除
}else {
//驗證失敗
echo "fail";
}
}
到這里使用支付寶SDK就結束了
這里還說一下 , 你的服務器必須開啟openssl拓展 , 調用check驗簽 , 必需開啟openssl