Files
shopify-ai-backup/dodo-webhooks.md

11 KiB

Dodo Payments Webhooks Setup Guide

This guide explains how to configure Dodo Payments webhooks for the Shopify AI App Builder to handle payment events automatically, including failed payments, disputes, refunds, and subscription cancellations.

Overview

The webhook system handles these events:

  • payment_succeeded: Process successful payments (top-ups, PAYG)
  • payment_failed: Cancel subscription on failed payments
  • payment_cancelled: Handle cancelled payments
  • payment_processing: Handle processing payments
  • payment_dispute_created: Cancel subscription when a dispute is opened
  • dispute_accepted: Handle accepted disputes
  • dispute_cancelled: Handle cancelled disputes
  • dispute_challenged: Handle challenged disputes
  • dispute_expired: Handle expired disputes
  • dispute_lost: Handle lost disputes
  • dispute_won: Handle won disputes
  • charge_refunded: Log refund events
  • refund_failed: Handle failed refunds
  • subscription_canceled: Downgrade user to hobby plan
  • subscription_payment_failed: Cancel subscription on recurring payment failures
  • subscription_active: Activate subscription
  • subscription_expired: Handle expired subscriptions
  • subscription_on_hold: Handle subscriptions on hold
  • subscription_plan_changed: Handle plan changes
  • subscription_renewed: Handle subscription renewals
  • subscription_updated: Handle subscription updates

Prerequisites

Before setting up webhooks, ensure you have:

  1. Dodo Payments account configured (see dodo.md)
  2. Your application deployed and accessible via public URL
  3. Dodo API key and environment configured

Step 1: Generate a Webhook Secret Key

  1. Log in to your Dodo Payments dashboard
  2. Navigate to Developer → Webhooks
  3. Click Create Webhook Secret
  4. Copy the generated webhook secret key (starts with whsec_)

Example webhook secret: whsec_abc123def456ghi789jkl012mno345pqr

Step 2: Configure Environment Variable

Add the webhook secret to your environment configuration:

# Add to your .env file or deployment environment variables
DODO_PAYMENTS_WEBHOOK_KEY=whsec_abc123def456ghi789jkl012mno345pqr

Important: Restart your application after adding this variable.

Step 3: Determine Your Webhook URL

Your webhook URL will be:

https://your-domain.com/webhooks/dodo

Examples:

  • Production: https://plugincompass.ai/webhooks/dodo
  • Staging: https://staging.plugincompass.ai/webhooks/dodo
  • Local development: Use a tunneling service like ngrok

Local Development with ngrok

If testing locally, use ngrok to expose your local server:

# Install ngrok if needed: https://ngrok.com/download

# Start ngrok (assuming your app runs on port 4000)
ngrok http 4000

# This will give you a URL like: https://abc123.ngrok.io
# Your webhook URL will be: https://abc123.ngrok.io/webhooks/dodo

Step 4: Register Webhook in Dodo Dashboard

  1. Navigate to Developer → Webhooks in Dodo Payments dashboard
  2. Click Add Webhook or Create Webhook
  3. Fill in the webhook details:
    • Webhook URL: https://your-domain.com/webhooks/dodo
    • Events to send: Select all events:
      • payment.succeeded
      • payment.failed
      • payment.cancelled
      • payment.processing
      • payment.dispute.created
      • dispute.accepted
      • dispute.cancelled
      • dispute.challenged
      • dispute.expired
      • dispute.lost
      • dispute.won
      • charge.refunded
      • refund.failed
      • subscription.canceled
      • subscription.payment.failed
      • subscription.active
      • subscription.expired
      • subscription.on_hold
      • subscription.plan_changed
      • subscription.renewed
      • subscription.updated
    • Secret: Paste your webhook secret key (from Step 1)
  4. Click Save or Create Webhook

Step 5: Test Webhook Configuration

Verify Webhook Endpoint

Check that your webhook endpoint is accessible:

curl -X POST https://your-domain.com/webhooks/dodo \
  -H "Content-Type: application/json" \
  -d '{"test": true}'

Expected response: {"received": true} (with HTTP 200 status)

Send Test Webhook

In the Dodo dashboard:

  1. Find your newly created webhook
  2. Click Send Test Event
  3. Select an event type (e.g., payment.succeeded)
  4. Check your application logs for webhook receipt

You should see log entries like:

[2026-01-20T16:30:45.123Z] Dodo webhook received {"type":"payment.succeeded","id":"evt_..."}

Step 6: Monitor Webhook Logs

Application Logs

Your application logs webhook events with the following format:

[timestamp] Dodo webhook received {"type":"event_type","id":"event_id"}
[timestamp] payment_succeeded: top-up processed via webhook {"userId":"...","tokens":...}
[timestamp] payment_failed: subscription cancelled {"userId":"...","email":"..."}

Dodo Dashboard Logs

Monitor webhook delivery in the Dodo dashboard:

  1. Navigate to Developer → Webhooks
  2. Click on your webhook
  3. View delivery history and retry failed events

Webhook Event Handlers

payment_succeeded

  • Processes successful one-time payments
  • Adds tokens for top-ups
  • Clears PAYG billing balance
  • Logs the event
  • Email sent to user with confirmation

payment_failed

  • Cancels the user's subscription
  • Downgrades to hobby plan
  • Logs the cancellation reason
  • Email sent to user

payment_cancelled

  • Logs cancelled payments
  • Email sent to user

payment_processing

  • Logs processing payments

