From 94ad9ba1909af205d728fed0bde96b5a9ebe0053 Mon Sep 17 00:00:00 2001 From: milky0217 Date: Mon, 25 May 2026 14:59:33 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20payment=5Fpage=E6=94=AF=E6=8C=81resume?= =?UTF-8?q?=E5=8F=82=E6=95=B0=E5=A4=8D=E7=94=A8=E5=B7=B2=E6=9C=89=E5=BE=85?= =?UTF-8?q?=E6=94=AF=E4=BB=98=E8=AE=A2=E5=8D=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/handlers/payment.rs | 45 +++++++++++++++++++++++++++++++---------- 1 file changed, 34 insertions(+), 11 deletions(-) diff --git a/src/handlers/payment.rs b/src/handlers/payment.rs index 58ba62c..f33f17e 100644 --- a/src/handlers/payment.rs +++ b/src/handlers/payment.rs @@ -596,6 +596,9 @@ pub struct PaymentPageQuery { /// JWT: 从 URL 参数传入(外部浏览器无 Cookie 时使用) #[serde(default)] pub jwt: Option, + /// 复用已有待支付订单的 order_no(不创建新订单) + #[serde(default)] + pub resume: Option, } #[get("/payment/page")] @@ -615,18 +618,38 @@ pub async fn payment_page( let pkg = get_package_info(&query.package_) .ok_or_else(|| AppError::BadRequest("无效的套餐类型".to_string()))?; - let order_no = Uuid::new_v4().to_string(); - let expires_at = pkg.days.map(|d| Utc::now() + chrono::Duration::days(d)); + // 复用已有待支付订单(如果提供了 resume order_no) + let order_no = if let Some(ref resume_no) = query.resume { + let existing: Option<(i32, String)> = sqlx::query_as( + r#"SELECT user_id, status FROM payment_orders WHERE order_no = $1"#, + ) + .bind(resume_no) + .fetch_optional(pool.get_ref()) + .await + .map_err(|e| AppError::Database(format!("查询订单失败: {}", e)))?; - db::create_payment_order( - pool.get_ref(), - claims.user_id, - &order_no, - &query.package_, - pkg.amount, - expires_at, - ) - .await?; + match existing { + Some((uid, status)) if uid == claims.user_id && status == "pending" => { + resume_no.clone() + } + _ => { + // 订单不存在/不属于该用户/已支付 → 创建新订单 + let new_no = Uuid::new_v4().to_string(); + let expires_at = pkg.days.map(|d| Utc::now() + chrono::Duration::days(d)); + db::create_payment_order( + pool.get_ref(), claims.user_id, &new_no, &query.package_, pkg.amount, expires_at, + ).await?; + new_no + } + } + } else { + let new_no = Uuid::new_v4().to_string(); + let expires_at = pkg.days.map(|d| Utc::now() + chrono::Duration::days(d)); + db::create_payment_order( + pool.get_ref(), claims.user_id, &new_no, &query.package_, pkg.amount, expires_at, + ).await?; + new_no + }; let base_url = std::env::var("APP_BASE_URL") .unwrap_or_else(|_| "https://dev.xmclassmate.top".to_string());