支付宝 barPay 返回的 stdClass 如何转为 PHP 数组?
支付老李
结论
$barPayResult->getResponse() 返回的是 PHP stdClass 对象,不是 JSON 字符串。可以先把返回值保存到变量中,再读取对象属性。如果后续代码需要使用数组,最好进行递归转换。直接使用 (array) 只会转换最外层对象,fund_bill_list 里的嵌套 stdClass 仍是对象。
直接接收并读取返回值
$response = $barPayResult->getResponse();
echo $response->code;
echo $response->msg;
echo $response->trade_no;
echo $response->out_trade_no;
print_r() 可能显示:
stdClass Object (
[code] => 10000
[msg] => Success
)
这是 PHP 调试对象时生成的文本,并不是 JSON,不能拿去做 JSON 解析。
推荐做法:递归转换为数组
可以编写一个递归函数,同时处理对象和嵌套数组:
function objectToArray($value)
{
if (is_object($value)) {
$value = get_object_vars($value);
}
if (is_array($value)) {
foreach ($value as $key => $item) {
$value[$key] = objectToArray($item);
}
}
return $value;
}
在支付结果处理中使用:
$barPay = new AlipayTradeService($config);
$barPayResult = $barPay->barPay($barPayRequestBuilder);
$tradeStatus = $barPayResult->getTradeStatus();
$response = objectToArray($barPayResult->getResponse());
switch ($tradeStatus) {
case 'SUCCESS':
echo '支付宝支付成功<br>';
$code = $response['code'] ?? '';
$message = $response['msg'] ?? '';
$tradeNo = $response['trade_no'] ?? '';
$outTradeNo = $response['out_trade_no'] ?? '';
$totalAmount = $response['total_amount'] ?? '0.00';
echo '响应码:' . htmlspecialchars((string) $code, ENT_QUOTES, 'UTF-8') . '<br>';
echo '响应信息:' . htmlspecialchars((string) $message, ENT_QUOTES, 'UTF-8') . '<br>';
echo '支付宝交易号:' . htmlspecialchars((string) $tradeNo, ENT_QUOTES, 'UTF-8') . '<br>';
echo '商户订单号:' . htmlspecialchars((string) $outTradeNo, ENT_QUOTES, 'UTF-8') . '<br>';
echo '订单金额:' . htmlspecialchars((string) $totalAmount, ENT_QUOTES, 'UTF-8') . '<br>';
if (!empty($response['fund_bill_list'])) {
foreach ($response['fund_bill_list'] as $fundBill) {
$channel = $fundBill['fund_channel'] ?? '';
$amount = $fundBill['amount'] ?? '0.00';
// 继续处理支付渠道和金额
}
}
break;
case 'FAILED':
$code = $response['code'] ?? '';
$message = $response['msg'] ?? '';
$subCode = $response['sub_code'] ?? '';
$subMessage = $response['sub_msg'] ?? '';
// 记录失败原因或进入业务失败处理
break;
case 'UNKNOWN':
default:
// 支付结果未知时,不要直接认定为成功或失败。
// 应根据当前 SDK 提供的查询接口继续确认订单状态。
break;
}
转换后的数据结构大致如下:
[
'code' => '10000',
'msg' => 'Success',
'buyer_logon_id' => 'men***@163.com',
'buyer_pay_amount' => '0.01',
'fund_bill_list' => [
[
'amount' => '0.01',
'fund_channel' => 'ALIPAYACCOUNT',
],
],
'out_trade_no' => '202011258648132323911',
'total_amount' => '0.01',
'trade_no' => '2020112522001481465704039997',
]
简便写法:通过 JSON 中转
如果返回对象中的数据都能用 JSON 正常表示,也可以这样转换:
$responseObject = $barPayResult->getResponse();
$responseArray = json_decode(
json_encode($responseObject, JSON_UNESCAPED_UNICODE),
true
);
这种写法同样可以处理嵌套对象,但需要检查编码和解码是否成功:
$json = json_encode($responseObject, JSON_UNESCAPED_UNICODE);
if ($json === false) {
throw new RuntimeException('返回数据编码失败:' . json_last_error_msg());
}
$responseArray = json_decode($json, true);
if (!is_array($responseArray)) {
throw new RuntimeException('返回数据转换失败:' . json_last_error_msg());
}
通过 JSON 中转的代码比较简短,但会增加一次编码和解码,也可能改变某些特殊数据类型。处理支付数据时,递归转换通常更直观,也更容易控制。
为什么不建议只使用 (array)
下面的写法只能转换第一层对象:
$response = (array) $barPayResult->getResponse();
转换后可以这样读取第一层字段:
echo $response['trade_no'];
不过,fund_bill_list 中的元素仍可能是 stdClass:
echo $response['fund_bill_list'][0]->fund_channel;
如果业务代码需要统一通过数组下标访问数据,应使用递归转换函数。
注意事项
getTradeStatus()是 SDK 封装后的交易状态,response.code是支付宝接口的响应码,两者含义不同。不能因为code === '10000'就忽略实际交易状态。- 支付状态未知时,不要立即发货,也不要把订单更新为支付成功。应通过订单查询等方式再次确认,具体状态名称和查询方法以项目使用的支付宝 SDK 为准。
trade_no、out_trade_no、buyer_user_id等标识符应按字符串保存,避免整数范围或前导零问题。- 不要用二进制浮点数精确比较金额。可以把金额保留为字符串,或者统一换算成分后使用整数处理。
- 可使用
??、isset()或array_key_exists()判断可选字段。支付失败时返回的字段可能与成功时不同,例如可能包含sub_code和sub_msg。 print_r()和var_dump()适合开发调试,不适合作为正式接口输出。生产页面也不应直接暴露完整的支付响应和用户信息。
备注:内容仅供参考。
