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

Laravel集成PayPal SDK:沙箱账户金额未更新问题求助

问题分析与解决方案

你遇到的核心问题是:PayPal REST API的支付流程没有走完最后一步——捕获已授权的支付金额。当用户在PayPal页面完成授权后,你只是跳转到了成功页,但没有告诉PayPal完成资金转账操作,所以沙箱账户里的金额不会发生变化。

接下来一步步帮你修正代码:

1. 完善success方法,添加支付捕获逻辑

在用户授权支付后,PayPal会把paymentId和PayerID作为查询参数返回给你的成功回调地址。你需要用这两个参数来完成支付的捕获:

use Illuminate\Http\Request;

public function success(Request $request){ 
    $apiContext = new \PayPal\Rest\ApiContext( 
        new \PayPal\Auth\OAuthTokenCredential( 
            'Ac.................asd', // 你的ClientID 
            'Ac.................sdf' // 你的ClientSecret 
        ) 
    );

    // 显式设置沙箱环境(如果你的ClientID是沙箱的,这一步可省略,但加上更稳妥)
    $apiContext->setConfig([
        'mode' => 'sandbox', // sandbox 或 live
        'log.LogEnabled' => true,
        'log.FileName' => storage_path('logs/paypal.log'),
        'log.LogLevel' => 'DEBUG' // 方便排查问题
    ]);

    try {
        // 获取PayPal返回的支付ID和PayerID
        $paymentId = $request->input('paymentId');
        $payerId = $request->input('PayerID');

        // 根据支付ID获取支付对象
        $payment = \PayPal\Api\Payment::get($paymentId, $apiContext);

        // 创建捕获请求
        $execution = new \PayPal\Api\PaymentExecution();
        $execution->setPayerId($payerId);

        // 执行捕获,完成资金转账
        $result = $payment->execute($execution, $apiContext);

        // 这里可以处理支付成功后的业务逻辑,比如更新订单状态、发送通知等
        return response()->json([
            'status' => 'success',
            'message' => '支付完成',
            'transaction_details' => $result
        ]);
    } catch (\Exception $ex) {
        // 捕获错误,处理失败逻辑
        \Log::error('PayPal支付捕获失败: ' . $ex->getMessage());
        return response()->json([
            'status' => 'error',
            'message' => '支付确认失败,请稍后重试',
            'error_info' => $ex->getMessage()
        ], 500);
    }
}

2. 优化createpayment方法的返回逻辑

你原来的createpayment方法最后用echo输出内容,这不符合Laravel的响应规范,应该改为跳转至PayPal授权页面:

public function createpayment(){ 
    $apiContext = new \PayPal\Rest\ApiContext( 
        new \PayPal\Auth\OAuthTokenCredential( 
            'Ac.................asd', // ClientID 
            'Ac.................sdf' // ClientSecret 
        ) 
    );

    // 添加沙箱配置,统一环境
    $apiContext->setConfig([
        'mode' => 'sandbox',
        'log.LogEnabled' => true,
        'log.FileName' => storage_path('logs/paypal.log'),
        'log.LogLevel' => 'DEBUG'
    ]);

    $payer = new \PayPal\Api\Payer(); 
    $payer->setPaymentMethod("paypal"); 

    $item1 = new \PayPal\Api\Item(); 
    $item1->setName('Ground Coffee 40 oz') 
          ->setCurrency('USD') 
          ->setQuantity(1) 
          ->setSku("123123") 
          ->setPrice(7.5); 

    $item2 = new \PayPal\Api\Item(); 
    $item2->setName('Granola bars') 
          ->setCurrency('USD') 
          ->setQuantity(5) 
          ->setSku("321321") 
          ->setPrice(2); 

    $itemList = new \PayPal\Api\ItemList(); 
    $itemList->setItems([$item1, $item2]); 

    $details = new \PayPal\Api\Details(); 
    $details->setShipping(1.2) 
            ->setTax(1.3) 
            ->setSubtotal(17.50); 

    $amount = new \PayPal\Api\Amount(); 
    $amount->setCurrency("USD") 
           ->setTotal(20) 
           ->setDetails($details); 

    $transaction = new \PayPal\Api\Transaction(); 
    $transaction->setAmount($amount) 
                ->setItemList($itemList) 
                ->setDescription("Payment description") 
                ->setInvoiceNumber(uniqid()); 

    $redirectUrls = new \PayPal\Api\RedirectUrls(); 
    $redirectUrls->setReturnUrl(route('success')) 
                 ->setCancelUrl(route('cancel')); 

    $payment = new \PayPal\Api\Payment(); 
    $payment->setIntent("sale") 
            ->setPayer($payer) 
            ->setRedirectUrls($redirectUrls) 
            ->setTransactions([$transaction]); 

    try { 
        $payment->create($apiContext); 
    } catch (\Exception $ex) { 
        // 用Laravel日志记录错误,方便排查
        \Log::error('PayPal支付链接生成失败: ' . $ex->getMessage());
        return redirect()->back()->with('error', '支付链接生成失败,请稍后重试');
    } 

    $approvalUrl = $payment->getApprovalLink(); 
    // 跳转到PayPal授权页面
    return redirect($approvalUrl); 
}

3. 沙箱测试的关键注意事项

  • 确保你使用的商家账户(关联ClientID的账户)和买家账户都是PayPal沙箱账户,不能用真实账户测试。
  • 检查沙箱账户余额:买家账户需要有足够的余额完成支付,商家账户需要是已验证的沙箱商家账户。
  • 查看storage/logs/paypal.log日志文件,如果捕获过程中出现错误,日志会帮你快速定位问题。

这样修改后,当用户完成PayPal授权跳转回成功页时,代码会自动执行支付捕获操作,沙箱里的商家账户会收到款项,买家账户余额也会相应扣除,同时成功页会返回结构化的支付响应。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 04:58:44