Universal TypeScript SDK for payment gateways — one API, zero vendor SDK dependencies.
Supported gateways: Stripe, Xendit, Midtrans, Doku
- Single
PaymentRequest/PaymentResponseinterface across all gateways - Zero vendor SDK dependencies — all communication via
fetch+ custom crypto - Runtime-agnostic (Bun, Node.js >= 18, Deno, edge runtimes)
- Dual ESM + CJS output
- Type-safe with strict TypeScript
- Webhook signature verification for all gateways
# npm
npm install unipay-sdk
# yarn
yarn add unipay-sdk
# pnpm
pnpm add unipay-sdk
# bun
bun add unipay-sdkimport { StripeGateway } from 'unipay-sdk/stripe';
const gateway = new StripeGateway();
gateway.initialize({
secretKey: 'sk_test_...',
});
const response = await gateway.createPayment({
amount: 2000,
currency: 'usd',
referenceId: 'order-123',
description: 'Test payment',
paymentMethod: 'card',
});
console.log(response.status); // 'PENDING', 'SUCCESS', etc.import { StripeGateway } from 'unipay-sdk/stripe';
const gateway = new StripeGateway();
gateway.initialize({ secretKey: 'sk_test_...' });
// Card payment
const response = await gateway.createPayment({
amount: 2000,
currency: 'usd',
referenceId: 'order-123',
paymentMethod: 'card',
});
// Check status
const status = await gateway.getPaymentStatus(response.transactionId);import { XenditGateway } from 'unipay-sdk/xendit';
const gateway = new XenditGateway();
gateway.initialize({ secretApiKey: 'xnd_...' });
// E-wallet payment
const response = await gateway.createPayment({
amount: 50000,
currency: 'IDR',
referenceId: 'order-456',
paymentMethod: 'ewallet',
country: 'ID',
});import { MidtransGateway } from 'unipay-sdk/midtrans';
const gateway = new MidtransGateway();
gateway.initialize({
serverKey: 'SB-Mid-server-...',
clientKey: 'SB-Mid-client-...',
isProduction: false,
});
// Bank transfer (BCA VA)
const response = await gateway.createPayment({
amount: 100000,
currency: 'IDR',
referenceId: 'order-789',
paymentMethod: 'bank_transfer',
bank: 'bca',
});import { DokuGateway } from 'unipay-sdk/doku';
const gateway = new DokuGateway();
gateway.initialize({
clientId: 'doku-client-...',
secretKey: 'doku-secret-...',
privateKey: '-----BEGIN RSA PRIVATE KEY-----\n...\n-----END RSA PRIVATE KEY-----',
isProduction: false,
});
// Virtual Account
const response = await gateway.createPayment({
amount: 75000,
currency: 'IDR',
referenceId: 'order-101',
paymentMethod: 'va',
customer: { name: 'John Doe', email: 'john@example.com' },
});For multi-gateway setups, use the UnipayClient facade:
import { UnipayClient } from 'unipay-sdk';
const client = new UnipayClient({
gateways: {
stripe: { secretKey: 'sk_test_...' },
xendit: { secretApiKey: 'xnd_...' },
},
});
// Use any configured gateway
const stripe = client.use('stripe');
const response = await stripe.createPayment({ ... });import { verifyWebhook } from 'unipay-sdk';
const event = verifyWebhook('stripe', payload, headers, webhookSecret, {
throwOnInvalid: true, // default
});
if (event.verified) {
console.log('Webhook verified:', event.eventType, event.transactionId);
}| Gateway | Card | E-wallet | Bank Transfer | VA | QRIS |
|---|---|---|---|---|---|
| Stripe | Yes | -- | -- | -- | -- |
| Xendit | -- | Yes | -- | -- | -- |
| Midtrans | Yes | Yes | Yes | Yes | Yes |
| Doku | -- | Yes | -- | Yes | -- |
The following areas require validation against a real sandbox account before production use:
-
Doku VA & H2H payload structures (
src/gateways/doku/mapper.ts): The request body structures for Virtual Account creation and Host-to-Host payments are based on Doku SNAP documentation. Verify against the latest official Doku API docs before going live. -
Doku card binding: Not implemented in v1. Use Doku.js client-side tokenization for card tokenization flows.
-
Midtrans status mapping: The SDK maps Midtrans
transaction_status+fraud_statuscombinations to a universal status. Verify the mapping matches your expected behavior for edge cases likechallengefraud status. -
Midtrans Classic Core API v2: This SDK uses the classic Core API v2 (
/v2/chargewith Basic Auth), not the newer BI-SNAP token-exchange variant. See Reconciliation Notes for why. -
Xendit v3 API: Uses v3 (
/v3/payment_requests) withrequest_amountfield (notamount). See Reconciliation Notes for details.
See Adding a Gateway for the extension pattern.
See Reconciliation Notes for decisions on API versioning and endpoint selection.
# Install dependencies
bun install
# Run tests
bun run test
# Run tests with coverage
bun run test -- --coverage
# Type check
bun run typecheck
# Lint
bun run lint
# Build
bun run build
# Run e2e sandbox tests (requires env vars)
bun run test:e2eMIT