Skip to main content

Stripe Webhooks Guide

ECOSIRE processes 6 Stripe webhook events that drive the full payment lifecycle — from checkout completion to subscription cancellation. This guide explains how each event is handled, how to test locally, and how to extend the webhook handler for custom business logic.


Introduction

ECOSIRE's billing system is event-driven: Stripe sends events to POST /api/billing/webhooks, and ECOSIRE acts on them automatically — issuing licenses, sending emails, and updating order records. No polling required.


Prerequisites

  • Stripe account (live or test)
  • ECOSIRE account with Billing module enabled
  • STRIPE_SECRET_KEY and STRIPE_WEBHOOK_SECRET configured in .env.local
  • Stripe CLI installed for local testing

Step 1 — Configure Stripe Webhook Endpoint

  1. Log in to the Stripe Dashboard.
  2. Go to Developers → Webhooks → Add endpoint.
  3. Set the endpoint URL: https://api.ecosire.com/api/billing/webhooks
  4. Select the 6 events ECOSIRE handles:
    • checkout.session.completed
    • invoice.paid
    • customer.subscription.deleted
    • customer.subscription.updated
    • charge.refunded
    • payment_intent.payment_failed
  5. Click Add endpoint and copy the Signing secret (whsec_...).
  6. Add it to your .env.local:
    STRIPE_WEBHOOK_SECRET=whsec_your_signing_secret

Step 2 — Understand Each Event

checkout.session.completed

Triggered when: A Stripe-hosted checkout finishes successfully.

ECOSIRE actions:

  1. Looks up or creates the customer's ECOSIRE account (matched by email).
  2. Creates a confirmed Sales Order for the purchased products.
  3. Issues license keys for all digital products in the order.
  4. Sends a purchase confirmation email with download links.

Key data fields: customer_email, amount_total, line_items, client_reference_id (ECOSIRE cart ID).


invoice.paid

Triggered when: A subscription invoice is paid (monthly/annual renewals).

ECOSIRE actions:

  1. Records the payment against the subscription order.
  2. Extends the license expiry date to the new period end.
  3. Sends a payment receipt email.

customer.subscription.deleted

Triggered when: A subscription is cancelled (either immediately or at period end).

ECOSIRE actions:

  1. Revokes all licenses associated with the subscription.
  2. Updates order status to cancelled.
  3. Sends a cancellation confirmation email.

customer.subscription.updated

Triggered when: A subscription changes status — e.g., activepast_due, or past_dueactive.

ECOSIRE actions:

  • past_due / unpaid: Suspends associated licenses.
  • active (from suspended): Reactivates licenses.
  • Plan change: Updates license tier.

charge.refunded

Triggered when: A full or partial refund is issued for a charge.

ECOSIRE actions:

  1. Revokes all licenses linked to the original order.
  2. Updates order status to refunded.
  3. Sends a refund confirmation email.

payment_intent.payment_failed

Triggered when: A payment attempt fails (card declined, insufficient funds, etc.).

ECOSIRE actions:

  1. Sends a payment failure notification email to the customer.
  2. Logs the failure reason for support visibility.

Step 3 — Test Locally with Stripe CLI

Install Stripe CLI:

# macOS
brew install stripe/stripe-cli/stripe

# Linux
curl -s https://packages.stripe.dev/api/security/keypair/stripe-cli-gpg/public | sudo gpg --dearmor -o /usr/share/keyrings/stripe.gpg
echo "deb [signed-by=/usr/share/keyrings/stripe.gpg] https://packages.stripe.dev/stripe-cli-debian-local stable main" | sudo tee -a /etc/apt/sources.list.d/stripe.list
sudo apt update && sudo apt install stripe

Forward Stripe events to your local API:

stripe listen --forward-to localhost:3001/api/billing/webhooks

Trigger test events:

# Simulate a successful checkout
stripe trigger checkout.session.completed

# Simulate a refund
stripe trigger charge.refunded

# Simulate subscription cancellation
stripe trigger customer.subscription.deleted

Step 4 — Verify Webhook Processing

After triggering a test event, check:

  1. Stripe Dashboard → Webhooks → Recent deliveries — should show 200 OK.
  2. ECOSIRE → Dashboard → Orders — new order created for checkout event.
  3. ECOSIRE → Dashboard → Licenses — license issued for digital products.
  4. Email inbox — purchase confirmation or receipt delivered.

Step 5 — Handle Custom Logic (Advanced)

To add custom processing on top of ECOSIRE's webhook handler, subscribe to ECOSIRE's own outbound webhooks (which fire after each Stripe event is processed):

// Your server receives ECOSIRE webhooks after Stripe processing is complete
app.post('/my-webhooks/ecosire', express.raw({ type: 'application/json' }), (req, res) => {
const event = JSON.parse(req.body.toString());

if (event.event === 'checkout.completed') {
const { orderId, customerEmail, licenses } = event.data;
// Your custom logic: send to CRM, Slack, etc.
notifySlack(`New order ${orderId} from ${customerEmail}`);
}

res.json({ received: true });
});

See Webhooks Reference for signature verification and all event payloads.


Troubleshooting

IssueSolution
401 Invalid signatureConfirm STRIPE_WEBHOOK_SECRET matches the Stripe dashboard signing secret
Webhook not receiving eventsVerify the endpoint URL is HTTPS and publicly accessible
Duplicate order createdECOSIRE deduplicates by checkout.session.id — ensure you are not calling the API twice
License not issuedCheck that the product in Stripe matches a product ID in ECOSIRE
Test events not workingRun stripe login and confirm CLI is forwarding to the correct port

Next Steps