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

开发WP插件集成PayPal按钮:无法获取服务器生成的Order ID

问题

我正在开发一款WordPress插件,用来在页面中添加PayPal按钮,采用PayPal官方示例的JS代码。在createOrder()方法中,我通过fetch调用后端的create-paypal-order.php接口获取订单ID,相关JS代码如下:

paypal.Buttons({
        createOrder() {   
            return fetch( dir + '/includes/api/create-paypal-order.php', {           
            method: "POST",
            headers: {
              "Content-Type": "application/json",
            },
            body: JSON.stringify({
              cart: [
                {
                  sku: "YOUR_PRODUCT_STOCK_KEEPING_UNIT",
                  quantity: "YOUR_PRODUCT_QUANTITY",
                },
              ],
            }),
            referrerPolicy: "origin-when-cross-origin" 
          })
          .then((response) => response.json())
          .then((order) => order.id)
          .then((order) => {console.log(order); return order;} );
        },
        // Finalize the transaction on the server after payer approval
        onApprove(order) {  
          ...
        },
      }).render('#paypal-button-container');

对应的PHP文件(create-paypal-order.php)代码如下:

function authenticate()
{
    $ch = false;
    $client_id = "Aeh...bbX";
    $client_secret = "EPRl...yZFw";
    $http_header = array("Content-Type: application/json");
    $post_fields = 'grant_type=client_credentials';
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, "https://api.sandbox.paypal.com/v1/oauth2/token");
    curl_setopt($ch, CURLOPT_HEADER, false);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_SSLVERSION , 6); //NEW ADDITION
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_USERPWD, $client_id.":".$client_secret);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $http_header);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $post_fields);

    $result = curl_exec($ch);
    $json = json_decode($result);
    $access_token = $json->access_token;
    curl_close($ch);
    return $access_token;
}

function create_order($access_token)
{
    $ch = false;
    $http_header = array
    (
        "Content-Type: application/json",
        "Authorization: Bearer " . $access_token,
        "PayPal-Request-Id: 7b92603e-77ed-4896-8e78-5dea2050476a",
    );
    $post_fields = '{}';
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, "https://api-m.sandbox.paypal.com/v2/checkout/orders");
    curl_setopt($ch, CURLOPT_HEADER, false);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_POST, false);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $http_header);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $post_fields);
    $result = curl_exec($ch);
    $json = json_encode($result);

    curl_close($ch);
    return $json;
}

$access_token = authenticate();
create_order($access_token);

10天前代码能正常获取order.id,现在出现错误:Unexpected end of JSON input\n at h…IwSW2JlwdPGZBlSA_Moyiy5KHbbX&currency=USD:3:91171,请问如何修复该错误并成功获取order.id?PHP文件是否存在问题?return的使用是否正确?


修复方案

1. 核心PHP问题修复(直接导致JSON解析错误)

你的PHP代码有3个致命问题:

  • 没有输出接口结果:调用create_order($access_token)后,没有用echo输出返回内容,前端fetch接收不到任何响应,触发“Unexpected end of JSON input”错误。
  • 错误的请求方法:PayPal创建订单API要求用POST请求,但你设置了CURLOPT_POST: false,这会导致请求失败。
  • 多余的JSON编码:$result是PayPal返回的原生JSON字符串,你用json_encode($result)会把它转成双重编码的JSON,前端解析必然出错。

修改后的create_order函数及执行代码:

function create_order($access_token)
{
    $ch = false;
    $http_header = array
    (
        "Content-Type: application/json",
        "Authorization: Bearer " . $access_token,
        "PayPal-Request-Id: 7b92603e-77ed-4896-8e78-5dea2050476a",
    );
    // 空的{}不符合PayPal订单要求,必须补充金额等核心信息
    $post_fields = json_encode([
        "intent" => "CAPTURE",
        "purchase_units" => [
            [
                "amount" => [
                    "currency_code" => "USD",
                    "value" => "10.00"
                ]
            ]
        ]
    ]);
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, "https://api-m.sandbox.paypal.com/v2/checkout/orders");
    curl_setopt($ch, CURLOPT_HEADER, false);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true); // 建议开启SSL验证,避免安全风险
    curl_setopt($ch, CURLOPT_POST, true); // 强制POST请求
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $http_header);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $post_fields);
    $result = curl_exec($ch);
    
    // 添加curl错误排查
    if(curl_errno($ch)){
        $error = curl_error($ch);
        curl_close($ch);
        http_response_code(500);
        echo json_encode(["error" => $error]);
        exit;
    }
    
    curl_close($ch);
    return $result;
}

$access_token = authenticate();
// 输出接口结果,让前端能拿到响应
echo create_order($access_token);

2. 修复access_token获取的请求头问题

PayPal获取access_token的接口要求Content-Type为application/x-www-form-urlencoded,之前用application/json不符合规范,容易触发兼容性问题:

function authenticate()
{
    $ch = false;
    $client_id = "Aeh...bbX";
    $client_secret = "EPRl...yZFw";
    // 修改为正确的请求头类型
    $http_header = array("Content-Type: application/x-www-form-urlencoded");
    $post_fields = 'grant_type=client_credentials';
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, "https://api.sandbox.paypal.com/v1/oauth2/token");
    curl_setopt($ch, CURLOPT_HEADER, false);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_USERPWD, $client_id.":".$client_secret);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $http_header);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $post_fields);

    $result = curl_exec($ch);
    
    // 添加错误排查
    if(curl_errno($ch)){
        $error = curl_error($ch);
        curl_close($ch);
        http_response_code(500);
        echo json_encode(["error" => $error]);
        exit;
    }
    
    $json = json_decode($result);
    // 检查是否成功获取access_token
    if(!isset($json->access_token)){
        http_response_code(500);
        echo json_encode(["error" => "获取access_token失败", "details" => $json]);
        exit;
    }
    $access_token = $json->access_token;
    curl_close($ch);
    return $access_token;
}

3. JS代码错误处理优化

给fetch添加错误捕获,避免后端返回非200状态码时的解析崩溃:

paypal.Buttons({
        createOrder() {   
            return fetch( dir + '/includes/api/create-paypal-order.php', {           
            method: "POST",
            headers: {
              "Content-Type": "application/json",
            },
            body: JSON.stringify({
              cart: [
                {
                  sku: "YOUR_PRODUCT_STOCK_KEEPING_UNIT",
                  quantity: "YOUR_PRODUCT_QUANTITY",
                },
              ],
            }),
            referrerPolicy: "origin-when-cross-origin" 
          })
          .then((response) => {
              if (!response.ok) {
                  throw new Error('接口请求失败');
              }
              return response.json();
          })
          .then((order) => {
              console.log(order);
              return order.id;
          })
          .catch(error => {
              console.error('创建订单失败:', error);
              // 可在此添加用户可见的错误提示
          });
        },
        onApprove(order) {  
          ...
        },
      }).render('#paypal-button-container');

关键问题总结

  1. PHP接口未echo返回结果,导致前端无数据可解析。
  2. 创建订单时用了GET请求(CURLOPT_POST: false),不符合PayPal API要求。
  3. 对PayPal返回的JSON字符串重复编码,导致解析失败。
  4. 获取access_token的请求头类型错误,存在兼容性风险。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 12:48:13