PAYATHON 2026

向 payment gateway 传值时出现 media type unsupported

支付阿杰

结论

HTTP 415 Unsupported Media Type 表示请求的 Content-Type 与支付网关支持的媒体类型不匹配,通常与字段是否成功填充无关。

如果支付网关要求普通表单提交,应使用 POST,浏览器发送的内容类型应为:

Content-Type: application/x-www-form-urlencoded

除非网关文档明确要求上传文件,否则不要将表单设置为 multipart/form-data。同时,所有 <input> 都必须放在完整的 <form> 标签内。

正确的表单结构

OpenCart 模板可以这样写:

<form action="<?php echo htmlspecialchars($action, ENT_QUOTES, 'UTF-8'); ?>"
      method="post">
    <input type="hidden" name="merchant_id"
           value="<?php echo htmlspecialchars($merchant_id, ENT_QUOTES, 'UTF-8'); ?>" />

    <input type="hidden" name="order_id"
           value="<?php echo htmlspecialchars($order_id, ENT_QUOTES, 'UTF-8'); ?>" />

    <input type="hidden" name="amount"
           value="<?php echo htmlspecialchars($amount, ENT_QUOTES, 'UTF-8'); ?>" />

    <input type="hidden" name="currency"
           value="<?php echo htmlspecialchars($currency, ENT_QUOTES, 'UTF-8'); ?>" />

    <input type="hidden" name="return_url"
           value="<?php echo htmlspecialchars($return_url, ENT_QUOTES, 'UTF-8'); ?>" />

    <input type="submit" value="Pay" class="button" />
</form>

普通 HTML 表单不设置 enctype 时,浏览器默认使用:

application/x-www-form-urlencoded

也可以显式声明:

<form action="https://gateway.example/payment"
      method="post"
      enctype="application/x-www-form-urlencoded">

常见错误

如果当前代码是下面这种形式:

<form action="https://gateway.example/payment"
      method="post"
      enctype="multipart/form-data">

浏览器会发送:

Content-Type: multipart/form-data; boundary=...

不少支付接口只接受 URL 编码表单或 JSON,收到这种请求后会直接返回 415 Unsupported Media Type。通常只需删除 enctype:

<form action="https://gateway.example/payment" method="post">

还要检查这些内容:

  • <form> 的 action 是否正确,method 是否为 "post"。
  • 每个字段是否都有网关规定的 name。服务器接收的是 name,不是 id。
  • 所有字段是否确实位于 <form>...</form> 内。
  • 是否误用了 multipart/form-data、text/plain 或其他网关不支持的编码方式。
  • 网关需要的是浏览器表单提交还是后端 API 请求。两种方式不能只靠修改隐藏字段来互换。
  • 金额、币种、签名和回调地址的字段名与格式是否完全符合网关文档。

如果网关要求 JSON

原生表单提交不会自动生成 JSON。如果接口明确要求:

Content-Type: application/json

应由 OpenCart 后端向网关发起请求,不要直接提交 HTML 表单。例如:

$payload = [
    'merchant_id' => $merchant_id,
    'order_id'    => $order_id,
    'amount'      => $amount,
    'currency'    => $currency,
];

$ch = curl_init($gatewayUrl);

curl_setopt_array($ch, [
    CURLOPT_POST           => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => [
        'Content-Type: application/json',
        'Accept: application/json',
    ],
    CURLOPT_POSTFIELDS     => json_encode($payload),
]);

$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

究竟应该使用 application/x-www-form-urlencoded、multipart/form-data 还是 application/json,要以支付网关的接口文档为准。变量有值并不代表可以排除 415。应打开浏览器开发者工具,在 Network 面板中查看实际请求的 Request Headers 和 Content-Type。

备注:内容仅供参考。