lockbook_server_lib/billing/
billing_model.rs1use crate::ServerError;
2use crate::config::Config;
3use google_androidpublisher3::api::SubscriptionPurchase;
4use lb_rs::model::api::{
5 AppStoreAccountState, FREE_TIER_USAGE_SIZE, GooglePlayAccountState, PREMIUM_TIER_USAGE_SIZE,
6 StripeAccountState, UnixTimeMillis, UpgradeAccountGooglePlayError,
7};
8use serde::{Deserialize, Serialize};
9use std::fmt::Debug;
10use uuid::Uuid;
11
12#[derive(Serialize, Deserialize, Debug, Clone, Default)]
13pub struct SubscriptionProfile {
14 pub billing_platform: Option<BillingPlatform>,
15 pub last_in_payment_flow: u64,
16}
17
18impl SubscriptionProfile {
19 pub fn data_cap(&self) -> u64 {
20 match &self.billing_platform {
21 Some(platform) => match platform {
22 BillingPlatform::Stripe(info) => {
23 if info.account_state == StripeAccountState::Ok {
24 PREMIUM_TIER_USAGE_SIZE
25 } else {
26 FREE_TIER_USAGE_SIZE
27 }
28 }
29 BillingPlatform::GooglePlay(info) => {
30 if info.account_state == GooglePlayAccountState::OnHold {
31 FREE_TIER_USAGE_SIZE
32 } else {
33 PREMIUM_TIER_USAGE_SIZE
34 }
35 }
36 BillingPlatform::AppStore(info) => {
37 if info.account_state == AppStoreAccountState::FailedToRenew
38 || info.account_state == AppStoreAccountState::Expired
39 {
40 FREE_TIER_USAGE_SIZE
41 } else {
42 PREMIUM_TIER_USAGE_SIZE
43 }
44 }
45 },
46 None => FREE_TIER_USAGE_SIZE,
47 }
48 }
49
50 pub fn bandwidth_cap(&self) -> usize {
52 let cap = match self.is_premium() {
53 true => self.data_cap(), false => self.data_cap() * 4, };
56
57 cap as usize
58 }
59
60 pub fn is_premium(&self) -> bool {
61 self.data_cap() == PREMIUM_TIER_USAGE_SIZE
62 }
63}
64
65#[derive(Serialize, Deserialize, Debug, Clone)]
66pub enum BillingPlatform {
67 Stripe(StripeUserInfo),
68 GooglePlay(GooglePlayUserInfo),
69 AppStore(AppStoreUserInfo),
70}
71
72impl BillingPlatform {
73 pub fn new_play_sub(
74 config: &Config, purchase_token: &str, expiry_information: SubscriptionPurchase,
75 ) -> Result<Self, ServerError<UpgradeAccountGooglePlayError>> {
76 let expiration_time = UnixTimeMillis::try_from(
77 expiry_information
78 .expiry_time_millis
79 .ok_or_else::<ServerError<UpgradeAccountGooglePlayError>, _>(|| {
80 internal!("Cannot get expiration time of a recovered subscription")
81 })?,
82 )
83 .map_err::<ServerError<UpgradeAccountGooglePlayError>, _>(|e| {
84 internal!("Cannot parse millis into int: {:?}", e)
85 })?;
86
87 Ok(Self::GooglePlay(GooglePlayUserInfo {
88 purchase_token: purchase_token.to_string(),
89 subscription_product_id: config
90 .billing
91 .google
92 .premium_subscription_product_id
93 .clone(),
94 subscription_offer_id: config.billing.google.premium_subscription_offer_id.clone(),
95 expiration_time,
96 account_state: GooglePlayAccountState::Ok,
97 }))
98 }
99}
100
101#[derive(Serialize, Deserialize, Debug, Clone)]
102pub struct GooglePlayUserInfo {
103 pub purchase_token: String,
104 pub subscription_product_id: String,
105 pub subscription_offer_id: String,
106 pub expiration_time: UnixTimeMillis,
107 pub account_state: GooglePlayAccountState,
108}
109
110#[derive(Serialize, Deserialize, Debug, Clone)]
111pub struct StripeUserInfo {
112 pub customer_id: String,
113 pub customer_name: Uuid,
114 pub price_id: String,
115 pub payment_method_id: String,
116 pub last_4: String,
117 pub subscription_id: String,
118 pub expiration_time: UnixTimeMillis,
119 pub account_state: StripeAccountState,
120}
121
122#[derive(Serialize, Deserialize, Debug, Clone)]
123pub struct AppStoreUserInfo {
124 pub account_token: String,
125 pub original_transaction_id: String,
126 pub subscription_product_id: String,
127 pub expiration_time: UnixTimeMillis,
128 pub account_state: AppStoreAccountState,
129}