Webhooks Integration
Learn how to robustly handle webhook events from CryptoPay in your application.
The Basics
Webhooks are the glue that holds your integration together. They allow your backend to stay in sync with the state of payments, subscriptions, and transfers on CryptoPay without polling.
How it works
- 1An event occurs in your CryptoPay account (e.g., payment succeeded).
- 2CryptoPay creates an Event object.
- 3CryptoPay sends the Event object to your webhook endpoint via HTTP POST.
- 4Your server receives the request, verifies the signature, and processes the event.
- 5Your server returns a 200 OK response.
"id": "evt_123...",
"type": "payment.succeeded",
"data": {...}
}
Typical webhook payload structure
Handling Events
Your webhook handler needs to be robust and secure. Here is a complete example of how to handle webhooks in a Node.js Express application.
server.js
const express = require('express');
const app = express();
const CryptoPay = require('CryptoPay');
// Initialize the client
const client = new CryptoPay('sk_test_...');
// Match the raw body to content type application/json
app.post('/webhook', express.raw({type: 'application/json'}), (request, response) => {
const sig = request.headers['x-CryptoPay-signature'];
const endpointSecret = "whsec_...";
let event;
try {
// Verify signature
event = client.webhooks.constructEvent(request.body, sig, endpointSecret);
} catch (err) {
console.log(`Webhook Error: ${err.message}`);
return response.status(400).send(`Webhook Error: ${err.message}`);
}
// Handle the event
switch (event.type) {
case 'payment_intent.succeeded':
const paymentIntent = event.data.object;
handlePaymentSuccess(paymentIntent);
break;
case 'payment_intent.failed':
const paymentFailed = event.data.object;
handlePaymentFailure(paymentFailed);
break;
// ... handle other event types
default:
console.log(`Unhandled event type ${event.type}`);
}
// Return a 200 response to acknowledge receipt of the event
response.json({received: true});
});
function handlePaymentSuccess(paymentIntent) {
console.log('Payment succeeded:', paymentIntent.id);
// Fulfill order, send email, etc.
}
function handlePaymentFailure(paymentIntent) {
console.log('Payment failed:', paymentIntent.id);
// Notify user, etc.
}
app.listen(3000, () => console.log('Running on port 3000'));Best Practices
Verify Signatures
Always verify the webhook signature to prevent replay attacks and ensure the request came from CryptoPay.
Handle Duplicates
Webhook endpoints may occasionally receive the same event more than once. Make your event processing idempotent.
Secure Your Endpoint
Use HTTPS for your webhook endpoint and consider adding IP allowlisting if possible.
Respond Quickly
Respond with a 2xx status code quickly. Perform complex logic (like sending emails) asynchronously.