fix: 防止用户误取消已付款订单-回调重新激活+2分钟内禁止取消+成功页30s超时提示

This commit is contained in:
2026-06-15 10:37:28 +08:00
parent e672f00b66
commit 43c349919d
2 changed files with 36 additions and 2 deletions

View File

@@ -643,7 +643,10 @@ pub async fn confirm_payment_order_by_orderno(
None => return Err(AppError::NotFound("订单不存在".to_string())),
};
if status != "pending" {
// 支付宝回调已通过 RSA2 验证。如果订单被用户误取消,重新激活。
if status == "cancelled" {
tracing::warn!("订单 {} 已被取消,但支付宝确认已收款,重新激活并处理支付", order_no);
} else if status != "pending" {
return Ok(());
}
@@ -662,7 +665,7 @@ pub async fn confirm_payment_order_by_orderno(
let result = sqlx::query(
r#"
WITH updated_order AS (
UPDATE payment_orders SET status = 'paid', paid_at = NOW() WHERE order_no = $1 AND status = 'pending' RETURNING package_type, user_id
UPDATE payment_orders SET status = 'paid', paid_at = NOW() WHERE order_no = $1 AND status IN ('pending', 'cancelled') RETURNING package_type, user_id
)
UPDATE users SET
is_member = true,
@@ -1123,6 +1126,22 @@ pub async fn cancel_payment_order(
return Err(AppError::BadRequest(format!("订单状态为 {},无法取消", status)));
}
// 防止用户误取消:支付宝支付确认通常在 5-30 秒内到达
// 2 分钟内的订单不允许取消,避免用户付款后误触取消按钮
let order_age: f64 = sqlx::query_scalar(
r#"SELECT EXTRACT(EPOCH FROM (NOW() - created_at)) FROM payment_orders WHERE order_no = $1"#,
)
.bind(order_no)
.fetch_one(pool)
.await
.map_err(|e| AppError::Database(format!("查询订单创建时间失败: {}", e)))?;
if order_age < 120.0 {
return Err(AppError::BadRequest(
"订单刚刚创建,支付可能仍在处理中,请 2 分钟后再试".to_string(),
));
}
sqlx::query("UPDATE payment_orders SET status = 'cancelled' WHERE order_no = $1")
.bind(order_no)
.execute(pool)