############################################################################### # Stripe — Checkout + Subscriptions (B-2.7 / B-2.8) ############################################################################### # # Required for the /checkout/ flow and the /webhooks/stripe receiver. # The application will boot without these — billing routes will redirect to # /tarifs with a "contact info@dictia.ca" message until the keys are set. # # Get these from https://dashboard.stripe.com (CAD account) # - Use sk_test_/pk_test_/whsec_test_ keys against the Stripe test mode for # pre-prod. Switch to live keys ONLY after end-to-end CAD/TVQ rehearsal. # STRIPE_SECRET_KEY=sk_test_... # or sk_live_... # STRIPE_PUBLISHABLE_KEY=pk_test_... # used client-side; not strictly needed for hosted Checkout # STRIPE_WEBHOOK_SECRET=whsec_... # for B-2.8 webhook signature verification ############################################################################### # Price IDs — one per plan, period, and (for hardware plans) setup fee. ############################################################################### # # Format: price_xxxxxxxxxxxxxxxxxxxxxxxxxx # Naming convention in this codebase: STRIPE__ # PLAN = DICTIA_8 | DICTIA_16 | DICTIA_CLOUD # TYPE = SETUP (one-time, hardware only) | MONTHLY | YEARLY # # Yearly Price = Monthly Price × 12 × 0.85 (15 % discount). Configure both # Prices in the Stripe Dashboard for each plan. # DictIA 8 (8-channel hardware bundle): 3 450 $ setup + 173 $/mo # STRIPE_DICTIA_8_SETUP=price_xxx # STRIPE_DICTIA_8_MONTHLY=price_xxx # STRIPE_DICTIA_8_YEARLY=price_xxx # DictIA 16 (16-channel hardware bundle): 5 750 $ setup + 201 $/mo # STRIPE_DICTIA_16_SETUP=price_xxx # STRIPE_DICTIA_16_MONTHLY=price_xxx # STRIPE_DICTIA_16_YEARLY=price_xxx # DictIA Cloud (SaaS-only, no hardware): 369 $/mo # STRIPE_DICTIA_CLOUD_MONTHLY=price_xxx # STRIPE_DICTIA_CLOUD_YEARLY=price_xxx ############################################################################### # Required Stripe Dashboard configuration ############################################################################### # # 1. Activate CAD currency on the account (Settings → Account → Currencies). # # 2. Enable Stripe Tax with TPS (5 %) and TVQ (9.975 %) for Quebec # (Tax → Settings → Tax registrations → Canada → Quebec). # All Checkout Sessions are created with `automatic_tax: { enabled: true }` # and `billing_address_collection: required` so Stripe computes taxes. # # 3. Enable Apple Pay + Google Pay # (Settings → Payment methods → Apple Pay, Google Pay). # Apple Pay requires verifying the dictia.ca domain via the Stripe-hosted # `.well-known/apple-developer-merchantid-domain-association` file. # # 4. For each plan, create: # - One recurring monthly Price (CAD, billing_scheme=per_unit) # - One recurring yearly Price (CAD, = monthly × 12 × 0.85) # For DictIA 8 and DictIA 16, also create a one-time Price for the setup fee. # # 5. Create a webhook endpoint (B-2.8) pointing at # https://your-domain.example/checkout/webhooks/stripe # (the route lives under the /checkout/* prefix; CSRF-exempt; signature- # verified via STRIPE_WEBHOOK_SECRET below). # # Subscribe at minimum to these 5 events (the only ones the handler # processes; all others are acknowledged with 200 + ignored): # - checkout.session.completed (creates Subscription row, sets # User.subscription_status='active') # - customer.subscription.updated (status / current_period_end sync) # - customer.subscription.deleted (marks status='canceled') # - invoice.payment_succeeded (renewal touch; recovers past_due) # - invoice.payment_failed (marks status='past_due') # # Copy the signing secret (whsec_...) into STRIPE_WEBHOOK_SECRET above. # Without that secret, the webhook endpoint returns 400 invalid_signature # on every delivery (Stripe will retry for up to 30 days).