Laravel中集成PayPal

36次阅读

共计 5351 个字符,预计需要花费 14 分钟才能阅读完成。

最近在写一个面向国外买家的一个商城项目,既然面向国外,那就要用到 PayPal 这个支付平台。因为在对接 PayPal 的过程中遇到了一些问题,花费了一些时间,所以把对接的过程记下来,也希望能帮助到用到 PayPal 的朋友。
我集成的是 paypal/rest-api-sdk-php。PayPal 的 api 有 v1 和 v2 两个版本,我用的这个是 v1 版本。
以下皆以代码的形式展现,没有截图,但我尽量用代码讲解明白。假设你已经有了用 laravel 写的一个项目:

Step:1 安装扩展包
composer require paypal/rest-api-sdk-php

Step:2 创建 paypal.php 配置文件
在 Config 目录新建 paypal.php 配置文件,内容如下
return [
‘paypal’ => [
/** set your paypal credential **/
‘client_id’ =>’paypal client_id’,
‘secret’ => ‘paypal secret ID’,
/**
* SDK 配置
*/
‘settings’ => array(
/**
* 沙盒测试 ’sandbox’ 或者 ‘live’
*/
‘mode’ => ‘sandbox’,
/**
* 请求超时时间
*/
‘http.ConnectionTimeOut’ => 1000,
/**
* 是否开启日志:true 开启,false 不开启
*/
‘log.LogEnabled’ => true,
/**
* 日志存储的文件
*/
‘log.FileName’ => storage_path() . ‘/logs/paypal.log’,
/**
* 日志级别 ‘DEBUG’, ‘INFO’, ‘WARN’ or ‘ERROR’
*
*/
‘log.LogLevel’ => ‘INFO’
),
],

‘2checkout’ => [
//
]
];

Step:3 创建路由
// 第一步:显示表单,这是一个简单的表单页面,我们把金额输入,然后点击提交
Route::get(‘paypal-form’, ‘Payment\PayPalController@payPalShow’)->name(‘paypal-form’);

// 第二步:第一步提交后发送请求,请求该方法,该方法用于创建订单,创建支付流程
Route::post(‘paypal-pay’, ‘Payment\PayPalController@pay’)->name(‘payment.paypay.pay’);

// 第三步:异步回调
Route::post(‘paypal-notify’, ‘Payment\PayPalController@payPalNotify’)->name(‘payment.paypal.notify’);

// 第三步:前端回调
Route::get(‘paypal-return’, ‘Payment\PayPalController@payPalReturn’)->name(‘payment.paypal.return’);

// 第三步:取消
Route::get(‘paypal-cancel’, ‘Payment\PayPalController@payPalCancel’)->name(‘payment.paypal.cancel’);

Step:3 创建控制器
<?php

namespace App\Http\Controllers\Payment;

use App\Http\Controllers\BaseController;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Input;
use PayPal\Api\Amount;
use PayPal\Api\Item;
use PayPal\Api\ItemList;
use PayPal\Api\Payer;
use PayPal\Api\Payment;
use PayPal\Api\PaymentExecution;
use PayPal\Api\RedirectUrls;
use PayPal\Api\Transaction;
use PayPal\Auth\OAuthTokenCredential;
use PayPal\Rest\ApiContext;

