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

PayPal REST API创建订单:Bash正常PHP报403 Forbidden

PayPal REST API创建订单PHP脚本返回403 Forbidden的原因

现象说明

Bash脚本调用PayPal REST API可正常完成认证并创建订单,但相同逻辑的PHP脚本在创建订单环节返回403 Forbidden错误。

问题核心原因

对比两段代码的请求头,关键差异在于创建订单接口的Content-Type设置错误:

  • Bash脚本中创建订单的请求头为Content-Type: application/json,符合PayPal v2/checkout/orders接口的要求(该接口仅接收JSON格式的请求体)
  • PHP脚本中错误将创建订单的Content-Type设置为application/x-www-form-urlencoded,导致PayPal服务器无法正确解析请求体,进而返回403权限拒绝错误。

另外,PHP认证接口使用的URL是api.sandbox.paypal.com,而Bash用的是api-m.sandbox.paypal.com,不过该差异不影响认证(两个域名均支持OAuth2 token接口),建议统一使用api-m.sandbox.paypal.com保持一致性。

修正方案

修改PHP脚本create_order函数的请求头,将Content-Type改为application/json:

$http_header = array
(
    "Content-Type: application/json", // 修正此处
    "Authorization: Bearer $access_token",
    "PayPal-Request-Id: 7b92603e-77ed-4896-8e78-5dea2050476a"
);

附:原代码及执行结果对比

正常运行的Bash脚本及执行结果

$ cat paypal.sh 
# https://developer.paypal.com/api/rest/authentication/

# https://developer.paypal.com/dashboard/applications/sandbox
CLIENT_ID="aaa"
CLIENT_SECRET="aaa"

# authenticate
RESULT=$( \
    curl \
    -s \
    -X POST "https://api-m.sandbox.paypal.com/v1/oauth2/token" \
    -u "${CLIENT_ID}:${CLIENT_SECRET}" \
    -H "Content-Type: application/x-www-form-urlencoded" \
    -d "grant_type=client_credentials")
ACCESS_TOKEN=$(echo ${RESULT} | sed 's/.*"access_token":"\([-_a-zA-Z0-9]*\)".*/\1/')
echo "ACCESS_TOKEN=${ACCESS_TOKEN}"

# create order
RESULT=$( \
    curl \
    -s \
    -X POST "https://api-m.sandbox.paypal.com/v2/checkout/orders" \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer ${ACCESS_TOKEN}" \
    -H "PayPal-Request-Id: 7b92603e-77ed-4896-8e78-5dea2050476a" \
    -d '{
  "intent": "CAPTURE",
  "purchase_units":
  [
    {
      "reference_id": "d9f80740-38f0-11e8-b467-0ed5f89f718b",
      "amount":
      {
        "currency_code": "EUR",
        "value": "10.00"
      }
    }
  ],
  "payment_source":
  {
    "paypal":
    {
      "experience_context":
      {
        "payment_method_preference": "IMMEDIATE_PAYMENT_REQUIRED",
        "payment_method_selected": "PAYPAL",
        "brand_name": "EXAMPLE INC",
        "locale": "en-US",
        "landing_page": "LOGIN",
        "shipping_preference": "SET_PROVIDED_ADDRESS",
        "user_action": "PAY_NOW",
        "return_url": "https://example.com/returnUrl",
        "cancel_url": "https://example.com/cancelUrl"
      }
    }
  }
}')
ORDER_ID=$(echo ${RESULT}     | sed 's/.*"id":"\([-a-zA-Z0-9_]*\)".*/\1/')
ORDER_STATUS=$(echo ${RESULT} | sed 's/.*"status":"\([A-Z_]*\)".*/\1/')
ORDER_HREF=$(echo ${RESULT}   | sed 's/.*"href":"\([-a-zA-Z0-9_:/.?=]*\)".*/\1/')
echo "ORDER_ID=${ORDER_ID}"
echo "ORDER_STATUS=${ORDER_STATUS}"
echo "ORDER_HREF=${ORDER_HREF}"

执行结果:

$ ./paypal.sh 
ACCESS_TOKEN=aaa
ORDER_ID=aaa
ORDER_STATUS=PAYER_ACTION_REQUIRED
ORDER_HREF=https://www.sandbox.paypal.com/checkoutnow?token=aaa

返回403的PHP脚本及执行结果

$ cat paypal.php 
<?php
function authenticate()
{
    $ch = false;
    $client_id = "aaa";
    $client_secret = "aaa";
    $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, false);
    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/x-www-form-urlencoded",
        "Authorization: Bearer $access_token",
        "PayPal-Request-Id: 7b92603e-77ed-4896-8e78-5dea2050476a"
    );
    $post_fields = '{
  "intent": "CAPTURE",
  "purchase_units":
  [
    {
      "reference_id": "d9f80740-38f0-11e8-b467-0ed5f89f718b",
      "amount":
      {
        "currency_code": "EUR",
        "value": "10.00"
      }
    }
  ],
  "payment_source":
  {
    "paypal":
    {
      "experience_context":
      {
        "payment_method_preference": "IMMEDIATE_PAYMENT_REQUIRED",
        "payment_method_selected": "PAYPAL",
        "brand_name": "EXAMPLE INC",
        "locale": "en-US",
        "landing_page": "LOGIN",
        "shipping_preference": "SET_PROVIDED_ADDRESS",
        "user_action": "PAY_NOW",
        "return_url": "https://example.com/returnUrl",
        "cancel_url": "https://example.com/cancelUrl"
      }
    }
  }
}';
    echo "create_order: access_token: $access_token
";
    echo "create_order: http_header: ";
    print_r($http_header);
    echo "create_order: post_fields: $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, true);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $http_header);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $post_fields);
    $result = curl_exec($ch);
    echo "create_order: result: ";
    print_r($result);
    echo "
";
    curl_close($ch);
}
$access_token = authenticate();
echo "access_token: ".$access_token."
";
create_order($access_token);
?>

执行结果:

$ php -f paypal.php 
access_token: aaa
create_order: access_token: aaa
create_order: http_header: Array
(
    [0] => Content-Type: application/x-www-form-urlencoded
    [1] => Authorization: Bearer aaa
    [2] => PayPal-Request-Id: 7b92603e-77ed-4896-8e78-5dea2050476a
)
create_order: post_fields: {
  "intent": "CAPTURE",
  "purchase_units":
  [
    {
      "reference_id": "d9f80740-38f0-11e8-b467-0ed5f89f718b",
      "amount":
      {
        "currency_code": "EUR",
        "value": "10.00"
      }
    }
  ],
  "payment_source":
  {
    "paypal":
    {
      "experience_context":
      {
        "payment_method_preference": "IMMEDIATE_PAYMENT_REQUIRED",
        "payment_method_selected": "PAYPAL",
        "brand_name": "EXAMPLE INC",
        "locale": "en-US",
        "landing_page": "LOGIN",
        "shipping_preference": "SET_PROVIDED_ADDRESS",
        "user_action": "PAY_NOW",
        "return_url": "https://example.com/returnUrl",
        "cancel_url": "https://example.com/cancelUrl"
      }
    }
  }
}
create_order: result: 403 Forbidden

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 09:41:20