Configure IPN URL
IPN URL is configured on the merchant management page in SePay:
- Log in to SePay
- Go to Payment Gateway → Configuration → IPN
- Enter your endpoint URL to receive IPN
- Save configuration
Important Note
The IPN URL must be a public HTTPS endpoint that SePay can reach from the internet (not localhost or an internal IP such as 127.0.0.1, 192.168.x), and the endpoint must return HTTP status code 200 to confirm successful receipt. When developing locally, expose your endpoint with ngrok, localtunnel, cloudflared or similar so SePay can call it.
Request from SePay to Merchant
POST
https://your-url (url you configured in IPN)Headers:
X-Secret-Key: <secret_key>
Content-Type: application/json
Note
X-Secret-Key: Secret key for authentication (only available when merchant configures auth type = SECRET_KEY)
Parameter list
timestampintegerrequired
Unix timestamp when notification is sent
notification_typestringrequired
Notification type: ORDER_PAID (successful payment), TRANSACTION_VOID (void transaction)
orderobjectrequired
Order information
transactionobjectrequired
Transaction information
customerobjectrequired
Customer information
Example request body:
REQUEST
{
"timestamp": 1757058220,
"notification_type": "ORDER_PAID",
"order": {
"id": "e2c195be-c721-47eb-b323-99ab24e52d85",
"order_id": "NPSETVI00101000042R",
"order_status": "CAPTURED",
"order_currency": "VND",
"order_amount": "50000.00",
"order_invoice_number": "SUB_202509_001",
"custom_data": [],
"user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
"ip_address": "14.xxx.xxx.xxx",
"order_description": "Premium package recurring payment for September 2025"
},
"transaction": {
"id": "384c66dd-41e6-4316-a544-b4141682595c",
"payment_method": "CARD",
"transaction_id": "68ba94ac80123",
"transaction_type": "PAYMENT",
"transaction_date": "2025-09-01 00:00:15",
"transaction_status": "APPROVED",
"transaction_amount": "50000",
"transaction_currency": "VND",
"authentication_status": "AUTHENTICATION_SUCCESSFUL",
"card_number": "4111XXXXXXXX1111",
"card_holder_name": "NGUYEN VAN A",
"card_expiry": "12/26",
"card_funding_method": "CREDIT",
"card_brand": "VISA"
},
"customer": {
"id": "bae12d2f-0580-4669-8841-cc35cf671613",
"customer_id": "CUST_001"
}
}Handle IPN endpoint:
PHPPHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Route::post('/payment/ipn', function(Request $request) {// Verify secret keyif ($request->header('X-Secret-Key') !== $secretKey) {return response()->json(['error' => 'Unauthorized'], 401);}$data = $request->json()->all();if ($data['notification_type'] === 'ORDER_PAID') {$order = Order::where('invoice_number', $data['order']['order_invoice_number'])->first();$order->status = 'paid';$order->save();}// Return 200 to acknowledge receiptreturn response()->json(['success' => true], 200);});