collab: Save Customer name and billing address to Customer on checkout (#33385)

We are collecting billing address and name on checkout now (for tax) but
we're not saving it back to the Customer level. Updating the Checkout
Session code to make`customer_update.address` equal to `auto`, instead
of the default `never`, as well as the same for `customer_update.name`.

Release Notes:

- N/A
This commit is contained in:
morgankrey 2025-06-25 15:06:14 -05:00 committed by GitHub
parent 8f9817173d
commit 6fb5500ef2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 125 additions and 12 deletions

View file

@ -16,9 +16,9 @@ use crate::stripe_client::{
StripeCreateCheckoutSessionLineItems, StripeCreateCheckoutSessionParams, StripeCreateCheckoutSessionLineItems, StripeCreateCheckoutSessionParams,
StripeCreateCheckoutSessionSubscriptionData, StripeCreateMeterEventParams, StripeCreateCheckoutSessionSubscriptionData, StripeCreateMeterEventParams,
StripeCreateMeterEventPayload, StripeCreateSubscriptionItems, StripeCreateSubscriptionParams, StripeCreateMeterEventPayload, StripeCreateSubscriptionItems, StripeCreateSubscriptionParams,
StripeCustomerId, StripeMeter, StripePrice, StripePriceId, StripeSubscription, StripeCustomerId, StripeCustomerUpdate, StripeCustomerUpdateAddress, StripeCustomerUpdateName,
StripeSubscriptionId, StripeSubscriptionTrialSettings, StripeMeter, StripePrice, StripePriceId, StripeSubscription, StripeSubscriptionId,
StripeSubscriptionTrialSettingsEndBehavior, StripeSubscriptionTrialSettings, StripeSubscriptionTrialSettingsEndBehavior,
StripeSubscriptionTrialSettingsEndBehaviorMissingPaymentMethod, UpdateSubscriptionItems, StripeSubscriptionTrialSettingsEndBehaviorMissingPaymentMethod, UpdateSubscriptionItems,
UpdateSubscriptionParams, UpdateSubscriptionParams,
}; };
@ -247,6 +247,11 @@ impl StripeBilling {
}]); }]);
params.success_url = Some(success_url); params.success_url = Some(success_url);
params.billing_address_collection = Some(StripeBillingAddressCollection::Required); params.billing_address_collection = Some(StripeBillingAddressCollection::Required);
params.customer_update = Some(StripeCustomerUpdate {
address: Some(StripeCustomerUpdateAddress::Auto),
name: Some(StripeCustomerUpdateName::Auto),
shipping: None,
});
let session = self.client.create_checkout_session(params).await?; let session = self.client.create_checkout_session(params).await?;
Ok(session.url.context("no checkout session URL")?) Ok(session.url.context("no checkout session URL")?)
@ -301,6 +306,11 @@ impl StripeBilling {
}]); }]);
params.success_url = Some(success_url); params.success_url = Some(success_url);
params.billing_address_collection = Some(StripeBillingAddressCollection::Required); params.billing_address_collection = Some(StripeBillingAddressCollection::Required);
params.customer_update = Some(StripeCustomerUpdate {
address: Some(StripeCustomerUpdateAddress::Auto),
name: Some(StripeCustomerUpdateName::Auto),
shipping: None,
});
let session = self.client.create_checkout_session(params).await?; let session = self.client.create_checkout_session(params).await?;
Ok(session.url.context("no checkout session URL")?) Ok(session.url.context("no checkout session URL")?)

View file

@ -154,6 +154,31 @@ pub enum StripeBillingAddressCollection {
Required, Required,
} }
#[derive(Debug, PartialEq, Clone)]
pub struct StripeCustomerUpdate {
pub address: Option<StripeCustomerUpdateAddress>,
pub name: Option<StripeCustomerUpdateName>,
pub shipping: Option<StripeCustomerUpdateShipping>,
}
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum StripeCustomerUpdateAddress {
Auto,
Never,
}
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum StripeCustomerUpdateName {
Auto,
Never,
}
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum StripeCustomerUpdateShipping {
Auto,
Never,
}
#[derive(Debug, Default)] #[derive(Debug, Default)]
pub struct StripeCreateCheckoutSessionParams<'a> { pub struct StripeCreateCheckoutSessionParams<'a> {
pub customer: Option<&'a StripeCustomerId>, pub customer: Option<&'a StripeCustomerId>,
@ -164,6 +189,7 @@ pub struct StripeCreateCheckoutSessionParams<'a> {
pub subscription_data: Option<StripeCreateCheckoutSessionSubscriptionData>, pub subscription_data: Option<StripeCreateCheckoutSessionSubscriptionData>,
pub success_url: Option<&'a str>, pub success_url: Option<&'a str>,
pub billing_address_collection: Option<StripeBillingAddressCollection>, pub billing_address_collection: Option<StripeBillingAddressCollection>,
pub customer_update: Option<StripeCustomerUpdate>,
} }
#[derive(Debug, PartialEq, Eq, Clone, Copy)] #[derive(Debug, PartialEq, Eq, Clone, Copy)]

