01
Verify the webhook
Every event is checked before anything runs. Stripe events are verified with an HMAC signature and a five-minute freshness window, so forged or replayed events are dropped. PayPal events are verified by asking PayPal itself.
- Unsigned or stale event: dropped, logged.
- Duplicate delivery: ignored, thanks to an idempotency guard.
02
Read the real reason
RevGuard asks the provider for the actual decline code rather than guessing from the event. "Insufficient funds", "do not honor", "expired card", and "processing error" all lead to different plans.
- Soft declines get retries.
- Hard declines skip straight to the customer.
03
Plan the retries (Stripe)
Money problems are retried around paydays. Technical problems are retried fast. Dead cards are never retried. Every plan stays inside the Visa and Mastercard retry limits, so aggressive dunning never earns you fines.
- PayPal runs its own retries, so this stage is skipped there.
04
Re-check before every action
Before each retry and each email, the workflow asks the provider whether the invoice is already paid. If it is, the whole sequence stops. This is the rule that prevents "you emailed me after I paid".
05
Email the customer, warmly
Only if retries did not work. A five-step sequence on days 0, 3, 7, 10, and 13 with a one-click, no-login link to update the payment method. Stripe customers land in the Stripe portal. PayPal customers land on their own PayPal automatic-payments page.
06
Log, notify, and signal your app
Every path ends in one outcome record: recovered, unrecoverable, or closed. It is logged, sent to the channels you turned on, and handed to your app as a single signal: restore access, or degrade to read-only. Never a hard cancel.