@mrlectus/paystack
v0.0.24
Published
An sdk for interacting with the paystack api
Maintainers
Readme
Paystack SDK
A fully typed, robust, and easy-to-use TypeScript SDK for interacting with the Paystack API.
Installation
npm install @mrlectus/paystack
# or
pnpm add @mrlectus/paystack
# or
yarn add @mrlectus/paystackUsage
Initialization
You can initialize the PaystackClient in two ways:
1. Using Environment Variables (Recommended)
Set PAYSTACK_SECRET in your environment variables, then initialize without arguments.
import { PaystackClient } from "@mrlectus/paystack";
const client = PaystackClient();2. Passing the Secret Key Directly
import { PaystackClient } from "@mrlectus/paystack";
const client = PaystackClient("YOUR_SECRET_KEY");Configuration
You can pass an optional configuration object to customize the client's behavior.
const client = PaystackClient("YOUR_SECRET_KEY", {
timeout: 20000, // Request timeout in milliseconds (default: 10000)
debug: true, // Enable debug logging for requests (default: false)
});Error Handling
The SDK throws PaystackApiError when the API returns a non-success status code (e.g., 4xx, 5xx) or when the API response indicates failure (status: false). You should wrap your API calls in a try-catch block to handle these errors gracefully.
import { PaystackClient, PaystackApiError } from "@mrlectus/paystack";
const client = PaystackClient();
try {
const response = await client.transactions.verify({ reference: "invalid-ref" });
console.log(response.data);
} catch (error) {
if (error instanceof PaystackApiError) {
console.error("Paystack API Error:", error.message);
console.error("Status Code:", error.statusCode); // e.g., 404
console.error("Error Details:", error.toJSON()); // Full error response from Paystack
} else {
console.error("Unexpected Error:", error);
}
}Features
The SDK covers the entire Paystack API surface area:
- Transactions: Initialize, verify, list, and manage payments.
- Customers: Create, validate, and manage customers.
- Transfers: Automate sending money to customers.
- Transfer Recipients: Manage beneficiaries for transfers.
- Plans & Subscriptions: Handle recurring billing and subscription plans.
- Payment Pages: Create and manage payment pages.
- Payment Requests: Manage payment requests and invoices.
- Refunds: Initiate and manage transaction refunds.
- Disputes: Handle transaction disputes.
- Subaccounts: Manage split payment accounts.
- Settlements: Insight into payouts.
- Dedicated Virtual Accounts: Manage virtual accounts for customers.
- Apple Pay: Manage Apple Pay domain registration.
- Bulk Charges: Process batched transactions.
- Direct Debit: Manage recurring debits.
- Terminal & Virtual Terminal: Manage POS and virtual terminal payments.
- Verification: Perform KYC/identity verification (BVN, Account Match, etc).
- Miscellaneous: List banks, countries, and states.
- Webhooks: Type-safe handling of webhook events using
WebhookEventData.
Examples
Initialize a Transaction
import { PaystackClient, PaystackApiError } from "@mrlectus/paystack";
const client = PaystackClient();
try {
const response = await client.transactions.initialize({
email: "[email protected]",
amount: "5000", // Amount in kobo
channels: ["card", "bank"],
});
console.log("Authorization URL:", response.data.authorization_url);
} catch (error) {
if (error instanceof PaystackApiError) {
console.error("Initialization Failed:", error.message);
}
}Create a Customer
try {
const customer = await client.customers.create({
email: "[email protected]",
first_name: "John",
last_name: "Doe",
phone: "+2348012345678",
});
console.log("Customer ID:", customer.data.id);
} catch (error) {
if (error instanceof PaystackApiError) {
console.error("Customer Creation Failed:", error.message);
}
}Initiate a Transfer
try {
// 1. Create a recipient
const recipient = await client.transferRecipients.create({
type: "nuban",
name: "Zombie Recipient",
account_number: "0123456789",
bank_code: "058",
currency: "NGN",
});
// 2. Initiate transfer
const transfer = await client.transfers.initiate({
source: "balance",
amount: 5000,
recipient: recipient.data.recipient_code,
reference: `ref-${Date.now()}`,
reason: "Holiday Bonus",
});
console.log("Transfer status:", transfer.data.status);
} catch (error) {
if (error instanceof PaystackApiError) {
console.error("Transfer Failed:", error.message);
}
}List Banks
try {
const banks = await client.miscellaneous.listBanks({
country: "nigeria",
use_cursor: true,
perPage: 10,
});
console.log("Banks retrieved:", banks.data.length);
} catch (error) {
console.error("Failed to list banks", error);
}Handling Webhooks
The SDK provides a discriminated union type WebhookEventData for all supported webhook events. This ensures robust type safety when processing events.
Using switch Statement (Express.js Example)
import express from "express";
import { WebhookEventData } from "@mrlectus/paystack";
const app = express();
app.post("/webhook", express.json(), (req, res) => {
// 1. Verify the signature (recommended)
// Paystack sends a HMAC SHA512 signature in the 'x-paystack-signature' header.
// You should verify this signature using your secret key.
const signature = req.headers["x-paystack-signature"] as string;
// 2. Cast the body to WebhookEventData
const event = req.body as WebhookEventData;
switch (event.event) {
case "charge.success":
// TypeScript automatically narrows 'event.data' to the correct payload
console.log("Payment Reference:", event.data.reference);
break;
case "transfer.success":
// TypeScript knows this is a Transfer event
console.log("Transfer Recipient:", event.data.recipient);
break;
default:
console.log("Unhandled event:", event.event);
}
res.sendStatus(200);
});Using ts-pattern
If you prefer a functional approach with pattern matching, you can use ts-pattern.
import { match } from "ts-pattern";
import { WebhookEventData } from "@mrlectus/paystack";
// ... inside your express route handler
const event = req.body as WebhookEventData;
match(event)
.with({ event: "charge.success" }, (evt) => {
console.log("Success:", evt.data.amount);
})
.with({ event: "refund.processed" }, (evt) => {
console.log("Refund:", evt.data.refund_reference);
})
.otherwise((evt) => {
console.log("Ignored event:", evt.event);
});Runtime Schema Validation
This SDK uses Zod for strict runtime schema validation. Every API request is validated against its expected schema before it is sent to Paystack. This prevents malformed requests and ensures your application fails fast with clear error messages if the input data is invalid.
TypeScript Support
The package is built with TypeScript and provides comprehensive type definitions for all API modules. This gives you:
- Autocompletion: Quickly discover available methods and payload properties.
- Type Safety: Catch potential bugs during development with strict typing for both requests and responses.
- Improved DX: Get inline documentation and hints directly in your IDE.
Together with runtime validation, this ensures a robust integration with the Paystack ecosystem.
License
MIT
