0.準備工作
支付寶賬號驗證
簽約接口
私鑰生成
1. 拼湊訂單
1.1 拼裝訂單
1.2 私鑰簽名
2 服務(wù)器端處理
2.1 支付寶處理流程圖
3 代碼實現(xiàn)
3.1 開啟CURL
3.2 填寫配置
3.3 訂單簽名
4 驗簽
1.1 私鑰生成
私鑰可以使用支付寶提供的RSA私鑰生成工具。
1.2 將生成的公鑰上傳到支付寶
在簽約管理處简肴,點擊查看PID | Key晃听。輸入支付密碼之后既可以查看相關(guān)的公鑰。
上傳公鑰
之后再添加密鑰處復(fù)制自己的公鑰(我的已經(jīng)添加過了,此處顯示為查看)
注意
- 此處是上傳密鑰能扒,而不是上傳私鑰佣渴,私鑰千萬不能泄露出去,切記初斑,在這里把自己的公鑰公布給支付寶就行辛润,讓支付寶能夠驗證你的簽名。
- 要在合作伙伴密鑰管理這里添加公鑰见秤。而不是下面的開放平臺密鑰管理的地方
上傳公鑰
2. 服務(wù)器端處理
2.1 支付寶處理流程圖
業(yè)務(wù)流程圖
業(yè)務(wù)流程圖
數(shù)據(jù)交互流程圖
簡單來說
- 客戶端發(fā)起支付請求砂竖,在自己的服務(wù)器端生成訂單并且使用私鑰給訂單簽名
- 客戶端使用拿到服務(wù)器端生成的字符串(訂單字符串+簽名字符串)交給支付寶SDK進行支付
- 支付寶會回調(diào)我們的服務(wù)器端,根據(jù)訂單信息中傳遞的回調(diào)地址來訪問我們的服務(wù)器鹃答,并且將訂單信息和支付寶的簽名字符串發(fā)送過來乎澄,我們可以在這個時候驗證支付是否成功。
3 代碼實現(xiàn)
根據(jù)上面的流程寫具體代碼即可测摔。
首先導(dǎo)入支付寶的PHP SDK三圆,下載地址
在支付寶文檔中心下載移動支付(SDK&DEMO下載)
解壓之后打開服務(wù)端demo->readme.txt。幾乎所有的東西都在這個文檔里了避咆。
3.1 開啟CURL
1舟肉、必須開啟curl服務(wù)
(1)使用Crul需要修改服務(wù)器中php.ini文件的設(shè)置,找到php_curl.dll去掉前面的";"即可
(2)文件夾中cacert.pem文件請務(wù)必放置到商戶網(wǎng)站平臺中(如:服務(wù)器上)查库,并且保證其路徑有效路媚,提供的代碼demo中的默認路徑是當前文件夾下——getcwd().'\\cacert.pem'```
### 3.2 填寫配置
2、需要配置的文件是:
alipay.config.php
key文件夾```
alipay.config.php.打開這個文件之后樊销,里面所有的配置信息都有相應(yīng)的中文注釋整慎,按照注釋填寫即可。
3.3 訂單簽名
首先在你的支付類中引入lib\alipay_notify.class.php文件围苫。
簽名實現(xiàn)工具裤园,需要的時候調(diào)用這個方法,傳遞需要參數(shù)剂府,然后將字符串返回給客戶端即可拧揽。
//調(diào)用方傳遞subject,body腺占,price即可獲取到簽名后的字符串淤袜,contentId在簽名過程中用不到,可以根據(jù)具體業(yè)務(wù)刪除或保留
public function aliSignUtil($subject, $body, $price, $contentId)
{
$order['partner'] = '"商戶號"';
$order['seller_id'] = '"商戶Id"';
$order['out_trade_no'] = '"' . $this->getOrderNo() . '"';//獲取訂單號衰伯,保證唯一
$order['subject'] = '"' . $subject . '"';
$order['body'] = '"' . $body . '"';
$order['total_fee'] = '"' . $price . '"';
$order['notify_url'] = '"回調(diào)地址"';//支付寶支付成功之后的回調(diào)地址铡羡,必須公網(wǎng)可以訪問
$order['service'] = '"mobile.securitypay.pay"';
$order['payment_type'] = '"1"';
$order['_input_charset'] = '"utf-8"';
$order['it_b_pay'] = '"30m"';
$order['return_url'] = '"m.alipay.com"';
//需要加簽的內(nèi)容處理成字符串
$data = createLinkstring($order);//支付寶提供的方法
//加簽
$data = rsaSign($data, AliPay . DIRECTORY_SEPARATOR . 'key' . DIRECTORY_SEPARATOR . 'rsa_private_key.pem');//支付寶提供的簽名方法,第二個參數(shù)是私鑰地址
$history['sign'] = str_replace("\"", "", $data);
$order['sign'] = '"' . urlencode($data) . '"';
$order['sign_type'] = '"RSA"';
//訂單信息處理成字符串
$result = createLinkstring($order);
//這里將history訂單信息保存到了數(shù)據(jù)庫,方便回調(diào)的時候根據(jù)訂單號查詢出是哪一個用戶產(chǎn)生的訂單。
$history['out_trade_no'] = str_replace("\"", "", $order['out_trade_no']);
$history['total_fee'] = str_replace("\"", "", $order['total_fee']);
$history['contentId'] = $contentId;
$this->saveOrder($history);//訂單歷史保存到數(shù)據(jù)庫
//返回訂單信息,客戶端可以根據(jù)result來調(diào)用支付寶進行支付螟够。
return html_entity_decode($result);
}
4驗簽
根據(jù)上面加簽時候填寫的回調(diào)地址读慎,寫支付寶驗簽代碼
$order = $_POST;
$sign = $order;
//去除簽名和簽名方式以及controller和action教翩,保留待簽名信息
unset($sign['sign']);
unset($sign['sign_type']);
unset($sign['c']);
unset($sign['a']);
ksort($sign);
$sign = createLinkstring($sign);
//驗證支付寶簽名
$result = false;
$result = rsaVerify(
$sign,
AliPay . DIRECTORY_SEPARATOR . 'key' . DIRECTORY_SEPARATOR . 'alipay_public_key.pem',
$order['sign']);
$db = new Medoo();
//在訂單歷史表中按支付寶回調(diào)訂單號查詢出訂單,判斷狀態(tài)
$result = $db->select('alipay', '*', ["out_trade_no" => $order["out_trade_no"]])[0];
//重復(fù)驗證
if ($result['status'] == '1') {
echo 'success';
exit();
}
if ($result && $order['trade_status'] == 'TRADE_SUCCESS') {//驗證支付寶簽名成功贪壳,并且是支付成功的回調(diào)
//這里可以確定是支付寶進行的回調(diào)饱亿,并且是第一次成功的回調(diào),在這里寫支付成功之后的邏輯就好
$result['status'] = '1';
$num = $db->update('alipay', $result, ["out_trade_no" => $order["out_trade_no"]]);
//添加購買歷史
$this->addBuyHistory("購買內(nèi)容", 100, $db, $result['userId']);
//購買內(nèi)容
if (!empty($result['contentId'])) {
$buy['contentId'] = $result['contentId'];
$buy['userId'] = $result['userId'];
$num = $db->insert('contentsubs', $buy);
}
//處理完成后輸出succes給支付寶
echo 'success';
}
自此闰靴,支付寶完成了一次完整的支付彪笼。