From 43c349919da0cbc6ec8f794d056cd96c718c1573 Mon Sep 17 00:00:00 2001 From: milky0217 Date: Mon, 15 Jun 2026 10:37:28 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E9=98=B2=E6=AD=A2=E7=94=A8=E6=88=B7?= =?UTF-8?q?=E8=AF=AF=E5=8F=96=E6=B6=88=E5=B7=B2=E4=BB=98=E6=AC=BE=E8=AE=A2?= =?UTF-8?q?=E5=8D=95-=E5=9B=9E=E8=B0=83=E9=87=8D=E6=96=B0=E6=BF=80?= =?UTF-8?q?=E6=B4=BB+2=E5=88=86=E9=92=9F=E5=86=85=E7=A6=81=E6=AD=A2?= =?UTF-8?q?=E5=8F=96=E6=B6=88+=E6=88=90=E5=8A=9F=E9=A1=B530s=E8=B6=85?= =?UTF-8?q?=E6=97=B6=E6=8F=90=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/db.rs | 23 +++++++++++++++++++++-- src/handlers/payment.rs | 15 +++++++++++++++ 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/src/db.rs b/src/db.rs index 04cc370..182897f 100644 --- a/src/db.rs +++ b/src/db.rs @@ -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) diff --git a/src/handlers/payment.rs b/src/handlers/payment.rs index 351dcfb..65b6efa 100644 --- a/src/handlers/payment.rs +++ b/src/handlers/payment.rs @@ -901,6 +901,11 @@ fn build_success_html(order_no: &str) -> String {
系统会自动处理,无需重复操作
订单号: {2}
+ "##,