Skip to main content

E-commerce Webhook Setup

1. Create E-commerce Endpoints

Create Order Events Endpoint

  1. Go to FlowCreate Endpoint
  2. Name: "Order Events"
  3. Copy endpoint URL for order webhooks

Create Payment Events Endpoint

  1. Go to FlowCreate Endpoint
  2. Name: "Payment Events"
  3. Copy endpoint URL for payment webhooks

2. Set Up Local Handler

Complete Order Handler

const express = require('express');
const crypto = require('crypto');
const app = express();

app.use(express.json());

// Order webhooks handler
app.post('/webhooks/orders', async (req, res) => {
const { event, data } = req.body;

try {
switch (event) {
case 'order.created':
await handleNewOrder(data.order);
break;

case 'order.shipped':
await handleOrderShipped(data.order);
break;

case 'order.cancelled':
await handleOrderCancellation(data.order);
break;

case 'order.refunded':
await handleOrderRefund(data.order);
break;
}

console.log(`Processed ${event}:`, data.order.id);
res.status(200).json({ received: true });

} catch (error) {
console.error('Order webhook error:', error);
res.status(200).json({ error: error.message });
}
});

async function handleNewOrder(order) {
console.log('New order:', order.id);
// Update inventory
for (const item of order.items) {
console.log(`Update stock for ${item.sku}: -${item.quantity}`);
}
// Send confirmation email
console.log(`Send confirmation to: ${order.customer.email}`);
}

async function handleOrderShipped(order) {
console.log('Order shipped:', order.id);
console.log(`Tracking: ${order.tracking_number}`);
// Send shipping notification
}

async function handleOrderCancellation(order) {
console.log('Order cancelled:', order.id);
// Restore inventory
// Process refund if paid
// Send cancellation notification
}

async function handleOrderRefund(order) {
console.log('Order refunded:', order.id);
console.log(`Refund amount: ${order.refund_amount}`);
// Process refund
// Update customer account
}

app.listen(3000, () => {
console.log('E-commerce webhook handler running on port 3000');
});

Payment Handler

// Payment webhooks handler  
app.post('/webhooks/payments', async (req, res) => {
const { event, data } = req.body;

try {
switch (event) {
case 'payment.succeeded':
await processSuccessfulPayment(data);
break;

case 'payment.failed':
await handlePaymentFailure(data);
break;

case 'payment.refunded':
await processRefund(data);
break;
}

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

} catch (error) {
console.error('Payment webhook error:', error);
res.status(200).json({ error: error.message });
}
});

async function processSuccessfulPayment(payment) {
console.log('Payment successful:', payment.id);
console.log(`Amount: ${payment.amount} ${payment.currency}`);
// Update order status
// Send payment confirmation
// Trigger fulfillment
}

async function handlePaymentFailure(payment) {
console.log('Payment failed:', payment.id);
console.log(`Reason: ${payment.failure_reason}`);
// Send payment failure notification
// Hold order
}

async function processRefund(refund) {
console.log('Refund processed:', refund.id);
// Update order status
// Send refund notification
}

3. Start Local Server

node server.js

4. Set Up CLI Forwarding

Forward Order Events

hookvm listen https://hookvm.com/hooks/order-endpoint-id --target http://localhost:3000/webhooks/orders

Forward Payment Events (separate terminal)

hookvm listen https://hookvm.com/hooks/payment-endpoint-id --target http://localhost:3000/webhooks/payments

5. Platform Integration

Shopify Setup

Create Webhook in Shopify Admin

  1. Go to SettingsNotifications
  2. Scroll to Webhooks section
  3. Click Create webhook

Order Created Webhook:

  • Event: Order creation
  • Format: JSON
  • URL: Your hookVM order endpoint
  • API Version: Latest

Order Paid Webhook:

  • Event: Order payment
  • Format: JSON
  • URL: Your hookVM payment endpoint
  • API Version: Latest

Shopify Webhook Verification

function verifyShopifyWebhook(data, hmacHeader) {
const calculated = crypto
.createHmac('sha256', process.env.SHOPIFY_WEBHOOK_SECRET)
.update(data, 'utf8')
.digest('base64');

return calculated === hmacHeader;
}

app.post('/webhooks/shopify/orders', (req, res) => {
const hmac = req.get('X-Shopify-Hmac-Sha256');
const body = JSON.stringify(req.body);

if (!verifyShopifyWebhook(body, hmac)) {
return res.status(401).send('Unauthorized');
}

// Transform Shopify format to your standard format
const standardOrder = {
event: 'order.created',
data: {
order: {
id: req.body.id,
customer: {
email: req.body.email,
name: `${req.body.customer.first_name} ${req.body.customer.last_name}`
},
items: req.body.line_items.map(item => ({
sku: item.sku,
quantity: item.quantity,
price: item.price
})),
total: req.body.total_price
}
}
};

// Process with your standard handler
handleNewOrder(standardOrder.data.order);
res.status(200).json({ received: true });
});

