php支付寶rsa加密-九游会j9娱乐平台
1. php開發中app怎麼接入支付寶
准備工作
app支付介面:alipay.trade.app.pay
伺服器端使用框架:tp5
登錄螞蟻金服開放平台 --> 創建應用 --> 添加app支付功能。具體查看官方文檔
下載官方 sdk (php版本資源)——當前sdk版本:106 生成時間:2017-07-25 11:46:10
將sdk原碼放置在tp5的vendor目錄下的alipay文件夾(可根據實際使用框架技術進行實際調整)。
支付介面調用原理
1、app支付系統架構
app支付系統架構圖
2、數據校驗原理
數據校驗原理
應用公鑰(商戶自身的rsa公鑰):支付寶使用該公鑰驗證該交易是商戶發起。
支付寶公鑰(支付寶的rsa公鑰):商戶使用該公鑰驗證該結果是支付寶返回的。
3、系統交互流程
系統交互流程圖
4、支付場景具體實現流程(最詳細圖解)
在集成app支付能力時,建議實現如下支付流程,創建訂單並支付,根據返回的結果確定支付狀態,並進行相應的異常處理,其過程如下圖所示.
支付場景具體實現流程
商家app在創建訂單並且喚起支付寶app支付,流程如上圖所示,根據第2.2,3步返回的支付結果,確定支付狀態,並且做相應的異常處理(必要時關閉訂單)
代碼實現
步驟1:商戶app端請求商戶伺服器介面,提交訂單數據。
步驟2:商戶伺服器端接收數據,然後對數據進行簽名,返回請求參數到商戶app端。
官方介面文檔:https://docs.open.alipay.com/204/105465/
——代碼如下:
//vendor();為tp5框架的方法,作用:導入第三方框架類庫
vendor('alipay.aop.aopclient');
vendor('alipay.aop.request.alipaytradeapppayrequest');
//實例化支付介面
$aop = new \aopclient();
$aop->gatewayurl = "https://openapi.alipay.com/gateway.do"; //支付寶網關
$aop->appid = 「應用id,填寫你的appid」;
$aop->rsaprivatekey = "商戶私鑰,您的原始格式rsa私鑰()";
$aop->alipayrsapublickey = "支付寶公鑰";
$aop->apiversion = '1.0';
$aop->signtype = "簽名方式,如 rsa2 ";
$aop->postcharset = 'utf-8';
$aop->format = "json";
//實例化具體api對應的request類,類名稱和介面名稱對應,當前調用介面名稱:alipay.trade.app.pay
$apprequest = new \alipaytradeapppayrequest();
//sdk已經封裝掉了公共參數,這里只需要傳入業務參數
$bizcontent = json_encode([
'body' => '余額充值', //訂單描述
'subject' => '充值', //訂單標題
'timeout_express' => '30m',
'out_trade_no' => 『20170125test01』, //商戶網站唯一訂單號
'total_amount' => '0.01', //訂單總金額
'proct_code' => 'quick_msecurity_pay', //固定值
]);
$apprequest->setnotify; //設置非同步通知地址
$apprequest->setbizcontent($bizcontent);
//這里和普通的介面調用不同,使用的是sdkexecute
$response = $aop->sdkexecute($apprequest);
//htmlspecialchars是為了輸出到頁面時防止被瀏覽器將關鍵參數html轉義,實際列印到日誌以及http傳輸不會有這個問題
echo htmlspecialchars($response);//就是orderstring 可以直接給客戶端請求,無需再做處理。
// 如果最後有問題可以嘗試把htmlspecialchars方法去掉,直接返回$response
說明:sdkexecute()方法,作用生成簽名,詳細步驟如下:
將請求參數組裝分下列3步,以最後第三步獲取到的請求為准。
1)將請求參數的鍵按字典排序,然後按照key=value&key=value方式拼接,得到未簽名原始字元串如下:
app_id=2015052600090779&biz_content={"timeout_express":"30m","proct_code":"quick_msecurity_pay","total_amount":"0.01","subject":"1","body":"我是測試數據","out_trade_no":"iqjzsrc1ymqb5hu"}&charset=utf-8&format=json&method=alipay.trade.app.pay¬ify_url=http://domain.merchant.com/payment_notify&sign_type=rsa2×tamp=2016-08-25 20:26:31&version=1.0
2)再對原始字元串進行簽名
app_id=2015052600090779&biz_content={"timeout_express":"30m","proct_code":"quick_msecurity_pay","total_amount":"0.01","subject":"1","body":"我是測試數據","out_trade_no":"iqjzsrc1ymqb5hu"}&charset=utf-8&format=json&method=alipay.trade.app.pay¬ify_url=http://domain.merchant.com/payment_notify&sign_type=rsa2×tamp=2016-08-25 20:26:31&version=1.0&sign= /=
3)最後對請求字元串的所有一級value(biz_content作為一個value)進行encode,編碼格式按請求串中的charset為准,沒傳charset按utf-8處理,獲得最終的請求字元串:
app_id=2015052600090779&biz_content={"timeout_express":"30m","proct_code":"quick_msecurity_pay","total_amount":"0.01","subject":"1","body":"我是测试数据","out_trade_no":"iqjzsrc1ymqb5hu"}&charset=utf-8&format=json&method=alipay.trade.app.pay¬ify_url=http://domain.merchant.com/payment_notify&sign_type=rsa2×tamp=2016-08-25 20:26:31&version=1.0&sign=+/=
步驟3:商戶app接收從商戶伺服器端返回的請求參數,然後調起支付寶支付面板。
若用戶支付成功,支付寶會同步給商戶app端返回一個支付結果。相應地,支付寶也會通過非同步通知給商戶伺服器端返回一個支付結果。
注意:由於同步通知和非同步通知都可以作為支付完成的憑證,且非同步通知支付寶一定會確保發送給商戶服務端。為了簡化集成流程,商戶可以將同步結果僅僅作為一個支付結束的通知(忽略執行校驗),實際支付是否成功,完全依賴服務端非同步通知。
步驟4:服務端非同步通知處理機制(支付寶主動發起通知,該方式才會被啟用)
官方介面文檔:https://docs.open.alipay.com/204/105301/
注意點:
1)必須保證伺服器非同步通知頁面(notify_url)上無任何字元,如空格、html標簽、開發系統自帶拋出的異常提示信息等;
2)支付寶是用post方式發送通知信息,因此該頁面中獲取參數的方式,如:$_post[『out_trade_no』];
3)程序執行完後必須列印輸出「success」(不包含引號)。如果商戶反饋給支付寶的字元不是success這7個字元,支付寶伺服器會不斷重發通知,直到超過24小時22分鍾。一般情況下,25小時以內完成8次通知(通知的間隔頻率一般是:4m,10m,10m,1h,2h,6h,15h);
4)當商戶收到伺服器非同步通知並列印出success時,伺服器非同步通知參數notify_id才會失效。
——代碼如下:
$aop = new aopclient;
$aop->alipayrsapublickey = '請填寫支付寶公鑰,一行字元串';
$flag = $aop->rsacheckv1($_post, null, "rsa2"); //驗證簽名
if($flag){
//校驗通知數據的正確性
$out_trade_no = $_post[『out_trade_no']; //商戶訂單號
$trade_no = $_post[『trade_no']; //支付寶交易號
$trade_status = $_post[『trade_status']; //交易狀態trade_status
$total_amount = $_post[『'total_amount']; //訂單的實際金額
$app_id = $_post[『app_id'];
if($app_id!=$this->config['app_id']) exit('fail'); //驗證app_id是否為該商戶本身
//只有交易通知狀態為trade_success或trade_finished時,支付寶才會認定為買家付款成功。
if($trade_status != 'trade_finished' && $trade_status != 'trade_success')
exit('fail');
//校驗訂單的正確性
if(!empty($out_trade_no)){
//1、商戶需要驗證該通知數據中的out_trade_no是否為商戶系統中創建的訂單號;
//2、判斷total_amount是否確實為該訂單的實際金額(即商戶訂單創建時的金額);
//3、校驗通知中的seller_id(或者seller_email) 是否為out_trade_no這筆單據的對應的操作方(有的時候,一個商戶可能有多個seller_id/seller_email)。
//上述1、2、3有任何一個驗證不通過,則表明本次通知是異常通知,務必忽略。在上述驗證通過後商戶必須根據支付寶不同類型的業務通知,正確的進行不同的業務處理,並且過濾重復的通知結果數據。
//校驗成功後在response中返回success,校驗失敗返回failure
}
exit('fail');
}
echo"fail"; //驗證簽名失敗
步驟5:當商戶app端接收到支付寶的同步返回結果為成功時,商戶app端再請求商戶伺服器端api,判斷訂單最終支付結果,並做出最終響應。
2. php 支付寶介面的md5簽名版本和rsa簽名版本的區別
md5 是基礎版,提示支付,查詢
rsa 為高級版,需要下載證書。提供退款功能
3. 支付寶加密技術是來自外國嗎
支付寶加密技術源自外國
一,支付寶採用md5加密技術
二,此技術為ronald l. rivestg開發產品
三,支付寶只是購買相關軟體服務技術及平台維護團隊
支付寶安全使用方法請咨詢淘寶或新浪微博三位粉 建議親們慎重使用
4. php 支付寶介面官方給的md5簽名版本和rsa簽名版本的區別
雖然支付寶官方還未提供相關sdk,php確實可以實現rsa方式的簽名,這點其實很重要,由於不熟悉,在遇到困難的時候,經常會不由自主地想到是否php不支持rsa簽名,乾脆用md5得了,這樣就沒有了前進的動力。其實說穿了md5和rsa簽名,不同的只是簽名方式的區別,其他的都一樣,因此我這里主要說一下如何用rsa進行簽名和驗簽。
首先你需要准備下面的東西:
php的openssl擴展里已經封裝好了驗簽的方法openssl_verify。
如果在windows下的php.ini需要開啟openssl模塊: extension=php_openssl.dll
商戶私鑰:
即rsa私鑰,按照手冊,按以下方式生成:
openssl genrsa -out rsa_private_key.pem 1024
商戶公鑰:
即rsa私鑰,按照手冊,按以下方式生成:
openssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem
生成之後,按照手冊的說明,需要在簽約平台上傳公鑰,需要注意的是,上傳的時候需要把所有的注釋和換行都去掉。
另外手冊中還有如下命令:
openssl pkcs8 -topk8 -inform pem -in rsa_private_key.pem -outform pem -nocrypt
該命令將rsa私鑰轉換成pkcs8格式,對於php來說,不需要。
支付寶公鑰:
根據手冊,在簽約平台獲得。
如果你直接復制下來的話,會得到一個字元串,需要進行下面的轉換;
1)把空格變成換行
2)添加註釋
比如你復制下來的公鑰是:
ztpfg0d3tu7jlqcacgql lbshiaitdgexamzmka3dv6wxy l48ymo0rys dwze4m
umuxhu/v6tit0ztxjn3ewrjctcyyttdv/rob3ckhexntkb76retkqqg57oww m9j
tcoccymdxeiwyts3cwidaqab,那轉換之後為:
-----begin public key-----
ztpfg0d3tu7jlqcacgql lbshiaitdgexamzmka3dv6wxy l48ymo0rys dwze4m
umuxhu/v6tit0ztxjn3ewrjctcyyttdv/rob3ckhexntkb76retkqqg57oww m9j
tcoccymdxeiwyts3cwidaqab
-----end public key-----
把公鑰保存在文件里。
注意這個是2048位的公鑰應該是9行或者10行,不能為1行,不然php的openssl_pkey_get_public無法讀取,pub_key_id的結果為false,如果沒有-----begin public key----- 和 -----end public key----- 可以自己加上,最後保存到一個rsa_public_key.pem文件中。
好了,現在已經有了所有的東西,先看簽名函數:
復制代碼
1 2 /**
3 * 簽名字元串
4 * @param $prestr 需要簽名的字元串
5 * return 簽名結果
6 */
7 function rsasign($prestr) {
8 $public_key= file_get_contents('rsa_private_key.pem');
9 $pkeyid = openssl_get_privatekey($public_key);
10 openssl_sign($prestr, $sign, $pkeyid);
11 openssl_free_key($pkeyid);
12 $sign = base64_encode($sign);
13 return $sign;
14 }
15 ?>
復制代碼
注意點:
1.$prestr的內容和md5一樣(參見手冊,但不包含最後的md5密碼)
2.簽名用商戶私鑰
3.最後的簽名,需要用base64編碼
4.這個函數返回的值,就是這次請求的rsa簽名。
驗簽函數:
復制代碼
1 2 /**
3 * 驗證簽名
4 * @param $prestr 需要簽名的字元串
5 * @param $sign 簽名結果
6 * return 簽名結果
7 */
8 function rsaverify($prestr, $sign) {
9 $sign = base64_decode($sign);
10 $public_key= file_get_contents('rsa_public_key.pem');
11 $pkeyid = openssl_get_publickey($public_key);
12 if ($pkeyid) {
13 $verify = openssl_verify($prestr, $sign, $pkeyid);
14 openssl_free_key($pkeyid);
15 }
16 if($verify == 1){
17 return true;
18 }else{
19 return false;
20 }
21 }
22 ?>
復制代碼
注意點:
1.$prestr的內容和md5一樣(參見手冊)
2.$sign是支付寶介面返回的sign參數用base64_decode解碼之後的二進制
3.驗簽用支付寶公鑰
4.這個函數返回一個布爾值,直接告訴你,驗簽是否通過
支付寶官方提供的php版sdk demo中只對md5加密方式進行了處理,但android 端和ios端 請求支付寶加密方式只能用rsa加密演算法,這時服務端php就無法驗證簽名了,所以需要對demo進行一些修改。
1、修改alipay_notify.class.php文件
verifynotify 函數第46行
$issign = $this->getsignveryfy($_post, $_post["sign"]);
改成
$issign = $this->getsignveryfy($_post, $_post["sign"], $_post["sign_type"]);
verifyreturn 函數第83行
$issign = $this->getsignveryfy($_get, $_get["sign"]);
改成
$issign = $this->getsignveryfy($_get, $_get["sign"], $_get["sign_type"]);
getsignveryfy 函數 116行
function getsignveryfy($para_temp, $sign) {
改成
function getsignveryfy($para_temp, $sign, $sign_type) {
getsignveryfy 函數 127行
switch (strtoupper(trim($this->alipay_config['sign_type']))) {
case "md5" :
$issgin = md5verify($prestr, $sign, $this->alipay_config['key']);
break;
default :
$issgin = false;
}
改成
switch (strtoupper(trim($sign_type))) {
case "md5" :
$issgin = md5verify($prestr, $sign, $this->alipay_config['key']);
break;
case "rsa" :
$issgin = rsaverify($prestr, $sign);
break;
default :
$issgin = false;
}
2、新建一個alipay_rsa.function.php文件
復制代碼
1 2 /* *
3 * rsa
4 * 詳細:rsa加密
5 * 版本:3.3
6 * 日期:2014-02-20
7 * 說明:
8 * 以下代碼只是為了方便商戶測試而提供的樣例代碼,商戶可以根據自己網站的需要,按照技術文檔編寫,並非一定要使用該代碼。
9 * 該代碼僅供學習和研究支付寶介面使用,只是提供一個參考。
10 */
11 /**
12 * 簽名字元串
13 * @param $prestr 需要簽名的字元串
14 * return 簽名結果
15 */
16 function rsasign($prestr) {
17 $public_key= file_get_contents('rsa_private_key.pem');
18 $pkeyid = openssl_get_privatekey($public_key);
19 openssl_sign($prestr, $sign, $pkeyid);
20 openssl_free_key($pkeyid);
21 $sign = base64_encode($sign);
22 return $sign;
23 }
24 /**
25 * 驗證簽名
26 * @param $prestr 需要簽名的字元串
27 * @param $sign 簽名結果
28 * return 簽名結果
29 */
30 function rsaverify($prestr, $sign) {
31 $sign = base64_decode($sign);
32 $public_key= file_get_contents('rsa_public_key.pem');
33 $pkeyid = openssl_get_publickey($public_key);
34 if ($pkeyid) {
35 $verify = openssl_verify($prestr, $sign, $pkeyid);
36 openssl_free_key($pkeyid);
37 }
38 if($verify == 1){
39 return true;
40 }else{
41 return false;
42 }
43 }
44 ?>