Context
A membership site on WordPress used Stripe for renewals. Webhooks updated access in theory. In practice, hosting restarts and plugin updates dropped events. Support tickets: "I paid but my account is locked."
They wanted insurance-not a rewrite of the whole membership stack.
What I built
- Verified Stripe webhook handler with signature check and idempotency keys stored in DB
- Nightly reconciler: pull last 48h of Stripe charges, compare to local membership table, flag gaps
- Slack message on mismatch with customer email, charge ID, and suggested fix link
- Small admin action: "replay webhook" for a single event without touching unrelated rows
Technical approach
Event log table as source of truth for processed webhook IDs. Reconciler read-only on Stripe side; fixes applied through the same code path as live webhooks to avoid two divergent update mechanisms.
Staging tested with Stripe CLI fixture events before production deploy.
Outcomes
- Missed renewal incidents dropped to near zero after first month
- Support could resolve most mismatches from Slack link without developer access
- Plugin upgrades continued; reconciliation caught the one bad deploy before Monday traffic
Stack
Stripe API · WordPress · PHP/Node glue · PostgreSQL · Slack incoming webhook