How IPN works in SePay Payment Gateway

Configure IPN endpoints in SePay Payment Gateway to receive automatic, real-time payment notifications and confirm orders securely on your server.

||

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

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 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);
});

The merchant Secret Key and how to regenerate it

The Payment Gateway has two different Secret Keys:

KeyWhere to find itWhat it is for
Merchant Secret KeyPayment Gateway → Configuration → Merchant informationSigns the payment form you send to checkout/init and authenticates API calls over Basic Auth (merchant_id:secret_key). Generated by SePay, in the form spsk_live_... (LIVE) or spsk_test_... (Test mode).
IPN Secret KeyPayment Gateway → Configuration → IPNAuthenticates the IPN that SePay sends to your system, using the Auth Type set on the IPN tab. You choose it yourself.

The two keys are independent: regenerating the merchant Secret Key does not change the Secret Key on the IPN tab, and vice versa.

When to regenerate

The merchant Secret Key is displayed only once, when it is created. After that the Merchant information page shows * characters only. Regenerate the key if you have lost it, or if it may have leaked (for example it was committed to Git, sent over chat, or someone who held it has left the company).

Steps

Only a SuperAdmin or Admin account of the company can do this.

  1. Go to Payment Gateway → Configuration → Merchant information (Cổng thanh toán → Cấu hình → Thông tin đơn vị).
  2. Check the Test Mode switch in the top right corner. You can only regenerate the key of the environment currently selected; to regenerate the LIVE key, turn Test Mode off first.
  3. Click Tạo lại (Regenerate) on the Secret Key row.
  4. In the confirmation dialog, check the environment badge (LIVE or Test mode).
  5. Type your merchant code (Merchant ID, shown under the merchant name) into the confirmation field, then click Tạo lại Secret Key (Regenerate Secret Key).
  6. Copy the new key from the dialog that opens, then click Tôi đã lưu key (I have saved the key).
The old key stops working at once, and this cannot be undone

As soon as you click Tạo lại Secret Key, the old key no longer works. Until your system switches to the new key:

  • A payment form signed with the old key is rejected, and your customer cannot reach the payment page.
  • An API call using the old key returns 401.

Regenerate at a quiet time, and have every place that stores the key ready to update before you click.

The new key is shown only once

Once the dialog is closed, the key is no longer shown anywhere in the interface. If you close it before saving, you have to regenerate again, and the key you just created stops working too.

After regenerating

The new key works immediately for both the checkout pages and the API; there is no period in which both keys work. Update the new key everywhere the old one was used:

  • Environment variables or configuration files on your server.
  • The WooCommerce or Haravan plugin, or any other CMS integration.
  • PHP / Node.js SDK configuration.
  • Internal services that sign payment forms themselves.

Limits and common errors

SituationMessageWhat to do
More than 3 regenerations within 1 hour in the same environment (LIVE and Test mode are counted separately)"Bạn đã tạo lại Secret Key quá nhiều lần, vui lòng thử lại sau khoảng N phút." (too many regenerations, try again in about N minutes)Wait the number of minutes in the message, then try again.
The environment changed after you opened the page (for example Test Mode was switched in another tab)"Bạn đang ở môi trường ... Vui lòng tải lại trang rồi thử lại." (you are in environment ..., reload the page and try again)Reload the page, check the Test Mode switch, then repeat the steps.
A colleague regenerated the key just before you"Secret Key vừa được tạo lại bởi người khác..." (the Secret Key was just regenerated by someone else)Open Nhật ký người dùng (User log) to see who regenerated it, and get the new key from them. Do not regenerate again, or the key they hold stops working.
No response in time (slow connection)"Yêu cầu quá hạn, Secret Key có thể đã được tạo lại..." (request timed out, the Secret Key may have been regenerated)Open Nhật ký người dùng (User log) and look for a "Tạo lại Secret Key cổng thanh toán" entry from just now. If it is there, the key changed but you never received the new one, so regenerate once more. If not, simply try again.
Every regeneration is logged

Each regeneration is recorded in the User log: who did it, when, and in which environment. The log never contains the key.