PAYATHON 2026

支付宝 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() 适合开发调试,不适合作为正式接口输出。生产页面也不应直接暴露完整的支付响应和用户信息。

备注:内容仅供参考。