fix: 修复2个支付安全漏洞-未经认证的payment_success确认+未禁用mock_confirm

This commit is contained in:
2026-06-02 11:46:26 +08:00
parent bcd9bc81e4
commit 5d6be08f32

View File

@@ -910,16 +910,13 @@ fn format_error_html(msg: &str, order_no: &str) -> String {
#[get("/payment/success")] #[get("/payment/success")]
pub async fn payment_success( pub async fn payment_success(
pool: web::Data<PgPool>, _pool: web::Data<PgPool>,
query: web::Query<AlipaySuccessQuery>, query: web::Query<AlipaySuccessQuery>,
) -> HttpResponse { ) -> HttpResponse {
let order_no = query.order_no.as_deref().unwrap_or(""); let order_no = query.order_no.as_deref().unwrap_or("");
// 同步确认订单(幂等:已确认的订单会跳过) // 不再在此处确认订单(安全原因: 此端点无认证, 任何人知道 order_no 即可激活会员)。
if !order_no.is_empty() // Mock 支付由 mock_confirm 在跳转前确认, 真实支付宝由 notify 异步回调确认。
&& let Err(e) = db::confirm_payment_order_by_orderno(pool.get_ref(), order_no).await {
tracing::warn!("支付成功页同步确认失败(可能是异步回调已处理): {}", e);
}
let html = build_success_html(order_no); let html = build_success_html(order_no);
HttpResponse::Ok() HttpResponse::Ok()
@@ -1028,6 +1025,7 @@ pub async fn create_order(
} }
/// POST /api/payment/mock-confirm /// POST /api/payment/mock-confirm
/// 仅在未配置支付宝时可用(否则用户可绕过真实支付)
#[post("/api/payment/mock-confirm")] #[post("/api/payment/mock-confirm")]
pub async fn mock_confirm( pub async fn mock_confirm(
pool: web::Data<PgPool>, pool: web::Data<PgPool>,
@@ -1035,8 +1033,13 @@ pub async fn mock_confirm(
body: web::Json<MockConfirmRequest>, body: web::Json<MockConfirmRequest>,
) -> Result<HttpResponse, AppError> { ) -> Result<HttpResponse, AppError> {
check_payment_maintenance()?; check_payment_maintenance()?;
let user_id = claims.user_id;
// 安全守卫:已配置支付宝时禁用 Mock 支付,防止绕过
if AlipayConfig::from_env().is_some() {
return Err(AppError::BadRequest("真实支付已启用Mock 支付不可用".to_string()));
}
let user_id = claims.user_id;
let expires_at = let expires_at =
db::confirm_payment_order(pool.get_ref(), &body.order_id, user_id).await?; db::confirm_payment_order(pool.get_ref(), &body.order_id, user_id).await?;