Files
freeshop/pay_notify.php
2026-08-14 10:55:06 +08:00

86 lines
2.4 KiB
PHP

<?php
/**
* 支付异步通知回调(支付宝 / 微信支付)
*
* 支付宝 POST 到此页面
* 微信支付 POST 到此页面
*
* 路由方式:通过 ?gateway=alipay 或 ?gateway=wechat 区分
*/
require __DIR__ . '/includes/init.php';
// 关闭输出缓冲,确保原始响应
ob_clean();
$gateway = trim($_GET['gateway'] ?? $_POST['gateway'] ?? '');
if (empty($gateway)) {
http_response_code(400);
exit('missing gateway param');
}
Payment::initGateways();
$gw = Payment::get($gateway);
if (!$gw) {
http_response_code(404);
exit('unknown gateway');
}
Logger::info('收到支付通知', ['gateway' => $gateway, 'raw_input' => file_get_contents('php://input')]);
// 收集所有参数
$params = array_merge($_GET, $_POST);
unset($params['gateway']);
if (!$gw->verifyNotify($params)) {
Logger::warn('支付通知验签失败', ['gateway' => $gateway]);
http_response_code(403);
exit('signature mismatch');
}
$tradeNo = $gw->getTradeNo($params);
$isPaid = $gw->isPaid($params);
// 查找对应的支付记录
$outTradeNo = $params['out_trade_no'] ?? '';
$stmt = db()->prepare('SELECT id,order_id,status FROM ' . tn('pay_logs') . ' WHERE order_id=? AND pay_method=? ORDER BY id DESC LIMIT 1');
$stmt->execute([$outTradeNo, $gateway]);
$payLog = $stmt->fetch();
if (!$payLog) {
Logger::error('支付通知:未找到支付记录', ['out_trade_no' => $outTradeNo]);
// 即使找不到记录也返回成功,避免重复通知
$gw->respondSuccess();
exit;
}
if ($payLog['status'] === 'paid') {
// 已处理过,直接返回成功
$gw->respondSuccess();
exit;
}
if ($isPaid) {
// 支付成功 → 更新订单状态
db()->beginTransaction();
try {
Payment::updatePayStatus($payLog['id'], 'paid', $tradeNo);
// 更新订单状态为已付款
db()->prepare('UPDATE ' . tn('orders') . ' SET status=\'paid\', paid_at=NOW() WHERE id=?')
->execute([$payLog['order_id']]);
db()->commit();
Logger::info('支付成功', ['order_id' => $payLog['order_id'], 'trade_no' => $tradeNo, 'gateway' => $gateway]);
// TODO: 发送支付成功通知邮件
} catch (Exception $e) {
db()->rollBack();
Logger::error('支付成功后更新订单失败', ['error' => $e->getMessage()]);
}
} else {
Logger::warn('支付未成功', ['trade_status' => $params['trade_status'] ?? '']);
}
$gw->respondSuccess();
exit;