payment_dispute_created

  • Immediately cancels the user's subscription
  • Downgrades to hobby plan
  • Logs the dispute ID and reason
  • Email sent to user

dispute_accepted

  • Handles accepted disputes
  • Email sent to user

dispute_cancelled

  • Handles cancelled disputes
  • Email sent to user

dispute_challenged

  • Handles challenged disputes
  • Email sent to user

dispute_expired

  • Handles expired disputes
  • Email sent to user

dispute_lost

  • Handles lost disputes
  • Email sent to user

dispute_won

  • Handles won disputes
  • Email sent to user

charge_refunded

  • Logs refund events
  • No automatic action (manual review recommended)
  • Tracks refunded amounts
  • Email sent to user

refund_failed

  • Handles failed refunds
  • Email sent to user

subscription_canceled

  • Downgrades user to hobby plan
  • Clears subscription data
  • Logs the cancellation
  • Email sent to user

subscription_payment_failed

  • Cancels subscription on recurring payment failure
  • Downgrades to hobby plan
  • Logs the failure event
  • Email sent to user

subscription_active

  • Activates subscription
  • Updates billing status
  • Email sent to user

subscription_expired

  • Downgrades user to hobby plan
  • Logs expiration
  • Email sent to user

subscription_on_hold

  • Places subscription on hold
  • Updates billing status
  • Email sent to user

subscription_plan_changed

  • Updates user plan
  • Logs plan change
  • Email sent to user

subscription_renewed

  • Marks subscription as renewed
  • Updates renewal date
  • Email sent to user

subscription_updated

  • Updates subscription details
  • Logs updates

Error Handling

The webhook endpoint:

  • Always returns HTTP 200 to acknowledge receipt
  • Logs all errors for debugging
  • Continues processing even if individual events fail
  • Uses timing-safe signature verification

Common Issues

Issue: Invalid signature error

  • Cause: Webhook secret mismatch
  • Solution: Verify DODO_PAYMENTS_WEBHOOK_KEY matches Dodo dashboard

Issue: Webhook not received

  • Cause: URL not publicly accessible or firewall blocking
  • Solution: Check URL accessibility and firewall settings

Issue: User not found in webhook

  • Cause: Missing userId in payment metadata
  • Solution: Ensure checkout sessions include userId in metadata

Security Best Practices

  1. Always use HTTPS: Webhooks must use HTTPS in production
  2. Verify signatures: The application validates webhook signatures
  3. Keep secrets secure: Never commit webhook secrets to version control
  4. Monitor logs: Regularly review webhook logs for suspicious activity
  5. Rate limiting: Dodo handles webhook delivery retries automatically

Webhook Signature Verification

The application uses HMAC-SHA256 signature verification:

const signature = req.headers['dodo-signature'];
const expectedSignature = `sha256=${crypto.createHmac('sha256', DODO_WEBHOOK_KEY).update(rawBody).digest('hex')}`;

If verification fails, the webhook returns HTTP 401.

Testing Different Scenarios

Test Failed Payment

  1. Create a test subscription
  2. Use a test card that will fail (e.g., expired card)
  3. Observe subscription cancellation in logs

Test Dispute Handling

  1. Create a test payment
  2. Create a test dispute in Dodo dashboard
  3. Observe subscription cancellation

Test Refund

  1. Create a test payment
  2. Process a refund in Dodo dashboard
  3. Observe refund logging

Troubleshooting

Check Webhook Delivery Status

In Dodo dashboard, view webhook delivery logs for:

  • Delivery attempts
  • Response codes
  • Error messages

Enable Debug Logging

Add to your environment temporarily:

LOG_LEVEL=debug

Verify Metadata in Checkout Sessions

Ensure your checkout sessions include metadata:

{
  metadata: {
    userId: 'user-uuid',
    type: 'subscription|topup|payg',
    tokens: 100000
  }
}

Production Checklist

  • Webhook secret configured in environment
  • Webhook endpoint accessible via HTTPS
  • All event types enabled in Dodo dashboard
  • Test webhooks sent successfully
  • Application logs show webhook receipt
  • Failed payments trigger subscription cancellation
  • Cancelled payments are logged
  • Processing payments are tracked
  • Disputes trigger subscription cancellation
  • Dispute accepted events are handled
  • Dispute cancelled events are handled
  • Dispute challenged events are handled
  • Dispute expired events are handled
  • Dispute lost events are handled
  • Dispute won events are handled
  • Refunds are logged correctly
  • Failed refunds are handled
  • Subscription cancellations downgrade users correctly
  • Subscription payment failures trigger cancellation
  • Subscription active events activate subscriptions
  • Subscription expired events downgrade users
  • Subscription on hold events are handled
  • Subscription plan changed events update plans
  • Subscription renewed events update renewal dates
  • Subscription updated events update subscription details
  • Email notifications are sent for all appropriate events

Webhook Reference

Endpoint

POST /webhooks/dodo

Headers

Content-Type: application/json
dodo-signature: sha256=...

Event Payload Structure

{
  "id": "evt_abc123",
  "type": "payment_succeeded",
  "data": {
    "id": "pay_xyz789",
    "amount": 7500,
    "currency": "usd",
    "status": "succeeded",
    "metadata": {
      "userId": "user-uuid",
      "type": "subscription"
    }
  },
  "created_at": "2026-01-20T16:30:45Z"
}

Support

  • Dodo Payments Documentation: https://docs.dodopayments.com
  • Dodo Support: Contact via Dodo dashboard
  • Application Issues: Check application logs first, then review this guide

Updates

Last updated: January 20, 2026