WooCommerce Setup

Create Webhook in WooCommerce

  1. Go to WooCommerceSettingsAdvancedWebhooks
  2. Click Add webhook

Order Created Webhook:

  • Topic: Order created
  • Delivery URL: Your hookVM order endpoint
  • Secret: Generate strong secret
  • API Version: WP REST API Integration v3

WooCommerce Webhook Verification

function verifyWooCommerceWebhook(payload, signature, secret) {
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(payload, 'utf8')
.digest('base64');

return signature === expectedSignature;
}

app.post('/webhooks/woocommerce/orders', (req, res) => {
const signature = req.headers['x-wc-webhook-signature'];
const payload = JSON.stringify(req.body);

if (!verifyWooCommerceWebhook(payload, signature, process.env.WC_WEBHOOK_SECRET)) {
return res.status(401).send('Invalid signature');
}

// Transform WooCommerce format
const standardOrder = {
event: 'order.created',
data: {
order: {
id: req.body.id,
customer: {
email: req.body.billing.email,
name: `${req.body.billing.first_name} ${req.body.billing.last_name}`
},
items: req.body.line_items.map(item => ({
sku: item.sku,
quantity: item.quantity,
price: item.price
})),
total: req.body.total
}
}
};

handleNewOrder(standardOrder.data.order);
res.status(200).json({ received: true });
});

Stripe Payment Integration

Create Webhook in Stripe Dashboard

  1. Go to DevelopersWebhooks
  2. Click Add endpoint
  3. Enter your hookVM payment endpoint URL
  4. Select events:
    • payment_intent.succeeded
    • payment_intent.payment_failed
    • charge.dispute.created

Stripe Webhook Handler

app.post('/webhooks/stripe', (req, res) => {
const signature = req.headers['stripe-signature'];

try {
const event = stripe.webhooks.constructEvent(
req.body,
signature,
process.env.STRIPE_WEBHOOK_SECRET
);

switch (event.type) {
case 'payment_intent.succeeded':
const payment = event.data.object;
processSuccessfulPayment({
id: payment.id,
amount: payment.amount,
currency: payment.currency,
order_id: payment.metadata.order_id
});
break;

case 'payment_intent.payment_failed':
const failed_payment = event.data.object;
handlePaymentFailure({
id: failed_payment.id,
failure_reason: failed_payment.last_payment_error?.message,
order_id: failed_payment.metadata.order_id
});
break;
}

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

} catch (err) {
console.error('Stripe webhook error:', err);
res.status(400).send(`Webhook Error: ${err.message}`);
}
});

6. Test Complete Setup

Test Order Flow

# Send test order webhook
curl -X POST https://hookvm.com/hooks/order-endpoint-id \
-H "Content-Type: application/json" \
-d '{
"event": "order.created",
"data": {
"order": {
"id": "order_123",
"customer": {
"email": "customer@example.com",
"name": "John Doe"
},
"items": [
{
"sku": "SHIRT_001",
"quantity": 2,
"price": "29.99"
}
],
"total": "59.98"
}
}
}'

Test Payment Flow

# Send test payment webhook
curl -X POST https://hookvm.com/hooks/payment-endpoint-id \
-H "Content-Type: application/json" \
-d '{
"event": "payment.succeeded",
"data": {
"id": "pay_123",
"amount": "5998",
"currency": "usd",
"order_id": "order_123"
}
}'

Verify Results

  1. Check CLI output for real-time event processing
  2. Review server logs for handler execution
  3. Monitor dashboard for webhook delivery status
  4. Test error scenarios with invalid data

7. Production Considerations

Error Handling

app.use((err, req, res, next) => {
console.error('Webhook processing error:', err);
res.status(200).json({
error: 'Internal processing error',
received: true
});
});

Idempotency

const processedEvents = new Set();

app.post('/webhooks/orders', (req, res) => {
const eventId = req.body.id || req.headers['x-event-id'];

if (processedEvents.has(eventId)) {
console.log('Duplicate event ignored:', eventId);
return res.status(200).json({ received: true });
}

processedEvents.add(eventId);
// Process event normally
});

Database Integration

async function handleNewOrder(order) {
// Save to database
await db.orders.create({
id: order.id,
customer_email: order.customer.email,
total: order.total,
status: 'pending',
created_at: new Date()
});

// Update inventory
for (const item of order.items) {
await db.inventory.decrement('quantity', {
where: { sku: item.sku },
by: item.quantity
});
}
}

Your e-commerce webhook system is now ready to handle real-time order and payment events with proper error handling and platform integration.