# PayPal 支付过程解析:Checkout 收银台与 Subscription 订阅计划实现全过程 **Published by:** [tangxue](https://paragraph.com/@tangxue/) **Published on:** 2025-01-16 **URL:** https://paragraph.com/@tangxue/paypal-checkout-subscription ## Content PayPal 支付过程解析:Checkout 收银台与 Subscription 订阅计划实现全过程 本文详细介绍了如何通过 PayPal 完成 Checkout 收银台支付 和 Subscription 订阅计划。我们将分步骤分析流程并提供代码实现,帮助开发者顺利集成 PayPal 支付功能。 一. 生命周期 1. Checkout - 收银台支付 以下是支付过程的详细拆解流程,类似于支付宝的收银台: 本地应用组装好参数并请求 Checkout 接口,接口同步返回一个支付 URL。 本地应用重定向至该 URL,用户登录 PayPal 账户并确认支付。支付后,用户跳转至设置好的本地应用地址。 本地请求 PayPal 执行付款接口发起扣款。 PayPal 发送异步通知至本地应用,本地应用进行验签操作。 验签成功后,执行支付完成后的业务逻辑,如修改订单状态、增加销量、发送邮件等。 2. Subscription - 订阅支付 订阅支付的流程如下: 创建一个 订阅计划。 激活该计划。 使用已激活的计划去创建订阅申请。 跳转至订阅申请链接获取用户授权并完成首期付款,支付后携带 token 跳转至本地应用地址。 回跳后请求执行订阅。 接收到订阅授权的异步回调后,验证支付成功并执行支付完成后的业务。 二. 具体实现 Checkout 安装 PayPal SDK $ composer require paypal/rest-api-sdk-php:* // 使用最新版本 配置 PayPal 文件 $ touch config/paypal.php 配置内容如下: <?php return [ 'sandbox' => [ 'client_id' => env('PAYPAL_SANDBOX_CLIENT_ID', ''), 'secret' => env('PAYPAL_SANDBOX_SECRET', ''), 'notify_web_hook_id' => env('PAYPAL_SANDBOX_NOTIFY_WEB_HOOK_ID', ''), 'checkout_notify_web_hook_id' => env('PAYPAL_SANDBOX_CHECKOUT_NOTIFY_WEB_HOOK_ID', ''), ], 'live' => [ 'client_id' => env('PAYPAL_CLIENT_ID', ''), 'secret' => env('PAYPAL_SECRET', ''), 'notify_web_hook_id' => env('PAYPAL_NOTIFY_WEB_HOOK_ID', ''), 'checkout_notify_web_hook_id' => env('PAYPAL_CHECKOUT_NOTIFY_WEB_HOOK_ID', ''), ], ]; 创建 PayPal 服务类 $ mkdir -p app/Services && touch app/Services/PayPalService.php 编写 Checkout 支付方法 <?php namespace App\Services; use PayPal\Api\Payment; use PayPal\Api\PaymentExecution; use PayPal\Api\RedirectUrls; use PayPal\Api\Transaction; use PayPal\Api\Amount; use PayPal\Api\ItemList; use PayPal\Api\Item; use PayPal\Api\Payer; class PayPalService { public function checkout(Order $order) { try { $payer = new Payer(); $payer->setPaymentMethod('paypal'); $item = new Item(); $item->setName($order->product->title) ->setDescription($order->no) ->setCurrency($order->product->currency) ->setQuantity(1) ->setPrice($order->total_amount); $itemList = new ItemList(); $itemList->setItems([$item]); $amount = new Amount(); $amount->setCurrency($order->product->currency) ->setTotal($order->total_amount); $transaction = new Transaction(); $transaction->setAmount($amount) ->setItemList($itemList) ->setDescription($order->no); $redirectUrls = new RedirectUrls(); $redirectUrls->setReturnUrl(route('payment.paypal.return', ['success' => 'true', 'no' => $order->no])) ->setCancelUrl(route('payment.paypal.return', ['success' => 'false', 'no' => $order->no])); $payment = new Payment(); $payment->setIntent('sale') ->setPayer($payer) ->setRedirectUrls($redirectUrls) ->setTransactions([$transaction]); $payment->create($this->apiContext); return $payment->getApprovalLink(); } catch (\Exception $e) { return null; } } } 配置控制器 $ php artisan make:controller PaymentsController <?php namespace App\Http\Controllers; use App\Models\Order; class PaymentController extends Controller { public function payByPayPalCheckout(Order $order) { $approvalUrl = app('paypal')->checkout($order); if (!$approvalUrl) { return json_encode(['code' => 500, 'msg' => 'Interval Error.', 'url' => '']); } return json_encode(['code' => 201, 'msg' => 'success.', 'url' => $approvalUrl]); } } Subscription 创建计划并激活计划 <?php namespace App\Services; use PayPal\Api\Plan; use PayPal\Api\PaymentDefinition; use PayPal\Api\ChargeModel; use PayPal\Api\MerchantPreferences; class PayPalService { public function createPlan(Order $order) { $plan = new Plan(); $plan->setName($order->no) ->setDescription($order->product->title) ->setType('INFINITE'); // 可选(FIXED | INFINITE) $paymentDefinition = new PaymentDefinition(); $paymentDefinition->setAmount(new Currency([ 'value' => $order->product->price, 'currency' => $order->product->currency ])); $merchantPreferences = new MerchantPreferences(); $merchantPreferences->setReturnUrl(route('subscriptions.paypal.return', ['success' => 'true', 'no' => $order->no])) ->setCancelUrl(route('subscriptions.paypal.return', ['success' => 'false', 'no' => $order->no])) ->setAutoBillAmount("yes"); $plan->setPaymentDefinitions([$paymentDefinition]); $plan->setMerchantPreferences($merchantPreferences); $output = $plan->create($this->apiContext); $patch = new Patch(); $patch->setOp('replace') ->setPath('/') ->setValue(new PayPalModel('{"state":"ACTIVE"}')); $patchRequest = new PatchRequest(); $patchRequest->addPatch($patch); $output->update($patchRequest, $this->apiContext); return $output; } } 控制器和路由 $ php artisan make:controller SubscriptionsController <?php namespace App\Http\Controllers; use App\Models\Order; class SubscriptionsController extends Controller { public function createPlan(Order $order) { $plan = app('paypal')->createPlan($order); $approvalUrl = app('paypal')->createAgreement($plan, $order); return json_encode(['code' => 201, 'msg' => 'success.', 'url' => $approvalUrl]); } } 常见问题解答 如何处理 PayPal 异常回调? 在接收到 PayPal 的回调时,需验证回调的有效性。使用 verify 方法来确认回调是否来自 PayPal。 如何配置 PayPal Webhook? 登录到 PayPal 开发者中心,添加 Webhook 并选择相应的事件类型。 ☞ WildCard | 一分钟注册,轻松订阅海外线上服务 使用门槛极低,微信支付宝均可开通使用。支持开通各类海外平台:ChatGPT、Claude、Google Play、Apple Store、OpenAI、X、Patreon、MidJourney、Amazon、POE、Microsoft、Facebook、GitHub、Telegram、PayPal等各类海淘订阅平台。使用邀请码:ACCPAY,立享消费0手续费,减免开卡费用。 通过本文,您已经掌握了如何使用 PayPal 完成 Checkout 收银台支付 和 Subscription 订阅支付 的集成。根据您的需求,选择适合的支付方式,顺利实现 PayPal 集成。 ## Publication Information - [tangxue](https://paragraph.com/@tangxue/): Publication homepage - [All Posts](https://paragraph.com/@tangxue/): More posts from this publication - [RSS Feed](https://api.paragraph.com/blogs/rss/@tangxue): Subscribe to updates