摘要:標準是為了最大限度保護持卡人數據的一套標準。實現符合標準的支付,有兩種方式加載的托管表單使用的托管表單,加載方便,安全性高,但是用戶定制程度不高,只能稍微改改表單樣式,可以使用自己設計的表單,調用做安全性校驗和數據發送接收。
PCI 標準是為了最大限度保護持卡人數據的一套標準。要求很多,可以看 PCI標準 站點了解。對于程序猿來說,要保證的是用戶的任何支付信息,都不走自己的服務器,不保存在自己的數據庫。
實現符合PCI標準的支付,有兩種方式
加載Authorize.net的托管表單
使用AcceptJs
Authorize.net的托管表單,加載方便,安全性高,但是用戶定制程度不高,只能稍微改改表單樣式,AcceptJs可以使用自己設計的表單,調用AcceptJs做安全性校驗和數據發送接收。
一. 前期準備工作 1.1 注冊一個沙盒環境賬號 (必須)沙盒環境賬號,可以用來在api文檔頁面直接調試各種接口,也可以在沙盒里面查看各種扣款記錄。
如果項目要上線,請注冊生產環境賬號,這里全部使用沙盒環境。
1.2 下載Authorize.net SDK (非必須)下載SDK到項目。
cd /your_php_project_path composer require authorizenet/authorizenet
再在項目中引入即可(如何引入可以看上面地址的介紹,這里不再重復)。
該項目的GITHUB地址:AuthorizeNet/sdk-php 可以在上面搜索、提出你的issues
使用SDK的php案列:AuthorizeNet/sample-code-php
Authorizenet官方實現的一個符合PCI標準的案列AuthorizeNet/accept-sample-app (這個沒有使用SDK)
1.3 不使用Authorize.net SDK (非必須)因為Authorize.net SDK 要求 php: >=5.5 , 所以只能自己封裝api請求了,具體如何封裝個人自便,但要說明的一點是,Authorize.net 的api,如果選擇的是json格式:
header("Content-type:text/json;charset=utf-8"); $curl = curl_init(); curl_setopt($curl, CURLOPT_URL, $this->authorizeUrl); curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); curl_setopt($curl, CURLOPT_COOKIESESSION, true); curl_setopt($curl, CURLOPT_HEADER, 0); curl_setopt($curl, CURLOPT_POST, 1); curl_setopt($curl, CURLOPT_POSTFIELDS, urldecode($data)); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0); curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2); // curl_setopt($curl, CURLOPT_HTTPHEADER, array("Content-Type: text/plain")); //xml request curl_setopt($curl, CURLOPT_HTTPHEADER, array("Accept: application/json")); $result = curl_exec($curl); $curlErrno = curl_errno($curl); $curlError = curl_error($curl); curl_close($curl);
返回的數據也是JSON格式,but。。。。,這個返回的json數據,是無法用
json_decode($result,true)
來解析的,需要
json_decode(substr($result, 3), true);
來解析。究其原因,應該是它返回的數據帶了BOM頭,詳細請移步 json-decode-returns-null
XML格式我沒有去寫代碼測試,各位有興趣可以自行測試,也可以在沙盒環境直接測試。
有個直接扣款的API,其中的ORDER參數要有順序,要有順序,要有順序,如果遇到一些API,調試一直報錯,但又沒有特別的原因,請注意看是否是順序問題。
1.4 各種環境地址內容 | 測試環境 | 生產環境 |
---|---|---|
api請求地址 | apitest url | api url |
Accept.js | Accept jstest url | Accept js url |
請求支付表單 | test payment/payment | accept payment/payment |
Manage Profiles | Manage Profiles | Manage Profiles |
Add Payment Profile | Add Payment Profile | Add Payment Profile |
Add Shipping Profile | Add Shipping Profile | Add Shipping Profile |
Edit Payment Profile | Edit Payment Profile | Edit Payment Profile |
Edit Shipping Profile | Edit Shipping Profile | Edit Shipping Profile |
需要請求的API : createCustomerProfileRequest
API的詳細文檔地址:createCustomerProfileRequest
CustomerProfile詳細介紹:customer_profiles
該API可以在創建CustomerProfileId 的同時,也創建PaymentProfileId 。但是PaymentProfileId需要的參數都是涉及到用戶敏感信息的,按照PCI標準,是不允許商戶收集,所以需要使用Authorize.net的托管表單來創建。
所以這一步只簡單的傳遞幾個參數即可,使用SDK創建代碼:
$customerProfile = new AnetAPICustomerProfileType(); $customerProfile->setDescription("Customer 2 Test PHP"); $customerProfile->setMerchantCustomerId("11211"); $customerProfile->setEmail($post["email"]); $request = new AnetAPICreateCustomerProfileRequest(); $request->setMerchantAuthentication($this->merchantAuthentication); $request->setProfile($customerProfile); $controller = new AnetControllerCreateCustomerProfileController($request); $response = $controller->executeWithApiResponse( etauthorizeapiconstantsANetEnvironment::SANDBOX);1.2 為添加PaymentInfo托管表單申請token
需要請求的API : getHostedProfilePageRequest
API的詳細文檔地址:getHostedProfilePageRequest
用上一步創建的CustomerProfileId $profileId = $response->getCustomerProfileId(); 來獲取token
$setting = new AnetAPISettingType(); $setting->setSettingName("hostedProfileIFrameCommunicatorUrl"); $url = Yii::$app->urlManager->createAbsoluteUrl(["authorizenet/special"]); $setting->setSettingValue($url); $request = new AnetAPIGetHostedProfilePageRequest(); $request->setMerchantAuthentication($this->merchantAuthentication); $request->setCustomerProfileId($profileId); $request->addToHostedProfileSettings($setting); $controller = new AnetControllerGetHostedProfilePageController($request); $response = $controller->executeWithApiResponse( etauthorizeapiconstantsANetEnvironment::SANDBOX);1.3 視圖頁面iframe使用token加載托管表單
此時該iframe里面還沒有任何東西,需要提交這個form表單才能加載托管表單,這里給一個函數讓他頁面加載的時候自動提交以加載托管表單。
var button = document.getElementById("submit"); button.click();1.4 捕獲響應并處理
我們回到 1.2 申請表單這里,這個API支持設置托管表單的很多屬性,比較有用的有 :
hostedProfileReturnUrl : 設置托管會話結束(用戶點擊SAVE)返回給用戶的頁面 (這里省略)
hostedProfileIFrameCommunicatorUrl : 用來接受、處理Authorize.net響應的頁面
上面設置的hostedProfileIFrameCommunicatorUrl的頁面為authorizenet/special
function callParentFunction(str) { var referrer = document.referrer; var s = {qstr : str , parent : referrer}; if(referrer == "https://test.authorize.net/customer/addPayment"){ switch(str){ case "action=successfulSave" : window.parent.parent.location.; break; } } } function receiveMessage(event) { if (event && event.data) { callParentFunction(event.data); } } if (window.addEventListener) { window.addEventListener("message", receiveMessage, false); } else if (window.attachEvent) { window.attachEvent("onmessage", receiveMessage); } if (window.location.hash && window.location.hash.length > 1) { callParentFunction(window.location.hash.substring(1)); }
這里設置成功保存paymentInfo 信息到Authorize.net之后就跳轉到 payment 頁面支付。
action有不同的狀態,可以根據action作相應的處理。
resizeWindow : 托管表單加載
successfulSave : 表單成功保存(CustomerProfile)
cancel : 用戶點擊取消按鈕
transactResponse :支付成功(payment)
需要請求的API : getCustomerProfileRequest
API的詳細文檔地址:getCustomerProfileRequest
$customer = $this->getCustomerProfile($profileId); $billTo = end($customer->getProfile()->getPaymentProfiles())->getBillTo();
因為一個CustomerProfi對應多個PaymentProfile ,這里獲取最后一個PaymentProfile。
1.2 為添加Payment托管表單申請token需要請求的API : getHostedPaymentPageRequest
API的詳細文檔地址:getHostedPaymentPageRequest
請求該URL,可以指定加載表單的樣式等各種參數,具體參考:Accept Hosted feature details page
$transactionRequestType = new AnetAPITransactionRequestType(); $transactionRequestType->setTransactionType("authCaptureTransaction"); $transactionRequestType->setAmount("12.23"); $customer = $this->getCustomerProfile(Yii::$app->session->get("profileId")); $billTo = end($customer->getProfile()->getPaymentProfiles())->getBillTo(); $transactionRequestType->setBillTo($billTo);//回填賬單地址 $customer = new AnetAPICustomerDataType(); $customer->setEmail(Yii::$app->session->get("email")); $customer->setId(Yii::$app->session->get("user_id")); $transactionRequestType->setCustomer($customer); $request = new AnetAPIGetHostedPaymentPageRequest(); $request->setMerchantAuthentication($this->merchantAuthentication); $request->setTransactionRequest($transactionRequestType); $setting3 = new AnetAPISettingType(); $setting3->setSettingName("hostedPaymentReturnOptions"); $setting3->setSettingValue("{"url": "https://www.basic.com/index.php?r=authorizenet/receipt", "cancelUrl": "https://www.basic.com/index.php?r=authorizenet/cancel", "showReceipt": false}"); $request->addToHostedPaymentSettings($setting3); //設置托管表單顯示email,且必填 (因為form表單沒有禁止修改email參數,所以可以設置email但不顯示在表單中,以防修改) $setting4 = new AnetAPISettingType(); $setting4->setSettingName("hostedPaymentCustomerOptions"); $setting4->setSettingValue("{"showEmail": true, "requiredEmail":true}"); $request->addToHostedPaymentSettings($setting4); $setting6 = new AnetAPISettingType(); $setting6->setSettingName("hostedPaymentIFrameCommunicatorUrl"); $url = Yii::$app->urlManager->createAbsoluteUrl(["authorizenet/special"]); $setting6->setSettingValue("{"url": "".$url.""}"); $request->addToHostedPaymentSettings($setting6); $controller = new AnetControllerGetHostedPaymentPageController($request); $response = $controller->executeWithApiResponse( etauthorizeapiconstantsANetEnvironment::SANDBOX); if (($response != null) && ($response->getMessages()->getResultCode() == "Ok") ) { return $response->getToken(); }1.3 視圖頁面iframe使用token加載托管表單
同 二.1.14 一致,可以設置為同一個頁面,通過referrer來判斷是完善支付信息表單的響應,還是支付表單的響應
如:
if(referrer == "https://test.authorize.net/customer/addPayment"){ //your code }else if(referrer == "https://test.authorize.net/payment/payment"){ //your code }else if(other){ //your code }3. 最終效果圖
(支付完成后的處理我沒做,無非就是彈個窗之類的告訴用戶支付成功,再處理后臺邏輯之類的)
可以看到,這里只可以回填賬單地址、客戶電話和email之類的信息。信用卡、信用卡過期時間、信用卡安全碼等都無法回填,需要用戶再次輸入,用戶體驗非常不好。
所以支付這一步我們可以不用托管表單,使用通過CustomerProfileID發起支付的API來完成
需要請求的API : createTransactionRequest
API的詳細文檔地址:createTransactionRequest
$paymentprofileid = $this->getCustomerProfile($profileid); $profileToCharge = new AnetAPICustomerProfilePaymentType(); $profileToCharge->setCustomerProfileId($profileid); $paymentProfile = new AnetAPIPaymentProfileType(); $paymentProfile->setPaymentProfileId($paymentprofileid); $profileToCharge->setPaymentProfile($paymentProfile); $transactionRequestType = new AnetAPITransactionRequestType(); $transactionRequestType->setTransactionType( "authCaptureTransaction"); $transactionRequestType->setAmount(5); $transactionRequestType->setProfile($profileToCharge); $request = new AnetAPICreateTransactionRequest(); $request->setMerchantAuthentication($this->merchantAuthentication); $request->setTransactionRequest( $transactionRequestType); $controller = new AnetControllerCreateTransactionController($request); $response = $controller->executeWithApiResponse( etauthorizeapiconstantsANetEnvironment::SANDBOX);4. 結尾補充
托管表單要求你的程序掛載在HTTPS域名下
還可以通過CustomerProfileId、paymentProfileId發起ARB(Auto Recurring Billing)扣款
需要請求的API : ARBCreateSubscriptionRequest
API的詳細文檔地址:getHostedPaymentPageRequest
關于APB的詳細介紹請看:recurring_billing
關于測試請看:testing_guide
可以填寫不同的 Zip Code 和 Card Code 來模擬不同的錯誤返回
(缺)1. 加載AccpectJS
(缺)2. 巴拉巴拉
(缺)
缺失的內容請自行參考官方demo。。。。。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/25624.html
摘要:前言之前的一個人安全部的大師傅把我們拉在了一起,然后逐漸發現群里大師傅們也發了建設經驗文章。月入職,一家具有支付牌照的互聯網金融公司,網絡運維部下。 前言 之前的一個人安全部的77大師傅把我們拉在了一起,然后逐漸發現群里大師傅們也發了建設經驗文章。好吧,這么懶得我也分享下自己的經驗,也就當對這2年多來的甲方經驗的總結。感謝群里的小伙伴們,感謝安全圈的各路大牛們和小伙伴們的幫助,更感謝朝...
摘要:本部分是可以找到有關功能和概念的大部分信息的地方。促銷系統包含一個高度可配置的促銷系統。異步消息通過與現代代理交互,實現應用程序消息的異步處理。將智能地將自己的配置信息與實施者在運行時提供的信息合并。添加了方法以允許包含任何符合的加密方案。 本部分是可以找到有關Broadleaf功能和概念的大部分信息的地方。我們描述了購物車修改,定價和付款等操作的重要性,以及Broadleaf支持的其...
摘要:而適配器其實在中應該是比較常見的一種了。在維基百科中,關于適配器模式的定義為在軟件工程中,適配器模式是一種軟件設計模式,允許從另一個接口使用現有類的接口。 適配器設計模式在JavaScript中非常有用,在處理跨瀏覽器兼容問題、整合多個第三方SDK的調用,都可以看到它的身影。 其實在日常開發中,很多時候會不經意間寫出符合某種設計模式的代碼,畢竟設計模式就是老前輩們總結提煉出來的一些能...
摘要:月,在谷歌云平臺會議上,我們在電子支付提供商的實踐中看到了成功。打破了單個程序到一套通過谷歌開源平臺容器編排引擎來合作的模式。這周,谷歌發布了的最新版本,版本是一個企業友好型平臺,比如說它支持有狀態應用程序。 我們聽說了很多關于容器編排執行得好,就能夠流水化 IT 和業務流程的信息。3 月,在谷歌云平臺會議上,我們在電子支付提供商 WePay 的實踐中看到了成功。WePay 打破了單個...
摘要:更不用說云計算服務提供商可能會免除服務水平協議中的任何責任。數據安全和員工大多數與員工相關的事件并不是惡意的。云計算服務提供商并不會為客戶承擔不必要的責任。越來越多的企業將業務遷移到云計算平臺,這意味著其對數據安全的責任顯著增加。具有各種敏感度的數據正在超出企業防火墻的范圍。企業將不再擁有控制權,其數據可能位于世界任何地方,并可能取決于其合作的云計算供應商。企業將業務遷移到公共云或使用混合云...
閱讀 3384·2023-04-26 01:46
閱讀 2906·2023-04-25 20:55
閱讀 5471·2021-09-22 14:57
閱讀 2974·2021-08-27 16:23
閱讀 1712·2019-08-30 14:02
閱讀 2063·2019-08-26 13:44
閱讀 644·2019-08-26 12:08
閱讀 2951·2019-08-26 11:47