如何使用PayPal实现循环扣款(订阅)功能?

在集成PayPal的循环扣款功能时,我们可能会遇到一些挑战。本文将结合自己的开发经验,介绍如何使用PayPal的支付接口实现这一功能。经过两天的研究,我成功完成了集成,并总结了这份使用指南,分享给大家。

PayPal的支付接口

PayPal提供了多种支付接口,分别适用于不同的业务需求。主要包括:

  1. Braintree接口:通过Braintree实现Express Checkout(稍后会介绍Braintree的功能)。
  2. REST API接口:通过创建App来使用REST API接口,是当前最主流的接口方式。
  3. NVP/SOAP API接口:属于旧接口,不再推荐使用,除非REST API无法满足需求。

Braintree接口

Braintree是PayPal收购的公司,除了支持PayPal支付外,还提供了包括升级计划、信用卡支付、客户信息管理等功能。虽然REST接口也支持大部分功能,但我更倾向于使用Braintree,因为它可以通过Dashboard方便地管理这些信息。然而,问题是Braintree在中国并不支持。

REST API接口

REST API是目前的主流接口,符合OAuth 2.0认证方式。如果你曾使用过OAuth 2.0和REST API接口,这部分内容应该不难理解。

旧接口(NVP/SOAP API)

除非你有特殊需求,否则不推荐使用这些旧接口。世界范围内,开发者都在迁移至OAuth 2.0和REST API,最好顺应这一趋势。

如何开始

要开始使用PayPal的REST API,首先建议安装官方提供的 PayPal-PHP-SDK,并参考其Wiki。

在开始之前,请确保你已创建并配置好PayPal的Sandbox账号,并完成以下设置:

  • Client ID
  • Client Secret
  • Webhook API:必须是HTTPS开头,端口为443,建议使用ngrok进行本地调试。
  • Return URL:注意要确保返回URL正确。

REST API接口概述

PayPal的API包含多个功能模块,每个模块有不同的用法和场景:

  • Payments:一次性支付接口,适用于单次支付,不支持循环扣款。
  • Payouts:暂无使用。
  • Authorization and Capture:支持用户通过PayPal账号登录并进行支付。
  • SaleOrder:这些接口与商城相关,当前未使用。
  • Billing Plan & Agreements:主要用于实现循环扣款功能(订阅)。本文重点讲解这一部分。
  • Vault:用于存储信用卡信息。
  • Payment ExperienceNotifications:这些用于支付体验和Webhook处理,不在本文讨论范围内。
  • Invoice:处理票据。
  • Identity:用于OAuth 2.0认证,获取token,便于调用其他API。

如何实现循环扣款

PayPal的循环扣款功能主要通过“升级计划”(Billing Plan)和“协议”(Agreement)来实现。整个流程可以分为四个步骤:

  1. 创建并激活升级计划。
  2. 创建订阅(Agreement),跳转到PayPal等待用户同意。
  3. 用户同意后,执行订阅。
  4. 获取扣款账单。

1. 创建升级计划

创建升级计划时,你需要关注以下几点:

  • 升级计划创建后初始状态为 CREATED,必须修改为 ACTIVE 才能正常使用。
  • 升级计划中包含两个重要对象:PaymentDefinitionMerchantPreferences,这两个对象不能为空。
  • 如果你希望创建一个 TRIAL 类型的计划,必须同时配置一个 REGULAR 的支付定义。
  • setSetupFee 方法用于设置首次扣款费用,而 Agreement 对象设置的是从第二次开始的扣款费用。

以下是一个创建标准月度计划的示例参数:

php
$param = [
"name" => "standard_monthly",
"display_name" => "Standard Plan",
"desc" => "Standard Plan for one month",
"type" => "REGULAR",
"frequency" => "MONTH",
"frequency_interval" => 1,
"cycles" => 0,
"amount" => 20,
"currency" => "USD"
];

2. 创建订阅(Agreement)

创建订阅时,PayPal会引导用户跳转到其网站以便用户同意。创建 Agreement 时需要注意以下事项:

  • setSetupFee 设置首次扣款费用,而 Agreement 设置第二次开始的费用。
  • setStartDate 设置第二次扣款的时间(按月循环时通常为当前时间加一个月)。

php
$param = [
'id' => 'P-26T36113JT475352643KGIHY', // 创建的Plan ID
'name' => 'Standard',
'desc' => 'Standard Plan for one month'
];

php
public function createPayment($param)
{
$apiContext = $this->getApiContext();
$agreement = new Agreement();

$agreement->setName($param['name'])
    ->setDescription($param['desc'])
    ->setStartDate(Carbon::now()->addMonths(1)->toIso8601String());

$plan = new Plan();
$plan->setId($param['id']);
$agreement->setPlan($plan);

$payer = new Payer();
$payer->setPaymentMethod('paypal');
$agreement->setPayer($payer);

try {
    $agreement = $agreement->create($apiContext);
    $approvalUrl = $agreement->getApprovalLink();
} catch (Exception $ex) {
    return "create payment failed, please retry or contact the merchant.";
}
return $approvalUrl; // 跳转到PayPal等待用户同意

}

3. 用户同意后,执行订阅

用户同意订阅后,需要执行 Agreementexecute 方法才能完成订阅。

php
public function onPay($request)
{
$apiContext = $this->getApiContext();
if ($request->has('success') && $request->success == 'true') {
$token = $request->token;
$agreement = new \PayPal\Api\Agreement();
try {
$agreement->execute($token, $apiContext);
} catch(\Exception $e) {
return null;
}
return $agreement;
}
return null;
}

4. 获取交易记录

在用户订阅后,可能需要几分钟才能生成扣款记录。如果没有记录,可以稍后再试。

php
public function transactions($id)
{
$apiContext = $this->getApiContext();
$params = ['start_date' => date('Y-m-d', strtotime('-15 years')), 'end_date' => date('Y-m-d', strtotime('+5 days'))];
try {
$result = Agreement::searchTransactions($id, $params, $apiContext);
} catch (\Exception $e) {
Log::error("get transactions failed" . $e->getMessage());
return null;
}
return $result->getAgreementTransactionList();
}

需要考虑的问题

在实现PayPal循环扣款功能时,遇到了一些需要特别注意的问题:

  1. Sandbox测试时的连接速度问题:国内连接PayPal时可能会出现超时或错误,需考虑用户关闭页面的情况。
  2. WebHook的实现:必须实现WebHook,以便在用户取消订阅时,网站能够收到通知。
  3. 订阅管理:当用户更换订阅计划时,需要取消旧的订阅计划,否则会出现重复收费的情况。
  4. 长时间操作的处理:订阅的切换是一个耗时较长的操作,建议将其放入队列中处理,以提高用户体验。

👉 野卡 | 一分钟注册,轻松订阅海外线上服务

(0)
上一篇 2025年3月20日
下一篇 2025年3月20日

相关推荐