Payment Providers
Integrate payment gateways with the PaymentProvider interface.
BirrJS uses a provider interface to abstract payment gateway logic. Each provider implements the same three methods.
Provider Interface
interface PaymentProvider {
initializeTransaction(request: TransactionRequest): Promise<TransactionResponse>;
verifyTransaction(txRef: string): Promise<VerificationResponse>;
handleWebhook(payload: unknown, rawBody: string | Buffer, headers: Record<string, string>): Promise<WebhookEvent>;
}TransactionRequest → TransactionResponse
type TransactionRequest = {
amount: number; // Minor units (e.g. 2990 = 29.90 ETB)
currency: string;
email: string;
firstName?: string;
lastName?: string;
phoneNumber?: string;
txRef: string; // Unique transaction reference
callbackUrl: string;
returnUrl?: string;
metadata?: Record<string, string>;
customization?: {
title?: string;
description?: string;
};
};
type TransactionResponse = {
success: boolean;
checkoutUrl?: string;
paymentInstructions?: PaymentInstructions;
txRef?: string;
error?: string;
};
type PaymentChannel = {
type: "telebirr" | "cbe" | "awash";
label: string;
value: string;
accountHolder?: string;
};
type PaymentInstructions = {
amount: number;
channels: PaymentChannel[];
};Available providers
BirrJS ships with the following provider packages. Each has its own dedicated page with full setup and usage details.
Chapa — redirect-based checkout
import { chapa } from "@birrjs/chapa";Redirect users to a Chapa checkout page for payment. Supports webhooks, callback URLs, and automatic subscription activation. See the Chapa provider page for configuration, events, and known gaps.
Vodit — receipt-based manual payment
import { vodit } from "@birrjs/vodit";Display bank account instructions for users to send money directly, then verify via receipt URL. Supports Telebirr, CBE, Zemen, BoA, and Awash. See the Vodit provider page for setup, per-bank parsing details, and recipient verification.
Switching Providers
Your app code never references the provider directly — all calls go through the PaymentProvider interface. Swapping from Chapa to Vodit means changing one import:
// Before
import { chapa } from "@birrjs/chapa";
// After
import { vodit } from "@birrjs/vodit";
createBirr({
provider: vodit({
apiKey: process.env.VODIT_API_KEY!,
channels: [
{ type: "telebirr", value: "0912345678", name: "Abebe Kebede" },
{ type: "cbe", value: "1000200030004000", name: "Abebe Kebede" },
],
}),
// Everything else stays the same
database: process.env.DATABASE_URL,
plans: [free, pro],
});Your subscribe(), check(), report(), and webhook handler all work identically regardless of which provider is configured.
Adding a New Provider
Create a new package (e.g. @birrjs/arifpay) with:
- A provider factory function that returns
PaymentProvider - Types for provider-specific request/response shapes
- A Zod schema for webhook payload validation
Chapa and Vodit are available now. The provider system is designed to make adding new ones straightforward — planned providers include ArifPay, Santim Pay and more.