@abshahin/payments-sdk
v0.6.0
Published
Unified, framework-agnostic payment SDK for Bun & TypeScript. Seamlessly integrate Moyasar, PayPal, Paymob and other payment gateways with type-safe lifecycle hooks and normalized webhooks.
Downloads
559
Maintainers
Readme
@abshahin/payments-sdk
Unified, framework-agnostic payment SDK for Bun & TypeScript. Seamlessly integrate Moyasar, PayPal, Paymob, Stripe, Tabby, Tamara and other payment gateways with type-safe lifecycle hooks and normalized webhooks.
Features
- 🔌 Multi-Gateway Support: Moyasar, PayPal, Paymob, Stripe, Tabby, Tamara
- 🪝 Lifecycle Hooks: Before, after, and error hooks for all operations
- 🔒 Type-Safe: Full TypeScript support with strict types
- 🌐 Framework-Agnostic: Works with Elysia, Express, Hono, or vanilla
Documentation
- Gateways
- Core Concepts
Package Structure
packages/payments/
├── src/
│ ├── index.ts # Main exports
│ ├── client.ts # PaymentClient orchestrator
│ ├── errors.ts # Custom error classes
│ ├── types/ # Type definitions
│ ├── hooks/ # Lifecycle hooks
│ └── gateways/ # Gateway implementations
├── dist/ # Built output
├── docs/ # Documentation
├── resources/ # Resources
├── package.json
├── README.md
└── tsconfig.jsonInstallation
bun add @abshahin/payments-sdkQuick Start
import { PaymentClient } from '@abshahin/payments-sdk';
const client = new PaymentClient({
moyasar: {
secretKey: process.env.MOYASAR_SECRET_KEY!,
webhookSecret: process.env.MOYASAR_WEBHOOK_SECRET,
},
defaultGateway: 'moyasar',
});
// Create a payment
const result = await client.createPayment({
amount: 100,
currency: 'SAR',
callbackUrl: 'https://example.com/callback',
moyasarSource: {
type: 'token',
token: 'tok_xxx'
},
metadata: { orderId: 'order_123' },
});
if (result.redirectUrl) {
// Redirect customer for 3DS verification
}Multi-Gateway Usage
const client = new PaymentClient({
moyasar: { secretKey: '...' },
paypal: { clientId: '...', clientSecret: '...' },
paymob: {
secretKey: '...',
publicKey: '...',
region: 'ksa',
},
stripe: {
secretKey: 'sk_...',
publishableKey: 'pk_...',
webhookSecret: 'whsec_...',
},
tabby: {
secretKey: 'sk_...',
merchantCode: 'your_merchant_code',
sandbox: true,
},
tamara: {
apiToken: 'your_api_token',
notificationToken: 'your_notification_token',
sandbox: true,
},
defaultGateway: 'moyasar',
});
// Use default gateway
await client.createPayment({ ... });
// Specify gateway explicitly
await client.createPayment({ ... }, 'paypal');
// Access gateway directly
const moyasar = client.gateway('moyasar');
// Access gateway directly
const moyasar = client.gateway('moyasar');
await moyasar.getPaymentStatus('pay_xxx');
// Stripe Checkout Example
const stripe = client.gateway('stripe');
const session = await stripe.createCheckoutSession({
amount: 200, // $200.00
currency: 'USD',
successUrl: 'https://example.com/success',
cancelUrl: 'https://example.com/cancel',
mode: 'payment',
lineItems: [
{
priceData: {
currency: 'USD',
productData: {
name: 'T-Shirt',
},
unitAmount: 2000, // 2000 cents = $20.00
},
quantity: 10,
}
]
});Stripe Webhook Note
For Stripe webhooks, you MUST pass the raw request body to verifyWebhook. If your framework parses JSON automatically, you need to access the raw body buffer or string before parsing.
// Example using Elysia
app.post('/webhook/stripe', async ({ request, body }) => {
const signature = request.headers.get('stripe-signature');
const rawBody = await Bun.readableStreamToText(request.body); // Get raw body
const isValid = client.gateway('stripe').verifyWebhook(
rawBody,
signature
);
});
Error Handling
import {
PaymentError,
PaymentAbortedError,
GatewayNotConfiguredError,
InvalidWebhookError,
GatewayApiError,
} from '@abshahin/payments-sdk';
try {
await client.createPayment({ ... });
} catch (error) {
if (error instanceof PaymentAbortedError) {
// Aborted by a hook
console.log('Aborted:', error.message);
} else if (error instanceof GatewayApiError) {
// Gateway API returned an error
console.log('Gateway error:', error.rawError);
} else if (error instanceof PaymentError) {
// Other payment error
console.log('Error code:', error.code);
}
}License
MIT
