1. 程式人生 > >農行支付介面的PHP實現

農行支付介面的PHP實現

農行的支付閘道器提供了PHP的開發說明和相關的程式包。它是利用webservice實現php和java的TrustPayClient提供服務的互動。由於webservice需要執行在tomcat,無法跟php常見的lamp執行環境合用,增加的系統的複雜度,無論從開發還是維護上看都是不好的。還好農行的java包是做到非常棒的,所有關鍵點都做log4j做了記錄,我們可以根據它的log檔案得到它提交和返回的資料報文。我們從log中可以看到農行是採用SHA1withRSA的演算法對資料進行簽名和驗籤。用SHA1withRSA演算法在php中我們可以用openssl擴充套件的openssl_sign()和openssl_verify()實現。下面詳細說明如何用openssl簡化農行介面的開發工作。
提交

發起交易的資料格式是這樣的

1
<MSG><Message><Merchant><ECMerchantType>B2C</ECMerchantType><MerchantID>233010300330A01</MerchantID></Merchant><TrxRequest><TrxType>PayReq</TrxType><Order><OrderNo>ON200306300001</OrderNo><OrderAmount>280.0</OrderAmount>
<OrderDesc>
Game Card Order</OrderDesc><OrderDate>2003/11/12</OrderDate><OrderTime>23:55:30</OrderTime><OrderURL>http://127.0.0.1/Merchant/MerchantQueryOrder.jsp?ON=ON200306300001&QueryType=1</OrderURL><OrderItems><OrderItem><ProductID>IP000001</ProductID><ProductName>中國移動IP卡</ProductName><UnitPrice>100.0</UnitPrice><Qty>1</Qty></OrderItem><OrderItem><ProductID>IP000002</ProductID><ProductName>網通IP卡</ProductName><UnitPrice>90.0</UnitPrice><Qty>2</Qty></OrderItem></OrderItems></Order><ProductType>1</ProductType><PaymentType>1</PaymentType><NotifyType>0</NotifyType><ResultNotifyURL>http://127.0.0.1/Merchant/MerchantResult.jsp</ResultNotifyURL><MerchantRemarks>Hi!</MerchantRemarks><PaymentLinkType>1</PaymentLinkType></TrxRequest></Message><Signature-Algorithm>SHA1withRSA</Signature-Algorithm><Signature>nfJAveUtLG1YHqsjUdopB8Jl9QX4ZtlQrUn+HoiCy0yS9An19z5IxTIVYOuQXjNnbMGgmZlCwK3dSSnRTLHxZMC3zJUiE58qEwxatOgHNFUhAHTBxkUMO5ikC7C5qm/9L67/Xp7kYvHK9Fo/8CyXckROb+w+eLYcPaYo6+Of2Dg=</Signature></MSG>

資料有以下幾部分構成

1
<MSG><Message>訂單資訊</Message><Signature-Algorithm>SHA1withRSA</Signature-Algorithm><Signature>訂單資訊的簽名</Signature></MSG>

訂單資訊的構造參考:

1
<Merchant><ECMerchantType>B2C</ECMerchantType><MerchantID>233010300330A01</MerchantID></Merchant><TrxRequest><TrxType>PayReq</TrxType><Order><OrderNo>ON200306300001</OrderNo><OrderAmount>280.0</OrderAmount><OrderDesc>Game Card Order</OrderDesc><OrderDate>2003/11/12</OrderDate><OrderTime>23:55:30</OrderTime><OrderURL>http://127.0.0.1/Merchant/MerchantQueryOrder.jsp?ON=ON200306300001&QueryType=1</OrderURL><OrderItems><OrderItem><ProductID>IP000001</ProductID><ProductName>中國移動IP卡</ProductName><UnitPrice>100.0</UnitPrice><Qty>1</Qty></OrderItem><OrderItem><ProductID>IP000002</ProductID><ProductName>網通IP卡</ProductName><UnitPrice>90.0</UnitPrice><Qty>2</Qty></OrderItem></OrderItems></Order><ProductType>1</ProductType><PaymentType>1</PaymentType><NotifyType>0</NotifyType><ResultNotifyURL>http://127.0.0.1/Merchant/MerchantResult.jsp</ResultNotifyURL><MerchantRemarks>Hi!</MerchantRemarks><PaymentLinkType>1</PaymentLinkType></TrxRequest>

