feat: add configurable verification and redemption codes

This commit is contained in:
237899745
2026-07-25 13:57:39 +08:00
parent d1f093685d
commit c6e96464d3
32 changed files with 2108 additions and 261 deletions

View File

@@ -3,6 +3,7 @@ use crate::api::envelope::Envelope;
use crate::error::{AppError, ErrorCode};
use crate::services::billing;
use crate::services::idempotency;
use crate::services::quota;
use crate::services::settings;
use crate::state::AppState;
@@ -153,7 +154,9 @@ async fn get_subscription(
FROM subscriptions s
JOIN plans p ON p.id = s.plan_id
WHERE s.user_id = $1
AND s.status IN ('active', 'trialing', 'past_due', 'canceled', 'incomplete')
AND s.status IN ('active', 'trialing', 'past_due')
AND s.current_period_start <= NOW()
AND s.current_period_end > NOW()
ORDER BY s.current_period_end DESC
LIMIT 1
"#,
@@ -239,11 +242,12 @@ async fn get_subscription(
struct UsageResponse {
period_start: DateTime<Utc>,
period_end: DateTime<Utc>,
used_units: i32,
included_units: i32,
bonus_units: i32,
total_units: i32,
remaining_units: i32,
used_units: i64,
included_units: i64,
bonus_units: i64,
redeemed_units: i64,
total_units: i64,
remaining_units: i64,
}
async fn get_usage(
@@ -262,33 +266,7 @@ async fn get_usage(
let billing = billing::get_user_billing(&state, user_id).await?;
#[derive(Debug, FromRow)]
struct UsageRow {
used_units: i32,
bonus_units: i32,
}
let usage = sqlx::query_as::<_, UsageRow>(
r#"
SELECT used_units, bonus_units
FROM usage_periods
WHERE user_id = $1 AND period_start = $2 AND period_end = $3
"#,
)
.bind(user_id)
.bind(billing.period_start)
.bind(billing.period_end)
.fetch_optional(&state.db)
.await
.map_err(|err| AppError::new(ErrorCode::Internal, "查询用量失败").with_source(err))?
.unwrap_or(UsageRow {
used_units: 0,
bonus_units: 0,
});
let included = billing.plan.included_units_per_period;
let total = included + usage.bonus_units;
let remaining = (total - usage.used_units).max(0);
let usage = quota::user_usage_balance(&state, &billing).await?;
Ok(Json(Envelope {
success: true,
@@ -296,10 +274,11 @@ async fn get_usage(
period_start: billing.period_start,
period_end: billing.period_end,
used_units: usage.used_units,
included_units: included,
included_units: usage.included_units,
bonus_units: usage.bonus_units,
total_units: total,
remaining_units: remaining,
redeemed_units: usage.redeemed_units,
total_units: usage.total_units,
remaining_units: usage.remaining_units,
},
}))
}