From 2c0bdf18ce1434db029d07e115c666c6f40b525a Mon Sep 17 00:00:00 2001 From: milky0217 Date: Tue, 2 Jun 2026 12:08:05 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20Mock=E6=94=AF=E4=BB=98=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?MOCK=5FPAY=5FKEY=E5=AF=86=E9=92=A5=E9=AA=8C=E8=AF=81(=E8=A7=84?= =?UTF-8?q?=E5=88=99:=E6=94=AF=E4=BB=98=E5=AE=9D=E4=BC=98=E5=85=88>?= =?UTF-8?q?=E5=90=AF=E7=94=A8=E5=BC=80=E5=85=B3>=E8=AF=B7=E6=B1=82?= =?UTF-8?q?=E5=A4=B4=E7=AD=BE=E5=90=8D)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/handlers/payment.rs | 42 +++++++++++++++++++++++++++++++++++------ 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/src/handlers/payment.rs b/src/handlers/payment.rs index c710b78..08c9bee 100644 --- a/src/handlers/payment.rs +++ b/src/handlers/payment.rs @@ -1024,20 +1024,50 @@ pub async fn create_order( }))) } +/// 检查 Mock 支付是否允许 +/// 规则(依次): +/// 1. 已配置支付宝 → 禁用(真实支付优先) +/// 2. MOCK_PAY_ENABLED != true → 禁用 +/// 3. MOCK_PAY_KEY 已设置 → 验证 X-Mock-Key 请求头 +fn check_mock_payment_allowed(req: &HttpRequest) -> Result<(), AppError> { + // 规则 1:有支付宝时永不走 Mock + if AlipayConfig::from_env().is_some() { + return Err(AppError::BadRequest("真实支付已启用,Mock 支付不可用".to_string())); + } + + // 规则 2:必须显式启用 Mock 支付 + if std::env::var("MOCK_PAY_ENABLED").ok() != Some("true".to_string()) { + return Err(AppError::Forbidden("Mock 支付未启用".to_string())); + } + + // 规则 3:如果设了 MOCK_PAY_KEY,验证请求头 + if let Ok(key) = std::env::var("MOCK_PAY_KEY") { + if !key.is_empty() { + let header_key = req + .headers() + .get("X-Mock-Key") + .and_then(|v| v.to_str().ok()) + .unwrap_or(""); + if header_key != key { + return Err(AppError::Forbidden("Mock 支付密钥错误".to_string())); + } + } + } + + Ok(()) +} + /// POST /api/payment/mock-confirm -/// 仅在未配置支付宝时可用(否则用户可绕过真实支付) +/// 所有 Mock 操作均需密钥授权(通过 MOCK_PAY_ENABLED + MOCK_PAY_KEY 控制) #[post("/api/payment/mock-confirm")] pub async fn mock_confirm( + req: HttpRequest, pool: web::Data, claims: web::ReqData, body: web::Json, ) -> Result { check_payment_maintenance()?; - - // 安全守卫:已配置支付宝时禁用 Mock 支付,防止绕过 - if AlipayConfig::from_env().is_some() { - return Err(AppError::BadRequest("真实支付已启用,Mock 支付不可用".to_string())); - } + check_mock_payment_allowed(&req)?; let user_id = claims.user_id; let expires_at =