背景
- 近期項目需要接入支付寶支付功能,其中開發使用了ThinkPHP3.2.3框架,通過參考開發平臺文檔可以知道,網站開發有兩種場景。
- 一種是手機網站支付,直接喚醒支付寶app進入支付操作;
- 另一種多是 PC 端顯示支付二維碼的形式,然后使用手機的支付寶app掃描。
一.接入配置
1).接入步驟
- 根據"快速接入"中的流程,兩者大同小異,都是進行:
- 第一步:創建應用并獲取APPID
- 第二步:配置密鑰
- 第三步:搭建和配置開發環境
- 第四步:調用接口
2).配置截圖
應用配置截圖
3).提示說明
- 雖然官方文檔已經做的很詳細、成熟,不過還是有幾點需要著重提醒一下,以免不必要的糾結。
- 應用創建成功后需要大概一到三天的審核
- 配置密鑰時建議下載其提供的加密工具,可參考RSA密鑰生成方法
- 此處我所下載的是開發平臺服務端SDK中的PHP版資源,而非DEMO文件,相信兩者還是有所區別的
二.手機網站支付接口實現
1).測試入口頁面
-
如下圖所示,我在此創建了一個簡單的入口文件,根據開發文檔中的介紹是需要統一編碼格式的,此處我選擇的是UTF-8
代碼參考-header處理
2).html代碼參考
-
需要注意的是,接口指明需要POST方式進行提交請求
入口界面參考截圖
3).支付寶配置信息
- 對于支付寶的配置信息,我寫在 Application/Common/Conf/config.php中
//支付寶 支付配置
'ALI_CONFIG' => array(
'gatewayUrl' => 'https://openapi.alipay.com/gateway.do',//支付寶網關(固定)'
'appId' => '2017xxxxxxxx9',//APPID即創建應用后生成
//由開發者自己生成: 請填寫開發者私鑰去頭去尾去回車,一行字符串
'rsaPrivateKey' => 'MIIExxxxxxxxxxxxxxxxxxxxxxxxxxxq',
//支付寶公鑰,由支付寶生成: 請填寫支付寶公鑰,一行字符串
'alipayrsaPublicKey' => 'IIBxxxxxxxxxxxxxxxxxxxEFAA',
'notifyUrl' => 'http://www.xxx.com/m/cartpay/notify_ali', // 支付成功通知地址
'returnUrl' => 'http://www.xxx.com', // 支付后跳轉地址
'returnPcUrl' => 'http://www.xxx.com/Home', // PC端掃碼支付后跳轉地址
),
4).服務端SDK導入
- 將前面所下載的SDK放入自定義的位置,在此,我習慣放在如下的路徑中,...\ThinkPHP\Library\Vendor\Alipay,特別提醒一點,對于各文件類的引用會依據代碼框架而不同,需要自行確認。
5).支付接口實現
在請求喚醒支付寶支付的路徑中進行接口代碼的編輯
代碼參考-手機端支付接口
提示
- 通過實驗發現,如果在電腦端進行此功能的支付測試,會報出如下的類似錯誤,個人認為源于手機和PC的內置配置不同
- 對于手機網站支付需要在手機上測試,可自行配置虛擬域名手機訪問即可,不要在此問題上花費不必要的時間
- 因為本人就是在電腦有報錯,手機端訪問卻能完美實現,從而走了驗證簽名的過程到最后卻并非錯在簽名,當然也不排除你的操作過程簽名一定是沒問題的哦.
無效簽名報錯
手機支付參考截圖
代碼實現如下:
/**
* 支付寶支付post提交頁面
*/
public function alipay(){
if (IS_POST){
Vendor('Alipay.aop.AopClient');
Vendor('Alipay.aop.request.AlipayTradeWapPayRequest');
//$out_trade_no = I('post.order_sn');
/*
* $out_trade_no 為自己業務邏輯中要支付的訂單號
* 可從POST數據中提取,具體安全起見可自行加密操作 此處僅舉例測試數據
* $order_amount 為要進行支付的金額 注意要用小數轉換
* 例如:3.50,10.00
* $aliConfig 獲取支付寶配置數據
*/
$out_trade_no = '2017M'.time();
$body = '歡迎購買商品,愿您購物愉快';
$subject = '你好';
$order_amount = 9.00;
$aliConfig = C('ALI_CONFIG');
$aop = new \AopClient();
$aop->gatewayUrl = $aliConfig['gatewayUrl'];
$aop->appId = $aliConfig['appId'];
$aop->rsaPrivateKey = $aliConfig['rsaPrivateKey'];
$aop->alipayrsaPublicKey=$aliConfig['alipayrsaPublicKey'];
$aop->apiVersion = '1.0';
$aop->postCharset='UTF-8';
$aop->format='json';
$aop->signType='RSA2';
$request = new \AlipayTradeWapPayRequest ();
$bizContent = "{" .
" \"body\":\"$body.\"," .
" \"subject\":\"$subject\"," .
" \"out_trade_no\":\"$out_trade_no\"," .
" \"timeout_express\":\"90m\"," .
" \"total_amount\":$order_amount," .
" \"product_code\":\"QUICK_WAP_WAY\"" .
" }";
$request->setBizContent($bizContent);
$request->setNotifyUrl($aliConfig['notifyUrl']);
$request->setReturnUrl($aliConfig['returnUrl']);
$result = $aop->pageExecute ( $request);
echo $result;
}else{
echo 'sorry,非法請求失敗';
}
}
6).支付成功后的通知處理
- 此時,通過獲取所提交過來的post數據,進行訂單號的剝離,從而進行下一步的業務邏輯處理即可.
[注意]:
- 接口文檔中有點明,支付通知功能最后需要輸出‘success’
- 此處的通知路徑要與配置中確定的 ‘notifyUrl’完全一致
/**
* 支付寶支付通知功能
*/
public function notify_ali(){
$out_trade_no = I('post.out_trade_no');
$this->toUpdatePayInfo($out_trade_no,'ali');
echo 'success';
}
三.電腦網站支付接口實現
- 對比來看,其實 PC 端的代碼設計與手機端大同小異,在此點明一下使用情景,可進行參考。
1).支付接口實現
電腦端支付接口代碼截圖
提示:
- 測試發現,接口中定義“subject”時,對于文字的數目有要求,不能超過四個字,至于字母似乎沒有特別限制,開發過程中原想顯示全部的商品名稱卻無法實現,還請注意。
- 提供的代碼暫時未進行界面的設計,可參考 手機端接口思想,接收并處理訂單信息后再喚醒支付寶,當前的代碼可以在公共文件配置正確的情況下,直接公網訪問接口鏈接即可展示效果。
- 支付成功后的通知處理,請參考手機端實現方式.
實現效果截圖
電腦端喚醒支付寶接口
手機掃碼效果
電腦端支付方式-登錄
3).代碼實現如下:
/**
* 電腦端喚醒 支付寶掃碼支付接口
*/
public function aliPayPage(){
$out_trade_no = '2017PC'.time();
$order_amount = '12.88';
$proName = "真米黑米 XXXXXX";
Vendor('Alipay.aop.AopClient');
Vendor('Alipay.aop.request.AlipayTradePagePayRequest');
//構造參數
$aop = new \AopClient();
$aliConfig = C('ALI_CONFIG');
$aop->gatewayUrl = $aliConfig['gatewayUrl'];
$aop->appId = $aliConfig['appId'];
$aop->rsaPrivateKey = $aliConfig['rsaPrivateKey'];
$aop->apiVersion = '1.0';
$aop->signType = 'RSA2';
$aop->postCharset= 'utf-8';
$aop->format='json';
$request = new \AlipayTradePagePayRequest ();
$request->setReturnUrl($aliConfig['returnPcUrl']);
$request->setNotifyUrl($aliConfig['notifyUrl']);
$request->setBizContent(
"{" .
" \"product_code\":\"FAST_INSTANT_TRADE_PAY\"," .
" \"subject\":\"$proName\"," .
" \"out_trade_no\":\"$out_trade_no\"," .
" \"total_amount\":$order_amount," .
" \"body\":\"Iphone6 16G\"" .
" }");
//請求
$result = $aop->pageExecute ($request);
//輸出
echo $result;
}