PAYATHON 2026

PHP 解析 JSON callback 中的 merchant_data

支付老李

结论

merchant_data 并不是已经解析好的嵌套数组,而是一段 JSON 字符串,需要再次调用 json_decode()。解析完成后,遍历其中的字段,通过 label 找到 first name 和 phone,再将它们写入文本文件。

回调数据中的名字标签是 fist_name,这很可能是 first_name 的拼写错误。代码仍应以支付平台实际返回的标签为准。

解析并保存字段

<?php

$json = file_get_contents('php://input');
$callback = json_decode($json, true);

if (!is_array($callback) || !isset($callback['merchant_data'])) {
    exit('Invalid callback data');
}

$merchantData = json_decode($callback['merchant_data'], true);

if (!is_array($merchantData)) {
    exit('Invalid merchant_data');
}

$values = [];

foreach ($merchantData as $field) {
    if (isset($field['label'], $field['value'])) {
        $values[$field['label']] = $field['value'];
    }
}

// 回调示例中实际使用的是 fist_name
$firstName = $values['fist_name'] ?? '';
$phone = $values['phone'] ?? '';

file_put_contents(
    'first_name.txt',
    $firstName . PHP_EOL,
    FILE_APPEND | LOCK_EX
);

file_put_contents(
    'phone.txt',
    $phone . PHP_EOL,
    FILE_APPEND | LOCK_EX
);

执行后,两个文件会分别追加以下内容:

john_doe

以及:

07777777777

保存到同一个文件

如果要把两个值保存在同一个文本文件中,可以先将它们组合成一行:

$line = sprintf(
    "first_name: %s, phone: %s%s",
    $firstName,
    $phone,
    PHP_EOL
);

file_put_contents(
    'merchant_data.txt',
    $line,
    FILE_APPEND | LOCK_EX
);

写入结果类似:

first_name: john_doe, phone: 07777777777

检查 JSON 解析错误

生产环境中不应直接忽略无效 JSON。对于较老的 PHP 版本,可以这样检查:

$callback = json_decode($json, true);

if (json_last_error() !== JSON_ERROR_NONE) {
    exit('Callback JSON error: ' . json_last_error_msg());
}

if (!isset($callback['merchant_data']) ||
    !is_string($callback['merchant_data'])) {
    exit('merchant_data is missing');
}

$merchantData = json_decode($callback['merchant_data'], true);

if (json_last_error() !== JSON_ERROR_NONE) {
    exit('merchant_data JSON error: ' . json_last_error_msg());
}

如果运行环境支持 JSON_THROW_ON_ERROR,也可以改用异常处理:

try {
    $callback = json_decode($json, true, 512, JSON_THROW_ON_ERROR);
    $merchantData = json_decode(
        $callback['merchant_data'] ?? '',
        true,
        512,
        JSON_THROW_ON_ERROR
    );
} catch (JsonException $e) {
    exit('Invalid JSON: ' . $e->getMessage());
}

注意事项

  • 示例数据使用的是 fist_name,不是 first_name。如果可以控制支付页面的自定义字段,建议将其统一改为正确拼写。
  • 手机号必须按字符串保存,否则开头的 0 可能会丢失。
  • 不建议将回调数据写入名为 robot.php 的文件。如果该文件位于网站可访问目录,原始内容可能被公开,也可能带来安全问题。应改用 .log 或 .txt 文件,并尽量将文件放在 Web 根目录之外。
  • 保存付款信息前,还需要验证支付平台提供的签名、订单号、金额和支付状态。仅检查 callback 中的 response_status 或 order_status,无法证明请求确实来自支付平台。
  • 支付平台可能重复发送回调。如果收到数据后还会执行发货、充值等操作,应根据 payment_id 或 order_id 做幂等处理,防止重复执行。

备注:内容仅供参考。