Sales tax on the setup fee: test-mode dry run
2026-10-09 · Stripe TEST mode (Sandbox) · stage TEST company (Fairhaven Residential (TEST)) on propflow-stage · code: branch feat/setup-fee-sales-tax (part 2) on top of #18415 (part 1)
Result
| Check | Result |
|---|---|
| Stripe page shows the $4,000.00 fee plus a sales tax line for 1601 Blake St, Denver CO 80202 | PASS: tax $206.00 (5.15%), total $4,206.00 |
| Clicking pay twice, the second time after the address was entered, serves the same page | PASS: same session id both times |
| A company that already has a Stripe customer can open the taxed page (the stored-customer path) | PASS: Stripe accepted it and saved the address on the customer |
| After paying, the company record keeps the fee and the tax apart | PASS: fee 400000, tax 20600, total 420600 (cents) |
| Billing card says "plus sales tax" before paying | PASS |
No bugs found. One thing to know: Colorado taxes this fee only in its 65 home-rule cities (Denver is one). The state treats it as exempt SaaS, so a Colorado customer billed outside those cities correctly pays $0 tax.
The two clicks
| Click | Checkout session | Session total at the time |
|---|---|---|
| New-customer page, first click | cs_test_a1xse1NKXD0xu6Vzzcc35KKjn6ThQICJRhocDHQPEOvrhPL3iepZi83kiY | $4,000.00 (no address yet) |
| Same page, second click after entering the Denver address | cs_test_a1xse1NKXD0xu6Vzzcc35KKjn6ThQICJRhocDHQPEOvrhPL3iepZi83kiY (same) | $4,206.00 |
| Stored-customer page (after the first page's bank payment failed), first click | cs_test_a1xS06qDozIWRk7uyzIAmfyXGQFrPT8AkjVqk0LaZJgQzooLpjJ4zjLR2C | $4,000.00 |
| Same page, second click after entering the Denver address | cs_test_a1xS06qDozIWRk7uyzIAmfyXGQFrPT8AkjVqk0LaZJgQzooLpjJ4zjLR2C (same) | $4,206.00 |
Each session's total was read back from Stripe just before the second click, so the reuse held while the page's total ($4,206.00) differed from the plan's fee ($4,000.00). Only one session was created per page.
Screenshots, the record Stripe's webhook wrote, and how it was run
Before: the Billing card
The Stripe page with sales tax
Failed bank payment, then retry on the stored customer
The first page was paid with Stripe's test account that fails after processing. The webhook stored failed with the customer id, and the card offered the button again. The retry opened a new page on the stored customer (customer_update on), which Stripe accepted.
Successful bank payment
The record on the stage TEST company after checkout.session.async_payment_succeeded (read from propflow-stage):
billingSetup: { setupFeeStatus: "paid", setupFeeCents: 400000, setupFeeTaxCents: 20600, setupFeeTotalCents: 420600,
checkoutSessionId: "cs_test_a1xS06qDozIWRk7uyzIAmfyXGQFrPT8AkjVqk0LaZJgQzooLpjJ4zjLR2C", stripeCustomerId: "cus_… (test)" }
Stripe's own read of that session: automatic_tax.status=complete, amount_subtotal=400000, total_details.amount_tax=20600, amount_total=420600. Breakdown: Denver city 5.15% standard_rated ($206.00); Colorado state 4% product_exempt ($0). The customer's address afterwards: 1601 Blake St, Denver CO 80202. Every forwarded webhook answered 200.
How it was run, and the cleanup
- A local dev server running the PR branch, with
STRIPE_SECRET_KEYset to the test key (every session id iscs_test_),DYNAMODB_TABLE_NAME=propflow-stageandAUTH_TABLE_NAME=propflow-auth-stage. Signed in as the stage smoke user; the session row was confirmed in the stage auth table and absent from prod. Nothing was written to live Stripe or to any production table. - The $4,000 plan was set through the staff route on the stage TEST company.
stripe listenforwarded the test webhooks. - Test-mode Stripe Tax mirrors live: tax settings active, default tax code
txcd_10103001, Colorado state registration plus the same 65 home-rule city registrations live has (set up by the prep lane). - Cleanup, read back from
propflow-stage: billingPlan, billingSetup and billingSetupCheckout removed from the stage TEST company. Both test sessions are complete (nothing left open). Key files deleted from the lane directory.