Payment Webhook
HTTP Method: POST
Endpoint URL: https://your-server.com/webhooks/payment (configured in your ALPPAY settings)
Description: ALPPAY sends this webhook to notify your server about payment creation or status changes.
Security: Verify the X-HMAC header to ensure the request is from ALPPAY.
Webhook Configuration
To receive payment webhooks:
- Contact [email protected] with your webhook endpoint URL
- Ensure your endpoint accepts POST requests
- Implement HMAC signature verification for security
- Respond with HTTP 200 OK to acknowledge receipt
Request Headers
Content-Type: application/jsonX-HMAC: signature_string— HMAC-SHA256 signature of the request body
Request Body (JSON)
{
"id": "285d8dce-7663-4580-ba7f-8afb2f2d3292",
"transactions": [
{
"paymentId": "285d8dce-7663-4580-ba7f-8afb2f2d3292",
"txnId": "0xe7238caa68382485141be0443d6ba7efd0bd9f6bac5a624bd059acc53af1bf1d19",
"receivedAmount": "20.00",
"asset": {
"short": "USDT",
"name": "Tether",
"logoUrl": "https://cryptologos.cc/logos/tether-usdt-logo.png",
"network": "tron"
},
"destTag": null,
"addressFrom": "TXkFpL3HmzE9KPpXGWNXdCbNcDYYn73U4C",
"addressTo": "TPSMckmxoQBQWfUcasbUs2cRUdh2EMQu4n",
"date": "2025-05-20T12:34:56Z"
}
],
"amount": "1000.00",
"totalReceivedAmount": "20.00",
"asset": {
"short": "USDT",
"name": "Tether",
"logoUrl": "https://cryptologos.cc/logos/tether-usdt-logo.png",
"network": "tron"
},
"addressTo": "TPSMckmxoQBQWfUcasbUs2cRUdh2EMQu4n",
"confirmsNeeded": 10,
"timeout": 9000,
"checkoutUrl": "https://your-shop.com/orders/40113049",
"status": "OPEN",
"customer": {
"id": 12312312,
"name": "John",
"email": "[email protected]"
},
"merchant": {
"id": "285d8dce-7663-4580-ba7f-8afb2f2d3292",
"name": "Your Company",
"siteUrl": "https://your-shop.com",
"logoUrl": "https://your-shop.com/logo.svg",
"email": "[email protected]"
},
"invoice": "INV-001",
"paymentRedirectUrl": "https://a-pay-system.com/en/invoice?id=285d8dce-7663-4580-ba7f-8afb2f2d3292",
"createdAt": "2025-05-20T12:34:56Z",
"updatedAt": "2025-05-20T12:34:56Z"
}
Field Descriptions
- id — Unique payment identifier
- transactions — Array of blockchain transactions:
paymentId— Reference to parent payment IDtxnId— Blockchain transaction hashreceivedAmount— Amount received in this transactionasset— Cryptocurrency detailsdestTag— Destination tag if applicableaddressFrom— Sender's wallet addressaddressTo— Receiving wallet addressdate— Transaction timestamp
- amount — Requested payment amount
- totalReceivedAmount — Sum of all received transactions
- asset — Primary payment cryptocurrency details
- addressTo — Payment receiving address
- confirmsNeeded — Required blockchain confirmations
- timeout — Payment expiration time in seconds
- checkoutUrl — Merchant's return URL
- status — Current payment status
- customer — Customer information
- merchant — Merchant account details
- invoice — Merchant's invoice reference
- paymentRedirectUrl — ALPPAY payment page URL
- createdAt — Payment creation timestamp
- updatedAt — Last update timestamp
Webhook Events and Status Changes
ALPPAY sends webhooks for the following payment events:
1. Payment Created
Sent when a new payment is created via API.
transactionsarray will be emptytotalReceivedAmountwill be "0.00"statusis "OPEN"
2. Payment Partially Paid
Sent when payment receives funds but less than requested amount.
transactionsarray contains received transaction(s)totalReceivedAmount<amountstatusis "OPEN"
3. Payment Completed
Sent when payment receives full requested amount.
transactionsarray contains received transaction(s)totalReceivedAmount>=amountstatusis "OPEN"
4. Payment Overpaid
Sent when payment receives more than requested amount.
transactionsarray contains received transaction(s)totalReceivedAmount>amountstatusis "OPEN"
5. Payment Expired
Sent when payment timeout is reached without full payment.
- No new transactions will be accepted
statusis "EXPIRED"
Required Response
Your server must respond with:
- HTTP Status:
200 OK - Body: Empty or simple acknowledgment
Example successful response:
HTTP/1.1 200 OK
Content-Length: 0
HMAC Signature Verification
Always verify the webhook authenticity using the X-HMAC header:
Node.js Example
import crypto from 'crypto';
function verifyWebhook(body, signature, secretKey) {
const expectedSignature = crypto
.createHmac('sha256', secretKey)
.update(JSON.stringify(body), 'utf8')
.digest('hex');
return signature === expectedSignature;
}
// In your webhook handler
import crypto from 'crypto';
function verifyWebhook(body, signature, secretKey) {
const expectedSignature = crypto
.createHmac('sha256', secretKey)
.update(JSON.stringify(body), 'utf8')
.digest('hex');
return signature === expectedSignature;
}
app.post('/webhooks/payment', (req, res) => {
const signature = req.headers['x-hmac'];
const isValid = verifyWebhook(req.body, signature, process.env.HMAC_SECRET);
if (!isValid) {
return res.status(401).send('Invalid signature');
}
const payment = req.body;
if (payment.status === 'EXPIRED') {
// Handle expired payment
console.log('Payment expired:', payment.invoice);
} else if (payment.status === 'OPEN') {
// Determine payment state based on received amount
if (payment.totalReceivedAmount === '0.00') {
console.log('Payment created:', payment.invoice);
} else if (payment.totalReceivedAmount < payment.amount) {
console.log('Payment partially paid:', payment.invoice);
} else if (payment.totalReceivedAmount === payment.amount) {
console.log('Payment completed:', payment.invoice);
} else if (payment.totalReceivedAmount > payment.amount) {
console.log('Payment overpaid:', payment.invoice);
}
}
res.status(200).send();
});
Handling Partial Payments
When a payment is partially paid, you'll receive a webhook with:
- Status remains
OPEN totalReceivedAmountshows the current totaltransactionsarray contains all received transactions
Example partial payment handling:
if (payment.status === 'OPEN' && parseFloat(payment.totalReceivedAmount) > 0) {
const percentPaid = (parseFloat(payment.totalReceivedAmount) / parseFloat(payment.amount)) * 100;
console.log(`Payment ${percentPaid.toFixed(2)}% complete`);
// Notify customer about partial payment
sendPartialPaymentNotification(payment.customer.email, payment.totalReceivedAmount, payment.amount);
}
Best Practices
- Always verify HMAC signature before processing
- Respond quickly (within 5 seconds) to avoid timeouts
- Use idempotent processing - same webhook may be sent multiple times
- Handle all status types including partial payments
- Store payment state to track payment progression
- Log all webhooks for debugging and reconciliation
- Implement proper error handling for webhook processing failures
Testing Webhooks
For testing webhook integration:
- Use ngrok or similar service to expose local endpoints
- Create test payments in sandbox environment
- Monitor webhook delivery in ALPPAY dashboard
- Test all status scenarios including partial payments