Recover failed WooCommerce Subscriptions payments

WooCommerce runs on your own WordPress install, so the failure signal comes from the store rather than a hosted platform. The advantage is a direct, tokenised pay-for-order URL you can put straight into a recovery message.

The WooCommerce Subscriptions events recovery depends on

order.updated → status: failed
A renewal order failed payment — open a recovery case.
order.updated → status: processing/completed
The renewal was paid. Close the case.
subscription status: on-hold
Woo suspended the subscription after the retry rule ran out.

Verifying WooCommerce Subscriptions webhooks

Scheme
HMAC-SHA256 over the raw body, base64-encoded
Signature location
X-WC-Webhook-Signature

Set the webhook secret in WooCommerce settings. Because the store is self-hosted, also restrict the endpoint by store domain.

import { createHmac, timingSafeEqual } from "crypto";

const digest = createHmac("sha256", process.env.WOO_WEBHOOK_SECRET!)
  .update(rawBody, "utf8")
  .digest("base64");

const sig = req.headers["x-wc-webhook-signature"] as string;
if (!timingSafeEqual(Buffer.from(digest), Buffer.from(sig))) {
  return new Response("Invalid signature", { status: 401 });
}

const order = JSON.parse(rawBody);   // topic: order.updated
if (order.status === "failed") {
  await rrlabs.enqueueRecovery({
    provider: "woocommerce",
    externalId: String(order.id),
    payUrl: order.payment_url,        // tokenised pay-for-order link
  });
}

Decline playbook for WooCommerce Subscriptions

Recovery actions per WooCommerce Subscriptions failure signal
Failure signalRecovery action
Gateway declined the stored tokenSend the pay-for-order URL so the customer can complete payment with any method.
Token expiredAsk for a new payment method through the My Account page before the subscription moves to on-hold.
Automatic retry rule exhaustedEscalate the channel — this is the last window before the subscription is suspended.

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

Does RRLabs need WordPress admin access?
No. It needs a webhook pointed at its endpoint and, optionally, read access to order data. It does not install plugins or modify the store.
What is the strongest WooCommerce recovery link?
The tokenised pay-for-order URL on the failed renewal order — it lets the customer pay without logging in or re-entering the cart.

Connect WooCommerce Subscriptions 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