整體上由Merchant商戶資訊段和TrxRequest請求資訊段,兩部分構成。

Signature是採用SHA1withRSA對訂單資訊進行簽名在base64 encode後得到,在php中可以用openssl實現。參考程式碼如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?php
 
$cert_file = "D:/user.pem";
$password = '666666';
 
$signature = null;
$toSign = "<Merchant><ECMerchantType>B2C</ECMerchantType><MerchantID>233010300330A01</MerchantID></Merchant><TrxRequest><TrxType>PayReq</TrxType><Order><OrderNo>ON200306300001</OrderNo><OrderAmount>280.0</OrderAmount><OrderDesc>Game Card Order</OrderDesc><OrderDate>2003/11/12</OrderDate><OrderTime>23:55:30</OrderTime><OrderURL>http://127.0.0.1/Merchant/MerchantQueryOrder.jsp?ON=ON200306300001&QueryType=1</OrderURL><OrderItems><OrderItem><ProductID>IP000001</ProductID><ProductName>中國移動IP卡</ProductName><UnitPrice>100.0</UnitPrice><Qty>1</Qty></OrderItem><OrderItem><ProductID>IP000002</ProductID><ProductName>網通IP卡</ProductName><UnitPrice>90.0</UnitPrice><Qty>2</Qty></OrderItem></OrderItems></Order><ProductType>1</ProductType><PaymentType>1</PaymentType><NotifyType>0</NotifyType><ResultNotifyURL>http://127.0.0.1/Merchant/MerchantResult.jsp</ResultNotifyURL><MerchantRemarks>Hi!</MerchantRemarks><PaymentLinkType>1</PaymentLinkType></TrxRequest>";
 
// $toSign簽名後的資料應該是nfJAveUtLG1YHqsjUdopB8Jl9QX4ZtlQrUn+HoiCy0yS9An19z5IxTIVYOuQXjNnbMGgmZlCwK3dSSnRTLHxZMC3zJUiE58qEwxatOgHNFUhAHTBxkUMO5ikC7C5qm/9L67/Xp7kYvHK9Fo/8CyXckROb+w+eLYcPaYo6+Of2Dg=
 
$fp = fopen($cert_file, "rb");
$priv_key = fread($fp, 8192);
fclose($fp);
//獲取pem檔案中的私鑰
$pkeyid = openssl_get_privatekey($priv_key,$password);
//使用使用者私鑰對訊息進行簽名
openssl_sign($toSign, $signature, $pkeyid);
// Free the key.
openssl_free_key($pkeyid);
 
$b64 = base64_encode( $signature );
echo $b64;
 
?>

程式碼中用到的user.pem由農行網銀後臺下載的pfx或則p12檔案轉換而已,pfx轉pem檔案的方法是:

1
openssl pkcs12 -nocerts -nodes -in cert.p12 -out user.pem

返回

返回的資料是POST回來的key為msg,內容是用base64編碼過的:

