IPN
IPN is an automatic payment notification mechanism that payment gateways (e.g., SePay, PayPal, Stripe...) send to your server when there is a change in transaction status — such as successful payment, failure, or cancellation.
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
IPN URL must be HTTPS and the endpoint must return HTTP status code 200 to confirm successful receipt.
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);});