採用 WordPress 搭建的網站,並使用 WooCommerce 外掛,現在需要接入支付寶支付功能。
1. 建立應用
1.1 登入
使用支付寶賬號登入開放平臺:
1.2 建立應用
登入之後是如下介面:
1.2.1 基礎資訊
基礎資訊中有應用名稱和應用圖示。應用名稱之前已經填過了,現在上傳自己的應用圖示就行了。應用基礎資訊在開發應用過程中可以無需稽覈隨時完善。但在應用申請上線時需要進行稽覈。
1.2.2 功能選項
功能選項模組中包含各種功能,您可以選擇自己需要的功能新增到功能列表中,現在預設新增了當面付、手機網站支付、 APP 支付功能。不同的功能有不同的使用條件,如果某個功能的使用條件是簽約,那麼在使用此項功能之前,需要簽約對應產品。點選 “+ 繼續新增”,跳到新增功能頁面,這裡有非常多的功能供選擇:
1.2.3 開發配置
- 應用閘道器:用於接收支付寶非同步通知,這裡可以不用設定。
- 授權回撥地址:第三方授權或者使用者資訊授權後回撥地址。授權連結中配置的 redirect_uri 值必須與此值保持一致。
- RSA2(SHA256) 金鑰 (推薦):開發者要保證介面中使用的秘鑰與此處的公鑰匹配,否則無法呼叫介面。介面引數 sign_type=RSA2 。
- RSA(SHA1) 金鑰:同上,介面引數為 sign_type=RSA 。
對介面加簽方式中的 “設定應用公鑰” 進行設定,會彈出如下視窗:
- 商戶應用公鑰:商戶自己生成的 RSA 公鑰,生成之後需要上傳公鑰到支付寶開放平臺以便支付寶使用該公鑰驗證交易是否由該商戶發起的;
- 商戶應用私鑰:商戶自己生成的 RSA 私鑰,商戶開發者使用生成的私鑰對請求字串進行加簽;
- 支付寶公鑰:支付寶的 RSA 公鑰,商戶使用該公鑰驗證結果是否由支付寶返回的。
生成商戶應用私鑰和應用公鑰:
點選右邊的連結:https://docs.open.alipay.com/291/105971,這裡介紹了生成商戶 RSA 金鑰的方法。根據指導,生成了应用公钥 2048.txt
和应用私钥 2048.txt
兩個檔案。生成的私鑰一定要妥善保管。私鑰需要填寫到程式碼中供簽名時使用;公鑰需要上傳到支付寶開放平臺。
上傳商戶應用公鑰到支付寶平臺:
把应用公钥 2048.txt
中的內容複製貼上到前面的框框中。然後儲存,彈出如下視窗:
可以隨時修改應用公鑰。
使用應用私鑰生成請求籤名
把 AppID 、應用私鑰、支付寶公鑰配置在程式碼中,對請求內容進行簽名,並對支付寶返回的內容進行驗籤。
支付寶開放平臺 SDK 封裝了簽名和驗簽過程,只需配置賬號和金鑰引數即可,推薦使用 SDK 。這個在開發過程中會介紹。
建立應用時的應用狀態為 “開發中”,無法線上上正式呼叫介面。按照上面的步驟設定好後,提交稽覈。
2 開發
應用稽覈透過後,變成已上線狀態。現在我們可以嘗試開發支付寶網站介面了。
2.1 下載服務端 SDK
為了幫助開發者呼叫開放介面,支付寶開放平臺提供了 “開放平臺服務端 SDK”,包含 JAVA 、 PHP 和.NET 三個版本,封裝了簽名&驗籤、 HTTP 介面請求等基礎功能。
https://docs.open.alipay.com/54/103419,選擇您熟悉的語言的 SDK 。我下載的是 PHP 版本的。這個頁面中有關於各語言版本 SDK 的詳細使用說明,可以仔細閱讀一遍。
將下載的 alipay-sdk-PHP-20171121170331.zip
解壓到專案目錄中去,比如專案資料夾為 alipay/
,那麼解壓後的 SDK 為 alipay/alipay-sdk-PHP-20171121170331/
。
2.2 介面呼叫配置
在 SDK 呼叫前需要進行初始化,程式碼如下:
| require_once(“alipay-sdk-PHP-20171121170331/AopSdk.php”); //構造引數 $aop = new AopClient (); $aop->gatewayUrl = ‘https://openapi.alipay.com/gateway.do’; // 向這個網址傳送支付、退款、查詢等請求 $aop->appId = ‘ 請填寫 APPID’; $aop->rsaPrivateKey = ‘ 請填寫商戶私鑰’; $aop->apiVersion = ‘1.0’; $aop->signType = ‘RSA2’; // 對字串進行前 ing 時使用的簽名演算法型別 $aop->postCharset= ‘utf-8’; $aop->format=‘json’; |
接下來,就可以用 $aop
來呼叫具體的 API 了。 $aop
只需要初始化一次,後續呼叫不同的 API 都可以使用同一個 $aop
物件。
2.3 向支付寶傳送支付請求
透過向支付寶閘道器傳送alipay.trade.page.pay
請求進行支付。
| $request = new AlipayTradePagePayRequest (); $request->setReturnUrl(‘ 請填寫您的頁面同步跳轉地址’); // 在支付完成之後,支付寶伺服器會跳轉到這個頁面,同時 GET 方式傳送支付結果引數 $request->setNotifyUrl(‘ 請填寫您的非同步通知地址’); // 支付完成後,支付寶伺服器會向這個網址傳送非同步通知訊息,支付結果必須以非同步通知為準,不能依賴同步跳轉 $request->setBizContent(‘{“product_code”:”FAST_INSTANT_TRADE_PAY”,”out_trade_no”:”20150320010101001″,”subject”:”Iphone6 16G”,”total_amount”:”88.88″,”body”:”Iphone6 16G”}’); // 請求 $result = $aop->pageExecute ($request); // $resule 是一個表單 // 輸出 echo $result; |
報文請求時會自動用應用私鑰進行簽名;支付寶收到請求之後,首先用應用公鑰對請求引數驗籤,然後返回表單 $result
,列印這個表單會把使用者重定向到支付頁面。
請求返回的結果 $result
的內容如下:
| <br /><form id=“alipaysubmit” action=“https://openapi.alipaydev.com/gateway.do?charset=UTF-8” method=“POST” name=“alipaysubmit”><input name=“biz_content” type=“hidden” value=“{“product_code“:”FAST_INSTANT_TRADE_PAY“,”body“:”hah“,”subject“:” 測試“,”total_amount“:”0.01“,”out_trade_no“:”201711279339773“}” /><input name=“app_id” type=“hidden” value=“2016090800411111” /><input name=“version” type=“hidden” value=“1.0” /><input name=“format” type=“hidden” value=“json” /><input name=“sign_type” type=“hidden” value=“RSA2” /><input name=“method” type=“hidden” value=“alipay.trade.page.pay” /><input name=“timestamp” type=“hidden” value=“2017-11-27 10:26:48” /><input name=“alipay_sdk” type=“hidden” value=“alipay-sdk-php-20161101” /><input name=“notify_url” type=“hidden” value=“https://www.example.com” /><input name=“return_url” type=“hidden” value=“https://www.example.com” /><input name=“charset” type=“hidden” value=“UTF-8” /><input name=“sign” type=“hidden” value=“nZG55zzL2PtHywMt0z93uCx+1W3JSo9tUk8AM32N2fvzeeapg6g55nVjGmdGRrSLDQzYibEP3imOqmS6I5u9e222v8BeZKPtZJUb4GMrvot0NXVSqRRDi/kmyURAI7d8+8wkpgQP3mEKg9YM4JddcWYQRFdM6W0kzKPd2N+hThjdchJ30wwwDtCAgZNs916t3YTW18ZTDxSSjDCHDDPd065PkUwNmLc1YwvumS+dKVEVDAy2/gcUjAyFTQx1A9fYW2kibyp2ohGQbjksogTEgOKE2yIuLVZWMTMcZ5k2en826OWV47UmKH07NzCjhqI45Wrkg8sXoY1mUZdvnXUvRQ==” /><input style=“display: none;” type=“submit” value=“ok” /></form><script>document.forms[‘alipaysubmit’].submit();</script> |
當使用者付過錢後,會跳轉到設定的 return url
中,並以 GET 方式返回支付結果引數。
2.4 處理非同步通知
由於同步返回的不可靠性,支付結果必須以非同步通知或查詢介面返回為準,不能依賴同步跳轉。
2.4.1 驗籤
支付成功後,支付寶除了向 return url
傳送同步通知外,還會以 POST 方式向 notify url
傳送非同步通知。商戶系統受到非同步通知後,首先需要用支付寶公鑰進行驗籤,確定訊息是否來自支付寶。 SDK 中封裝了驗籤介面。
| $arr = $_POST; $arr[‘fund_bill_list’] = stripslashes($arr[‘fund_bill_list’]); $aop = new AopClient(); $aop->alipayrsaPublicKey = ‘ 支付寶公鑰’; $signtype = ‘RSA2’ $flag = $aop->rsaCheckV1($arr, ‘ 支付寶公鑰’, $signtype); if ($flag) { //驗籤成功 // 進行通知資料的二次檢驗 // 根據交易狀態進行商戶的自身業務 echo ‘success’; } else { // 驗籤失敗,記錄異常日誌 echo ‘fail’; } |
剛開始的時候,出現了驗籤失敗的結果。後來在網上搜了一下,發現這是因為 PHP 自動將 fund_bill_list
中的特殊字元前加了轉義符,需要把跳脫字元去掉才行。所以如果驗籤沒透過,不妨加上 $arr['fund_bill_list'] = stripslashes($arr['fund_bill_list']);
試試。
2.4.2 二次檢驗
驗籤透過後,需要按照以下步驟檢驗資料的正確性:
- 1 、商戶需要驗證該通知資料中的 out_trade_no 是否為商戶系統中建立的訂單號;
- 2 、判斷 total_amount 是否確實為該訂單的實際金額(即商戶訂單建立時的金額);
- 3 、校驗通知中的 seller_id(或者 seller_email) 是否為 out_trade_no 這筆單據的對應的操作方(有的時候,一個商戶可能有多個 seller_id/seller_email);
- 4 、驗證 app_id 是否為該商戶本身。
上述 1 、 2 、 3 、 4 有任何一個驗證不透過,則表明本次通知是異常通知,務必忽略。
在上述驗證透過後商戶必須根據支付寶不同型別的業務通知,正確的進行不同的業務處理,並且過濾重複的通知結果資料。在支付寶的業務通知中,只有交易通知狀態為 TRADE_SUCCESS 或 TRADE_FINISHED 時,支付寶才會認定為買家付款成功。
注意:
狀態 TRADE_SUCCESS 的通知觸發條件是商戶簽約的產品支援退款功能的前提下,買家付款成功;
交易狀態 TRADE_FINISHED 的通知觸發條件是商戶簽約的產品不支援退款功能的前提下,買家付款成功;或者,商戶簽約的產品支援退款功能的前提下,交易已經成功並且已經超過可退款期限。
2.4.3 繼續商戶自身的業務邏輯
在驗籤、二次校透過後,根據 trade_status
進行後續業務處理。
| <br />// 交易狀態 $trade_status = $_POST[‘trade_status’]; if($trade_status == ‘TRADE_FINISHED’ || $trade_status==‘TRADE_SUCCESS’) { // 判斷該訂單是否在商戶網站中已經做過處理,如果沒有的話執行商戶的業務程式 } |
3 問題集錦
1. 除錯錯誤,請回到請求來源地,重新發起請求。
錯誤程式碼 missing-signature 錯誤原因: 缺少簽名引數
解答:
這是因為 alipay.trade.page.pay
請求結果裡面沒有 sign,為什麼呢?https://openclub.alipay.com/read.php?tid=2333&fid=46 給出了原因。
php 環境必須 5.5 以上,而現在的伺服器上透過 php -v
命令檢視,版本是 PHP 5.3.28 。升級之後這個問題解決了。
2. 支付請求提交後,返回 “訂單資訊無法識別,建議聯絡賣家” 的錯誤提示?
解答:
$request->setBizContent();
中每個引數值都應該是字串,比如'"' . $value1 . '"'
。
參考
[1] 電腦網站支付快速接入
[2] 建立應用
[3] 生成 RSA 金鑰
[4] 上傳應用公鑰並獲取支付寶公鑰
[5] 使用應用私鑰生成請求籤名
[6] 服務端 SDK
[7] alipay.trade.page.pay
[8] 電腦網站支付結果非同步通知
原文來自:victoriawy.com 感謝作者提供又一個支付寶解決方案。