View file

@ -12,9 +12,10 @@ use crate::stripe_client::{
StripeCheckoutSessionMode, StripeCheckoutSessionPaymentMethodCollection, StripeClient, StripeCheckoutSessionMode, StripeCheckoutSessionPaymentMethodCollection, StripeClient,
StripeCreateCheckoutSessionLineItems, StripeCreateCheckoutSessionParams, StripeCreateCheckoutSessionLineItems, StripeCreateCheckoutSessionParams,
StripeCreateCheckoutSessionSubscriptionData, StripeCreateMeterEventParams, StripeCreateCheckoutSessionSubscriptionData, StripeCreateMeterEventParams,
StripeCreateSubscriptionParams, StripeCustomer, StripeCustomerId, StripeMeter, StripeMeterId, StripeCreateSubscriptionParams, StripeCustomer, StripeCustomerId, StripeCustomerUpdate,
StripePrice, StripePriceId, StripeSubscription, StripeSubscriptionId, StripeSubscriptionItem, StripeMeter, StripeMeterId, StripePrice, StripePriceId, StripeSubscription,
StripeSubscriptionItemId, UpdateCustomerParams, UpdateSubscriptionParams, StripeSubscriptionId, StripeSubscriptionItem, StripeSubscriptionItemId, UpdateCustomerParams,
UpdateSubscriptionParams,
}; };
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@ -36,6 +37,7 @@ pub struct StripeCreateCheckoutSessionCall {
pub subscription_data: Option<StripeCreateCheckoutSessionSubscriptionData>, pub subscription_data: Option<StripeCreateCheckoutSessionSubscriptionData>,
pub success_url: Option<String>, pub success_url: Option<String>,
pub billing_address_collection: Option<StripeBillingAddressCollection>, pub billing_address_collection: Option<StripeBillingAddressCollection>,
pub customer_update: Option<StripeCustomerUpdate>,
} }
pub struct FakeStripeClient { pub struct FakeStripeClient {
@ -233,6 +235,7 @@ impl StripeClient for FakeStripeClient {
subscription_data: params.subscription_data, subscription_data: params.subscription_data,
success_url: params.success_url.map(|url| url.to_string()), success_url: params.success_url.map(|url| url.to_string()),
billing_address_collection: params.billing_address_collection, billing_address_collection: params.billing_address_collection,
customer_update: params.customer_update,
}); });
Ok(StripeCheckoutSession { Ok(StripeCheckoutSession {

View file

@ -22,10 +22,11 @@ use crate::stripe_client::{
StripeCheckoutSessionPaymentMethodCollection, StripeClient, StripeCheckoutSessionPaymentMethodCollection, StripeClient,
StripeCreateCheckoutSessionLineItems, StripeCreateCheckoutSessionParams, StripeCreateCheckoutSessionLineItems, StripeCreateCheckoutSessionParams,
StripeCreateCheckoutSessionSubscriptionData, StripeCreateMeterEventParams, StripeCreateCheckoutSessionSubscriptionData, StripeCreateMeterEventParams,
StripeCreateSubscriptionParams, StripeCustomer, StripeCustomerId, StripeMeter, StripePrice, StripeCreateSubscriptionParams, StripeCustomer, StripeCustomerId, StripeCustomerUpdate,
StripePriceId, StripePriceRecurring, StripeSubscription, StripeSubscriptionId, StripeCustomerUpdateAddress, StripeCustomerUpdateName, StripeCustomerUpdateShipping,
StripeSubscriptionItem, StripeSubscriptionItemId, StripeSubscriptionTrialSettings, StripeMeter, StripePrice, StripePriceId, StripePriceRecurring, StripeSubscription,
StripeSubscriptionTrialSettingsEndBehavior, StripeSubscriptionId, StripeSubscriptionItem, StripeSubscriptionItemId,
StripeSubscriptionTrialSettings, StripeSubscriptionTrialSettingsEndBehavior,
StripeSubscriptionTrialSettingsEndBehaviorMissingPaymentMethod, UpdateCustomerParams, StripeSubscriptionTrialSettingsEndBehaviorMissingPaymentMethod, UpdateCustomerParams,
UpdateSubscriptionParams, UpdateSubscriptionParams,
}; };
@ -446,6 +447,7 @@ impl<'a> TryFrom<StripeCreateCheckoutSessionParams<'a>> for CreateCheckoutSessio
subscription_data: value.subscription_data.map(Into::into), subscription_data: value.subscription_data.map(Into::into),
success_url: value.success_url, success_url: value.success_url,
billing_address_collection: value.billing_address_collection.map(Into::into), billing_address_collection: value.billing_address_collection.map(Into::into),
customer_update: value.customer_update.map(Into::into),
..Default::default() ..Default::default()
}) })
} }
@ -541,3 +543,50 @@ impl From<StripeBillingAddressCollection> for stripe::CheckoutSessionBillingAddr
} }
} }
} }
impl From<StripeCustomerUpdateAddress> for stripe::CreateCheckoutSessionCustomerUpdateAddress {
fn from(value: StripeCustomerUpdateAddress) -> Self {
match value {
StripeCustomerUpdateAddress::Auto => {
stripe::CreateCheckoutSessionCustomerUpdateAddress::Auto
}
StripeCustomerUpdateAddress::Never => {
stripe::CreateCheckoutSessionCustomerUpdateAddress::Never
}
}
}
}
impl From<StripeCustomerUpdateName> for stripe::CreateCheckoutSessionCustomerUpdateName {
fn from(value: StripeCustomerUpdateName) -> Self {
match value {
StripeCustomerUpdateName::Auto => stripe::CreateCheckoutSessionCustomerUpdateName::Auto,
StripeCustomerUpdateName::Never => {
stripe::CreateCheckoutSessionCustomerUpdateName::Never
}
}
}
}
impl From<StripeCustomerUpdateShipping> for stripe::CreateCheckoutSessionCustomerUpdateShipping {
fn from(value: StripeCustomerUpdateShipping) -> Self {
match value {
StripeCustomerUpdateShipping::Auto => {
stripe::CreateCheckoutSessionCustomerUpdateShipping::Auto
}
StripeCustomerUpdateShipping::Never => {
stripe::CreateCheckoutSessionCustomerUpdateShipping::Never
}
}
}
}
impl From<StripeCustomerUpdate> for stripe::CreateCheckoutSessionCustomerUpdate {
fn from(value: StripeCustomerUpdate) -> Self {
stripe::CreateCheckoutSessionCustomerUpdate {
address: value.address.map(Into::into),
name: value.name.map(Into::into),
shipping: value.shipping.map(Into::into),
}
}
}

