PAYATHON 2026

支付宝APP支付成功后如何获取返回数据中的trade_no

支付小周

结论

支付宝 APP 支付完成后,trade_no 最好从支付宝服务器发送的异步通知中获取,不要直接信任 APP 返回的支付结果。

PHP 异步通知接口完成签名验证,并确认 trade_status、金额、商户号等信息无误后,可以直接读取:

$tradeNo = $_POST['trade_no'] ?? '';

如果客户端需要立即展示支付结果,也可以解析 APP 支付 SDK 返回数据中的 result 字段,再从 alipay_trade_app_pay_response 中读取 trade_no。不过,这个值只能用于展示或作为查询线索,不能作为后台确认支付成功的唯一依据。

APP 返回数据的常见结构

不同客户端 SDK 版本和封装方式返回的数据可能有所不同,常见结构大致如下:

{
  "resultStatus": "9000",
  "memo": "",
  "result": "alipay_trade_app_pay_response={\"code\":\"10000\",\"msg\":\"Success\",\"trade_no\":\"2026xxxxxxxx\",\"out_trade_no\":\"ORDER123\"}&sign=xxxx&sign_type=RSA2"
}

各字段的含义如下:

  • resultStatus 是客户端 SDK 返回的状态。
  • result 通常是查询字符串,不能直接对整个字段执行 json_decode()。
  • alipay_trade_app_pay_response 是包含支付结果的 JSON 数据。
  • trade_no 是支付宝交易号。
  • out_trade_no 是商户系统创建订单时提交的订单号。

PHP 解析 APP 返回结果

假设 APP 将完整的支付结果作为 JSON 请求体提交给 PHP 后台,可以这样解析:

<?php

$rawBody = file_get_contents('php://input');
$appResult = json_decode($rawBody, true);

if (!is_array($appResult)) {
    throw new RuntimeException('支付结果格式错误');
}

$resultStatus = (string)($appResult['resultStatus'] ?? '');
$resultString = (string)($appResult['result'] ?? '');

if ($resultStatus !== '9000' || $resultString === '') {
    throw new RuntimeException('客户端未返回支付成功结果');
}

parse_str($resultString, $resultParameters);

$responseJson = $resultParameters['alipay_trade_app_pay_response'] ?? '';

if ($responseJson === '') {
    throw new RuntimeException('缺少 alipay_trade_app_pay_response');
}

$paymentResponse = json_decode($responseJson, true);

if (!is_array($paymentResponse)) {
    throw new RuntimeException('支付宝支付响应解析失败');
}

if (($paymentResponse['code'] ?? '') !== '10000') {
    throw new RuntimeException(
        '支付宝业务处理失败:' . ($paymentResponse['sub_msg'] ?? $paymentResponse['msg'] ?? '未知错误')
    );
}

$tradeNo = (string)($paymentResponse['trade_no'] ?? '');

if ($tradeNo === '') {
    throw new RuntimeException('支付结果中没有 trade_no');
}

echo $tradeNo;

主要的解析过程是:

parse_str($appResult['result'], $resultParameters);

$paymentResponse = json_decode(
    $resultParameters['alipay_trade_app_pay_response'],
    true
);

$tradeNo = $paymentResponse['trade_no'] ?? '';

如果 APP 已经解析过 SDK 返回值,只向后台提交 result 字符串,后台可以直接从 parse_str() 开始处理。

推荐做法:从支付宝异步通知获取

创建 APP 支付订单时,需要设置支付宝能够访问的 notify_url。支付状态变化后,支付宝会向该地址发送表单格式的 POST 请求。

PHP 可以这样接收:

<?php

$notifyData = $_POST;

$tradeNo = (string)($notifyData['trade_no'] ?? '');
$outTradeNo = (string)($notifyData['out_trade_no'] ?? '');
$tradeStatus = (string)($notifyData['trade_status'] ?? '');

if ($tradeNo === '' || $outTradeNo === '') {
    http_response_code(400);
    echo 'failure';
    exit;
}

// 此处必须使用支付宝 SDK 和支付宝公钥验证签名。
// 验签通过后,还应核对订单号、金额、商户身份等信息。

if (
    $tradeStatus === 'TRADE_SUCCESS'
    || $tradeStatus === 'TRADE_FINISHED'
) {
    // 使用 out_trade_no 查询本地订单。
    // 核对 total_amount、app_id、seller_id 等信息。
    // 以幂等方式更新订单,并保存 $tradeNo。

    echo 'success';
    exit;
}

echo 'failure';

异步通知通常以 application/x-www-form-urlencoded 格式提交,因此应从 $_POST 中获取参数,不要默认将通知内容按 JSON 解析。

验签时不要修改原始参数

调用支付宝 SDK 验签前,需要使用完整的通知参数。不要提前删除、转义或重新格式化业务字段。具体的方法名取决于项目安装的支付宝 PHP SDK,常见调用形式如下:

$isVerified = $aopClient->rsaCheckV1(
    $_POST,
    $alipayPublicKey,
    'RSA2'
);

不同 SDK 版本的验签方法和参数形式可能不同,应以项目当前使用的 SDK 接口为准。只有 $isVerified === true 时,才能继续处理订单。

不能只判断 resultStatus === "9000"

9000 只表示客户端认为支付流程已经成功结束,不能单独证明后台收到了真实、有效且金额正确的付款。APP 返回的数据来自客户端环境,可能被伪造、篡改或重复提交。

后台确认支付时,至少要完成以下检查:

  1. 验证支付宝异步通知签名。
  2. 检查 trade_status 是否为可接受状态。
  3. 使用 out_trade_no 查找本地订单。
  4. 核对 total_amount 与订单应付金额。
  5. 核对 app_id、收款方身份等商户信息。
  6. 以幂等方式更新订单,避免重复发货或重复充值。
  7. 保存支付宝的 trade_no,用于退款、查询和对账。

如果异步通知暂时没有到达,后台可以使用商户订单号 out_trade_no 调用支付宝交易查询接口。对查询响应完成验签并核对订单信息后,再获取 trade_no 和实际交易状态。

备注:内容仅供参考。