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., active → past_due, or past_due → active.

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​