105 lines
3.5 KiB
Markdown
105 lines
3.5 KiB
Markdown
# Academy Billing Production Rollout
|
|
|
|
Last updated: 2026-05-19
|
|
|
|
This note covers the remaining non-code steps required to move Academy Stripe billing from implemented-in-app to production-ready.
|
|
|
|
## Readiness Check
|
|
|
|
Run the local readiness command before enabling the rollout flag:
|
|
|
|
```bash
|
|
php artisan academy:billing-health
|
|
php artisan academy:billing-health --json
|
|
php artisan academy:billing-health --strict
|
|
```
|
|
|
|
What it checks:
|
|
- Stripe publishable key, secret key, and webhook secret are configured and not placeholder values
|
|
- Academy billing price IDs are present for all configured plans
|
|
- Cashier webhook and Academy billing routes are registered
|
|
- Billing tables and Cashier user columns exist locally
|
|
- Moderation Academy billing overview route is available
|
|
|
|
`--strict` exits non-zero when blocking issues are found, which makes it suitable for CI or pre-deploy checks.
|
|
|
|
## Environment Variables
|
|
|
|
The following values must be set with real production values before enabling Academy billing:
|
|
|
|
```dotenv
|
|
SKINBASE_ACADEMY_ENABLED=true
|
|
ACADEMY_BILLING_ENABLED=true
|
|
ACADEMY_STRIPE_SUBSCRIPTION_NAME=academy
|
|
|
|
STRIPE_KEY=pk_live_...
|
|
STRIPE_SECRET=sk_live_...
|
|
STRIPE_WEBHOOK_SECRET=whsec_...
|
|
CASHIER_CURRENCY=eur
|
|
CASHIER_CURRENCY_LOCALE=sl_SI
|
|
|
|
ACADEMY_CREATOR_MONTHLY_PRICE_ID=price_...
|
|
ACADEMY_PRO_MONTHLY_PRICE_ID=price_...
|
|
```
|
|
|
|
Do not enable `ACADEMY_BILLING_ENABLED=true` until the webhook endpoint and Billing Portal are configured in Stripe.
|
|
|
|
## Stripe Dashboard Steps
|
|
|
|
Create these products:
|
|
- Skinbase Academy Creator
|
|
- Skinbase Academy Pro
|
|
|
|
Create these recurring prices:
|
|
- `creator_monthly`
|
|
- `pro_monthly`
|
|
|
|
Configure the production webhook endpoint:
|
|
- URL: `https://skinbase.org/stripe/webhook`
|
|
- Signing secret: copy into `STRIPE_WEBHOOK_SECRET`
|
|
|
|
Recommended subscribed events:
|
|
- `checkout.session.completed`
|
|
- `customer.subscription.created`
|
|
- `customer.subscription.updated`
|
|
- `customer.subscription.deleted`
|
|
- `customer.updated`
|
|
- `customer.deleted`
|
|
- `payment_method.automatically_updated`
|
|
- `invoice.payment_succeeded`
|
|
- `invoice.payment_failed`
|
|
- `invoice.payment_action_required`
|
|
|
|
Configure Stripe Billing Portal:
|
|
- Allow payment method updates
|
|
- Allow plan changes
|
|
- Allow cancellation
|
|
- Allow invoice history access
|
|
|
|
## Deployment Sequence
|
|
|
|
1. Deploy code and migrations.
|
|
2. Populate production env with live Stripe values and production price IDs.
|
|
3. Run `php artisan academy:billing-health --strict` on the target environment.
|
|
4. Confirm the webhook endpoint is reachable and signature verification is active.
|
|
5. Test a full Stripe test-mode or low-risk live transaction.
|
|
6. Verify the subscription appears in local Cashier tables and Academy access updates from synced state.
|
|
7. Verify `/moderation/academy/billing` shows the expected audit event and subscription counts.
|
|
8. Enable `ACADEMY_BILLING_ENABLED=true` only after the prior checks pass.
|
|
|
|
## Smoke Test Checklist
|
|
|
|
After rollout:
|
|
- Guest can view Academy pricing
|
|
- Guest cannot start checkout
|
|
- Verified user can start checkout
|
|
- Success page does not grant access by itself
|
|
- Webhook sync creates or updates the local subscription rows
|
|
- Creator plan unlocks creator content but not pro content
|
|
- Pro plan unlocks creator and pro content
|
|
- Billing Portal opens and returns to `/academy/billing`
|
|
- Canceling a subscription keeps access during grace period and removes it after end
|
|
|
|
## Operational Note
|
|
|
|
The moderation billing overview at `/moderation/academy/billing` is visibility-only. It is not a manual entitlement system and should not be used to bypass Stripe billing state. |