2023年如何使用PHP对接PayPal Billing Agreements?
2023年PHP实现PayPal不定额不定时扣款方案
原有的Billing Agreements接口及旧版Merchant SDK已废弃,2023年官方推荐使用**Orders API + 参考交易(Reference Transactions)**实现不定额、不定时的扣款需求,以下是具体实现步骤:
一、方案说明
参考交易是PayPal针对无需用户重复授权的后续扣款场景提供的替代方案,支持任意金额、任意时间发起扣款,完全适配新版PHP环境,且是当前官方唯一认可的合规方案。
二、前置准备
- 必须使用PayPal企业账户(个人账户无法申请参考交易权限)
- 登录PayPal商家后台,联系客服申请开通「参考交易」权限(需审核)
- 使用PayPal官方最新的v2 PHP SDK:
paypal/checkout-sdk-php
三、具体实现步骤
1. 安装SDK
通过Composer安装官方SDK:
composer require paypal/checkout-sdk-php
2. 发起首次授权请求(获取用户授权)
此步骤用于引导用户完成首次授权,生成后续扣款所需的授权凭证:
<?php use PayPalCheckoutSdk\Core\PayPalHttpClient; use PayPalCheckoutSdk\Core\SandboxEnvironment; use PayPalCheckoutSdk\Orders\OrdersCreateRequest; // 配置环境(生产环境替换为ProductionEnvironment) $clientId = '你的PayPal Client ID'; $clientSecret = '你的PayPal Client Secret'; $environment = new SandboxEnvironment($clientId, $clientSecret); $client = new PayPalHttpClient($environment); // 创建授权订单 $request = new OrdersCreateRequest(); $request->prefer('return=representation'); $request->body = [ "intent" => "AUTHORIZE", "application_context" => [ "return_url" => "你的授权成功回调地址", "cancel_url" => "你的授权取消回调地址" ], "purchase_units" => [[ "amount" => [ "currency_code" => "USD", "value" => "0.01" // 授权阶段可设置极小金额,后续扣款不受此限制 ] ]] ]; try { $response = $client->execute($request); // 跳转至PayPal授权页面 foreach ($response->result->links as $link) { if ($link->rel === 'approve') { header("Location: {$link->href}"); exit; } } } catch (Exception $e) { die("授权请求失败:{$e->getMessage()}"); } ?>
3. 回调验证并保存授权凭证
用户授权完成后,PayPal会跳转至你设置的return_url,携带token参数(对应订单ID),此时需验证授权并保存关键凭证:
<?php use PayPalCheckoutSdk\Core\PayPalHttpClient; use PayPalCheckoutSdk\Core\SandboxEnvironment; use PayPalCheckoutSdk\Orders\OrdersAuthorizeRequest; $clientId = '你的PayPal Client ID'; $clientSecret = '你的PayPal Client Secret'; $environment = new SandboxEnvironment($clientId, $clientSecret); $client = new PayPalHttpClient($environment); $orderId = $_GET['token']; // 完成授权验证 $request = new OrdersAuthorizeRequest($orderId); $request->prefer('return=representation'); try { $response = $client->execute($request); // 保存授权ID和用户payerID到数据库,关联至对应用户 $authorizationId = $response->result->purchase_units[0]->payments->authorizations[0]->id; $payerId = $response->result->payer->payer_id; // 此处添加数据库存储逻辑 } catch (Exception $e) { die("授权验证失败:{$e->getMessage()}"); } ?>
4. 发起不定额不定时扣款
使用保存的authorizationId即可发起任意金额的扣款:
<?php use PayPalCheckoutSdk\Core\PayPalHttpClient; use PayPalCheckoutSdk\Core\SandboxEnvironment; use PayPalCheckoutSdk\Payments\CapturesCreateRequest; $clientId = '你的PayPal Client ID'; $clientSecret = '你的PayPal Client Secret'; $environment = new SandboxEnvironment($clientId, $clientSecret); $client = new PayPalHttpClient($environment); // 从数据库取出目标用户的authorizationId $authorizationId = '用户的授权ID'; // 创建扣款请求 $request = new CapturesCreateRequest($authorizationId); $request->body = [ "amount" => [ "currency_code" => "USD", "value" => "19.99" // 本次扣款的自定义金额 ] ]; try { $response = $client->execute($request); if ($response->result->status === 'COMPLETED') { echo "扣款成功,交易ID:{$response->result->id}"; // 此处添加业务逻辑处理 } else { echo "扣款状态异常:{$response->result->status}"; } } catch (Exception $e) { die("扣款失败:{$e->getMessage()}"); } ?>
四、关键注意事项
- 参考交易权限需PayPal人工审核开通,提交申请时需说明业务场景
- 授权凭证长期有效,但PayPal可能根据风险规则限制部分扣款请求,建议定期检查授权状态
- 生产环境需将
SandboxEnvironment替换为ProductionEnvironment - 单次扣款金额不得超过PayPal给你的账户设置的上限,具体以后台权限为准
内容的提问来源于stack exchange,提问作者Phantom
相关产品推荐
相关产品推荐

