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>
前端展示效果
其他的就没什么问题了