PAYATHON 2026

如何获取并存储支付回调 URL 中的参数

支付小周

结论

不需要使用 cURL。支付服务商重定向到 pay_completed.php 后,PHP 会自动解析 URL 中的查询参数,可以直接通过 $_GET 读取:

$transaction = $_GET['transaction'] ?? null;
$orderId = $_GET['order_id'] ?? null;

以这个 URL 为例:

http://mywebsite.sa/pay_completed.php?transaction=284&order_id=

$transaction 的值是字符串 "284"。由于 URL 没有为 order_id 提供实际值,$orderId 是空字符串。

获取并检查参数

执行数据库操作前,先检查参数是否存在且不为空:

<?php

$transaction = trim($_GET['transaction'] ?? '');
$orderId = trim($_GET['order_id'] ?? '');

if ($transaction === '' || $orderId === '') {
    http_response_code(400);
    exit('缺少 transaction 或 order_id 参数');
}

// 参数有效后再执行后续处理

如果接口规定 transaction 必须是整数,还可以进一步验证:

<?php

$transaction = filter_input(INPUT_GET, 'transaction', FILTER_VALIDATE_INT);
$orderId = trim($_GET['order_id'] ?? '');

if ($transaction === false || $transaction === null) {
    http_response_code(400);
    exit('transaction 参数无效');
}

if ($orderId === '') {
    http_response_code(400);
    exit('order_id 参数为空');
}

如果支付服务商的交易号可能包含字母、连字符或其他字符,就不要使用 FILTER_VALIDATE_INT,而要按照接口文档规定的格式进行验证。

更新数据库

使用 PDO 预处理语句写入数据库,不要将 URL 参数直接拼接到 SQL 中:

<?php

$transaction = trim($_GET['transaction'] ?? '');
$orderId = trim($_GET['order_id'] ?? '');

if ($transaction === '' || $orderId === '') {
    http_response_code(400);
    exit('缺少必要参数');
}

$pdo = new PDO(
    'mysql:host=localhost;dbname=payment;charset=utf8mb4',
    'db_user',
    'db_password',
    [
        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
        PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
    ]
);

$stmt = $pdo->prepare(
    'UPDATE orders
     SET transaction_id = :transaction_id
     WHERE order_id = :order_id'
);

$stmt->execute([
    ':transaction_id' => $transaction,
    ':order_id' => $orderId,
]);

if ($stmt->rowCount() === 0) {
    // 可能是订单不存在,也可能是数据没有发生变化
    http_response_code(404);
    exit('未找到对应订单或订单无需更新');
}

echo '支付结果已处理';

请将数据库地址、账号、表名和字段名替换为项目的实际配置。在生产环境中,数据库凭据通常应保存在环境变量或受保护的配置文件中。

为什么不需要 cURL

cURL 用于主动向其他服务器发送 HTTP 请求。例如,服务器调用支付平台的查询接口确认交易状态时,可以使用 cURL。

这里的请求方向不同。支付平台已经向用户浏览器返回重定向地址,浏览器随后访问你的 pay_completed.php。PHP 会将 URL 中的查询参数自动解析到 $_GET,直接读取即可。

不要只凭重定向参数确认支付成功

用户可以修改浏览器地址栏中的参数,例如手动访问:

https://mywebsite.sa/pay_completed.php?transaction=284&order_id=123

所以,不能仅凭 transaction 和 order_id 就将订单标记为已支付。更可靠的处理流程是:

  1. 接收并验证参数。
  2. 如果支付平台支持签名验证,校验平台提供的签名。
  3. 或者由服务器调用支付平台的交易查询 API,核对交易状态、订单号、金额和币种。
  4. 确认交易成功后,再使用预处理语句更新数据库。
  5. 确保重复回调或刷新页面时,不会重复扣库存或记账。

如果支付服务商提供服务器端 webhook,应优先通过 webhook 处理支付状态,重定向页面只用于向用户展示结果。

示例 URL 中的 order_id 是空的:

&order_id=

这说明支付服务商没有返回该值,或者提交支付请求时没有正确传递订单号。PHP 无法从空参数中恢复订单号,需要检查支付 API 的请求字段、回调字段配置和支付服务商的接口文档。

备注:内容仅供参考。