E-commerce Webhook Setup
1. Create E-commerce Endpoints
Create Order Events Endpoint
- Go to Flow → Create Endpoint
- Name: "Order Events"
- Copy endpoint URL for order webhooks
Create Payment Events Endpoint
- Go to Flow → Create Endpoint
- Name: "Payment Events"
- 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
- Go to Settings → Notifications
- Scroll to Webhooks section
- 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
- Go to WooCommerce → Settings → Advanced → Webhooks
- 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
- Go to Developers → Webhooks
- Click Add endpoint
- Enter your hookVM payment endpoint URL
- Select events:
payment_intent.succeededpayment_intent.payment_failedcharge.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
- Check CLI output for real-time event processing
- Review server logs for handler execution
- Monitor dashboard for webhook delivery status
- 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.