PayPal支付php開發,thinkphp3.2,移動端的WebView
阿新 • • 發佈:2018-11-09
paypal支付後臺部分程式碼,框架用的thinkphp,有些程式碼不能直接複製,後臺有幾個坑要注意一下,生產模式填的不是production,是LIVE,四個字母都要大寫(這個我吃了虧,查了好多外國資料才知道),並且切換除錯CLIENT_ID和CLIENT_SECRET也要更換,除錯模式為sanbox。
還有一點就是支付選的幣種,你正式上線的時候,paypal的賬號裡面也必須擁有相應幣種的支付
<?php namespace PayApi\Controller; vendor('PayPal.autoload'); use Think\Controller; use Think\Log; class TestController extends Controller { private $CLIENT_ID = '你的CLIENT_ID'; private $CLIENT_SECRET = '你的CLIENT_SECRET'; public function getToken(){ $apiContext = new \PayPal\Rest\ApiContext( new \PayPal\Auth\OAuthTokenCredential($this->CLIENT_ID,$this->CLIENT_SECRET) ); $apiContext->setConfig( array( 'mode' => 'LIVE', // 'log.LogEnabled' => true, // 'log.FileName' => '../PayPal.log', // 'log.LogLevel' => 'DEBUG', // PLEASE USE `INFO` LEVEL FOR LOGGING IN LIVE ENVIRONMENTS // 'cache.enabled' => true, //'cache.FileName' => '/PaypalCache' // for determining paypal cache directory // 'http.CURLOPT_CONNECTTIMEOUT' => 30 // 'http.headers.PayPal-Partner-Attribution-Id' => '123123123' //'log.AdapterFactory' => '\PayPal\Log\DefaultLogFactory' // Factory class implementing \PayPal\Log\PayPalLogFactory ) ); return $apiContext; } // 建立PayPal付款賬單 public function createPay(){ $money = I('post.money'); $user_id = I('post.user_id'); if (empty($money) || empty($order['user_id']) ) { $result['msg'] = 'Parameter Error'; $result['code'] = 0; }else{ $apiContext = $this->getToken(); $payer = new \PayPal\Api\Payer(); $payer->setPaymentMethod('paypal'); // 設定幣種 $amount = new \PayPal\Api\Amount(); $amount->setTotal($money); $amount->setCurrency('USD'); // 設定訂單金額 $transaction = new \PayPal\Api\Transaction(); $transaction->setAmount($amount); $payment = new \PayPal\Api\Payment(); $payment->setIntent('sale') ->setPayer($payer) ->setTransactions(array($transaction)) ->setRedirectUrls($redirectUrls); try { $payment->create($apiContext); $result['paymentID'] = $payment->id; if (!empty($result['paymentID'])) { // 處理業務邏輯 // ... $result['msg'] = 'Success'; $result['code'] = 200; }else{ $result['msg'] = 'Create payment failure'; $result['code'] = 0; } // echo "\n\nRedirect user to approval_url: " . $payment->getApprovalLink() . "\n"; } catch (\PayPal\Exception\PayPalConnectionException $ex) { // This will print the detailed information on the exception. //REALLY HELPFUL FOR DEBUGGING // dump($ex->getData());exit(); $result['msg'] = 'Create payment failure'; $result['code'] = 0; } } $this->ajaxReturn($result); } // 執行檢查PayPal付款賬單 public function executePay(){ $paymentID = I('post.paymentID'); $payerID = I('post.payerID'); $apiContext = $this->getToken(); $paymentObj = new \PayPal\Api\Payment(); $transaction = new \PayPal\Api\Transaction(); $payment = $paymentObj::get($paymentID, $apiContext); $execution = new \PayPal\Api\PaymentExecution(); $execution->setPayerId($payerID); try { $payment->execute($execution, $apiContext); $state = $payment->transactions[0]->related_resources[0]->sale->state; $approval = $payment->state; if ($state == 'completed' && $approval == 'approved') { // 支付完成,更改訂單狀態 // ... $result['code'] = 200; $result['msg'] = 'Success'; }else{ $result['code'] = 0; $result['msg'] = 'NO pay'; } } catch (Exception $ex) { $result['code'] = 0; $result['msg'] = 'Executed Payment'; } $this->ajaxReturn($result); } }
前端html程式碼,根據具體業務需求來,我這邊是給app內webview用的,對接安卓和蘋果,分別注入不一樣的函式,用的不同的js程式碼
<!DOCTYPE html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge,chrome=1"> <meta name="format-detection" content="telephone=no"/> <meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=no"> <title></title> <script src="https://www.paypalobjects.com/api/checkout.js"></script> <script src="https://code.jquery.com/jquery-3.1.1.min.js"></script> <style type="text/css"> body{background: #eee;} .content{ background: #fff; margin-left: 0.5%; margin-top:25px; width: 99%; height: 500px; } .contain-top{ font-family: "Microsoft YaHei"; text-align: center; padding-top: 20px; font-size: 20px; color: #FF4040; width: 100%; height: 80px; border-bottom: 1px dotted #ccc; } .contain-bot{ width: 100%; } #paypal-button-container{ margin: 0 auto; margin-top: 75px; margin-bottom: 75px; width: 80%; height: 80px; } </style> </head> <body> <div class="content"> <div class="contain-top"> Please click the button below to complete the payment </div> <div class="contain-bot" id="paypalbutton"> <div class="button"> <div id="paypal-button-container"></div> </div> </div> </div> <script> var money = 10; var user_id = 1; var pay_from = 'ios'; if (pay_from == 'ios') { function setupWebViewJavascriptBridge(callback) { if (window.WebViewJavascriptBridge) { return callback(WebViewJavascriptBridge); } if (window.WVJBCallbacks) { return window.WVJBCallbacks.push(callback); } window.WVJBCallbacks = [callback]; var WVJBIframe = document.createElement('iframe'); WVJBIframe.style.display = 'none'; WVJBIframe.src = 'wvjbscheme://__BRIDGE_LOADED__'; document.documentElement.appendChild(WVJBIframe); setTimeout(function() { document.documentElement.removeChild(WVJBIframe) }, 0) } setupWebViewJavascriptBridge(function(bridge) { bridge.registerHandler('showResult', function(data, responseCallback) { responseCallback('js執行過了'); }) }) } paypal.Button.render({ env: 'production', // sandbox | production style: { label: 'paypal', size: 'responsive', // small | medium | large | responsive shape: 'rect', // pill | rect color: 'blue', // gold | blue | silver | black tagline: false }, // Show the buyer a 'Pay Now' button in the checkout flow commit: true, // payment() is called when the button is clicked payment: function() { // Set up a url on your server to create the payment var CREATE_URL = '建立支付訂單的路徑'; var data = { money:money, user_id:user_id }; // Make a call to your server to set up the payment return paypal.request.post(CREATE_URL, data) .then(function(res) { if (res.code == 200) { return res.paymentID; }else{ if (pay_from == 'ios') { var postdata = {'code': res.code,'msg': res.msg}; WebViewJavascriptBridge.callHandler('showResult', postdata, function(response) { document.getElementById("returnValue").value = response; }) }else{ JsInterface.showResult(res.code); } } }); }, // onAuthorize() is called when the buyer approves the payment onAuthorize: function(data, actions) { // Set up a url on your server to execute the payment var EXECUTE_URL = '後臺支付完成驗證的路徑'; // Set up the data you need to pass to your server var data = { paymentID: data.paymentID, payerID: data.payerID }; // Make a call to your server to execute the payment return paypal.request.post(EXECUTE_URL, data) .then(function (res) { if (pay_from == 'ios') { var postdata = {'code': res.code,'msg': res.msg}; WebViewJavascriptBridge.callHandler('showResult', postdata, function(response) { document.getElementById("returnValue").value = response; }) }else{ JsInterface.showResult(res.code); } }); } }, '#paypal-button-container'); </script> </body>
前端展示效果
其他的就沒什麼問題了