# 如何通过 PayPal 实现循环扣款(订阅功能)? **Published by:** [woduni](https://paragraph.com/@woduni/) **Published on:** 2025-01-15 **URL:** https://paragraph.com/@woduni/paypal ## Content 介绍在业务开发中,经常需要集成 PayPal 支持循环扣款功能。然而,市面上鲜有详细的开发教程。本文将结合实际案例,详解如何使用 PayPal 的支付接口实现订阅功能,并探讨可能遇到的问题及优化方案。PayPal 接口分类PayPal 提供了多套支付接口,开发者可以根据需求选择适合的方式:Braintree 接口:提供支付、升级计划、信用卡管理等功能。REST API 接口:主流接口,采用 OAuth 2.0 认证,支持多种支付模式。NVP/SOAP API 接口:旧版接口,不推荐使用。为什么选择 REST API?REST API 是主流的开发接口,支持 OAuth 2.0 认证和现代化的支付方式,适合构建订阅功能。PayPal 官方提供了详细的 API 文档,开发者可以参考快速上手。 ☞ WildCard | 一分钟注册,轻松订阅海外线上服务 使用 WildCard 虚拟卡可轻松绑定 PayPal,开通订阅服务。支持微信、支付宝支付,邀请码:ACCPAY,享 0 手续费,减免开卡费用。实现循环扣款的四个步骤1. 创建升级计划(Billing Plan)升级计划用于定义订阅周期、费用等关键信息。以下是创建计划时的关键点:状态激活:计划创建后默认处于 CREATED 状态,需将其设置为 ACTIVE。费率定义:包括周期、金额、货币等信息。首次扣款:通过 setSetupFee 设置订阅后的首次扣款费用。示例代码$param = [ "name" => "standard_monthly", "desc" => "Standard Plan for one month", "type" => "REGULAR", "frequency" => "MONTH", "frequency_interval" => 1, "cycles" => 0, "amount" => 20, "currency" => "USD" ]; public function createPlan($param) { $plan = new Plan(); $plan->setName($param['name']) ->setDescription($param['desc']) ->setType('INFINITE'); $paymentDefinition = new PaymentDefinition(); $paymentDefinition->setName($param['name']) ->setType($param['type']) ->setFrequency($param['frequency']) ->setFrequencyInterval((string)$param['frequency_interval']) ->setCycles((string)$param['cycles']) ->setAmount(new Currency(['value' => $param['amount'], 'currency' => $param['currency']])); $merchantPreferences = new MerchantPreferences(); $merchantPreferences->setReturnUrl("https://yourdomain.com/success") ->setCancelUrl("https://yourdomain.com/cancel") ->setSetupFee(new Currency(['value' => $param['amount'], 'currency' => 'USD'])); $plan->setPaymentDefinitions([$paymentDefinition]); $plan->setMerchantPreferences($merchantPreferences); try { $plan->create($this->apiContext); } catch (Exception $ex) { // 错误处理 } return $plan; } 2. 创建订阅协议(Agreement)订阅协议链接用户与升级计划,为用户生成支付链接以完成订阅。示例代码$param = [ 'id' => 'P-123456789', // 计划 ID 'name' => 'Standard', 'desc' => 'Standard Plan for one month' ]; public function createAgreement($param) { $agreement = new Agreement(); $agreement->setName($param['name']) ->setDescription($param['desc']) ->setStartDate(Carbon::now()->addMonth()->toIso8601String()); $plan = new Plan(); $plan->setId($param['id']); $agreement->setPlan($plan); $payer = new Payer(); $payer->setPaymentMethod('paypal'); $agreement->setPayer($payer); try { $agreement->create($this->apiContext); return $agreement->getApprovalLink(); } catch (Exception $ex) { // 错误处理 } } 3. 执行订阅用户同意后,需要调用 Agreement::execute 方法完成订阅。示例代码public function executeAgreement($token) { $agreement = new Agreement(); try { $agreement->execute($token, $this->apiContext); } catch (Exception $ex) { // 错误处理 } return $agreement; } 4. 查询交易记录获取用户订阅后的扣款记录,用于统计或展示。示例代码public function getTransactions($agreementId) { $params = [ 'start_date' => '2025-01-01', 'end_date' => '2025-12-31' ]; try { $result = Agreement::searchTransactions($agreementId, $params, $this->apiContext); } catch (Exception $ex) { // 错误处理 } return $result->getAgreementTransactionList(); } 需要考虑的问题在实际开发中需特别注意以下问题:网络超时:国内连接 PayPal Sandbox 环境较慢,建议处理用户中途退出场景。Webhook 监听:需实现 Webhook 接口以接收用户取消订阅的通知。升级计划切换:若用户切换订阅计划,需取消旧协议并创建新协议。原子性操作:订阅的创建、切换和支付流程应设计为原子性操作,建议使用队列实现。通过以上步骤,即可实现 PayPal 的循环扣款功能。如果您需要便捷的虚拟卡服务完成绑定和支付,推荐使用 WildCard 提供的一站式支付解决方案。 ☞ WildCard | 一分钟注册,轻松订阅海外线上服务 ## Publication Information - [woduni](https://paragraph.com/@woduni/): Publication homepage - [All Posts](https://paragraph.com/@woduni/): More posts from this publication - [RSS Feed](https://api.paragraph.com/blogs/rss/@woduni): Subscribe to updates