You've already forked AstralRinth
Payments/subscriptions support (#943)
* [wip] Payments/subscriptions support * finish * working payment flow * finish subscriptions, lint, clippy, etc * docker compose
This commit is contained in:
@@ -3,6 +3,7 @@ pub mod v2;
|
||||
pub mod v3;
|
||||
|
||||
pub use v3::analytics;
|
||||
pub use v3::billing;
|
||||
pub use v3::collections;
|
||||
pub use v3::ids;
|
||||
pub use v3::images;
|
||||
|
||||
119
src/models/v3/billing.rs
Normal file
119
src/models/v3/billing.rs
Normal file
@@ -0,0 +1,119 @@
|
||||
use crate::models::ids::Base62Id;
|
||||
use crate::models::ids::UserId;
|
||||
use chrono::{DateTime, Utc};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)]
|
||||
#[serde(from = "Base62Id")]
|
||||
#[serde(into = "Base62Id")]
|
||||
pub struct ProductId(pub u64);
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct Product {
|
||||
pub id: ProductId,
|
||||
pub metadata: ProductMetadata,
|
||||
pub prices: Vec<ProductPrice>,
|
||||
pub unitary: bool,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(tag = "type", rename_all = "kebab-case")]
|
||||
pub enum ProductMetadata {
|
||||
Midas,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)]
|
||||
#[serde(from = "Base62Id")]
|
||||
#[serde(into = "Base62Id")]
|
||||
pub struct ProductPriceId(pub u64);
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct ProductPrice {
|
||||
pub id: ProductPriceId,
|
||||
pub product_id: ProductId,
|
||||
pub prices: Price,
|
||||
pub currency_code: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(tag = "type", rename_all = "kebab-case")]
|
||||
pub enum Price {
|
||||
OneTime {
|
||||
price: i32,
|
||||
},
|
||||
Recurring {
|
||||
intervals: HashMap<PriceDuration, i32>,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Hash, Eq, PartialEq, Debug, Copy, Clone)]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
pub enum PriceDuration {
|
||||
Monthly,
|
||||
Yearly,
|
||||
}
|
||||
|
||||
impl PriceDuration {
|
||||
pub fn from_string(string: &str) -> PriceDuration {
|
||||
match string {
|
||||
"monthly" => PriceDuration::Monthly,
|
||||
"yearly" => PriceDuration::Yearly,
|
||||
_ => PriceDuration::Monthly,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_str(&self) -> &'static str {
|
||||
match self {
|
||||
PriceDuration::Monthly => "monthly",
|
||||
PriceDuration::Yearly => "yearly",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)]
|
||||
#[serde(from = "Base62Id")]
|
||||
#[serde(into = "Base62Id")]
|
||||
pub struct UserSubscriptionId(pub u64);
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct UserSubscription {
|
||||
pub id: UserSubscriptionId,
|
||||
pub user_id: UserId,
|
||||
pub price_id: ProductPriceId,
|
||||
pub interval: PriceDuration,
|
||||
pub status: SubscriptionStatus,
|
||||
pub created: DateTime<Utc>,
|
||||
pub expires: DateTime<Utc>,
|
||||
pub last_charge: Option<DateTime<Utc>>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Eq, PartialEq)]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
pub enum SubscriptionStatus {
|
||||
Active,
|
||||
PaymentProcessing,
|
||||
PaymentFailed,
|
||||
Cancelled,
|
||||
}
|
||||
|
||||
impl SubscriptionStatus {
|
||||
pub fn from_string(string: &str) -> SubscriptionStatus {
|
||||
match string {
|
||||
"active" => SubscriptionStatus::Active,
|
||||
"payment-processing" => SubscriptionStatus::PaymentProcessing,
|
||||
"payment-failed" => SubscriptionStatus::PaymentFailed,
|
||||
"cancelled" => SubscriptionStatus::Cancelled,
|
||||
_ => SubscriptionStatus::Cancelled,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_str(&self) -> &'static str {
|
||||
match self {
|
||||
SubscriptionStatus::Active => "active",
|
||||
SubscriptionStatus::PaymentProcessing => "payment-processing",
|
||||
SubscriptionStatus::PaymentFailed => "payment-failed",
|
||||
SubscriptionStatus::Cancelled => "cancelled",
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,3 @@
|
||||
use thiserror::Error;
|
||||
|
||||
pub use super::collections::CollectionId;
|
||||
pub use super::images::ImageId;
|
||||
pub use super::notifications::NotificationId;
|
||||
@@ -15,6 +13,9 @@ pub use super::teams::TeamId;
|
||||
pub use super::threads::ThreadId;
|
||||
pub use super::threads::ThreadMessageId;
|
||||
pub use super::users::UserId;
|
||||
pub use crate::models::billing::UserSubscriptionId;
|
||||
pub use crate::models::v3::billing::{ProductId, ProductPriceId};
|
||||
use thiserror::Error;
|
||||
|
||||
/// Generates a random 64 bit integer that is exactly `n` characters
|
||||
/// long when encoded as base62.
|
||||
@@ -133,6 +134,9 @@ base62_id_impl!(OAuthClientId, OAuthClientId);
|
||||
base62_id_impl!(OAuthRedirectUriId, OAuthRedirectUriId);
|
||||
base62_id_impl!(OAuthClientAuthorizationId, OAuthClientAuthorizationId);
|
||||
base62_id_impl!(PayoutId, PayoutId);
|
||||
base62_id_impl!(ProductId, ProductId);
|
||||
base62_id_impl!(ProductPriceId, ProductPriceId);
|
||||
base62_id_impl!(UserSubscriptionId, UserSubscriptionId);
|
||||
|
||||
pub mod base62_impl {
|
||||
use serde::de::{self, Deserializer, Visitor};
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
pub mod analytics;
|
||||
pub mod billing;
|
||||
pub mod collections;
|
||||
pub mod ids;
|
||||
pub mod images;
|
||||
|
||||
@@ -14,7 +14,6 @@ pub const DELETED_USER: UserId = UserId(127155982985829);
|
||||
bitflags::bitflags! {
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct Badges: u64 {
|
||||
// 1 << 0 unused - ignore + replace with something later
|
||||
const MIDAS = 1 << 0;
|
||||
const EARLY_MODPACK_ADOPTER = 1 << 1;
|
||||
const EARLY_RESPACK_ADOPTER = 1 << 2;
|
||||
@@ -53,6 +52,7 @@ pub struct User {
|
||||
pub has_password: Option<bool>,
|
||||
pub has_totp: Option<bool>,
|
||||
pub payout_data: Option<UserPayoutData>,
|
||||
pub stripe_customer_id: Option<String>,
|
||||
|
||||
// DEPRECATED. Always returns None
|
||||
pub github_id: Option<u64>,
|
||||
@@ -86,6 +86,7 @@ impl From<DBUser> for User {
|
||||
has_password: None,
|
||||
has_totp: None,
|
||||
github_id: None,
|
||||
stripe_customer_id: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user