採用 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 感謝作者提供又一個支付寶解決方案。