feat(billing): grant 30-day signup free trial via Stripe Checkout (BUNYIP-209) #248
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/bunyip-209-signup-trial-period"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
New users now get a one-time 30-day free trial on their first checkout instead of an immediate paid subscription. The trial length is config-driven: StripeConfig gains trial_period_days (u32), read from BUNYIP_BILLING_TRIAL_PERIOD_DAYS with a 30-day fallback, plumbed through from_env and from_db_model.
Eligibility is tracked per user. A new migration adds users.has_used_trial BOOLEAN NOT NULL DEFAULT FALSE. create_checkout_session takes an eligible_for_trial flag (the membership handler passes !db_user.has_used_trial): when eligible it sets subscription_data.trial_period_days = config.trial_period_days and payment_method_collection = IfRequired so the trial starts with no card up front, and tags the session with trial=true metadata. When not eligible the session is byte-for-byte the prior immediate-billing flow.
The trial is burned only when the checkout finalizes, not at session creation, so an abandoned checkout never consumes it. The checkout.session.completed webhook calls UserRepository::mark_trial_used when the completed session carries trial=true metadata; the UPDATE sets has_used_trial = TRUE and is idempotent on Stripe retries/replays. A returning user (has_used_trial = TRUE) therefore gets the existing no-trial flow on any later subscribe.
Operator action documented in dev-docs/stripe-test-mode.md: mirror the same 30-day trial on the membership product in the Stripe Dashboard as defense in depth for any subscription created outside our checkout helper.
#BUNYIP-209