Nile PayNile Pay

Payment Events

Event-driven payment status tracking with on, once, and wait

PaymentInstance Events

The PaymentInstance returned by collectPayment() emits events as the payment progresses through its lifecycle.

const payment = nile.collectPayment({ /* ... */ });

payment.on("processing", handleProcessing);
payment.on("success", handleSuccess);
payment.on("failed", handleFailed);
payment.on("cancelled", handleCancelled);
payment.on("error", handleError);

Event Reference

EventPayloadWhen It Fires
processingTransactionPayment initiated, awaiting customer confirmation
successTransactionPayment completed successfully
failedTransactionPayment failed (customer rejected or timeout)
cancelledTransactionPayment cancelled by customer or system
errorPaymentErrorNetwork error or polling timeout during lifecycle

on(event, handler)

Registers a handler for an event. Handler is called every time the event fires.

payment.on("success", (tx) => {
  console.log("Transaction ID:", tx.transactionId);
});

once(event, handler)

Registers a handler that fires only once, then automatically removes itself.

payment.once("success", (tx) => {
  // This runs only on first success
  fulfillOrder(tx.metadata.orderId);
});

off(event, handler)

Removes a previously registered handler.

const handler = (tx) => console.log(tx.status);

payment.on("success", handler);
// ... later
payment.off("success", handler);

Chaining

Event methods return the PaymentInstance, enabling chaining.

payment
  .on("success", handleSuccess)
  .on("failed", handleFailed)
  .on("cancelled", handleCancelled)
  .on("error", handleError);

wait()

Returns a Promise<Transaction> that resolves when a terminal state is reached (success, failed, or cancelled). Rejects on error or timeout.

try {
  const tx = await payment.wait();
  
  if (tx.status === "successful") {
    // Order confirmed
  } else {
    // Handle failed/cancelled
  }
} catch (error) {
  // Network error or timeout exceeded
}

Express Route Handler Example

import express from "express";
import { createNilePay } from "@nilepay/sdk";

const app = express();
const nile = createNilePay({ /* config */ });

app.post("/api/pay", async (req, res) => {
  const { amount, phone, orderId } = req.body;
  const reference = crypto.randomUUID();

  const payment = nile.collectPayment({
    amount,
    currency: "UGX",
    customer: { phone },
    reference,
    metadata: { orderId },
  });

  // Respond immediately, process async
  res.json({ reference, status: "initiated" });

  // Handle outcome asynchronously
  payment
    .on("success", (tx) => {
      updateOrderStatus(orderId, "paid");
      sendConfirmationEmail(tx.customer.email);
    })
    .on("failed", (tx) => {
      updateOrderStatus(orderId, "payment_failed");
    })
    .on("error", (err) => {
      console.error("Payment error:", err.message);
      // Implement retry logic if needed
    });
});

When to Use Events vs wait()

ScenarioApproach
HTTP API with immediate responseUse on() handlers, respond 202 Accepted
Background job/processorUse on() for state updates
CLI or scriptUse await payment.wait()
Need specific state onlyUse once()

Transaction Payload

interface Transaction {
  transactionId: string;
  reference: string;
  status: TransactionStatus;
  amount: number;
  currency: string;
  providerReference?: string;
  createdAt: string;
  updatedAt: string;
}

type TransactionStatus = 
  | "pending" 
  | "processing" 
  | "successful" 
  | "failed" 
  | "cancelled";

On this page