1
PE1TRz48TWVzc2FnZT48VHJ4UmVzcG9uc2U+PFJldHVybkNvZGU+MDAwMDwvUmV0dXJuQ29kZT48RXJyb3JNZXNzYWdlPjwvRXJyb3JNZXNzYWdlPjxFQ01lcmNoYW50VHlwZT5CMkM8L0VDTWVyY2hhbnRUeXBlPjxNZXJjaGFudElEPjIzMzAxMDMwMDMzMEEwMTwvTWVyY2hhbnRJRD48VHJ4VHlwZT5QYXlSZXN1bHQ8L1RyeFR5cGU+PE9yZGVyTm8+MTI5ODk1ODQyNTMxODU8L09yZGVyTm8+PEFtb3VudD4wLjAzPC9BbW91bnQ+PEJhdGNoTm8+MDAwMDAxPC9CYXRjaE5vPjxWb3VjaGVyTm8+MDAwMDEyPC9Wb3VjaGVyTm8+PEhvc3REYXRlPjIwMTEvMDMvMDE8L0hvc3REYXRlPjxIb3N0VGltZT4xMzozNjozMDwvSG9zdFRpbWU+PE1lcmNoYW50UmVtYXJrcz5IaSE8L01lcmNoYW50UmVtYXJrcz48UGF5VHlwZT5QQVkwMTwvUGF5VHlwZT48Tm90aWZ5VHlwZT4wPC9Ob3RpZnlUeXBlPjxQYXlJUD42MC4xOTAuNzMuMTIyPC9QYXlJUD48UGF5UmVmZXJlcj5sdXNlbi52aXAuaXNob3BleC5jbjwvUGF5UmVmZXJlcj48aVJzcFJlZj4zNjAzMDExMzkxNTM8L2lSc3BSZWY+PC9UcnhSZXNwb25zZT48L01lc3NhZ2U+PFNpZ25hdHVyZS1BbGdvcml0aG0+U0hBMXdpdGhSU0E8L1NpZ25hdHVyZS1BbGdvcml0aG0+PFNpZ25hdHVyZT5MM0VlQW1yMTdPYTloaHVxU0E5NEFXSEVhVjN5RnFOTHZZQ29qem0xVm5PMWtMSnVhVkZTekdyV0Y3NjhPMUtMelBaY1M1MVFMRko1dUFMUlFtUVM1Ylp3Tm5kZ1FHeUxPZGRaMUpjRGdjazh3RE9UYkJPSTJFQWRhdElGL0czR1QrRENoRkVyVlZMR01oa1VGRTRpVTVrM3YvdXMwM3pZQ1UxbUR4SzFtbGM9PC9TaWduYXR1cmU+PC9NU0c+

base64解碼後是這樣:

1
2
3
4
5
6
7
8
9
10
11
<MSG><Message><TrxResponse><ReturnCode>0000</ReturnCode><ErrorMessage></ErrorMes
sage><ECMerchantType>B2C</ECMerchantType><MerchantID>233010300330A01</MerchantID
><TrxType>PayResult</TrxType><OrderNo>12989584253185</OrderNo><Amount>0.03</Amou
nt><BatchNo>000001</BatchNo><VoucherNo>000012</VoucherNo><HostDate>2011/03/01</H
ostDate><HostTime>13:36:30</HostTime><MerchantRemarks>Hi!</MerchantRemarks><PayT
ype>PAY01</PayType><NotifyType>0</NotifyType><PayIP>60.190.73.122</PayIP><PayRef
erer>lusen.vip.ishopex.cn</PayReferer><iRspRef>360301139153</iRspRef></TrxRespon
se></Message><Signature-Algorithm>SHA1withRSA</Signature-Algorithm><Signature>L3
EeAmr17Oa9hhuqSA94AWHEaV3yFqNLvYCojzm1VnO1kLJuaVFSzGrWF768O1KLzPZcS51QLFJ5uALRQm
QS5bZwNndgQGyLOddZ1JcDgck8wDOTbBOI2EAdatIF/G3GT+DChFErVVLGMhkUFE4iU5k3v/us03zYCU
1mDxK1mlc=</Signature></MSG>

我們需要對Message段的資料進行和Signature段的資料進行驗籤。同提交請求時一樣,php有openssl_verify這個函式可以對農行提交過來的資料進行驗證。測試用例見下文:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<?php
 
