PayPal沙箱订阅支付未触发Subscription Activated事件且onApprove回调未执行问题
遇到这种订阅流程卡壳的情况确实头疼,我帮你从沙箱配置、前端代码、后端逻辑三个维度梳理排查方向和修复建议:
一、先排查PayPal沙箱环境的基础配置(最容易踩坑的点)
确认订阅计划状态
你代码里硬编码的P-1CK57730EG37NBR3D6I这类Plan ID,必须在PayPal沙箱后台处于Active状态(不能是Draft)。登录PayPal沙箱开发者平台,进入Billing > Plans,检查对应计划的状态,确保已发布激活。使用正确的沙箱测试资源
- 必须用PayPal官方提供的沙箱测试卡号(不能用真实信用卡或随便填的假卡),比如:
Visa卡号:4032037785858459 有效期:12/28(未来任意日期) CVV:123 邮编:95131 - 测试用的买家账号必须是沙箱后台创建的Personal类型账号,不能用真实PayPal账号登录沙箱。
- 必须用PayPal官方提供的沙箱测试卡号(不能用真实信用卡或随便填的假卡),比如:
Webhook配置验证
你说后端只收到Subscription Created事件,没收到Activated,先做这两步:- 沙箱后台Webhook页面,确认已订阅
BILLING.SUBSCRIPTION.ACTIVATED事件; - 用PayPal的Webhook Simulator手动触发
BILLING.SUBSCRIPTION.ACTIVATED事件,测试后端是否能正常接收(本地开发需用ngrok暴露后端端口,PayPal无法访问localhost); - 务必确保后端正确验证PayPal Webhook的签名,签名验证失败会导致事件被忽略,PayPal官方有现成的签名验证SDK可以直接用。
- 沙箱后台Webhook页面,确认已订阅
二、前端代码的潜在问题修复
1. 优化PayPalScriptProvider配置
确保配置和订阅计划的参数匹配,比如添加货币类型(必须和你创建的Plan货币一致):
<PayPalScriptProvider options={{ clientId: "AX6MHzLGwPRzkcrnhNw-JCT0aE1d5h8jiMcXqpG7PGD2lNiAM5UWLTeuo", vault: true, intent: "subscription", components: "buttons", currency: "USD", // 替换为你计划对应的货币 locale: "en_US" }} > {paypalButtons} </PayPalScriptProvider>
2. 确保onApprove回调被触发
先添加日志确认回调是否真的没执行:
onApprove={async (data, actions) => { console.log("=== onApprove 已触发 ==="); // 先加这行日志看控制台输出 console.log("[3] Approval Data:", data); try { if (!data.subscriptionID) { throw new Error("No subscription ID received from PayPal"); } // 把后端请求和PayPal弹窗流程解耦,避免阻塞SDK自动关闭弹窗 setTimeout(async () => { await handlePayPalSuccess(data.subscriptionID); }, 100); // 主动让PayPal完成流程关闭弹窗 await actions.subscription.get(); } catch (err) { console.error("onApprove error:", err); alert("Payment failed. Please try again."); } }}
如果控制台没看到=== onApprove 已触发 ===,说明PayPal在创建订阅后没有完成授权流程,问题回到沙箱配置;如果有输出,说明是handlePayPalSuccess里的逻辑有问题。
3. 检查handlePayPalSuccess的字段映射
你在请求后端时做了字段重映射:
body: JSON.stringify({ ...formData, paypalSubscriptionId: subscriptionId, website: formData.name, name: formData.username, })
务必确认后端接口/auth/brand/signup期望的字段和你传递的完全一致,字段不匹配会导致请求失败,但这不会影响PayPal的onApprove触发,只是会导致前端跳转到错误页。
三、后端逻辑补充验证
后端收到
paypalSubscriptionId后,主动调用PayPal的订阅详情API:GET https://api-m.sandbox.paypal.com/v1/billing/subscriptions/{subscription_id}检查返回的订阅状态是否为
ACTIVE,如果是PENDING,说明沙箱里的订阅需要手动激活(极少数情况,比如试用计划设置了手动激活)。确保后端的Webhook接收逻辑没有过滤掉
BILLING.SUBSCRIPTION.ACTIVATED事件,并且正确处理了事件的签名验证。
内容来源于stack exchange