View file

@ -8,8 +8,9 @@ use crate::stripe_billing::StripeBilling;
use crate::stripe_client::{ use crate::stripe_client::{
FakeStripeClient, StripeBillingAddressCollection, StripeCheckoutSessionMode, FakeStripeClient, StripeBillingAddressCollection, StripeCheckoutSessionMode,
StripeCheckoutSessionPaymentMethodCollection, StripeCreateCheckoutSessionLineItems, StripeCheckoutSessionPaymentMethodCollection, StripeCreateCheckoutSessionLineItems,
StripeCreateCheckoutSessionSubscriptionData, StripeCustomerId, StripeMeter, StripeMeterId, StripeCreateCheckoutSessionSubscriptionData, StripeCustomerId, StripeCustomerUpdate,
StripePrice, StripePriceId, StripePriceRecurring, StripeSubscription, StripeSubscriptionId, StripeCustomerUpdateAddress, StripeCustomerUpdateName, StripeMeter, StripeMeterId, StripePrice,
StripePriceId, StripePriceRecurring, StripeSubscription, StripeSubscriptionId,
StripeSubscriptionItem, StripeSubscriptionItemId, StripeSubscriptionTrialSettings, StripeSubscriptionItem, StripeSubscriptionItemId, StripeSubscriptionTrialSettings,
StripeSubscriptionTrialSettingsEndBehavior, StripeSubscriptionTrialSettingsEndBehavior,
StripeSubscriptionTrialSettingsEndBehaviorMissingPaymentMethod, UpdateSubscriptionItems, StripeSubscriptionTrialSettingsEndBehaviorMissingPaymentMethod, UpdateSubscriptionItems,
@ -431,6 +432,14 @@ async fn test_checkout_with_zed_pro() {
call.billing_address_collection, call.billing_address_collection,
Some(StripeBillingAddressCollection::Required) Some(StripeBillingAddressCollection::Required)
); );
assert_eq!(
call.customer_update,
Some(StripeCustomerUpdate {
address: Some(StripeCustomerUpdateAddress::Auto),
name: Some(StripeCustomerUpdateName::Auto),
shipping: None,
})
);
} }
} }
@ -516,6 +525,14 @@ async fn test_checkout_with_zed_pro_trial() {
call.billing_address_collection, call.billing_address_collection,
Some(StripeBillingAddressCollection::Required) Some(StripeBillingAddressCollection::Required)
); );
assert_eq!(
call.customer_update,
Some(StripeCustomerUpdate {
address: Some(StripeCustomerUpdateAddress::Auto),
name: Some(StripeCustomerUpdateName::Auto),
shipping: None,
})
);
} }
// Successful checkout with extended trial. // Successful checkout with extended trial.
@ -574,5 +591,13 @@ async fn test_checkout_with_zed_pro_trial() {
call.billing_address_collection, call.billing_address_collection,
Some(StripeBillingAddressCollection::Required) Some(StripeBillingAddressCollection::Required)
); );
assert_eq!(
call.customer_update,
Some(StripeCustomerUpdate {
address: Some(StripeCustomerUpdateAddress::Auto),
name: Some(StripeCustomerUpdateName::Auto),
shipping: None,
})
);
} }
} }