IPN

IPN là cơ chế thông báo thanh toán tự động mà cổng thanh toán (ví dụ SePay, PayPal, Stripe...) gửi đến máy chủ của bạn (server) khi có thay đổi trạng thái giao dịch — như thanh toán thành công, thất bại hoặc bị hủy.


Cấu hình IPN URL

  • IPN URL được cấu hình tại trang quản lý merchant trên SePay:
  1. Đăng nhập vào SePay
  2. Vào Cổng thanh toán → Cấu hình → IPN
  3. Nhập URL endpoint của bạn để nhận IPN
  4. Lưu cấu hình
Lưu ý quan trọng
  • IPN URL phải là HTTPS
  • Endpoint phải trả về HTTP status code 200 để xác nhận đã nhận thành công

Request từ SePay đến Merchant

POST
https://your-url (url bạn cấu hình trong IPN)
  -H "X-Secret-Key: <secret_key>" \
  -H "Content-Type: application/json" \
Ghi chú

X-Secret-Key: Secret key để xác thực (chỉ có khi merchant cấu hình auth type = SECRET_KEY)

  • Danh sách tham số
TênLoạiBắt buộcMô tả
timestamp
integerBắt buộc
Unix timestamp khi gửi thông báo
notification_type
stringBắt buộc
Loại thông báo:
ORDER_PAID:
  • Gửi khi: Thanh toán một lần thành công
  • Xử lý: Cập nhật đơn hàng, kích hoạt dịch vụ

TRANSACTION_VOID:
  • Gửi khi: Hủy giao dịch thành công
  • Xử lý: Hoàn tiền, hủy/tạm dừng dịch vụ
order
objectBắt buộc
Thông tin đơn hàng
transaction
objectBắt buộc
Thông tin giao dịch
customer
objectBắt buộc
Thông tin khách hàng
  • Ví dụ 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": "Thanh toán định kỳ gói Premium tháng 9/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"
  }
}
  • Xử lý IPN endpoint:
PHP
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);
});