$ret = array (
  'MSG' => 'PE1TRz48TWVzc2FnZT48VHJ4UmVzcG9uc2U+PFJldHVybkNvZGU+MDAwMDwvUmV0dXJuQ29kZT48RXJyb3JNZXNzYWdlPjwvRXJyb3JNZXNzYWdlPjxFQ01lcmNoYW50VHlwZT5CMkM8L0VDTWVyY2hhbnRUeXBlPjxNZXJjaGFudElEPjIzMzAxMDMwMDMzMEEwMTwvTWVyY2hhbnRJRD48VHJ4VHlwZT5QYXlSZXN1bHQ8L1RyeFR5cGU+PE9yZGVyTm8+MTI5ODk1ODQyNTMxODU8L09yZGVyTm8+PEFtb3VudD4wLjAzPC9BbW91bnQ+PEJhdGNoTm8+MDAwMDAxPC9CYXRjaE5vPjxWb3VjaGVyTm8+MDAwMDEyPC9Wb3VjaGVyTm8+PEhvc3REYXRlPjIwMTEvMDMvMDE8L0hvc3REYXRlPjxIb3N0VGltZT4xMzozNjozMDwvSG9zdFRpbWU+PE1lcmNoYW50UmVtYXJrcz5IaSE8L01lcmNoYW50UmVtYXJrcz48UGF5VHlwZT5QQVkwMTwvUGF5VHlwZT48Tm90aWZ5VHlwZT4wPC9Ob3RpZnlUeXBlPjxQYXlJUD42MC4xOTAuNzMuMTIyPC9QYXlJUD48UGF5UmVmZXJlcj5sdXNlbi52aXAuaXNob3BleC5jbjwvUGF5UmVmZXJlcj48aVJzcFJlZj4zNjAzMDExMzkxNTM8L2lSc3BSZWY+PC9UcnhSZXNwb25zZT48L01lc3NhZ2U+PFNpZ25hdHVyZS1BbGdvcml0aG0+U0hBMXdpdGhSU0E8L1NpZ25hdHVyZS1BbGdvcml0aG0+PFNpZ25hdHVyZT5MM0VlQW1yMTdPYTloaHVxU0E5NEFXSEVhVjN5RnFOTHZZQ29qem0xVm5PMWtMSnVhVkZTekdyV0Y3NjhPMUtMelBaY1M1MVFMRko1dUFMUlFtUVM1Ylp3Tm5kZ1FHeUxPZGRaMUpjRGdjazh3RE9UYkJPSTJFQWRhdElGL0czR1QrRENoRkVyVlZMR01oa1VGRTRpVTVrM3YvdXMwM3pZQ1UxbUR4SzFtbGM9PC9TaWduYXR1cmU+PC9NU0c+',
);
 
$msg = base64_decode($ret['MSG']);
 
preg_match("/\<Message\>(.*)\<\/Message\>.*\<Signature\>(.*)\<\/Signature\>/i",$msg,$match);
$contents = $match[1];
$signature = $match[2];
 
$pub_cert_file = "TrustPay.pem";
verify($contents,$signature,$pub_cert_file );          
 
function verify($data,$signature,$cert_file){
    $fp = fopen($cert_file, "r");
    $cert = fread($fp, 8192);
    fclose($fp);
    $pubkeyid = openssl_get_publickey($cert);
    $signature = base64_decode($signature);
    // state whether signature is okay or not
    $ok = openssl_verify($data, $signature, $pubkeyid);
    openssl_free_key($pubkeyid);
    return $ok;
}
 
?>

程式碼中TrustPay.pem可以這麼生成

1
openssl x509 -inform DER -in TrustPay.cer  -out TrustPay.pem

-EOF-

相關推薦

業務程式碼:基於spring的銀行支付介面模型實現

1.業務邏輯     當用戶選擇某一特定商品後,點選支付按鈕;跳轉到對應的支付頁面,在使用者選擇對應的支付銀行方式後,在頁面實現對應的優惠資訊。同時點選支付後,根據銀行對應的報文要求,進行支付。 2.邏輯分析   3.技術點: 工廠模式,反

支付寶APP支付介面-PHP

       最近做了一個基於微信,alipay的支付功能,主要包括alipay的wap(喚醒支付寶APP),pc,APP支付,前兩者基於MD5簽名,後者基於RSA簽名; 微信的內部瀏覽器支付,APP支付,至於wap,需要申請,達到一定的條件才能審批通過,目前只有京東,1號

農行支付介面的PHP實現

農行的支付閘道器提供了PHP的開發說明和相關的程式包。它是利用webservice實現php和java的TrustPayClient提供服務的互動。由於webservice需要執行在tomcat,無法跟php常見的lamp執行環境合用,增加的系統的複雜度,無論從開發還是維

PHP實現RSA簽名生成訂單功能【支付寶示例】

score www. 密鑰 base var var_dump 完成 ada 轉義 //組合簽名 $a=time(); $b=substr($a, 1); //生成隨機訂單號 $orderid= $b.mt_rand(10000,99999); //合作身份者id,以20

php實現支付寶授權登錄

gin mem pau info redirect direct ember csrf攻擊 登錄 第一步: 登錄到螞蟻金服開放平臺 https://open.alipay.com/platform/home.htm,前提是有商戶號。創建應用之後,然後到開發者中心開通對應功

PHP實現 APP端微信支付功能

