PAYATHON 2026

Facebook payment 打开支付对话框时报 API Error Code: 1383008

支付阿杰

结论

API Error Code: 1383008 通常与回调页面能否在浏览器中打开无关,而是 Facebook 无法按照支付协议验证或调用该 URL。排查时应重点检查支付配置、服务器端可访问性、回调响应格式和商品参数。

如果使用旧版 Facebook Canvas Payments / Facebook Credits,还要先确认当前应用是否仍能使用该接口。已经下线的支付能力无法通过修改 callback URL 恢复。

排查步骤

1. 确认应用具备支付资格

在 Meta 应用后台逐项检查:

  • 应用已退出 Development Mode,或者当前账号已加入管理员、开发者或测试人员名单。
  • 该应用已启用支付产品。
  • 应用域名、Canvas URL、Secure Canvas URL 与实际域名一致。
  • 商户、公司、收款账户和必要的合规信息已配置完成。
  • 当前商品类型、币种和用户所在地区受到支持。

如果后台配置不完整,即使 callback URL 返回 200 OK,支付对话框也可能无法打开。

2. 从公网验证 callback URL

仅在本机或浏览器中测试还不够,Facebook 的服务器必须能够直接访问该地址。

callback URL 需要满足以下条件:

  • 使用有效的 HTTPS 证书。
  • 不是 localhost、内网 IP 或只能通过测试网络访问的域名。
  • DNS 已在公网生效。
  • 不依赖浏览器 Cookie 或登录状态。
  • 不会返回登录页、验证码或 WAF 挑战页面。
  • 尽量不经过 301、302 等重定向。
  • 能够在合理时间内返回 2xx。
  • 防火墙、CDN 和反向代理不会拦截 Facebook 发出的请求。

可以使用一台不在公司网络中的服务器进行检查:

curl -i https://example.com/facebook/payment/callback

普通 GET 请求成功只能说明该地址可以访问,不能证明支付回调处理正确。实际回调可能使用 POST,并携带 signed_request 等参数。

3. 正确处理 signed_request

不能直接信任支付回调中的数据,应使用应用密钥验证签名。下面是一个简化的 PHP 示例:

<?php

function parseSignedRequest(string $signedRequest, string $appSecret): ?array
{
    [$encodedSignature, $encodedPayload] = explode('.', $signedRequest, 2);

    $decode = static function (string $value): string {
        return base64_decode(
            strtr($value, '-_', '+/')
        );
    };

    $signature = $decode($encodedSignature);
    $payload = json_decode($decode($encodedPayload), true);

    if (!is_array($payload)) {
        return null;
    }

    $expectedSignature = hash_hmac(
        'sha256',
        $encodedPayload,
        $appSecret,
        true
    );

    if (!hash_equals($expectedSignature, $signature)) {
        return null;
    }

    return $payload;
}

$signedRequest = $_POST['signed_request'] ?? '';
$data = parseSignedRequest($signedRequest, getenv('FACEBOOK_APP_SECRET'));

if ($data === null) {
    http_response_code(400);
    echo 'Invalid signed_request';
    exit;
}

// 根据所使用的 Payments API 协议处理请求并返回规定的响应。
http_response_code(200);
header('Content-Type: application/json');
echo json_encode(['success' => true]);

这段代码只演示签名校验。实际响应结构应以应用正在使用的 Payments API 版本及其文档为准,不能随意返回 JSON。

4. 检查支付对话框参数

如果调用支付对话框时传入了商品 URL,需要确认该地址是公开、稳定的 HTTPS URL,并且能够返回 Facebook 要求的商品元数据。

示意调用如下:

FB.ui(
  {
    method: 'pay',
    action: 'purchaseitem',
    product: 'https://example.com/products/item-1001'
  },
  function (response) {
    if (!response) {
      console.error('Payment dialog closed or failed');
      return;
    }

    if (response.error_code) {
      console.error(response.error_code, response.error_message);
      return;
    }

    console.log(response);
  }
);

逐项核对以下内容:

  • method 和 action 属于应用实际接入的 API。
  • product 使用完整的 HTTPS URL。
  • Facebook 爬虫可以访问商品 URL。
  • 商品元数据中的价格、币种、标题和图片符合要求。
  • 商品 URL 不会返回重定向页、登录页或 HTML 错误页。
  • 代码使用的 App ID 与后台配置 callback URL 的应用一致。

5. 查看服务器日志

在 callback URL 对应的服务中记录:

  • 请求时间和 HTTP 方法。
  • 请求路径和状态码。
  • User-Agent。
  • 是否收到 signed_request。
  • 签名验证结果。
  • 处理耗时。
  • 应用异常和反向代理错误。

不要将完整的 signed_request、App Secret、Access Token 或支付用户信息写入公开日志。

如果打开支付对话框时服务器完全没有收到请求,问题更可能出在应用资格、支付产品配置、商品 URL 或接口可用性上。如果服务器收到了请求,但返回 4xx、5xx 或错误的响应格式,应优先检查并修复回调处理逻辑。

容易忽略的问题

  • 测试环境的域名配置正确,但代码使用了生产环境的 App ID。
  • callback URL 的路径大小写不一致。
  • TLS 证书链不完整。浏览器可能允许访问,但服务器端验证会失败。
  • Cloudflare、WAF 或限流规则拦截了回调。
  • 回调接口要求 CSRF Token,导致外部 POST 请求被拒绝。
  • 接口先返回重定向,再跳转到实际处理地址。
  • PHP、Node.js 或代理层未正确解析表单格式的请求体。
  • 对话框参数仍在使用已经废弃的 Facebook Credits 示例。

1383008 在不同的历史支付接口中不一定表示完全相同的失败原因,不能只凭错误码认定某个字段有问题。建议先确认接口仍受支持,再检查应用的支付资格,然后验证 Facebook 服务器是否确实访问了 callback URL,最后核对回调协议和支付对话框参数。

备注:内容仅供参考。