# PayPal支付完整教程：Checkout收银台与Subscription订阅计划

By [linli](https://paragraph.com/@linli-2) · 2025-01-17

---

本文详细介绍了如何使用PayPal支付接口，包括Checkout收银台支付与Subscription订阅支付计划的完整流程。我们将一步步解析这些支付过程，帮助您顺利实现集成。

一、生命周期解析
--------

### 1\. Checkout - 收银台支付

下面是Checkout支付的流程图，类似于支付宝的收银台支付：

Checkout流程

#### 流程详解：

1.  本地应用组装好参数并请求Checkout接口，接口同步返回一个支付URL；
    
2.  本地应用重定向至此URL，用户登录PayPal账户并确认支付，支付后跳转到设置好的本地应用地址；
    
3.  本地请求PayPal执行付款接口发起扣款；
    
4.  PayPal发送异步通知至本地应用，本地收到数据包后进行验签；
    
5.  验签成功后，执行支付后的业务，如修改订单状态、增加销量、发送邮件等。
    

### 2\. Subscription - 订阅支付

下面是Subscription支付的流程图：

Subscription流程

#### 流程详解：

1.  创建一个订阅计划；
    
2.  激活该计划；
    
3.  使用激活的计划创建订阅申请；
    
4.  用户授权并完成第一期付款，支付后携带token跳转至设置好的本地应用地址；
    
5.  回跳后请求执行订阅；
    
6.  收到订阅授权的异步回调，验证支付结果，执行支付完成后的业务。
    

二、具体实现
------

### 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', ''),
        ],
    
        'live' => [
            'client_id' => env('PAYPAL_CLIENT_ID', ''),
            'secret' => env('PAYPAL_SECRET', ''),
            'notify_web_hook_id' => env('PAYPAL_NOTIFY_WEB_HOOK_ID', ''),
        ],
    ];
    

#### 创建PayPal服务类

    $ mkdir -p app/Services && touch app/Services/PayPalService.php
    

### 代码实现

使用PayPal API来执行支付与订阅。以下是服务类的部分代码：

    namespace App\Services;
    
    use PayPal\Api\Currency;
    use PayPal\Api\Payment;
    use PayPal\Api\RedirectUrls;
    use PayPal\Api\Transaction;
    use PayPal\Api\Payer;
    use PayPal\Api\Amount;
    use PayPal\Api\ItemList;
    use PayPal\Api\Item;
    use PayPal\Api\PaymentExecution;
    use Symfony\Component\HttpKernel\Exception\HttpException;
    
    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]);
    
                $details = new Details();
                $details->setShipping(0)
                        ->setSubtotal($order->total_amount);
    
                $amount = new Amount();
                $amount->setCurrency($order->product->currency)
                       ->setTotal($order->total_amount)
                       ->setDetails($details);
    
                $transaction = new Transaction();
                $transaction->setAmount($amount)
                            ->setItemList($itemList)
                            ->setDescription($order->no)
                            ->setInvoiceNumber(uniqid());
    
                $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 (HttpException $e) {
                Log::error('PayPal Checkout Create Failed', ['msg' => $e->getMessage(), 'code' => $e->getStatusCode()]);
                return null;
            }
        }
    }
    

### 订阅流程

#### 创建订阅计划并激活

    public function createPlan(Order $order)
    {
        try {
            $plan = new Plan();
            $plan->setName($order->no)
                 ->setDescription($order->product->title)
                 ->setType('INFINITE');
    
            $paymentDefinition = new PaymentDefinition();
            $paymentDefinition->setAmount(new Currency([
                'value' => $order->product->price,
                'currency' => $order->product->currency
            ]));
    
            $plan->setPaymentDefinitions([$paymentDefinition]);
            $plan->create($this->apiContext);
    
            $patch = new Patch();
            $value = new PayPalModel('{"state":"ACTIVE"}');
            $patch->setOp('replace')
                  ->setPath('/')
                  ->setValue($value);
            $patchRequest = new PatchRequest();
            $patchRequest->addPatch($patch);
            $plan->update($patchRequest, $this->apiContext);
    
            return Plan::get($plan->getId(), $this->apiContext);
        } catch (HttpException $e) {
            Log::error('PayPal Create Plan Failed', ['msg' => $e->getMessage()]);
            return false;
        }
    }
    

常见问题
----

*   **微软邮箱问题**：使用outlook、hotmail、live等邮箱注册PayPal账户，升级至GPT Plus或绑定API后会出现账户封禁的问题，建议避免使用这些邮箱。
    
*   **排队等待问题**：若在PayPal升级页面看到排队提示，可以尝试使用提供的链接直接进入升级页面，避免排队。
    
*   **取消自动续费**：PayPal订阅会默认自动续费，确保在不再需要订阅时手动取消自动续费设置。
    

* * *

☞ [WildCard | 一分钟注册，轻松订阅海外线上服务](https://bit.ly/bewildcard)使用门槛极低，微信支付宝均可开通使用。支持开通各类海外平台：ChatGPT、Claude、Google Play、Apple Store、OpenAI、X、Patreon、MidJourney、Amazon、POE、Microsoft、Facebook、GitHub、Telegram、PayPal等各类海淘订阅平台。使用邀请码：ACCPAY，立享消费0手续费，减免开卡费用。

---

*Originally published on [linli](https://paragraph.com/@linli-2/paypal-checkout-subscription)*
