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

Google Apps Script调用PayPal REST API出现400(INVALID_REQUEST)错误排查求助

解决Google Apps Script调用PayPal API订阅接口返回400错误的问题

我一眼就看出问题所在了——你在Google Apps Script里处理请求体的方式不对,导致发送给PayPal的请求格式不符合要求。

问题根源

Postman会自动帮你把JSON请求体正确编码发送,但Google Apps Script的UrlFetchApp默认行为不一样:当你直接把JavaScript对象传给payload时,它会自动将对象编码成表单格式(application/x-www-form-urlencoded),而不是JSON格式。哪怕你在headers里设置了Content-Type: application/json,UrlFetchApp还是会用默认的表单编码覆盖这个设置,最终PayPal收到的是格式错误的请求体,自然返回400报错。

修复方案

你需要做两个关键修改:

  1. 将请求体对象转换为JSON字符串(用JSON.stringify())
  2. 在请求参数里明确指定contentType: "application/json",确保请求按JSON格式发送

修改后的完整代码如下:

function restCall (){
  var restEndpoint = "https://api-m.sandbox.paypal.com/v1/billing/subscriptions"
  var head = {
    "Authorization":"Bearer "+ TokenProperties.getAccessToken(),
    "PayPal-Request-Id": "1111-1111-1111-1111"
  }
  var postPayload = {
    "plan_id": "P-09E19660L3543673CMETTBBA",
    "subscriber": {
      "name": {
        "given_name": "John",
        "surname": "Doe"
      },
      "email_address": "sb-y9erz7310462@personal.example.com"
    },
    "application_context": {
      "brand_name": "Test",
      "user_action": "SUBSCRIBE_NOW",
      "payment_method": {
        "payer_selected": "PAYPAL",
        "payee_preferred": "IMMEDIATE_PAYMENT_REQUIRED"
      },
      "return_url": "https://example.com/returnUrl",
      "cancel_url": "https://example.com/cancelUrl"
    }
  }
  var params = {
    headers: head,
    method: "POST",
    contentType: "application/json", // 明确指定JSON内容类型
    payload : JSON.stringify(postPayload), // 将对象转为JSON字符串
    muteHttpExceptions: true // 可选,方便查看完整错误响应
  }
  try {
    var response = UrlFetchApp.fetch(restEndpoint, params);
    console.log("Success response: " + response.getContentText());
  } catch(e) {
    console.log("Error details: " + e.message);
  }
}

额外提示

  • 我在代码里加了try-catch和muteHttpExceptions: true,这样你能看到更详细的错误信息,方便后续排查
  • 可以打印一下TokenProperties.getAccessToken()的结果,确保令牌是有效的(虽然Postman能正常请求,但GAS里可能令牌获取逻辑有问题,不过概率不大)
  • 移除了headers里的Content-Type,因为params里的contentType会自动设置请求头,避免重复设置导致冲突

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 09:42:33