diff --git a/crates/api_clients/artcraft/artcraft_api_defs/src/moderation/user_stripe_data/moderator_get_user_stripe_customer_ids.rs b/crates/api_clients/artcraft/artcraft_api_defs/src/moderation/user_stripe_data/moderator_get_user_stripe_customer_ids.rs index 97308cfd3d..ab97dafd09 100644 --- a/crates/api_clients/artcraft/artcraft_api_defs/src/moderation/user_stripe_data/moderator_get_user_stripe_customer_ids.rs +++ b/crates/api_clients/artcraft/artcraft_api_defs/src/moderation/user_stripe_data/moderator_get_user_stripe_customer_ids.rs @@ -27,6 +27,9 @@ pub struct ModeratorUserStripeCustomerIdEntry { pub stripe_customer_id: String, pub payments_namespace: PaymentsNamespace, pub source: ModeratorStripeCustomerIdSource, + + /// Link to the customer in the Stripe dashboard for the namespace's account. + pub stripe_dashboard_url: String, } /// Which table the customer id was found in. diff --git a/crates/service/plugins/billing_artcraft/src/utils/artcraft_stripe_config.rs b/crates/service/plugins/billing_artcraft/src/utils/artcraft_stripe_config.rs index 91bb3c83c9..1fba72effd 100644 --- a/crates/service/plugins/billing_artcraft/src/utils/artcraft_stripe_config.rs +++ b/crates/service/plugins/billing_artcraft/src/utils/artcraft_stripe_config.rs @@ -2,6 +2,8 @@ use stripe::Client; #[derive(Clone)] pub struct ArtcraftStripeConfig { + /// The Stripe account id (eg. "acct_..."), used to build dashboard links. + pub stripe_account_id: String, pub secret_key: String, pub secret_webhook_signing_key: String, pub checkout_success_url: String, @@ -11,6 +13,8 @@ pub struct ArtcraftStripeConfig { #[derive(Clone)] pub struct ArtcraftStripeConfigWithClient { + /// The Stripe account id (eg. "acct_..."), used to build dashboard links. + pub stripe_account_id: String, pub secret_key: String, pub secret_webhook_signing_key: String, pub checkout_success_url: String, @@ -22,6 +26,7 @@ pub struct ArtcraftStripeConfigWithClient { impl ArtcraftStripeConfig { pub fn to_config_with_client(&self) -> ArtcraftStripeConfigWithClient { ArtcraftStripeConfigWithClient { + stripe_account_id: self.stripe_account_id.clone(), secret_key: self.secret_key.clone(), secret_webhook_signing_key: self.secret_webhook_signing_key.clone(), checkout_success_url: self.checkout_success_url.clone(), diff --git a/crates/service/web/storyteller_web/src/http_server/endpoints/moderation/user_stripe_data/moderator_get_user_stripe_customer_ids_handler.rs b/crates/service/web/storyteller_web/src/http_server/endpoints/moderation/user_stripe_data/moderator_get_user_stripe_customer_ids_handler.rs index f013792c2f..3701f7d84e 100644 --- a/crates/service/web/storyteller_web/src/http_server/endpoints/moderation/user_stripe_data/moderator_get_user_stripe_customer_ids_handler.rs +++ b/crates/service/web/storyteller_web/src/http_server/endpoints/moderation/user_stripe_data/moderator_get_user_stripe_customer_ids_handler.rs @@ -11,6 +11,7 @@ use artcraft_api_defs::moderation::user_stripe_data::moderator_get_user_stripe_c ModeratorUserStripeCustomerIdEntry, }; use mysql_queries::queries::users::user_stripe_customer_links::list_user_stripe_customer_links_for_user::list_user_stripe_customer_links_for_user; +use enums::common::payments_namespace::PaymentsNamespace; use mysql_queries::queries::users::user_subscriptions::list_stripe_customer_ids_for_user_subscriptions::list_stripe_customer_ids_for_user_subscriptions; use tokens::tokens::users::UserToken; @@ -67,12 +68,14 @@ pub async fn moderator_get_user_stripe_customer_ids_handler( let mut customer_ids = Vec::with_capacity(customer_links.len() + subscription_customer_ids.len()); customer_ids.extend(customer_links.into_iter().map(|link| ModeratorUserStripeCustomerIdEntry { + stripe_dashboard_url: stripe_dashboard_customer_url(&server_state, link.payments_namespace, &link.stripe_customer_id), stripe_customer_id: link.stripe_customer_id, payments_namespace: link.payments_namespace, source: ModeratorStripeCustomerIdSource::CustomerLink, })); customer_ids.extend(subscription_customer_ids.into_iter().map(|subscription| ModeratorUserStripeCustomerIdEntry { + stripe_dashboard_url: stripe_dashboard_customer_url(&server_state, subscription.subscription_namespace, &subscription.stripe_customer_id), stripe_customer_id: subscription.stripe_customer_id, payments_namespace: subscription.subscription_namespace, source: ModeratorStripeCustomerIdSource::Subscription, @@ -83,3 +86,16 @@ pub async fn moderator_get_user_stripe_customer_ids_handler( customer_ids, })) } + +/// Each payments namespace bills through a different Stripe account. +fn stripe_dashboard_customer_url( + server_state: &ServerState, + payments_namespace: PaymentsNamespace, + stripe_customer_id: &str, +) -> String { + let stripe_account_id = match payments_namespace { + PaymentsNamespace::Artcraft => &server_state.stripe_artcraft.stripe_account_id, + PaymentsNamespace::FakeYou => &server_state.stripe.stripe_account_id, + }; + format!("https://dashboard.stripe.com/{}/customers/{}", stripe_account_id, stripe_customer_id) +} diff --git a/crates/service/web/storyteller_web/src/startup/setup_stripe_artcraft.rs b/crates/service/web/storyteller_web/src/startup/setup_stripe_artcraft.rs index 23c76d9a01..30f91bc313 100644 --- a/crates/service/web/storyteller_web/src/startup/setup_stripe_artcraft.rs +++ b/crates/service/web/storyteller_web/src/startup/setup_stripe_artcraft.rs @@ -5,6 +5,7 @@ use errors::AnyhowResult; pub fn setup_stripe_artcraft() -> AnyhowResult { Ok(ArtcraftStripeConfig { + stripe_account_id: easyenv::get_env_string_required("STRIPE_ARTCRAFT_ACCOUNT_ID")?, secret_key: easyenv::get_env_string_required("STRIPE_ARTCRAFT_SECRET_KEY")?, secret_webhook_signing_key: easyenv::get_env_string_required("STRIPE_ARTCRAFT_SECRET_WEBHOOK_KEY")?, checkout_success_url: easyenv::get_env_string_required("STRIPE_ARTCRAFT_CHECKOUT_SUCCESS_URL")?, diff --git a/crates/service/web/storyteller_web/src/startup/setup_stripe_fakeyou.rs b/crates/service/web/storyteller_web/src/startup/setup_stripe_fakeyou.rs index 694485f264..47b6e85e41 100644 --- a/crates/service/web/storyteller_web/src/startup/setup_stripe_fakeyou.rs +++ b/crates/service/web/storyteller_web/src/startup/setup_stripe_fakeyou.rs @@ -31,5 +31,6 @@ pub fn setup_stripe_fakeyou() -> AnyhowResult { Ok(StripeSettings { config: stripe_configs, client: stripe_client, + stripe_account_id: easyenv::get_env_string_required("STRIPE_FAKEYOU_ACCOUNT_ID")?, }) } diff --git a/crates/service/web/storyteller_web/src/state/server_state.rs b/crates/service/web/storyteller_web/src/state/server_state.rs index 78e60bdce0..ac1ff64572 100644 --- a/crates/service/web/storyteller_web/src/state/server_state.rs +++ b/crates/service/web/storyteller_web/src/state/server_state.rs @@ -219,6 +219,9 @@ pub struct EphemeralInMemoryCaches { pub struct StripeSettings { pub config: StripeConfig, pub client: stripe::Client, + + /// The Stripe account id (eg. "acct_..."), used to build dashboard links. + pub stripe_account_id: String, } /// Flags set at service startup