PAYATHON 2026

PHP调用支付宝交易查询API报错,支付接口调用正常

支付老李

结论

支付接口正常,但交易查询接口报错,通常不代表整个 SDK 不可用。问题多半出在查询接口的调用方法、请求参数或返回值处理上。

支付宝 PHP SDK 的支付接口可能使用 pageExecute()、sdkExecute() 等方法。alipay.trade.query 是普通 OpenAPI,需要通过 execute() 调用,请求类为 AlipayTradeQueryRequest。查询时还要提供有效的 out_trade_no 或 trade_no。

问题中没有具体错误信息和完整代码,因此暂时无法确定唯一原因。可以按下面的顺序检查。

正确的调用示例

下面的示例适用于常见的 AopClient 版支付宝 PHP SDK。不同版本的命名空间和加载方式可能不同,请以项目实际安装的 SDK 为准。

<?php

$aop = new AopClient();

$aop->gatewayUrl = 'https://openapi.alipay.com/gateway.do';
$aop->appId = '你的 APPID';
$aop->rsaPrivateKey = '应用私钥';
$aop->alipayrsaPublicKey = '支付宝公钥';
$aop->signType = 'RSA2';
$aop->postCharset = 'UTF-8';
$aop->format = 'json';

$request = new AlipayTradeQueryRequest();

$bizContent = [
    // out_trade_no 和 trade_no 至少提供一个
    'out_trade_no' => '你的商户订单号',
];

$request->setBizContent(
    json_encode($bizContent, JSON_UNESCAPED_UNICODE)
);

try {
    $response = $aop->execute($request);

    $node = 'alipay_trade_query_response';

    if (!isset($response->$node)) {
        throw new RuntimeException(
            '支付宝返回结构异常:' .
            json_encode($response, JSON_UNESCAPED_UNICODE)
        );
    }

    $result = $response->$node;

    if (($result->code ?? '') !== '10000') {
        printf(
            "查询失败:code=%s,sub_code=%s,msg=%s,sub_msg=%s\n",
            $result->code ?? '',
            $result->sub_code ?? '',
            $result->msg ?? '',
            $result->sub_msg ?? ''
        );
    } else {
        printf(
            "查询成功:trade_status=%s,trade_no=%s\n",
            $result->trade_status ?? '',
            $result->trade_no ?? ''
        );
    }
} catch (Throwable $e) {
    echo '调用异常:' . $e->getMessage();
}

如果要使用支付宝交易号查询,可以改成:

$bizContent = [
    'trade_no' => '支付宝交易号',
];

支付接口生成请求字符串的方式不能直接用于查询接口。例如:

// 页面支付可能这样调用
$aop->pageExecute($payRequest);

// App 支付可能这样调用
$aop->sdkExecute($payRequest);

// 交易查询应这样调用
$aop->execute($queryRequest);

重点排查项

1. 检查请求类

交易查询接口通常使用:

AlipayTradeQueryRequest

请求类、SDK 命名空间或自动加载配置不正确时,可能出现「类不存在」或接口方法不匹配等异常。

如果项目通过 Composer 加载 SDK,请确认入口文件已经加载:

require_once __DIR__ . '/vendor/autoload.php';

具体命名空间取决于安装的 SDK 包,不要混用不同版本文档中的类名。

2. 确认使用了 execute()

alipay.trade.query 是服务端查询接口,通常应这样调用:

$response = $aop->execute($request);

支付接口能正常调用,只能说明支付请求的生成流程可用,无法证明查询接口使用了正确的执行方法。

3. 检查 biz_content 是否为合法 JSON

建议先构造 PHP 数组,再调用 json_encode():

$bizContent = [
    'out_trade_no' => $outTradeNo,
];

$json = json_encode($bizContent, JSON_UNESCAPED_UNICODE);

if ($json === false) {
    throw new RuntimeException(
        'biz_content JSON 编码失败:' . json_last_error_msg()
    );
}

$request->setBizContent($json);

不要手工拼接 JSON。订单号中一旦包含引号、反斜杠或其他特殊字符,手工拼接可能造成格式错误。

4. 确认订单号属于当前应用和环境

查询的订单必须与当前网关、应用和商户配置一致。需要逐项检查:

  • 是否使用正式环境网关查询沙箱订单;
  • 是否使用沙箱网关查询正式订单;
  • out_trade_no 是否与支付时提交的商户订单号完全一致;
  • 订单是否由当前 app_id 对应的应用创建;
  • 订单是否刚刚提交,支付宝尚未成功受理;
  • out_trade_no 是否被截断、转换成数字或带有多余空格。

商户订单号最好始终按字符串处理:

$outTradeNo = trim((string) $outTradeNo);

不要用浮点数保存长订单号,否则可能丢失精度。

5. 不要只读取最外层返回对象

查询接口的业务结果一般在以下节点中:

$response->alipay_trade_query_response

各字段的含义如下:

  • code 表示网关或业务处理结果;
  • sub_code 表示更具体的错误代码;
  • msg 是主错误信息;
  • sub_msg 是详细错误说明;
  • trade_status 是查询成功后的交易状态。

判断是否成功时,不能只看 $response 是否为空,还要检查业务节点中的 code:

$result = $response->alipay_trade_query_response ?? null;

if ($result === null) {
    // 返回结构异常
} elseif (($result->code ?? '') === '10000') {
    // 查询成功
} else {
    // 根据 sub_code 和 sub_msg 定位业务错误
}

根据错误类型继续定位

如果程序直接抛出 PHP 异常,先检查 SDK 加载、请求类、证书或密钥文件、网络连接和 PHP 扩展。

如果支付宝已经返回 JSON,但 code 不是 10000,请完整记录这些字段:

$logData = [
    'code' => $result->code ?? null,
    'msg' => $result->msg ?? null,
    'sub_code' => $result->sub_code ?? null,
    'sub_msg' => $result->sub_msg ?? null,
];

error_log(json_encode($logData, JSON_UNESCAPED_UNICODE));

可以根据错误类型继续检查:

  • 签名验证失败:核对应用私钥、支付宝公钥、app_id 和 signType;
  • 参数无效:核对 biz_content、参数名称和 JSON 格式;
  • 交易不存在:核对订单号、应用归属以及沙箱或正式环境;
  • 权限不足:确认应用是否具有对应产品和接口的权限;
  • 返回解析失败:检查响应节点名称,以及对象和数组的访问方式。

排查时要保留完整的 code、sub_code、msg、sub_msg 和异常堆栈,但不要在日志中输出应用私钥、支付宝公钥原文或其他敏感凭据。

还需要补充的信息

如果按上述方法仍无法解决,需要补充以下信息:

  • 完整错误信息或异常堆栈;
  • 查询接口的调用代码;
  • SDK 的准确包名和版本;
  • 当前使用的是沙箱环境还是正式环境;
  • 返回的 code、sub_code、msg 和 sub_msg;
  • PHP 版本和 SDK 加载方式。

订单号可以脱敏,密钥必须删除。只说「交易查询 API 报错」,无法判断具体是 PHP 运行异常、签名错误、参数错误、权限问题,还是查询了不属于当前应用的订单。

备注:内容仅供参考。