4.6 KiB
4.6 KiB
SePay Webhooks
Real-time payment notifications from SePay to your server.
Setup
- Access WebHooks menu in dashboard
- Click "+ Add webhooks"
- Configure:
- Name: Descriptive identifier
- Event Selection:
All,In_only,Out_only - Conditions: Bank accounts, VA filtering, payment code requirements
- Webhook URL: Your callback endpoint (must be publicly accessible)
- Is Verify Payment: Flag for validation
- Authentication:
No_Authen,OAuth2.0, orApi_Key
- Click "Add" to finalize
Payload Structure
{
"id": 92704,
"gateway": "Vietcombank",
"transactionDate": "2023-03-25 14:02:37",
"accountNumber": "0123499999",
"code": null,
"content": "payment content",
"transferType": "in",
"transferAmount": 2277000,
"accumulated": 19077000,
"subAccount": null,
"referenceCode": "MBVCB.3278907687"
}
Fields:
id- Unique transaction ID (use for deduplication)gateway- Bank nametransactionDate- Transaction timestampaccountNumber- Bank account numbercode- Payment code (if available)content- Transfer description/contenttransferType- "in" (incoming) or "out" (outgoing)transferAmount- Transaction amountaccumulated- Account balance after transactionsubAccount- Sub-account identifierreferenceCode- Bank transaction reference
Authentication
API Key:
Authorization: Apikey YOUR_KEY
Content-Type: application/json
OAuth 2.0: Provide token endpoint, client ID, and client secret in dashboard.
No Authentication: Available but not recommended for production. Consider IP whitelisting.
Response Requirements
Success Response:
HTTP/1.1 200 OK
{
"success": true
}
Accepted: Any 2xx status code (200-201) Timeout: Respond within 5 seconds
Auto-Retry Mechanism
Policy:
- Retries up to 7 times over ~5 hours
- Fibonacci sequence intervals (1, 1, 2, 3, 5, 8, 13... minutes)
Duplicate Prevention:
// Primary: Use transaction ID
const exists = await db.transactions.findOne({ sepay_id: data.id });
if (exists) return { success: true };
// Alternative: Composite key
const key = `${data.referenceCode}-${data.transferType}-${data.transferAmount}`;
Implementation Examples
Node.js/Express
app.post('/webhook/sepay', async (req, res) => {
const transaction = req.body;
// Check duplicates
if (await isDuplicate(transaction.id)) {
return res.json({ success: true });
}
// Process transaction
if (transaction.transferType === 'in') {
await processPayment({
amount: transaction.transferAmount,
content: transaction.content,
referenceCode: transaction.referenceCode
});
}
// Save to database
await db.transactions.insert(transaction);
res.json({ success: true });
});
PHP
<?php
$data = json_decode(file_get_contents('php://input'), true);
// Check duplicates
$exists = $db->query("SELECT id FROM transactions WHERE sepay_id = ?", [$data['id']]);
if ($exists) {
echo json_encode(['success' => true]);
exit;
}
// Process payment
if ($data['transferType'] == 'in') {
processPayment($data['transferAmount'], $data['content']);
}
// Save to database
$db->insert('transactions', [
'sepay_id' => $data['id'],
'amount' => $data['transferAmount'],
'content' => $data['content'],
'reference_code' => $data['referenceCode']
]);
header('Content-Type: application/json');
echo json_encode(['success' => true]);
Security Best Practices
- IP Whitelisting: Restrict endpoint to SePay IPs
- API Key Verification: Validate authorization header
- HTTPS Only: Use SSL/TLS
- Duplicate Detection: Prevent double processing
- Logging: Maintain webhook logs
- Timeout Handling: Respond quickly (<5s)
- Idempotency: Same webhook multiple times = same result
Monitoring
Dashboard Features:
- View webhook attempts
- Check response status
- Review retry history
- Manual retry option
Application Monitoring:
- Log all webhook receipts
- Track processing time
- Alert on failures
- Monitor duplicate rate
OAuth2 Webhook Management API
Available Scopes: webhook:read, webhook:write, webhook:delete
List Webhooks:
GET /api/v1/webhooks
Get Details:
GET /api/v1/webhooks/{id}
Create:
POST /api/v1/webhooks
{
"bank_account_id": 123,
"name": "My Webhook",
"event_type": "All",
"authen_type": "Api_Key",
"webhook_url": "https://example.com/webhook",
"is_verify_payment": true
}
Update:
PATCH /api/v1/webhooks/{id}
Delete:
DELETE /api/v1/webhooks/{id}