摘要:原文地址支付支付步驟為獲取支付寶的配置信息。將得到的數據請求支付寶客戶端進行支付。端將拼接好的字符串拿去請求支付寶客戶端即可調起支付寶進行支付。向支付寶申請新訂單,獲取支付。成功請求回來后,就可以向支付寶發出一次支付請求。
支付寶在所有支付方式中最好開發的了,因為文檔比較清晰,而且開發起來也比較簡單。因此,支付寶的坑是相對較少的。
原文地址
APP支付步驟為:
獲取支付寶的配置信息。
生成商家訂單信息。
根據訂單信息生成待校驗數據。
生成請求給支付寶的加密字符串。
將待校驗數據和加密字符串拼接,返回給APP。
APP將得到的數據請求支付寶客戶端進行支付。
由于APP支付是由APP去調起支付寶支付,所以服務端需要做的事情就是將請求參數封裝好之后返回APP即可。
獲取支付寶的配置信息。
支付時需要的配置信息有:
key: 交易安全校驗碼。
app_id:支付寶分配給開發者的應用ID。
生成商家訂單信息。
這個步驟由商家自行生成。支付寶那邊只需要知道的訂單信息為:
subject: 必填。商品的標題/交易標題/訂單標題/訂單關鍵字等。
total_amount: 必填。訂單價格。
out_trade_no: 必填。商戶網站唯一訂單號。
body: 非必填。交易的具體描述信息。
根據訂單信息生成待校驗數據。
APP支付的詳細請求參數: 點擊查看
生成請求給支付寶的加密字符串。
</>復制代碼
$sign = $alipaySubmit->buildRequestParaForApp($para_token);
其中, buildRequestParaForApp 的實現為:
對待簽名參數數組排序
</>復制代碼
/**
* 對數組排序
* @param $para 排序前的數組
* return 排序后的數組
*/
function argSort($para) {
ksort($para);
reset($para);
return $para;
}
生成簽名結果(阿里推薦的是RSA2的簽名方式,這里項目用的是RSA)
</>復制代碼
/**
* RSA簽名
* @param $data 待簽名數據
* @param $private_key_path 商戶私鑰文件路徑
* return 簽名結果
*/
function rsaSign($data, $private_key_path) {
$priKey = file_get_contents($private_key_path);
$res = openssl_get_privatekey($priKey);
openssl_sign($data, $sign, $res);
openssl_free_key($res);
//base64編碼
$sign = base64_encode($sign);
return $sign;
}
將待校驗數據和加密字符串拼接,返回給APP。
</>復制代碼
$url = "";
foreach ($para_token as $key => $value) {
$url .= $key."=".urlencode($value)."&";
}
return $url."sign=".urlencode($sign);
APP將得到的數據請求支付寶客戶端進行支付。
APP端將拼接好的字符串拿去請求支付寶客戶端即可調起支付寶進行支付。拼接好的字符串大致如下圖所示:
網頁版支付步驟為:
設置支付寶的配置信息。
向支付寶申請新訂單,獲取支付token。
攜帶token進行訂單支付。
網頁版的支付寶支付相對于APP調起支付寶要復雜,因為網頁支付時,需要多次請求支付寶服務器獲取支付的必要參數。
設置支付寶配置信息。
</>復制代碼
/**調用授權接口alipay.wap.trade.create.direct獲取授權碼token**/
//返回格式
private $format = "";
//必填,不需要修改
//版本
private $v = "";
//必填,不需要修改
//請求號
private $req_id = "";
//必填,須保證每次請求都是唯一
//**req_data詳細信息**
//服務器異步通知頁面路徑
private $notify_url = "";
//需http://格式的完整路徑,不允許加?id=123這類自定義參數
//頁面跳轉同步通知頁面路徑
private $call_back_url = "";
//需http://格式的完整路徑,不允許加?id=123這類自定義參數
//賣家支付寶賬戶
private $seller_email = "";
//必填
//商戶訂單號
private $out_trade_no = "";
//商戶網站訂單系統中唯一訂單號,必填
//訂單名稱
private $subject = "";
//必填
//付款金額
private $total_fee = "";
//必填
//請求業務參數詳細
private $req_data = "";
//必填
//配置
private $alipay_config = array();
/************************************************************/
向支付寶申請新訂單,并獲取訂單的token。
請求token的service為: alipay.wap.trade.create.direct。
構造參數:
</>復制代碼
$para_token = array(
"service" => "alipay.wap.trade.create.direct",
// 合作者身份(partner ID)
"partner" => trim($this->alipay_config["partner"]),
// APP使用的是RSA,網頁版使用的是MD5
"sec_id" => trim($this->alipay_config["sign_type"]),
// 返回的數據格式
"format" => $this->format,
// 版本號?
"v" => $this->v,
// 唯一的請求號
"req_id" => $this->req_id,
// 請求參數
"req_data" => $req_data,
// 字符集,一般為utf8即可。
"_input_charset" => trim(strtolower($this->alipay_config["input_charset"]))
);
將構造好的請求參數,進行處理,字典排序,拼接字符串,簽名:
</>復制代碼
$para_filter = paraFilter($para_temp);
$para_sort = argSort($para_filter);
$mysign = $this->buildRequestMysign($para_sort);
//簽名結果與簽名方式加入請求提交參數組中
$para_sort["sign"] = $mysign;
return $para_sort;
處理:過濾值為空的數據,過濾簽名類型和簽名。
</>復制代碼
function paraFilter($para) {
$para_filter = array();
while (list ($key, $val) = each ($para)) {
if($key == "sign" || $key == "sign_type" || $val == "")continue;
else $para_filter[$key] = $para[$key];
}
return $para_filter;
}
字典排序:
</>復制代碼
/**
* 對數組排序
* @param $para 排序前的數組
</>復制代碼
*/
function argSort($para) {
ksort($para);
reset($para);
return $para;
}
```
簽名:
```php
/**
* 生成簽名結果
* @param $para_sort 已排序要簽名的數組
* return 簽名結果字符串
*/
function buildRequestMysign($para_sort) {
//把數組所有元素,按照“參數=參數值”的模式用“&”字符拼接成字符串
$prestr = createLinkstring($para_sort);
$mysign = "";
switch (strtoupper(trim($this->alipay_config["sign_type"]))) {
case "MD5" :
// MD5直接將密鑰拼接在字符串后面再進行MD5加密。
$mysign = md5Sign($prestr, $this->alipay_config["key"]);
break;
case "RSA" :
// RSA則是先讀取商戶的私鑰,再用該密鑰對字符串進行加密。
$mysign = rsaSign($prestr, $this->alipay_config["private_key_path"]);
break;
case "0001" :
$mysign = rsaSign($prestr, $this->alipay_config["private_key_path"]);
break;
default :
$mysign = "";
}
return $mysign;
}
```
3. 用構造好的參數請求支付寶后臺申請新訂單:
**注意:請求時,必須帶上SSL證書。**
```php
$sResult = getHttpResponsePOST($this->alipay_gateway_new, $this->alipay_config["cacert"],$request_data,trim(strtolower($this->alipay_config["input_charset"])));
```
請求函數的實現:
```php
/**
* 遠程獲取數據,POST模式
* 注意:
* 1.使用Crul需要修改服務器中php.ini文件的設置,找到php_curl.dll去掉前面的";"就行了
* 2.文件夾中cacert.pem是SSL證書請保證其路徑有效,目前默認路徑是:getcwd()."cacert.pem"
* @param $url 指定URL完整路徑地址
* @param $cacert_url 指定當前工作目錄絕對路徑
* @param $para 請求的數據
* @param $input_charset 編碼格式。默認值:空值
* return 遠程輸出的數據
*/
function getHttpResponsePOST($url, $cacert_url, $para, $input_charset = "") {
if (trim($input_charset) != "") {
$url = $url."_input_charset=".$input_charset;
}
$curl = curl_init($url);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, true);//SSL證書認證
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2);//嚴格認證
curl_setopt($curl, CURLOPT_CAINFO,$cacert_url);//證書地址
curl_setopt($curl, CURLOPT_HEADER, 0 ); // 過濾HTTP頭
curl_setopt($curl,CURLOPT_RETURNTRANSFER, 1);// 顯示輸出結果
curl_setopt($curl,CURLOPT_POST,true); // post傳輸數據
curl_setopt($curl,CURLOPT_POSTFIELDS,$para);// post傳輸數據
$responseText = curl_exec($curl);
//var_dump( curl_error($curl) );//如果執行curl過程中出現異常,可打開此開關,以便查看異常內容
curl_close($curl);
return $responseText;
}
```
處理支付寶返回的數據,并獲取token。
```php
//URLDECODE返回的信息
$html_text = urldecode($html_text);
//解析遠程模擬提交后返回的信息
$para_html_text = parseResponse($html_text);
//獲取request_token
$request_token = $para_html_text["request_token"];
```
parseResponse函數的實現:
```php
/**
* 解析遠程模擬提交后返回的信息
* @param $str_text 要解析的字符串
* @return 解析結果
*/
function parseResponse($str_text) {
//以“&”字符切割字符串
$para_split = explode("&",$str_text);
//把切割后的字符串數組變成變量與數值組合的數組
foreach ($para_split as $item) {
//獲得第一個=字符的位置
$nPos = strpos($item,"=");
//獲得字符串長度
$nLen = strlen($item);
//獲得變量名
$key = substr($item,0,$nPos);
//獲得數值
$value = substr($item,$nPos+1,$nLen-$nPos-1);
//放入數組中
$para_text[$key] = $value;
}
if( ! empty ($para_text["res_data"])) {
//解析加密部分字符串
if($this->alipay_config["sign_type"] == "0001") {
$para_text["res_data"] = rsaDecrypt($para_text["res_data"], $this->alipay_config["private_key_path"]);
}
//token從res_data中解析出來(也就是說res_data中已經包含token的內容)
$doc = new DOMDocument();
$doc->loadXML($para_text["res_data"]);
$para_text["request_token"] = $doc->getElementsByTagName( "request_token" )->item(0)->nodeValue;
}
return $para_text;
}
```
攜帶token進行訂單支付。
成功請求token回來后,就可以向支付寶發出一次支付請求。
同樣構造請求數據:
</>復制代碼
//業務詳細只需要攜帶步驟2的token即可。
$req_data = "" . $request_token . " ";
//必填
//構造要請求的參數數組,無需改動
$parameter = array(
"service" => "alipay.wap.auth.authAndExecute",
// 合作者身份(partner ID)
"partner" => trim($this->alipay_config["partner"]),
// 簽名類型
"sec_id" => trim($this->alipay_config["sign_type"]),
// 和步驟2一致
"format" => $this->format,
"v" => $this->v,
"req_id" => $this->req_id,
// 業務詳細參數
"req_data" => $req_data,
// 字符集,一般為utf8.
"_input_charset" => trim(strtolower($this->alipay_config["input_charset"]))
);
將這些參數,在頁面中傳送給支付寶即可發起一次支付請求。
在PHP 中的實現就是將這些參數,渲染至HTML中,再將HTML中的表單提交即可。
到此,網頁版的支付寶支付完成整個流程。
支付結果異步通知在上面,我們看到有兩個參數傳給了支付寶:
call_back_url: 交易成功后,支付寶頁面上“返回到商家頁面”的地址(同步回調)
notify_url: 交易狀態變更后,支付寶通知網站的回調地址(異步通知)
</>復制代碼
對于手機網站支付產生的交易,支付寶會根據原始支付API中傳入的異步通知地址notify_url,通過POST請求的形式將支付結果作為參數通知到商戶系統。
對于App支付產生的交易,支付寶會根據原始支付API中傳入的異步通知地址notify_url,通過POST請求的形式將支付結果作為參數通知到商戶系統。
支付寶異步通知官方文檔中寫的比較清楚,什么時候出發通知,返回什么參數,注意事項都有,開發者可以根據自己的情況查看具體信息。
驗簽步驟可以移步至這里
這里就簡單的用手上的項目舉例說明,支付寶通知后,后臺是如何進行驗簽和處理訂單。
</>復制代碼
public function app_notifyOp(){
$payment_api = $this->_get_payment_api();
$payment_config = $this->_get_payment_config();
// 支付寶是用POST方式發送通知信息
$callback_info = $payment_api->getNotifyInfoApp($_POST);
if($callback_info) {
//驗證成功
if ($callback_info["order_state"]) {
// 如果是支付成功則改變訂單狀態
$result = $this->_update_order($callback_info["out_trade_no"], $callback_info["trade_no"]);
}else{
// 如果是退款成功則修改退訂的相關狀態
$result = $this->_app_refund($callback_info["out_trade_no"], $callback_info["trade_no"], $callback_info["refund_fee"]);
}
if($result["state"]) {
echo "success";die;
}
}
//驗證失敗
echo "fail";die;
}
獲取支付寶通知數據
支付寶異步通知是POST請求,返回的數據結構如下:
</>復制代碼
{
"total_amount": "31.00",
"buyer_id": "ID",
"trade_no": "TRADE_NO",
"body": "pay_sn:580546601841783375",
"notify_time": "2017-04-27 09:50:59",
"subject": "580546601841783375",
"sign_type": "RSA",
"buyer_logon_id": "ID",
"auth_app_id": "APPID",
"charset": "utf-8",
"notify_type": "trade_status_sync",
"invoice_amount": "31.00",
"out_trade_no": "580546601841783375_r",
"trade_status": "TRADE_SUCCESS",
"gmt_payment": "2017-04-27 09:50:58",
"version": "1.0",
"point_amount": "0.00",
"sign": "SIGNATURE",
"gmt_create": "2017-04-27 09:50:58",
"buyer_pay_amount": "31.00",
"receipt_amount": "31.00",
"fund_bill_list": "[{"amount":"31.00","fundChannel":"ALIPAYACCOUNT"}]",
"app_id": "APPID",
"seller_id": "SELLERID",
"notify_id": "8414394a1190f25edbbec9ba4b98642mem",
"seller_email": "YOUR_ALIPAY_ACCOUNT"
}
驗簽數據
驗簽需要支付寶的公鑰
驗簽和簽名的流程是一樣的,都是將所有除了 sign 以外的參數,進行字典排序,并以 key=value 的形式以 & 符號拼成字符串,再使用密鑰進行簽名,將得到的簽名與支付寶返回的簽名進行對比,完成驗簽過程。
</>復制代碼
function getSignVeryfy($para_temp, $sign) {
//除去待簽名參數數組中的空值和簽名參數
$para = paraFilter($para_temp);
//對待簽名參數數組排序
$para = argSort($para);
//把數組所有元素,按照“參數=參數值”的模式用“&”字符拼接成字符串
$prestr = createLinkstring($para);
$prestr = htmlspecialchars_decode($prestr);
$isSgin = false;
switch (strtoupper(trim($this->alipay_config["sign_type"]))) {
case "MD5" :
$isSgin = md5Verify($prestr, $sign, $this->alipay_config["key"]);
break;
case "RSA" :
$isSgin = rsaVerify($prestr, trim($this->alipay_config["ali_public_key_path"]), $sign);
break;
case "0001" :
$isSgin = rsaVerify($prestr, trim($this->alipay_config["ali_public_key_path"]), $sign);
break;
default :
$isSgin = false;
}
logResult($log);
return $isSgin;
}
但是這里有個坑,就是返回數據中的 fund_bill_list 是經過html轉義的(如例子中的數據: [{"amount":"31.00","fundChannel":"ALIPAYACCOUNT"}]),如果直接使用該參數進行簽名,則會導致簽名失敗。這里就需要將字符串轉義了: [{"amount":"31.00","fundChannel":"ALIPAYACCOUNT"}] ,用轉義后的參數值進行簽名,通過校驗。
更改訂單狀態
驗簽完畢后,后臺就可以根據實際情況進行訂單狀態的更改。
完畢祝各位程序猿在開發支付寶支付時不再有坑,也希望支付寶在后續的更新中不再埋雷。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/22931.html
摘要:前者集成在中,后者主要是為微信用戶提供了另一種支付方式需要在微信的內置瀏覽器中打開頁面,再調起微信支付。步驟商戶后臺收到用戶支付單,調用微信支付統一下單接口。拿到所有參數后,就可以在頁面中發起微信支付的請求了。 微信支付,支持的支付方式比較多:有掃碼支付,刷卡支付,APP支付和公眾號支付。其中,APP和網站上最常用的就是APP支付和公眾號支付。前者集成在APP中,后者主要是為微信用戶提...
摘要:上線時間問題發布審核時間,微信小時內會審核完成,但是支付寶官方公示是上線審核需要三到五個工作日,據親測,實際支付寶審核印版不會超過小時,但是支付寶的審核相比較微信真的很嚴格。 前言: 最近一個月接收一個支付寶小程序項目,并進行原生開發,現將遇到的問題,爬過的坑給大家進行分享,希望讀者可以少走彎路,以下介紹的內容將從大方面到細節進行展開。 廢話少言,直接開始步入正題 ①:上傳、發布問...
摘要:在中巧用解決跳轉到第三方平臺時不能回調的問題比如支付在開發中遇到不少的坑,絕大部分解決了但是在我們的中如果跳轉到第三方網站上時,那么問題來了此時我們的是不能監聽到你在其它網站上的事件的,所以當你想要回退到我們自己上時請緊握你的蛋小編在開發這 在ionic中巧用iframe解決跳轉到第三方平臺時不能回調的問題-比如支付 在ionic開發中遇到不少的坑,絕大部分解決了但是在我們的app...
摘要:原文見我的博客,點擊進入使用開發微信公眾號下站點的填坑之旅本文為我創業過程中,開發項目的填坑之旅。作為一個技術宅男,我的項目是做一個微信公眾號,前后端全部自己搞定,不浪費國家一分錢。 原文見我的博客,點擊進入使用vue開發微信公眾號下SPA站點的填坑之旅 本文為我創業過程中,開發項目的填坑之旅。作為一個技術宅男,我的項目是做一個微信公眾號,前后端全部自己搞定,不浪費國家一分錢^_^。 ...
摘要:目前正在寫一個微信公眾號的小項目,記錄一下遇到的問題和解決方法主要是前端。前端提交時使用,在后端再取出對應的微信支付看了下文檔,以前是需要用喚起支付,而現在則是把微信內置到了微信的瀏覽器中。 目前正在寫一個微信公眾號的小項目,記錄一下遇到的問題和解決方法(主要是前端)。內容持續更新中~ 主要實現 前后端分離前端為 SPA 單頁面使用微信的JSSDK微信支付 技術方案 后端使用 php ...
閱讀 1753·2021-09-22 15:25
閱讀 1313·2019-08-29 12:34
閱讀 1920·2019-08-26 13:57
閱讀 3197·2019-08-26 10:48
閱讀 1453·2019-08-26 10:45
閱讀 800·2019-08-23 18:23
閱讀 742·2019-08-23 18:01
閱讀 1953·2019-08-23 16:07