fix: 支付后增加会员时长验证(verify_membership_after_payment)防止ELSE静默错误

This commit is contained in:
2026-06-07 16:34:30 +08:00
parent b806d0c7e0
commit caf3c7cc61

View File

@@ -615,6 +615,12 @@ pub async fn confirm_payment_order(
// 发送支付成功通知
let _ = insert_payment_notification(pool, user_id, order_no).await;
// 验证会员到期时间是否正常
if let Err(e) = verify_membership_after_payment(pool, order_no).await {
tracing::warn!("会员到期时间验证异常 (订单 {}): {}", order_no, e);
}
Ok(new_expires)
}
@@ -685,6 +691,11 @@ pub async fn confirm_payment_order_by_orderno(
let _ = insert_payment_audit_log(pool, order_no, uid, "paid", None, None).await;
// 发送支付成功通知
let _ = insert_payment_notification(pool, uid, order_no).await;
// 验证会员到期时间是否正常
if let Err(e) = verify_membership_after_payment(pool, order_no).await {
tracing::warn!("会员到期时间验证异常 (订单 {}): {}", order_no, e);
}
}
Ok(())
@@ -1046,6 +1057,11 @@ pub async fn admin_force_confirm_order(
)
.await;
// 验证会员到期时间是否正常
if let Err(e) = verify_membership_after_payment(pool, order_no).await {
tracing::warn!("会员到期时间验证异常 (订单 {}): {}", order_no, e);
}
result
} else {
// 订单已处理,只写日志
@@ -1185,3 +1201,64 @@ pub async fn admin_refund_order(
Ok(())
}
/// 支付确认后验证会员到期时间是否正常
/// 用于捕获 ELSE INTERVAL '0 days' 的静默错误
async fn verify_membership_after_payment(
pool: &PgPool,
order_no: &str,
) -> Result<(), AppError> {
#[derive(Debug, sqlx::FromRow)]
struct PaymentResult {
package_type: String,
paid_at: chrono::DateTime<chrono::Utc>,
membership_expires_at: Option<chrono::DateTime<chrono::Utc>>,
}
let row = sqlx::query_as::<_, PaymentResult>(
r#"
SELECT po.package_type, po.paid_at, u.membership_expires_at
FROM payment_orders po
JOIN users u ON u.id = po.user_id
WHERE po.order_no = $1
"#,
)
.bind(order_no)
.fetch_optional(pool)
.await
.map_err(|e| AppError::Database(format!("验证查询失败: {}", e)))?;
let r = match row {
Some(r) => r,
None => return Err(AppError::NotFound("验证查询:订单不存在".to_string())),
};
if r.package_type == "permanent" {
return Ok(()); // 永久会员不累计
}
let expires = match r.membership_expires_at {
Some(e) => e,
None => {
let msg = format!("支付验证失败:{} 非永久套餐但会员到期为 NULL", r.package_type);
tracing::error!("{}", msg);
return Err(AppError::Internal(msg));
}
};
let actual_days = (expires - r.paid_at).num_days();
// 预期至少 25 天(最短月卡 30 天,允许 5 天误差)
if actual_days < 25 {
let msg = format!(
"支付验证失败:套餐 {} 仅增加 {} 天会员时长(预期 >= 25 天),可能触发了 ELSE 分支",
r.package_type, actual_days
);
tracing::error!("{}", msg);
return Err(AppError::Internal(msg));
}
tracing::info!("支付验证通过:{} 增加 {} 天", r.package_type, actual_days);
Ok(())
}