class PayPalController extends BaseController
{
private $_api_context;

public function __construct()
{
$payPal_config = config(‘payment.payPal’);
// 初始化 PayPal Api context
$this->_api_context = new ApiContext(new OAuthTokenCredential(
$payPal_config[‘client_id’],
$payPal_config[‘secret’]
));
$this->_api_context->setConfig($payPal_config[‘setting’]);
}

// 显示表单
public function payPalShow()
{
return view(‘payment.paypal’);
}

// 第二步,请求这里
public function pay(Request $request)
{
$payer = new Payer();
$payer->setPaymentMethod(‘paypal’);

// 产品名称,币种,数量,单个产品金额
$item1 = new Item();
$item1->setName(‘item1’)
->setCurrency(‘USD’)
->setQuantity(1)
->setPrice($request->get(‘amount’));

// 将所有产品集合到 ItemList 中
$item_list = new ItemList();
$item_list->setItems([$item1]);

$amount = new Amount();
$amount->setCurrency(‘USD’)
->setTotal($request->get(‘amount’));

// 生成交易
$transaction = new Transaction();
$transaction->setAmount($amount)
->setItemList($item_list)
->setDescription(‘ 你的交易 ’)
->setNotifyUrl(route(‘notify_url’)) // 注意,这里设置异步回调地址
->setInvoiceNumber($order->order_number); // 这里设置订单号

// 设置前端回调地址和取消支付地址
$redirect_urls = new RedirectUrls();
$redirect_urls->setReturnUrl(route(‘payment.paypal.cancel’))
->setCancelUrl(route(‘payment.paypal.cancel’));

$payment = new Payment();
$payment->setIntent(‘Sale’)
->setPayer($payer)
->setRedirectUrls($redirect_urls)
->setTransactions(array($transaction));
try {
// 这里生成支付流程
$payment->create($this->_api_context);
} catch (\PayPal\Exception\PayPalConnectionException $ex) {
if (config(‘app.debug’)) {
session()->put(‘error’,’Connection timeout’);
return redirect()->route(‘paypal-form’);

/** echo “Exception: ” . $ex->getMessage() . PHP_EOL; **/
/** $err_data = json_decode($ex->getData(), true); **/
/** exit; **/

} else {
session()->put(‘error’,’Some error occur, sorry for inconvenient’);
return redirect()->route(‘paypal-form’);
}
}

foreach($payment->getLinks() as $link) {
if($link->getRel() == ‘approval_url’) {
$redirect_url = $link->getHref();
break;
}
}

// $payment->getId() 得到的是支付流水号
session()->put(‘paypal_payment_id’, $payment->getId());

if(isset($redirect_url)) {
// 跳转到支付页面
return redirect()->away($redirect_url);
}

session()->put(‘error’,’Unknown error occurred’);
return session()->route(‘paypal-form’);
}

public function payPalReturn(Request $request)
{
// 支付成功后,在前端页面跳转回来时,url 地址中会带有 paymentID 和 PayerID
$payment_id = session()->get(‘paypal_payment_id’);
session()->forget(‘paypal_payment_id’);

if (empty(Input::get(‘PayerID’)) || empty(Input::get(‘token’))) {
session()->put(‘error’,’Payment failed’);

return redirect()->route(‘paypal-form’);
}
$payment = Payment::get($payment_id, $this->_api_context);
$execution = new PaymentExecution();
$execution->setPayerId(Input::get(‘PayerID’));
$result = $payment->execute($execution, $this->_api_context);

// 当拿到的状态时 approved 表示支付成功
if ($result->getState() == ‘approved’) {

session()->put(‘success’,’Payment success’);
return redirect()->route(‘paypal-form’);
}
session()->put(‘error’,’Payment failed’);

return redirect()->route(‘paypal-form’);
}

public function payPalNotify()
{
Log::info(12312, Input::get());
// 这里写我们的业务逻辑,订单状态更新,物流信息等等.
}
}

Step:4 创建表单
<form class=”form-horizontal” method=”POST” id=”payment-form” role=”form” action=”{!! URL::route(‘paypal-pay’) !!}” >
{{csrf_field() }}

<div class=”form-group{{$errors->has(‘amount’) ? ‘ has-error’ : ” }}”>
<label for=”amount” class=”col-md-4 control-label”>Amount</label>

<div class=”col-md-6″>
<input id=”amount” type=”text” class=”form-control” name=”amount” value=”{{old(‘amount’) }}” autofocus>

@if ($errors->has(‘amount’))
<span class=”help-block”>
<strong>{{$errors->first(‘amount’) }}</strong>
</span>
@endif
</div>
</div>

<div class=”form-group”>
<div class=”col-md-6 col-md-offset-4″>
<button type=”submit” class=”btn btn-primary”>
Paywith Paypal
</button>
</div>
</div>
</form>
以上既是我做商城项目时 PayPal 的对接流程,因为英语不好的问题,开发起来会出现很多问题,如果英文好,想知道更多的用法,可以看 PayPal 的开发者文档,还有 demo 演示。

正文完
 0