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

Laravel集成PayPal v2 SDK支付失败问题求助

PayPal v2 SDK 集成 Laravel 问题排查与解决

1. 纠正 SDK 依赖包

你安装的 paypal/paypal-payouts-sdk 是用于**批量付款(Payouts)**的包,不适合普通支付订单场景。正确的 PayPal v2 支付 SDK 是 paypal/paypal-checkout-sdk,执行以下操作替换:

# 卸载错误包
composer remove paypal/paypal-payouts-sdk
# 安装正确的支付 SDK
composer require paypal/paypal-checkout-sdk

2. 解决 net::ERR_CONNECTION_TIMED_OUT 问题

  • 确认服务器/本地环境可访问 PayPal 沙盒域名(api-m.sandbox.paypal.com),排查防火墙、代理或 VPN 限制。
  • 在 Laravel .env 文件中正确配置沙盒凭据:
PAYPAL_MODE=sandbox
PAYPAL_CLIENT_ID=你的沙盒客户端ID
PAYPAL_CLIENT_SECRET=你的沙盒密钥

3. 修复 Create_order_error 与 JSON 解析错误

这类错误(Unexpected token '<')通常是后端创建订单的接口返回了HTML 错误页面(比如 Laravel 异常页面),而非预期的 JSON 响应。排查与修复步骤:

  • 确保后端接口捕获异常并返回 JSON 格式错误信息,示例控制器代码:
<?php

namespace App\Http\Controllers;

use PayPalCheckoutSdk\Core\PayPalHttpClient;
use PayPalCheckoutSdk\Core\SandboxEnvironment;
use PayPalCheckoutSdk\Orders\OrdersCreateRequest;
use Illuminate\Http\Request;

class PayPalController extends Controller
{
    public function createOrder()
    {
        $environment = new SandboxEnvironment(env('PAYPAL_CLIENT_ID'), env('PAYPAL_CLIENT_SECRET'));
        $client = new PayPalHttpClient($environment);

        $request = new OrdersCreateRequest();
        $request->prefer('return=representation');
        $request->body = [
            "intent" => "CAPTURE",
            "purchase_units" => [[
                "amount" => [
                    "currency_code" => "USD",
                    "value" => "10.00"
                ]
            ]]
        ];

        try {
            $response = $client->execute($request);
            return response()->json(['id' => $response->result->id]);
        } catch (\Exception $e) {
            return response()->json(['error' => $e->getMessage()], 500);
        }
    }
}
  • 前端 PayPal 按钮代码示例(确保调用正确后端接口,带 CSRF 令牌):
<script src="https://www.paypal.com/sdk/js?client-id=你的沙盒客户端ID&currency=USD"></script>

<div id="paypal-button-container"></div>

<script>
paypal.Buttons({
    createOrder: function(data, actions) {
        return fetch('/api/paypal/create-order', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content
            }
        }).then(function(response) {
            if (!response.ok) throw new Error('请求失败');
            return response.json();
        }).then(function(orderData) {
            return orderData.id;
        });
    },
    onApprove: function(data, actions) {
        return actions.order.capture().then(function(details) {
            alert('交易完成:' + details.payer.name.given_name);
        });
    },
    onError: function(err) {
        console.error('PayPal 错误:', err);
    }
}).render('#paypal-button-container');
</script>

4. 修复 Guzzle 400 Bad Request 错误

400 错误(INVALID_REQUEST)通常是请求格式或参数不符合 PayPal v2 规范,正确的 Guzzle 请求示例:

use GuzzleHttp\Client;

$client = new Client();

// 第一步:获取访问令牌
$tokenResponse = $client->post('https://api-m.sandbox.paypal.com/v1/oauth2/token', [
    'auth' => [env('PAYPAL_CLIENT_ID'), env('PAYPAL_CLIENT_SECRET')],
    'form_params' => ['grant_type' => 'client_credentials']
]);
$tokenData = json_decode($tokenResponse->getBody(), true);
$accessToken = $tokenData['access_token'];

// 第二步:创建订单
try {
    $orderResponse = $client->post('https://api-m.sandbox.paypal.com/v2/checkout/orders', [
        'headers' => [
            'Content-Type' => 'application/json',
            'Authorization' => 'Bearer ' . $accessToken
        ],
        'json' => [
            "intent" => "CAPTURE",
            "purchase_units" => [[
                "amount" => [
                    "currency_code" => "USD",
                    "value" => "10.00"
                ]
            ]]
        ]
    ]);
    $orderData = json_decode($orderResponse->getBody(), true);
    dd($orderData);
} catch (\GuzzleHttp\Exception\ClientException $e) {
    // 打印详细错误信息用于排查
    dd(json_decode($e->getResponse()->getBody(), true));
}

注意事项:

  • 必须使用 json 参数传递请求体,而非 form_params,同时确保请求头 Content-Type 为 application/json。
  • 检查 purchase_units、amount 的结构是否完全符合 PayPal v2 规范,避免拼写错误或参数缺失。

参考规范

  • PayPal v2 订单 API:重点关注创建订单、捕获订单的参数结构与必填项
  • Laravel 官方文档:API 响应格式、CSRF 保护的规范要求

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 21:55:18