Recover failed PayPal payments

PayPal subscriptions fail for reasons a card processor never sees — a funding source removed, a billing agreement cancelled, or a currency the buyer's account cannot cover. Recovery here is mostly about getting the buyer back into PayPal to fix the funding source.

The PayPal events recovery depends on

BILLING.SUBSCRIPTION.PAYMENT.FAILED
A recurring PayPal payment failed — open a recovery case.
PAYMENT.SALE.COMPLETED
A subscription payment cleared. Close the case.
BILLING.SUBSCRIPTION.CANCELLED
The billing agreement ended.

Verifying PayPal webhooks

Scheme
Asymmetric — verified server-side by PayPal's API
Signature location
PayPal-Transmission-Sig (plus id, time and cert URL headers)

PayPal does not use a shared-secret HMAC. Post the transmission headers and event body to /v1/notifications/verify-webhook-signature and require verification_status: SUCCESS.

const res = await fetch(
  "https://api-m.paypal.com/v1/notifications/verify-webhook-signature",
  {
    method: "POST",
    headers: { "Content-Type": "application/json", Authorization: `Bearer ${accessToken}` },
    body: JSON.stringify({
      transmission_id: req.headers["paypal-transmission-id"],
      transmission_time: req.headers["paypal-transmission-time"],
      cert_url: req.headers["paypal-cert-url"],
      auth_algo: req.headers["paypal-auth-algo"],
      transmission_sig: req.headers["paypal-transmission-sig"],
      webhook_id: process.env.PAYPAL_WEBHOOK_ID,
      webhook_event: JSON.parse(rawBody),
    }),
  },
);

const { verification_status } = await res.json();
if (verification_status !== "SUCCESS") return new Response("Invalid", { status: 401 });

Decline playbook for PayPal

Recovery actions per PayPal failure signal
Failure signalRecovery action
Funding source declinedAsk the buyer to add or reselect a funding source in PayPal, with a direct link to the agreement.
Billing agreement cancelled by buyerTreat as voluntary churn — do not retry; route to a win-back message instead.
Temporary declineAllow PayPal's retry to run and send a short reminder rather than a card-update request.

What happens after a payment fails

  1. T+0s

    Payment failed

    Provider webhook received and verified

  2. T+2s

    AI analysis

    Decline reason classified, amount at risk scored

  3. T+5s

    Dynamic email

    Copy generated for that decline code and customer

  4. Day 2

    Smart retry

    Retry scheduled only when the decline code is retryable

  5. Day 2

    WhatsApp push

    Second channel used when the email went unanswered

  6. On success

    Recovered

    Counted only when the provider confirms the charge

Timings describe the configured workflow, not a guaranteed outcome. Every step is skipped when the decline reason makes it counter-productive.

Frequently asked questions

Why can't PayPal webhooks be verified with a local HMAC?
PayPal signs events asymmetrically and expects verification through its own API endpoint, so the check requires a server-side call rather than a local digest comparison.
Is a failed PayPal payment involuntary churn?
Usually, unless the buyer cancelled the billing agreement themselves — that event is voluntary and should not be retried.

Connect PayPal with read-only credentials

RRLabs reads failure events and orchestrates recovery. It never holds card data and never becomes the merchant of record.

Get early access