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/json
X-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 (Status: OPEN)
Sent when a new payment is created via API.
transactions
array will be emptytotalReceivedAmount
will be "0.00"
2. Payment Partially Paid (Status: OPEN)
Sent when payment receives funds but less than requested amount.
transactions
array contains received transaction(s)totalReceivedAmount
<amount
- Payment remains OPEN for additional transactions
3. Payment Completed (Status: COMPLETED)
Sent when payment receives full requested amount.
totalReceivedAmount
>=amount
- All required confirmations received
4. Payment Overpaid (Status: COMPLETED)
Sent when payment receives more than requested amount.
totalReceivedAmount
>amount
- Excess funds included in the payment
5. Payment Expired (Status: EXPIRED)
Sent when payment timeout is reached without full payment.
- No new transactions will be accepted
6. Payment Cancelled (Status: CANCELLED)
Sent if payment is manually cancelled.
7. AML Check Failed (Status: AML_CHECK_FAILED)
Sent when payment fails anti-money laundering compliance check.
- Payment cannot be completed
- Funds may be frozen pending investigation
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
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');
}
// Process the payment update
const payment = req.body;
switch(payment.status) {
case 'COMPLETED':
// Mark order as paid
updateOrderStatus(payment.invoice, 'PAID');
break;
case 'EXPIRED':
// Handle expired payment
updateOrderStatus(payment.invoice, 'PAYMENT_EXPIRED');
break;
case 'AML_CHECK_FAILED':
// Flag for manual review
flagOrderForReview(payment.invoice);
break;
}
res.status(200).send();
});
Handling Partial Payments
When a payment is partially paid, you'll receive a webhook with:
- Status remains
OPEN
totalReceivedAmount
shows the current totaltransactions
array 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);
}
Retry Policy
If your server doesn't respond with 200 OK:
- ALPPAY will retry the webhook up to 5 times
- Retry intervals: 1 minute, 5 minutes, 30 minutes, 2 hours, 12 hours
- After 5 failed attempts, the webhook is marked as failed
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
Common Integration Patterns
Order Status Management
function processPaymentWebhook(payment) {
switch(payment.status) {
case 'OPEN':
if (payment.totalReceivedAmount === '0.00') {
// New payment created
logPaymentCreated(payment);
} else {
// Partial payment received
updateOrderPartialPayment(payment);
}
break;
case 'COMPLETED':
// Full payment received
markOrderAsPaid(payment);
sendConfirmationEmail(payment.customer.email);
break;
case 'EXPIRED':
// Payment window closed
cancelOrder(payment.invoice);
break;
case 'AML_CHECK_FAILED':
// Compliance issue
flagForManualReview(payment);
notifyComplianceTeam(payment);
break;
}
}
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