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_KEYandSTRIPE_WEBHOOK_SECRETconfigured in.env.local- Stripe CLI installed for local testing
Step 1 — Configure Stripe Webhook Endpoint
- Log in to the Stripe Dashboard.
- Go to Developers → Webhooks → Add endpoint.
- Set the endpoint URL:
https://api.ecosire.com/api/billing/webhooks - Select the 6 events ECOSIRE handles:
checkout.session.completedinvoice.paidcustomer.subscription.deletedcustomer.subscription.updatedcharge.refundedpayment_intent.payment_failed
- Click Add endpoint and copy the Signing secret (
whsec_...). - 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:
- Looks up or creates the customer's ECOSIRE account (matched by email).
- Creates a confirmed Sales Order for the purchased products.
- Issues license keys for all digital products in the order.
- 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:
- Records the payment against the subscription order.
- Extends the license expiry date to the new period end.
- Sends a payment receipt email.
customer.subscription.deleted
Triggered when: A subscription is cancelled (either immediately or at period end).
ECOSIRE actions:
- Revokes all licenses associated with the subscription.
- Updates order status to
cancelled. - 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:
- Revokes all licenses linked to the original order.
- Updates order status to
refunded. - Sends a refund confirmation email.
payment_intent.payment_failed
Triggered when: A payment attempt fails (card declined, insufficient funds, etc.).
ECOSIRE actions:
- Sends a payment failure notification email to the customer.
- 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:
- Stripe Dashboard → Webhooks → Recent deliveries — should show
200 OK. - ECOSIRE → Dashboard → Orders — new order created for checkout event.
- ECOSIRE → Dashboard → Licenses — license issued for digital products.
- 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
| Issue | Solution |
|---|---|
401 Invalid signature | Confirm STRIPE_WEBHOOK_SECRET matches the Stripe dashboard signing secret |
| Webhook not receiving events | Verify the endpoint URL is HTTPS and publicly accessible |
| Duplicate order created | ECOSIRE deduplicates by checkout.session.id — ensure you are not calling the API twice |
| License not issued | Check that the product in Stripe matches a product ID in ECOSIRE |
| Test events not working | Run stripe login and confirm CLI is forwarding to the correct port |
Next Steps
- Billing API — Programmatic billing management
- Webhooks Reference — Full event payload reference
- License Verification — Implement license checks in your app