Skip to content

charge()

Initiates a payment transaction. Returns a Transaction object with a checkoutUrl to redirect the customer to.


zirzir.charge(params: ChargeParams): Promise<Transaction>

FieldTypeRequiredDescription
amountnumberYesAmount to charge. Integer for ETB (no fractional birr), decimal for USD
currencystringYesISO 4217 currency code. e.g. ETB, KES, USD
emailstringYesCustomer email address
txRefstringYesYour unique transaction reference. Must be unique per transaction
firstNamestringNoCustomer first name
lastNamestringNoCustomer last name
phonestringNoCustomer phone number. Required for mobile money providers
returnUrlstringNoURL to redirect customer after payment
callbackUrlstringNoWebhook URL for async payment notifications
descriptionstringNoPayment description shown on checkout page
metadataRecord<string, any>NoArbitrary key-value data attached to the transaction
providerProviderNameNoOverride provider for this transaction (server mode only)

Note on phone: Telebirr and CBEBirr require a phone number — the charge will fail without it. Chapa and Santim make it optional.


interface Transaction {
id: string // Zirzir transaction ID (zz_tx_...)
externalId: string // Provider's transaction ID
status: TransactionStatus // 'pending' | 'success' | 'failed' | 'cancelled' | 'refunded'
amount: number
currency: string
provider: ProviderName
txRef: string // Your reference, echoed back
checkoutUrl: string | null // Redirect URL (null for direct-debit flows)
callbackUrl: string | null
returnUrl: string | null
description: string | null
metadata: Record<string, any>
raw: Record<string, any> // Unmodified provider response
createdAt: string // ISO 8601
updatedAt: string
}

import { Zirzir } from '@zirzir/sdk'
const zirzir = new Zirzir({
provider: 'chapa',
credentials: { secretKey: process.env.CHAPA_SECRET_KEY! }
})
const tx = await zirzir.charge({
amount: 1500,
currency: 'ETB',
firstName: 'Tigist',
lastName: 'Alemu',
txRef: 'invoice_2024_001',
description: 'Payment for Invoice #2024-001',
returnUrl: 'https://yourapp.com/payment/success',
callbackUrl: 'https://yourapp.com/webhooks/zirzir',
metadata: {
orderId: '9182',
plan: 'premium'
}
})
// Redirect customer
res.redirect(tx.checkoutUrl)
import zirzir
client = zirzir.Zirzir(
provider="chapa",
credentials={"secret_key": os.environ["CHAPA_SECRET_KEY"]}
)
tx = client.charge(
amount=1500,
currency="ETB",
first_name="Tigist",
last_name="Alemu",
tx_ref="invoice_2024_001",
description="Payment for Invoice #2024-001",
return_url="https://yourapp.com/payment/success",
callback_url="https://yourapp.com/webhooks/zirzir",
metadata={"order_id": "9182", "plan": "premium"}
)
return redirect(tx.checkout_url)
tx, err := client.Charge(context.Background(), zirzir.ChargeParams{
Amount: 1500,
Currency: "ETB",
FirstName: "Tigist",
LastName: "Alemu",
TxRef: "invoice_2024_001",
Description: "Payment for Invoice #2024-001",
ReturnURL: "https://yourapp.com/payment/success",
CallbackURL: "https://yourapp.com/webhooks/zirzir",
Metadata: map[string]any{
"order_id": "9182",
"plan": "premium",
},
})
if err != nil {
// handle error
}
http.Redirect(w, r, tx.CheckoutURL, http.StatusFound)

ErrorDescription
ZirzirValidationErrorRequired field missing or invalid
ZirzirProviderErrorProvider returned an error. Check .providerCode and .providerMessage
ZirzirNetworkErrorNetwork timeout or connectivity issue
ZirzirDuplicateTxRefErrortxRef already used. Must be unique per transaction
import { ZirzirProviderError } from '@zirzir/sdk'
try {
const tx = await zirzir.charge({ ... })
} catch (err) {
if (err instanceof ZirzirProviderError) {
console.error(err.providerCode) // Provider's error code
console.error(err.providerMessage) // Provider's error message
}
}

Telebirr initiates a USSD push to the customer’s phone instead of a web checkout. checkoutUrl will be null. The customer receives a prompt on their phone to confirm.

Similar to Telebirr — USSD-based. phone is required. Sandbox behavior differs significantly from production; see CBEBirr Provider Guide.

Standard web checkout. Supports multiple payment methods (bank transfer, mobile money, cards) on the same checkout page.

Uses STK Push (Lipa Na M-Pesa). phone must be in the format 2547XXXXXXXX. checkoutUrl is null.