diff --git a/src/handlers/payment.rs b/src/handlers/payment.rs index 3885ece..a55a3d4 100644 --- a/src/handlers/payment.rs +++ b/src/handlers/payment.rs @@ -675,12 +675,28 @@ pub async fn payment_page( } } } 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 existing: Option = sqlx::query_scalar( + r#"SELECT order_no FROM payment_orders + WHERE user_id = $1 AND package_type = $2 AND status = 'pending' + ORDER BY created_at DESC LIMIT 1"#, + ) + .bind(claims.user_id) + .bind(&query.package_) + .fetch_optional(pool.get_ref()) + .await + .map_err(|e| AppError::Database(format!("查询已有订单失败: {}", e)))?; + + if let Some(no) = existing { + 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")