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:

  1. Log in to SePay
  2. Go to Payment Gateway → Configuration → IPN
  3. Enter your endpoint URL to receive IPN
  4. 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 key
if ($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 receipt
return response()->json(['success' => true], 200);
});