在实现 PayPal 自动续费的过程中,官方提供了五个基本步骤。除了这些步骤,实际开发中还需要处理支付结果和订阅管理等问题:
- 事先创建并激活订阅计划;
- 用户创建订阅,跳转到 PayPal 网站以等待用户同意;
- 用户同意后,跳转回网站并执行订阅;
- 获取用户账单,包括每次扣款结果通知的接收或支付结果的主动查询;
- 处理用户取消订阅等通知。
使用 PayPal SDK
要使用 PayPal SDK,可以通过以下命令安装:
bash
composer require paypal/rest-api-sdk-php
官方提供了完整的 示例代码,可以帮助开发者更好地理解如何使用 SDK。
此外,可以通过 PayPal Sandbox 方便地进行调试。
创建并激活订阅计划
- 订阅计划(Billing Plan)相当于产品,需要为每个商品创建不同的计划,价格可以根据不同用户在创建协议时进行调整;
- 在 Payment 中创建
TRIAL类型支付时,必须同时存在REGULAR的支付。TRIAL并不能自动判断用户是否为新用户,因此首次优惠需要通过业务代码自行实现; - 创建用户订阅协议时,协议生效时间必须在当前时间24小时以后,因此循环扣款的设置无法立即生效,最早需要24小时。若业务需要立即进行首次扣款,可以使用
MerchantPreferences的setSetupFee来设置首次扣款的费用; - PayPal SDK 可能会报错
"NotifyUrl" value is NULL,这是 PayPal 服务端的错误,官方尚未修复,解决办法可参考 此链接。
创建订阅
用户可以针对同一订阅计划创建多个订阅协议(Billing Agreement),创建后会跳转至 PayPal 网站等待用户同意协议。由于协议开始时间 start_date 最早为当前时间24小时之后,因此该值实际上设置的是第二次扣款时间。如果设置按月付款,start_date 需要设置为一个月后,并通过 setSetupFee 设置首次扣款费用。
创建订阅后,尚未生成 Agreement.id,此时需要从跳转链接中提取出 token,以便将创建的订阅与用户同意后的协议信息相对应。
php
$link = $agreement->getApprovalLink();
parse_str(parse_url($link, PHP_URL_QUERY), $params);
$token = $params[‘token’];
- 同一个订阅计划可以被同一个用户多次订阅,因此在执行新协议时,需要手动取消该用户之前的协议;
- 实际扣款时间可能会有延迟,每次循环扣款执行的时间通常会比
AgreementDetail.next显示的时间晚几个小时。为了保证连续性,可以设置提前一天扣款; - 可以在
My Apps -> REST API apps -> WEBHOOKS设置webhook通知。当每次循环扣款成功时,PayPal 会发送PAYMENT.SALE.COMPLETED的事件通知,可以通过其中的billing_agreement_id字段与已创建的订阅相匹配,找出对应付款的协议; - 每次
AgreementDetail都会返回下次收款时间next参数。可以在超过这个时间后,通过Agreement::searchTransactions方法查询该协议的所有交易。需要注意的是,PayPal 实际的扣款时间一般都会延迟,因此需要多次重试。