real_stripe_client.rs

  1use std::str::FromStr as _;
  2use std::sync::Arc;
  3
  4use anyhow::{Context as _, Result};
  5use async_trait::async_trait;
  6use serde::Serialize;
  7use stripe::{CreateCustomer, Customer, CustomerId, ListCustomers, Price, PriceId, Recurring};
  8
  9use crate::stripe_client::{
 10    CreateCustomerParams, StripeClient, StripeCustomer, StripeCustomerId, StripeMeter, StripePrice,
 11    StripePriceId, StripePriceRecurring,
 12};
 13
 14pub struct RealStripeClient {
 15    client: Arc<stripe::Client>,
 16}
 17
 18impl RealStripeClient {
 19    pub fn new(client: Arc<stripe::Client>) -> Self {
 20        Self { client }
 21    }
 22}
 23
 24#[async_trait]
 25impl StripeClient for RealStripeClient {
 26    async fn list_customers_by_email(&self, email: &str) -> Result<Vec<StripeCustomer>> {
 27        let response = Customer::list(
 28            &self.client,
 29            &ListCustomers {
 30                email: Some(email),
 31                ..Default::default()
 32            },
 33        )
 34        .await?;
 35
 36        Ok(response
 37            .data
 38            .into_iter()
 39            .map(StripeCustomer::from)
 40            .collect())
 41    }
 42
 43    async fn create_customer(&self, params: CreateCustomerParams<'_>) -> Result<StripeCustomer> {
 44        let customer = Customer::create(
 45            &self.client,
 46            CreateCustomer {
 47                email: params.email,
 48                ..Default::default()
 49            },
 50        )
 51        .await?;
 52
 53        Ok(StripeCustomer::from(customer))
 54    }
 55
 56    async fn list_prices(&self) -> Result<Vec<StripePrice>> {
 57        let response = stripe::Price::list(
 58            &self.client,
 59            &stripe::ListPrices {
 60                limit: Some(100),
 61                ..Default::default()
 62            },
 63        )
 64        .await?;
 65
 66        Ok(response.data.into_iter().map(StripePrice::from).collect())
 67    }
 68
 69    async fn list_meters(&self) -> Result<Vec<StripeMeter>> {
 70        #[derive(Serialize)]
 71        struct Params {
 72            #[serde(skip_serializing_if = "Option::is_none")]
 73            limit: Option<u64>,
 74        }
 75
 76        let response = self
 77            .client
 78            .get_query::<stripe::List<StripeMeter>, _>(
 79                "/billing/meters",
 80                Params { limit: Some(100) },
 81            )
 82            .await?;
 83
 84        Ok(response.data)
 85    }
 86}
 87
 88impl From<CustomerId> for StripeCustomerId {
 89    fn from(value: CustomerId) -> Self {
 90        Self(value.as_str().into())
 91    }
 92}
 93
 94impl TryFrom<StripeCustomerId> for CustomerId {
 95    type Error = anyhow::Error;
 96
 97    fn try_from(value: StripeCustomerId) -> Result<Self, Self::Error> {
 98        Self::from_str(value.0.as_ref()).context("failed to parse Stripe customer ID")
 99    }
100}
101
102impl From<Customer> for StripeCustomer {
103    fn from(value: Customer) -> Self {
104        StripeCustomer {
105            id: value.id.into(),
106            email: value.email,
107        }
108    }
109}
110
111impl From<PriceId> for StripePriceId {
112    fn from(value: PriceId) -> Self {
113        Self(value.as_str().into())
114    }
115}
116
117impl TryFrom<StripePriceId> for PriceId {
118    type Error = anyhow::Error;
119
120    fn try_from(value: StripePriceId) -> Result<Self, Self::Error> {
121        Self::from_str(value.0.as_ref()).context("failed to parse Stripe price ID")
122    }
123}
124
125impl From<Price> for StripePrice {
126    fn from(value: Price) -> Self {
127        Self {
128            id: value.id.into(),
129            unit_amount: value.unit_amount,
130            lookup_key: value.lookup_key,
131            recurring: value.recurring.map(StripePriceRecurring::from),
132        }
133    }
134}
135
136impl From<Recurring> for StripePriceRecurring {
137    fn from(value: Recurring) -> Self {
138        Self { meter: value.meter }
139    }
140}