fix: 支付后增加会员时长验证(verify_membership_after_payment)防止ELSE静默错误
This commit is contained in:
77
src/db.rs
77
src/db.rs
@@ -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(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user