feat(billing): collect business name, address, and tax ID at checkout (#558)

This commit is contained in:
Ben Senescu 2026-08-27 18:56:26 -04:00 committed by GitHub
parent b0248f2acd
commit accac73e16
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 20 additions and 1 deletions

View File

@ -11,7 +11,10 @@ import { useStickToBottom } from "@/client/components/chat/useStickToBottom";
import { captureClientEvent } from "@/client/lib/posthog"; import { captureClientEvent } from "@/client/lib/posthog";
import { getStandardErrorMessage } from "@/client/lib/error-messages"; import { getStandardErrorMessage } from "@/client/lib/error-messages";
import { buildCheckoutSuccessUrl } from "@/client/features/billing/checkout-url"; import { buildCheckoutSuccessUrl } from "@/client/features/billing/checkout-url";
import { AUTUMN_PAID_PLAN_ID } from "@/shared/billing"; import {
AUTUMN_CHECKOUT_SESSION_PARAMS,
AUTUMN_PAID_PLAN_ID,
} from "@/shared/billing";
import { FREE_ONBOARDING_QUESTION_LIMIT } from "@/shared/onboardingChat"; import { FREE_ONBOARDING_QUESTION_LIMIT } from "@/shared/onboardingChat";
import { import {
ChatComposer, ChatComposer,
@ -131,6 +134,7 @@ export function OnboardingChatConversation({
planId: AUTUMN_PAID_PLAN_ID, planId: AUTUMN_PAID_PLAN_ID,
redirectMode: "always", redirectMode: "always",
successUrl: buildCheckoutSuccessUrl("/onboarding?step=3"), successUrl: buildCheckoutSuccessUrl("/onboarding?step=3"),
checkoutSessionParams: AUTUMN_CHECKOUT_SESSION_PARAMS,
}); });
} catch (checkoutErr) { } catch (checkoutErr) {
setCheckoutError( setCheckoutError(

View File

@ -13,6 +13,7 @@ import { parseTopUpAmount } from "@/client/features/billing/HostedBillingContent
import { getBillingRouteState } from "@/client/features/billing/route-state"; import { getBillingRouteState } from "@/client/features/billing/route-state";
import { getCustomerPlanStatus } from "@/client/features/billing/plan-detection"; import { getCustomerPlanStatus } from "@/client/features/billing/plan-detection";
import { import {
AUTUMN_CHECKOUT_SESSION_PARAMS,
AUTUMN_PAID_PLAN_ID, AUTUMN_PAID_PLAN_ID,
BILLING_ROUTE, BILLING_ROUTE,
AUTUMN_SEO_DATA_BALANCE_FEATURE_ID, AUTUMN_SEO_DATA_BALANCE_FEATURE_ID,
@ -103,6 +104,7 @@ function BillingPage() {
planId: AUTUMN_PAID_PLAN_ID, planId: AUTUMN_PAID_PLAN_ID,
redirectMode: "always", redirectMode: "always",
successUrl: buildCheckoutSuccessUrl(BILLING_ROUTE), successUrl: buildCheckoutSuccessUrl(BILLING_ROUTE),
checkoutSessionParams: AUTUMN_CHECKOUT_SESSION_PARAMS,
}); });
} }
@ -282,6 +284,7 @@ function BillingPage() {
planId: AUTUMN_SEO_DATA_TOP_UP_PLAN_ID, planId: AUTUMN_SEO_DATA_TOP_UP_PLAN_ID,
redirectMode: "always", redirectMode: "always",
successUrl: window.location.href, successUrl: window.location.href,
checkoutSessionParams: AUTUMN_CHECKOUT_SESSION_PARAMS,
featureQuantities: [ featureQuantities: [
{ {
featureId: AUTUMN_SEO_DATA_TOPUP_BALANCE_FEATURE_ID, featureId: AUTUMN_SEO_DATA_TOPUP_BALANCE_FEATURE_ID,

View File

@ -12,6 +12,7 @@ import { getCustomerPlanStatus } from "@/client/features/billing/plan-detection"
import { normalizeAuthRedirect } from "@/lib/auth-redirect"; import { normalizeAuthRedirect } from "@/lib/auth-redirect";
import { useCanManageBilling } from "@/client/features/team/organizationQueries"; import { useCanManageBilling } from "@/client/features/team/organizationQueries";
import { import {
AUTUMN_CHECKOUT_SESSION_PARAMS,
AUTUMN_MANAGED_ACCESS_FEATURE_ID, AUTUMN_MANAGED_ACCESS_FEATURE_ID,
AUTUMN_PAID_PLAN_ID, AUTUMN_PAID_PLAN_ID,
} from "@/shared/billing"; } from "@/shared/billing";
@ -200,6 +201,7 @@ function SubscribePage() {
planId: AUTUMN_PAID_PLAN_ID, planId: AUTUMN_PAID_PLAN_ID,
redirectMode: "always", redirectMode: "always",
successUrl: successUrl.toString(), successUrl: successUrl.toString(),
checkoutSessionParams: AUTUMN_CHECKOUT_SESSION_PARAMS,
}); });
} catch (err) { } catch (err) {
setError( setError(

View File

@ -16,6 +16,16 @@ export const AUTUMN_SEO_DATA_CREDITS_PER_USD = 1000;
export const SEO_DATA_COST_MARKUP = 1.28; export const SEO_DATA_COST_MARKUP = 1.28;
export const LOW_CREDITS_THRESHOLD_USD = 0.25; export const LOW_CREDITS_THRESHOLD_USD = 0.25;
// Passed through to Stripe's checkout.sessions.create so checkout collects the
// legal business name, tax ID (EU VAT etc.), and full billing address — makes
// invoices valid for business customers. Display only, no Stripe Tax. Stripe
// requires customer_update.name "auto" to collect tax IDs for an existing customer.
export const AUTUMN_CHECKOUT_SESSION_PARAMS = {
tax_id_collection: { enabled: true },
billing_address_collection: "required",
customer_update: { name: "auto", address: "auto" },
} as const;
export function roundUsdForBilling(value: number) { export function roundUsdForBilling(value: number) {
return Math.round(value * 100000) / 100000; return Math.round(value * 100000) / 100000;
} }