@@ -15,6 +15,29 @@ type BillingSession = {
1515 readonly userId : string ;
1616} ;
1717
18+ const ATTACH_PATH = "/api/billing/attach" ;
19+
20+ // Stripe Checkout hides the VAT / tax ID field unless the session asks for it.
21+ // Autumn always passes an existing Stripe customer, and Stripe then requires
22+ // `customer_update.name = "auto"` so it can save the business name. Set on the
23+ // server so every checkout gets it, whatever the client sends.
24+ export const CHECKOUT_TAX_ID_PARAMS = {
25+ tax_id_collection : { enabled : true } ,
26+ billing_address_collection : "required" ,
27+ customer_update : { name : "auto" , address : "auto" } ,
28+ } as const ;
29+
30+ export const withCheckoutTaxIdCollection = ( pathname : string , body : unknown ) : unknown => {
31+ if ( pathname !== ATTACH_PATH || typeof body !== "object" || body === null ) return body ;
32+ const { checkoutSessionParams, ...rest } = body as {
33+ readonly checkoutSessionParams ?: Record < string , unknown > ;
34+ } ;
35+ return {
36+ ...rest ,
37+ checkoutSessionParams : { ...checkoutSessionParams , ...CHECKOUT_TAX_ID_PARAMS } ,
38+ } ;
39+ } ;
40+
1841export const resolveBillingOrganization = ( request : Request , session : BillingSession ) =>
1942 Effect . gen ( function * ( ) {
2043 // FAIL CLOSED: no header, no org. The AutumnProvider always sends the
@@ -84,7 +107,7 @@ const handler = Effect.gen(function* () {
84107 request : {
85108 url : url . pathname ,
86109 method : request . method ,
87- body,
110+ body : withCheckoutTaxIdCollection ( url . pathname , body ) ,
88111 } ,
89112 customerId : org . id ,
90113 customerData : {
0 commit comments