docs(deploy): the installer's Stripe steps match what phase 5 actually needs
It still named two webhook events; the application handles six, and the four new ones are the billing cycle itself — renewals, failed payments, status changes and endings. It also said nothing about stripe:sync-catalogue, without which Stripe has no prices and nothing can be sold at all. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>feat/portal-design
parent
8c3a79e258
commit
4f3e11ae5e
|
|
@ -330,10 +330,17 @@ Still to do, in this order:
|
||||||
|
|
||||||
1. Point the DNS records at ${PUBLIC_IP} and put TLS in front (Zoraxy,
|
1. Point the DNS records at ${PUBLIC_IP} and put TLS in front (Zoraxy,
|
||||||
Caddy or nginx). ${ADMIN_DOMAIN} must NOT be publicly resolvable.
|
Caddy or nginx). ${ADMIN_DOMAIN} must NOT be publicly resolvable.
|
||||||
2. Enter STRIPE_WEBHOOK_SECRET in $INSTALL_DIR/.env — Stripe dashboard →
|
2. Enter STRIPE_SECRET and STRIPE_WEBHOOK_SECRET in $INSTALL_DIR/.env —
|
||||||
Developers → Webhooks → https://${APP_DOMAIN}/webhooks/stripe, events
|
Stripe dashboard → Developers → Webhooks →
|
||||||
checkout.session.completed and checkout.session.async_payment_succeeded.
|
https://${APP_DOMAIN}/webhooks/stripe, subscribing all six events:
|
||||||
3. Sign in and switch the website to hidden under Settings until you are
|
checkout.session.completed checkout.session.async_payment_succeeded
|
||||||
|
invoice.paid invoice.payment_failed
|
||||||
|
customer.subscription.updated customer.subscription.deleted
|
||||||
|
3. Mirror the plan catalogue into Stripe — nothing can be sold until it knows
|
||||||
|
what it is billing for. Look first; a Stripe Price cannot be deleted:
|
||||||
|
docker compose exec app php artisan stripe:sync-catalogue --dry-run
|
||||||
|
docker compose exec app php artisan stripe:sync-catalogue
|
||||||
|
4. Sign in and switch the website to hidden under Settings until you are
|
||||||
ready to be found (Settings → Website visibility).
|
ready to be found (Settings → Website visibility).
|
||||||
|
|
||||||
Updating later — as ${APP_USER}, not as root:
|
Updating later — as ${APP_USER}, not as root:
|
||||||
|
|
|
||||||
|
|
@ -65,9 +65,36 @@ kept failing until the worker was restarted.
|
||||||
the hostnames in `ADMIN_HOSTS` and 404s everywhere else, but keeping it out
|
the hostnames in `ADMIN_HOSTS` and 404s everywhere else, but keeping it out
|
||||||
of public DNS is the layer above that.
|
of public DNS is the layer above that.
|
||||||
- **`STRIPE_WEBHOOK_SECRET`.** Stripe dashboard → Developers → Webhooks →
|
- **`STRIPE_WEBHOOK_SECRET`.** Stripe dashboard → Developers → Webhooks →
|
||||||
`https://<app-domain>/webhooks/stripe`, events `checkout.session.completed`
|
`https://<app-domain>/webhooks/stripe`. The secret starts with `whsec_` and
|
||||||
and `checkout.session.async_payment_succeeded`. The secret starts with
|
differs between test and live mode. Subscribe all six events the application
|
||||||
`whsec_` and differs between test and live mode.
|
handles — the first two open a contract, the rest are the billing cycle,
|
||||||
|
which is Stripe's:
|
||||||
|
|
||||||
|
```
|
||||||
|
checkout.session.completed
|
||||||
|
checkout.session.async_payment_succeeded
|
||||||
|
invoice.paid
|
||||||
|
invoice.payment_failed
|
||||||
|
customer.subscription.updated
|
||||||
|
customer.subscription.deleted
|
||||||
|
```
|
||||||
|
|
||||||
|
- **The Stripe catalogue.** Nothing can be sold until Stripe knows what it is
|
||||||
|
billing for:
|
||||||
|
|
||||||
|
```
|
||||||
|
docker compose exec app php artisan stripe:sync-catalogue --dry-run # look first
|
||||||
|
docker compose exec app php artisan stripe:sync-catalogue
|
||||||
|
```
|
||||||
|
|
||||||
|
Run it again after publishing any new plan version. It is idempotent, and it
|
||||||
|
has to be: a Stripe Price cannot be edited or deleted, so a duplicate is
|
||||||
|
permanent. `--dry-run` lists exactly what would be created.
|
||||||
|
|
||||||
|
- **A look at the catalogue itself.** `php artisan plans:check` reports
|
||||||
|
overlapping availability windows, plans on sale with no live version, and
|
||||||
|
missing prices. Worth running after any plan change — all of it is computed
|
||||||
|
when read, so a mistake announces itself at a customer's checkout otherwise.
|
||||||
- **Backups.** At minimum the MariaDB volume and `/etc/wireguard` in the
|
- **Backups.** At minimum the MariaDB volume and `/etc/wireguard` in the
|
||||||
`wireguard` volume — losing the hub key means re-peering every host.
|
`wireguard` volume — losing the hub key means re-peering every host.
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue