同一批JSON有时成功、有时返回400 Decoding error,客户端本地解析也没问题。这种偶发性要优先怀疑传输层:请求体被截断、gzip标头与实际内容不一致,或API网关解压后仍把Content-Encoding:gzip传给Magento。
保存一份失败请求的原始证据
在客户端记录请求ID、Content-Length、Content-Encoding和请求体SHA-256,不要记录Token和客户隐私。服务端按同一请求ID记录接收到的字节数与哈希。两端哈希不同,问题发生在代理链。
sha256sum payload.json curl -v --data-binary @payload.json \ -H 'Content-Type: application/json' \ -H 'Authorization: Bearer ***' \ https://example.com/rest/V1/your/endpoint
gzip请求要么完整支持,要么关闭
HTTP响应gzip很常见,但压缩请求体并非所有Nginx和PHP组合都会自动处理。如果网关已解压请求体,必须移除或改写Content-Encoding;否则下游会对普通JSON再解压一次并失败。先用未压缩data-binary请求建立基线。
检查大小限制与超时
nginx -T | grep -E 'client_max_body_size|client_body_timeout|proxy_request_buffering' php -i | grep -E 'post_max_size|max_input_time'
超限常返回413,但自定义网关可能统一映射成400。比较失败请求大小是否集中在某个阈值,查看Nginx error log有没有client intended to send too large body或upstream prematurely closed。
JSON本身也要按字节验证
- Content-Type明确为application/json并使用UTF-8;
- 去掉UTF-8 BOM和不可见控制字符;
- 金额用数字或约定字符串,不使用NaN或Infinity;
- 不要用普通表单编码发送JSON;
- PHP端读取php://input一次后不要让插件再次读取空流。
最终在相同代理链连续发送多种大小的固定payload并核对哈希。修好后错误率应归零,而不是因为重试掩盖偶发失败。