1.我封裝好的一個支付類檔案,多餘的東西都去除掉了,並且把配置引數放到了這個支付類中,只需要修改Weixinpayandroid方法內的幾個引數就可以直接複製使用: class Wxpayandroid { //引數配置 public $config = array( 'appid' =&

php微信支付介面開發,獲取php微信掃碼支付返回結果,php開發微信支付demo原始碼

現在很多網站都是用php開發的, 一些觀看了子恆老師微信公眾號運營視訊後, 想要更加深入的學習, 留言說“php怎麼做微信支付介面開發呢?” “有沒有php微信支付介面開發的demo例項” 下面來詳細談談… 一、 php微信支付介面開發要做的準備 只有你先準備配置好, 然後才能正確

php實現base64圖片上傳方式例項程式碼 前端介面問題

php實現base64圖片上傳方式例項程式碼 html程式碼 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transit

php 實現app微信支付

class Wxpay { /* 配置引數 */ private $config = array( 'appid' => "wxc888888888", /*微信開放平臺上的應用id*/ 'mch_id' => "88

php 支付支付介面

我用的官方sdk    https://docs.open.alipay.com/270/106291/直接aop資料夾放到PHP環境 配置 AopClient.php這個檔案  祕鑰和公鑰搞了一會 這個一定要配置正確    //應用ID&

PHP學習——28 PHP面向物件(抽象類與抽象方法、介面實現)

一、抽象類與抽象方法 <?php // 任何一個類,如果它裡面至少有一個方法是被宣告為抽象的,那麼這個類就必須被宣告為抽象的。 abstract class Person // 定義為抽象的類不能被例項化。 { public $name; public function __co

App介面設計之token的php實現

  App介面設計之token的php實現 為了保證移動端和服務端資料傳輸相對安全,需要對介面進行加密傳輸。 一、token的設計目的:  因為APP端沒有和PC端一樣的session機制,所以無法判斷使用者是否登陸,以及無法保持使用者狀態,所以就需要一種機制

PHP開發支付寶微信個人免籤支付介面例項

這是一個PHP開發支付寶微信個人免籤支付介面例項,支付寶微信即時到帳介面,使用原生支付寶即時到帳介面修改而來,即可實現多介面收款功能,開發只需要按照支付寶即時到帳介面開發即可,減少開發難度   需要修改的檔案: notify_url.php return_url.php 同步和非同

PHP實現微信支付(微信小程式版)

先解答上一篇部落格中form_id的獲取方法: js程式碼 Page({ formSubmit: function (e) { console.log("formid:"+e.detail.formId) }, }) wxml程式碼 <

PHP呼叫支付支付介面操作步驟

1.首先掃碼登入支付寶個人主頁點選開發平臺 2.點選開發接入,找到開發服務點選沙箱 3.進入沙箱環境 4.應用中選擇電腦網站支付,然後選擇demo下載 5.下載完畢解壓後將檔案複製到WWW目錄下,新建站點,進行訪問 6.回到沙箱應用,開始配置檔案

PHP實現微信支付(jsapi支付)和退款(無需整合支付SDK

1.PHP實現微信支付(jsapi支付)流程 2.ThinkPHP中實現微信支付(jsapi支付)流程 3.PHP實現微信申請退款 這幾篇都是使用了微信官方給的PHP版本的SDK,進行支付的時候寫程式碼可以省不少事,步驟也挺簡化,但是整合SDK有很多坑,很多人說

django2.0呼叫微信支付介面實現PC端掃碼支付

準備工作: 程式碼實現: 目錄結構 class WeChartPay(object): def __init__( self, appid, mch_id,

PHP支付寶APP支付介面

1-1:首先下載支付寶官方SDK,我的是PHP版的,起名“alipay” 1-2:配置檔案 config.php // 支付寶 'ALIPAY_CONFIG' =>[ 'app_id' =>'12345678', /

php實現base64圖片上傳方式例項程式碼 前端介面問題

php實現base64圖片上傳方式例項程式碼 html程式碼 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/x

PHP實現支付寶小程式使用者授權的工具類

背景 最近專案需要上線支付寶小程式,同時需要走使用者的授權流程完成使用者資訊的儲存,以前做過微信小程式的開發,本以為實現授權的過程是很簡單的事情,但是再實現的過程中還是遇到了不少的坑,因此記錄一下實現的過程 學到的知識 支付寶開放介面的呼叫模式以及實現方式 支付寶小程式授權的流程 RSA加密方式 吐