支付宝支付沙盒 PHP 返回 SYSTEM_ERROR,是代码还是平台问题?
结论
SYSTEM_ERROR 通常表示支付宝网关或沙盒在处理请求时发生了内部异常,不能只凭这个错误码就认定 PHP 代码有问题。如果同一套请求此前可以正常运行,签名校验也已通过,接口又没有返回明确的参数或权限错误,那么沙盒环境暂时不稳定的可能性更大。
不过,SYSTEM_ERROR 是通用错误,具体原因还要结合响应中的 code、sub_code、sub_msg 和 request_id 判断。请求参数、密钥或网关配置有误时,支付宝通常会返回更具体的错误信息,不会只给出 SYSTEM_ERROR。
先检查完整响应
不要只记录 msg,最好保存支付宝返回的完整响应:
$response = $aop->execute($request);
$result = $response->alipay_trade_precreate_response ?? null;
if ($result === null) {
error_log('Alipay raw response: ' . json_encode(
$response,
JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES
));
throw new RuntimeException('支付宝响应结构异常');
}
error_log('Alipay response: ' . json_encode(
$result,
JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES
));
if (($result->code ?? '') !== '10000') {
printf(
"支付请求失败:code=%s, msg=%s, sub_code=%s, sub_msg=%s\n",
$result->code ?? '',
$result->msg ?? '',
$result->sub_code ?? '',
$result->sub_msg ?? ''
);
}
不同版本的 PHP SDK 可能返回不同的对象结构,应以实际响应为准。排查时至少保留这些信息:
codemsgsub_codesub_msgrequest_id- 请求时间
app_id- 接口名称
out_trade_no
日志中不要写入应用私钥、支付宝公钥原文或用户敏感信息。
核对沙盒配置
PHP SDK 的基本配置可参考以下写法:
$aop = new AopClient();
$aop->gatewayUrl = 'https://openapi.alipaydev.com/gateway.do';
$aop->appId = '你的沙盒应用 APPID';
$aop->rsaPrivateKey = '你的应用私钥';
$aop->alipayrsaPublicKey = '沙盒环境对应的支付宝公钥';
$aop->signType = 'RSA2';
$aop->charset = 'UTF-8';
$aop->format = 'json';
逐项检查以下配置和参数:
gatewayUrl是否指向沙盒网关,而非正式环境网关。appId是否属于当前使用的沙盒应用。- 应用私钥是否与上传到该沙盒应用的应用公钥配对。
alipayrsaPublicKey填写的是否为支付宝公钥,不能误填成应用公钥。signType是否与应用配置一致。biz_content是否为合法的 JSON。- 金额、订单号、商品标题等必填参数是否为空,格式是否正确。
- 当前应用是否已获得对应接口的权限。
以 alipay.trade.precreate 为例:
$request = new AlipayTradePrecreateRequest();
$bizContent = [
'out_trade_no' => 'TEST_' . date('YmdHis'),
'total_amount' => '0.01',
'subject' => '沙盒支付测试',
];
$request->setBizContent(json_encode(
$bizContent,
JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES
));
$response = $aop->execute($request);
如果 PHP SDK 能生成签名并收到支付宝的业务响应,说明网络请求至少已经到达网关。不过,请求内容仍有可能触发服务端异常,因此还不能完全排除参数相关的问题。
如何判断是不是沙盒平台问题
建议按下面的顺序排查:
- 使用相同参数重新请求一次,确认问题不是由偶发的网络异常引起。
- 查看完整响应中有没有更具体的
sub_code和sub_msg。 - 使用支付宝提供的接口调试方式发送相同的业务参数。
- 更换一个新的
out_trade_no进行沙盒测试。 - 等待几分钟后再次调用。
- 查看支付宝开放平台是否记录了对应的调用日志或异常提示。
- 如果调试请求和 PHP 请求都返回相同的
SYSTEM_ERROR,问题更可能出在沙盒平台。 - 如果调试请求成功,但 PHP 请求失败,应重点检查 SDK、签名、公私钥及请求参数的编码。
沙盒环境偶尔会出现服务异常。但在没有平台公告或官方工单结论时,不宜直接断定支付宝发生了故障。
避免重复支付或订单状态不一致
遇到系统错误后,不要直接认定订单创建失败。服务端可能已经受理了请求,只是在返回结果时发生异常。对于使用固定 out_trade_no 的交易,应先调用 alipay.trade.query 查询订单状态,再决定是否重试。
$queryRequest = new AlipayTradeQueryRequest();
$queryRequest->setBizContent(json_encode([
'out_trade_no' => $outTradeNo,
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
$queryResponse = $aop->execute($queryRequest);
重试时不要无条件生成新的订单号,否则可能创建多个支付订单。只有确认原订单不存在,或者业务明确允许重新下单时,才应使用新的 out_trade_no。
处理建议
如果完整响应中只有通用的 SYSTEM_ERROR,并且已经确认网关、APPID、密钥、签名方式和业务参数均无误,可以暂时按支付宝沙盒服务异常处理。记录 request_id 和请求时间,稍后重试,同时向支付宝开放平台提交工单。
提交问题时,应提供接口名称、错误码、sub_code、request_id、请求时间以及脱敏后的业务参数。只提供一句 SYSTEM_ERROR,通常无法准确定位原因。
备注:内容仅供参考。
