支付宝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 返回的数据来自客户端环境,可能被伪造、篡改或重复提交。
后台确认支付时,至少要完成以下检查:
- 验证支付宝异步通知签名。
- 检查
trade_status是否为可接受状态。 - 使用
out_trade_no查找本地订单。 - 核对
total_amount与订单应付金额。 - 核对
app_id、收款方身份等商户信息。 - 以幂等方式更新订单,避免重复发货或重复充值。
- 保存支付宝的
trade_no,用于退款、查询和对账。
如果异步通知暂时没有到达,后台可以使用商户订单号 out_trade_no 调用支付宝交易查询接口。对查询响应完成验签并核对订单信息后,再获取 trade_no 和实际交易状态。
备注:内容仅供参考。
