| Field | Value |
|---|---|
| Date | 09 Jun 2026 |
| Status | ✅ Complete |
| GitHub Commits | 4209021, 1b45857 |
Stripe migrated from test to live keys on production, webhook infrastructure set up on
both environments, a professional payment success page built, and a second Twilio security
incident resolved (historical credentials in git history).
Stripe account configured at accounts@resolvit.com.au (AU). Live keys activated on prod.
Dev remains on test/sandbox keys (sk_test_) — correct setup.
CRITICAL: Production is on LIVE keys. Real customer payments will be charged.
Do not run billing tests on prod — always use dev for testing.
Installed Stripe CLI v1.42.5 on dev for local webhook testing.
Install path: /usr/bin/stripe (via JFrog apt repo)
Correct apt repo: packages.stripe.dev/stripe-cli-debian-local (not stripe-cli-apt-stable)
Usage:
stripe login --api-key sk_test_...
stripe listen --forward-to http://10.0.0.41/api/webhooks/stripe/
stripe listen --print-secret # get the exact webhook secret without terminal wrapping
Note: stripe listen generates a new webhook secret each time it starts.
Always use --print-secret to get the exact value — terminal line wrapping can truncate it.
Update STRIPE_WEBHOOK_SECRET in dev .env with the exact value from --print-secret.
Webhook was returning 400 on all events. Root cause: the webhook secret in .env was
missing one character (cc03 instead of cc033) due to terminal line wrapping when
copying from the stripe listen output.
Fix: always use stripe listen --print-secret to get the clean value.
Created a professional branded payment success page at /api/portal/payment-success/
Previously the success URL redirected to /invoices which required admin login,
causing customers to land on the login page after paying. Now fixed.
URL pattern:
/api/portal/payment-success/?invoice=YC-2026-XXXX
Set in both apps/billing/pdf.py and apps/billing/email.py as the Stripe success_url.
The Yealin logo wasn't accessible because STATICFILES_DIRS was not set in base.py.
Django's collectstatic only picked up app-level static/ folders, not the project-level
static/ directory.
Fix: added STATICFILES_DIRS = [BASE_DIR / 'static'] to config/settings/base.py.
Run python manage.py collectstatic after any changes to static/ files.
Logo path: static/images/yealin-logo.png → served at /static/images/yealin-logo.png
Twilio sent a second automated security alert about credentials found in git history:
https://github.com/ounyai/yealin-billing/blob/18cbb9c5.../.env.example
The historical commit contained real credentials:
All exposed credentials were already superseded — no active credentials were compromised.
Actions taken:
All draft/issued invoices regenerated on prod with: