@yae-tools/webxpay-sdk
v0.1.0
Published
Production-ready, type-safe Node.js SDK for WebxPay payment gateway
Maintainers
Readme
WebxPay SDK
Production-ready, type-safe Node.js SDK for WebxPay payment gateway integration.
Features
- 🔐 Type-Safe: Full TypeScript support with comprehensive type definitions
- ✅ Production-Ready: Built-in retry logic, error handling, and logging
- 🎯 Simple API: Clean, intuitive class-based API
- 🔄 Automatic Retries: Exponential backoff for failed requests
- 📝 Comprehensive Logging: Structured logging with Pino
- 🪝 Webhook Support: Express middleware for payment callbacks
- ✨ Validation: Runtime validation with Zod
- 🧪 Well-Tested: Extensive unit test coverage
Installation
npm install @yae-tools/webxpay-sdkOr with yarn:
yarn add @yae-tools/webxpay-sdkQuick Start
import { WebxPayClient } from '@yae-tools/webxpay-sdk';
// Initialize the client
const client = new WebxPayClient({
publicKey: process.env.WEBXPAY_PUBLIC_KEY,
secretKey: process.env.WEBXPAY_SECRET_KEY,
});
// Create a payment
const paymentForm = await client.createPayment({
orderId: 'ORDER-12345',
amount: 100.00,
currency: 'LKR',
customer: {
firstName: 'John',
lastName: 'Doe',
email: '[email protected]',
contactNumber: '+94771234567',
address: '123 Main Street, Colombo'
}
});
// Send the form HTML to the client
res.send(paymentForm.formHtml);Configuration
Basic Configuration
const client = new WebxPayClient({
publicKey: 'YOUR_PUBLIC_KEY',
secretKey: 'YOUR_SECRET_KEY',
});Advanced Configuration
const client = new WebxPayClient({
publicKey: 'YOUR_PUBLIC_KEY',
secretKey: 'YOUR_SECRET_KEY',
// Logging configuration
logging: {
level: 'info', // trace, debug, info, warn, error, fatal
prettyPrint: false // Enable for development
},
// Retry configuration
retry: {
maxAttempts: 3, // Maximum retry attempts
backoffMs: 1000, // Initial backoff delay
backoffStrategy: 'exponential', // exponential, linear, constant
maxBackoffMs: 30000 // Maximum backoff delay
},
// Custom endpoints (optional)
endpoints: {
checkoutUrl: 'https://custom-checkout-url.com',
callbackUrl: 'https://your-domain.com/webhook'
},
// Request timeout
timeout: 30000 // 30 seconds
});API Reference
Creating a Payment
const paymentForm = await client.createPayment({
orderId: 'unique-order-id',
amount: 100.00,
currency: 'LKR', // Optional, defaults to 'LKR'
customer: {
firstName: 'John',
lastName: 'Doe',
email: '[email protected]',
contactNumber: '+94771234567',
address: '123 Main Street',
city: 'Colombo', // Optional
postalCode: '00100', // Optional
country: 'Sri Lanka' // Optional
},
customFields: { // Optional
invoiceNumber: 'INV-001',
notes: 'Special delivery'
},
description: 'Order payment' // Optional
});
// Response includes:
// - formHtml: Auto-submitting HTML form
// - redirectUrl: WebxPay checkout URL
// - encryptedPayment: Encrypted payment data
// - formData: Raw form data objectVerifying Payments
const result = await client.verifyPayment({
payment: req.body.payment, // Base64 payment data
signature: req.body.signature // Base64 signature
});
if (result.isValid && result.status === 'APPROVED') {
console.log('Payment successful!');
console.log('Order ID:', result.data.orderId);
console.log('Amount:', result.data.amount);
console.log('Transaction Ref:', result.data.transactionRef);
} else {
console.error('Payment failed:', result.error);
}Webhook Handling
import express from 'express';
const app = express();
app.use(express.urlencoded({ extended: false }));
// Setup webhook endpoint
app.post('/webhook', client.webhookHandler({
onSuccess: async (payload) => {
console.log('Payment successful:', payload.payment.data);
// Update your database
await updateOrderStatus(
payload.payment.data.orderId,
'PAID'
);
},
onFailure: async (error, payload) => {
console.error('Payment failed:', error);
// Handle failed payment
if (payload?.payment?.data) {
await updateOrderStatus(
payload.payment.data.orderId,
'FAILED'
);
}
},
onEvent: async (payload) => {
// Called for all events before onSuccess/onFailure
console.log('Webhook event:', payload.event);
}
}));Complete Express Example
import express from 'express';
import { WebxPayClient } from '@yae-tools/webxpay-sdk';
const app = express();
app.use(express.urlencoded({ extended: false }));
const client = new WebxPayClient({
publicKey: process.env.WEBXPAY_PUBLIC_KEY!,
secretKey: process.env.WEBXPAY_SECRET_KEY!,
logging: { level: 'info' }
});
// Initiate payment
app.post('/api/payment/create', async (req, res) => {
try {
const paymentForm = await client.createPayment({
orderId: `ORDER-${Date.now()}`,
amount: parseFloat(req.body.amount),
currency: 'LKR',
customer: {
firstName: req.body.firstName,
lastName: req.body.lastName,
email: req.body.email,
contactNumber: req.body.contactNumber,
address: req.body.address
}
});
res.send(paymentForm.formHtml);
} catch (error) {
console.error('Payment creation failed:', error);
res.status(500).json({ error: 'Payment creation failed' });
}
});
// Handle payment callback
app.post('/api/payment/callback', client.webhookHandler({
onSuccess: async (payload) => {
console.log('Payment approved:', payload.payment.data?.orderId);
// Update order status, send confirmation email, etc.
},
onFailure: async (error) => {
console.error('Payment failed:', error.message);
// Handle failure, notify customer, etc.
}
}));
app.listen(3000, () => {
console.log('Server running on port 3000');
});Error Handling
The SDK provides specific error types for different scenarios:
import {
WebxPayError,
ValidationError,
SignatureError,
EncryptionError
} from '@yae-tools/webxpay-sdk';
try {
await client.createPayment(invalidData);
} catch (error) {
if (error instanceof ValidationError) {
console.error('Invalid payment data:', error.validationErrors);
} else if (error instanceof SignatureError) {
console.error('Signature verification failed');
} else if (error instanceof EncryptionError) {
console.error('Encryption/decryption failed');
} else if (error instanceof WebxPayError) {
console.error('WebxPay error:', error.code, error.message);
}
}TypeScript Support
Full TypeScript support with comprehensive type definitions:
import {
WebxPayClient,
PaymentRequest,
PaymentVerificationResult,
WebhookPayload,
PaymentStatus
} from '@yae-tools/webxpay-sdk';
const request: PaymentRequest = {
orderId: 'ORDER-123',
amount: 100,
currency: 'LKR',
customer: {
firstName: 'John',
lastName: 'Doe',
email: '[email protected]',
contactNumber: '+94771234567',
address: '123 Main St'
}
};
const result: PaymentVerificationResult = await client.verifyPayment(data);Testing
Run the test suite:
npm testRun tests with coverage:
npm run test:coverageBuilding
Build the SDK:
npm run buildThis generates:
- CommonJS build in
dist/cjs - ES Modules build in
dist/esm - Type definitions in
dist/types
Environment Variables
Create a .env file:
WEBXPAY_PUBLIC_KEY=your-public-key-here
WEBXPAY_SECRET_KEY=your-secret-key-hereMigration from Sample Code
If you're migrating from the official WebxPay sample code:
Before:
var express = require("express");
var NodeRSA = require("node-rsa");
app.get("/", function (req, res) {
const key = new NodeRSA("-----BEGIN PUBLIC KEY-----...");
const encrypted = key.encrypt(orderId + "|" + price, "base64");
res.render("./public/form.html", { encrypted: encrypted });
});After:
import { WebxPayClient } from '@yae-tools/webxpay-sdk';
const client = new WebxPayClient({
publicKey: process.env.WEBXPAY_PUBLIC_KEY!,
secretKey: process.env.WEBXPAY_SECRET_KEY!
});
app.get("/", async (req, res) => {
const paymentForm = await client.createPayment({
orderId: 'ORDER-123',
amount: 100,
currency: 'LKR',
customer: { /* ... */ }
});
res.send(paymentForm.formHtml);
});Support
- 📖 API Documentation
- 💬 GitHub Issues
- 📧 Email: [email protected]
License
MIT © Your Name
Contributing
Contributions are welcome! Please read our Contributing Guide for details.
Changelog
See CHANGELOG.md for a list of changes.
