You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

未执行$agreement->execute能否触发PayPal订阅Webhook?用户未返回回调URL的解决办法

解决PayPal订阅用户未返回回调URL导致无法激活的问题

我明白你现在的困境——用户在PayPal完成订阅授权后,如果没有跳回你的成功URL,$agreement->execute($token)就不会被调用,订阅也就没法生效,这确实会让人头疼。结合你的代码和PayPal的实际机制,这里有几个可行的解决方案:

1. 配置自动触发的回调端点(无需用户手动跳转)

PayPal会主动向你设置的return URL发送请求,不管用户是否手动跳转回你的网站。你可以把return URL设置为服务器端的处理脚本(比如你的index.php),这样即使用户关闭了PayPal页面,PayPal依然会把token参数发送到这个脚本,你就能在后台自动执行协议激活:

修改你创建Agreement的代码,显式设置跳转URL(如果没在应用全局配置过的话):

// 在创建Agreement之前,添加跳转URL配置
$redirectUrls = new \PayPal\Api\RedirectUrls();
$redirectUrls->setReturnUrl('https://your-domain.com/index.php?status=success')
             ->setCancelUrl('https://your-domain.com/index.php?status=cancel');
$agreement->setRedirectUrls($redirectUrls);

// 后续创建协议的代码保持不变
$agreement->setName('Basic Plan')->setDescription('Some info')->setStartDate($date);
// ... 其他代码

这样用户完成授权后,PayPal会直接向return URL发送GET请求,你的index.php就能自动捕获token并执行激活,不需要依赖用户手动操作。

2. 利用Webhook事件异步激活订阅

如果return URL的方式有顾虑,你可以通过PayPal Webhook监听BILLING.AGREEMENT.CREATED或BILLING.SUBSCRIPTION.APPROVED事件(根据API版本略有差异)。当用户在PayPal端完成授权后,PayPal会发送这个事件到你的Webhook端点,里面包含协议ID和token信息:

  • 在Webhook处理脚本中,解析事件数据获取协议对应的token
  • 调用$agreement->execute($token, $apiContext)完成订阅激活

⚠️ 注意:必须确保你的Webhook端点能正确验证PayPal的请求签名,避免伪造请求触发错误操作。

3. 定时查询协议状态作为兜底方案

作为最后补救措施,你可以设置一个定时任务(比如Cron),定期查询所有处于CREATED状态的协议,尝试获取对应的token并执行激活:

// 示例:定时查询待激活协议并执行
try {
    $agreementList = \PayPal\Api\Agreement::all(
        ['start_index' => 0, 'count' => 20], 
        $apiContext
    );
    foreach ($agreementList->getAgreements() as $agreement) {
        // 只处理已创建但未激活的协议
        if ($agreement->getStatus() === 'CREATED') {
            // 从你之前记录的数据库中获取该协议对应的token
            $token = get_token_from_db($agreement->getId());
            if ($token) {
                $agreement->execute($token, $apiContext);
            }
        }
    }
} catch (Exception $ex) {
    // 处理查询或执行失败的情况,比如用户已取消授权
    error_log('订阅激活失败:' . $ex->getMessage());
}

这个方案需要你在创建协议时,把协议ID和对应的token(或关联的用户信息)记录到数据库,方便后续关联查询。

优化你的现有代码

在Subscribe.php中创建协议后,记得记录关键信息到数据库,方便后续补救:

try {
    $agreement = $agreement->create($apiContext);
    $approvalUrl = $agreement->getApprovalLink();
    // 记录协议ID和token到数据库,用于后续异步激活
    save_subscription_record(
        $agreement->getId(), 
        $agreement->getToken(), 
        $_SESSION['user_id'] // 关联当前用户
    );
    redirect($approvalUrl);
} catch (Exception $ex) {
    print_r($ex->getData());
}

内容的提问来源于stack exchange,提问作者Markian

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:37:30