@flixora/airxpay
v0.0.5
Published
AirXPay Initialization Data activities API__for Node & Express etc.
Readme
@flixora/airxpay 🚀
Official AirXPay SDK for Node.js - Easily integrate merchant onboarding and payment services into your application.
📦 Installation
npm install @flixora/airxpay
# or
yarn add @flixora/airxpay🔑 Environment Setup
Create a .env file in your project root:
AIRXPAY_SECRET_KEY=your_secret_key_here
AIRXPAY_CLIENT_KEY=your_client_key_here📝 Complete Express.js Controller Example
Here's a production-ready controller showing how to integrate the SDK in your Express.js application:
// controllers/sellerController.ts
import { Request, Response } from "express";
import { AirXPay } from "@flixora/airxpay";
// 🔒 Backend keys from .env
const AIRXPAY_SECRET_KEY = process.env.AIRXPAY_SECRET_KEY || "";
const AIRXPAY_CLIENT_KEY = process.env.AIRXPAY_CLIENT_KEY || "";
if (!AIRXPAY_SECRET_KEY)
throw new Error("AIRXPAY_SECRET_KEY is not defined in .env");
if (!AIRXPAY_CLIENT_KEY)
throw new Error("AIRXPAY_CLIENT_KEY is not defined in .env");
/**
* ✅ CREATE SELLER (CREATE MERCHANT)
* frontend sends publicKey as 'publicKey' in body
*/
export const createSeller = async (req: Request, res: Response) => {
console.log("📥 [CREATE SELLER] Request received:", new Date().toISOString());
try {
const { seller, publicKey } = req.body;
console.log("📦 [CREATE SELLER] Body keys:", Object.keys(req.body));
// 🔹 Validate required fields
if (!seller?.merchantName || !seller?.merchantEmail) {
return res.status(400).json({
success: false,
message: "merchantName and merchantEmail are required",
});
}
if (!publicKey) {
return res.status(400).json({
success: false,
message: "frontend public key is required",
});
}
// 🔹 Prepare merchant data
const merchantData = {
merchantName: seller.merchantName,
merchantEmail: seller.merchantEmail,
merchantPhone: seller.merchantPhone,
businessName: seller.businessName,
businessType: seller.businessType || "individual",
businessCategory: seller.businessCategory,
country: seller.country || "India",
nationality: seller.nationality || "Indian",
dob: seller.dob,
mode: seller.mode || "test",
metadata: seller.metadata || {},
kycDetails: seller.kycDetails,
bankDetails: seller.bankDetails,
publicKey,
};
console.log("🔑 [CREATE SELLER] Prepared merchant data:", {
merchantName: merchantData.merchantName,
merchantEmail: merchantData.merchantEmail,
hasPublicKey: !!merchantData.publicKey,
});
// 🔹 Call SDK → which calls company backend → returns token + merchant
console.log("📡 [CREATE SELLER] Calling AirXPay.flixora.createMerchant...");
const result = await AirXPay.flixora.createMerchant(publicKey, {
...merchantData,
clientKey: AIRXPAY_CLIENT_KEY,
secretKey: AIRXPAY_SECRET_KEY,
});
console.log("✅ [CREATE SELLER] Merchant created successfully:", {
merchantId: result.merchant.merchantId,
airxpayMerchantId: result.merchant.airxpayMerchantId,
status: result.merchant.status,
});
// 🔹 Return final response to frontend
return res.status(200).json({
success: true,
message: "Merchant created successfully",
merchantId: result.merchant.merchantId,
airxpayMerchantId: result.merchant.airxpayMerchantId,
walletId: result.merchant.walletId,
status: result.merchant.status,
kycStatus: result.merchant.kycStatus,
isKycCompleted: result.merchant.isKycCompleted,
isBankDetailsCompleted: result.merchant.isBankDetailsCompleted,
mode: result.merchant.mode,
token: result.token,
});
} catch (error: any) {
console.error("❌ [CREATE SELLER] Error:", error);
return res.status(error.statusCode || 500).json({
success: false,
message: error.message || "Failed to create merchant",
error: error.data || null,
});
}
};🔍 Controller Explanation (Step by Step)
Let me break down what's happening in the controller:
1. Environment Variables Setup
const AIRXPAY_SECRET_KEY = process.env.AIRXPAY_SECRET_KEY || "";
const AIRXPAY_CLIENT_KEY = process.env.AIRXPAY_CLIENT_KEY || "";AIRXPAY_SECRET_KEY: Your secret key for authentication (never exposed to frontend)AIRXPAY_CLIENT_KEY: Your client key for identification- Both keys are loaded from
.envfile for security
2. Request Validation
if (!seller?.merchantName || !seller?.merchantEmail) {
return res.status(400).json({ success: false, message: "..." });
}
if (!publicKey) {
return res.status(400).json({ success: false, message: "..." });
}- Validates that frontend sent required fields
- Checks for
merchantName,merchantEmail, andpublicKey - Returns 400 error if any required field is missing
3. Data Preparation
const merchantData = {
merchantName: seller.merchantName,
merchantEmail: seller.merchantEmail,
merchantPhone: seller.merchantPhone,
businessName: seller.businessName,
businessType: seller.businessType || "individual", // Default value
country: seller.country || "India", // Default value
nationality: seller.nationality || "Indian", // Default value
mode: seller.mode || "test", // Default to test mode
kycDetails: seller.kycDetails, // Optional KYC documents
bankDetails: seller.bankDetails, // Optional bank details
publicKey, // Frontend public key
};- Maps frontend data to SDK expected format
- Sets default values for optional fields
- Includes KYC and bank details if provided
4. SDK Call
const result = await AirXPay.flixora.createMerchant(publicKey, {
...merchantData,
clientKey: AIRXPAY_CLIENT_KEY,
secretKey: AIRXPAY_SECRET_KEY,
});- Calls the SDK's
createMerchantmethod - Passes frontend public key and merchant data
- Adds backend keys (
clientKey,secretKey) for authentication - SDK internally calls company backend API
5. Response Handling
return res.status(200).json({
success: true,
message: "Merchant created successfully",
merchantId: result.merchant.merchantId,
airxpayMerchantId: result.merchant.airxpayMerchantId,
walletId: result.merchant.walletId,
status: result.merchant.status,
kycStatus: result.merchant.kycStatus,
isKycCompleted: result.merchant.isKycCompleted,
isBankDetailsCompleted: result.merchant.isBankDetailsCompleted,
mode: result.merchant.mode,
token: result.token,
});- Returns success response to frontend
- Includes all important merchant data:
merchantId: Your internal merchant IDairxpayMerchantId: AirXPay's system IDwalletId: Merchant's wallet IDstatus: Current merchant statuskycStatus: KYC verification statustoken: Auth token for future API calls
6. Error Handling
catch (error: any) {
return res.status(error.statusCode || 500).json({
success: false,
message: error.message || "Failed to create merchant",
error: error.data || null,
});
}- Catches any errors from SDK or backend
- Returns appropriate HTTP status code
- Sends error details to frontend
🎯 Alternative Usage Patterns
Pattern 1: Minimal Implementation
// If you only need basic merchant creation
export const quickCreateSeller = async (req: Request, res: Response) => {
try {
const { email, name, publicKey } = req.body;
const result = await AirXPay.flixora.createMerchant(publicKey, {
merchantName: name,
merchantEmail: email,
clientKey: process.env.AIRXPAY_CLIENT_KEY!,
secretKey: process.env.AIRXPAY_SECRET_KEY!,
});
res.json({ success: true, token: result.token });
} catch (error) {
res.status(500).json({ success: false, error: error.message });
}
};Pattern 2: With KYC Documents
// When frontend sends KYC documents
export const createSellerWithKYC = async (req: Request, res: Response) => {
try {
const { seller, publicKey, kycDocs } = req.body;
const result = await AirXPay.flixora.createMerchant(publicKey, {
merchantName: seller.name,
merchantEmail: seller.email,
merchantPhone: seller.phone,
kycDetails: {
panCardUrl: kycDocs.panCard,
aadhaarUrl: kycDocs.aadhaar,
selfieUrl: kycDocs.selfie,
},
clientKey: process.env.AIRXPAY_CLIENT_KEY!,
secretKey: process.env.AIRXPAY_SECRET_KEY!,
});
res.json({ success: true, data: result });
} catch (error) {
res.status(500).json({ success: false, error: error.message });
}
};Pattern 3: With Bank Details
// When frontend provides bank information
export const createSellerWithBank = async (req: Request, res: Response) => {
try {
const { seller, publicKey, bank } = req.body;
const result = await AirXPay.flixora.createMerchant(publicKey, {
merchantName: seller.name,
merchantEmail: seller.email,
bankDetails: {
accountHolderName: bank.holderName,
accountNumber: bank.accountNumber,
ifscCode: bank.ifsc,
upiId: bank.upi,
},
clientKey: process.env.AIRXPAY_CLIENT_KEY!,
secretKey: process.env.AIRXPAY_SECRET_KEY!,
});
res.json({ success: true, data: result });
} catch (error) {
res.status(500).json({ success: false, error: error.message });
}
};Pattern 4: NestJS Controller
// sellers.controller.ts
import { Controller, Post, Body } from '@nestjs/common';
import { AirXPay } from '@flixora/airxpay';
@Controller('sellers')
export class SellersController {
@Post('create')
async createSeller(@Body() body: any) {
try {
const { seller, publicKey } = body;
const result = await AirXPay.flixora.createMerchant(publicKey, {
merchantName: seller.name,
merchantEmail: seller.email,
clientKey: process.env.AIRXPAY_CLIENT_KEY!,
secretKey: process.env.AIRXPAY_SECRET_KEY!,
});
return { success: true, data: result };
} catch (error) {
throw new Error(`Failed to create seller: ${error.message}`);
}
}
}Pattern 5: Koa.js Middleware
// middleware/airxpay.ts
import { Context, Next } from 'koa';
import { AirXPay } from '@flixora/airxpay';
export const createSellerMiddleware = async (ctx: Context, next: Next) => {
try {
const { seller, publicKey } = ctx.request.body;
const result = await AirXPay.flixora.createMerchant(publicKey, {
merchantName: seller.name,
merchantEmail: seller.email,
clientKey: process.env.AIRXPAY_CLIENT_KEY!,
secretKey: process.env.AIRXPAY_SECRET_KEY!,
});
ctx.body = { success: true, data: result };
} catch (error) {
ctx.status = 500;
ctx.body = { success: false, error: error.message };
}
};📚 API Reference
AirXPay.flixora.createMerchant(publicKey, merchantData)
Creates a new merchant in the AirXPay system.
Parameters:
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| publicKey | string | ✅ | Frontend public key for authentication |
| merchantData | MerchantData | ✅ | Merchant details object |
MerchantData Object:
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| merchantName | string | ✅ | Full name of the merchant |
| merchantEmail | string | ✅ | Email address |
| merchantPhone | string | ❌ | Phone number (10-15 digits) |
| businessName | string | ❌ | Business/Store name |
| businessType | 'individual' \| 'company' | ❌ | Type of business |
| mode | 'test' \| 'live' | ❌ | Environment mode |
| kycDetails | KycDocuments | ❌ | KYC document URLs/info |
| bankDetails | BankDetails | ❌ | Bank account details |
| clientKey | string | ✅ | Your client key from env |
| secretKey | string | ✅ | Your secret key from env |
Returns: Promise<MerchantResponse>
AirXPay.flixora.getMerchantStatus(token)
Fetches the current status of a merchant.
Parameters:
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| token | string | ✅ | Token received from createMerchant |
Returns: Promise<MerchantData> - Clean merchant data object
🎯 Features
- ✅ Full TypeScript Support - Complete type definitions
- 🔐 Secure - Automatic token management and refresh
- 📡 Event Driven - Subscribe to SDK events
- ⚡ Performance Monitoring - Built-in execution time measurement
- 🛡️ Validation - Input validation for all operations
- 🔌 Plugin System - Extend functionality with custom plugins
- 🚀 Framework Agnostic - Works with Express, NestJS, Koa, Fastify
📡 Events
Subscribe to SDK events for real-time updates:
import { AirXPay } from '@flixora/airxpay';
// Listen for merchant creation
AirXPay.events.on('merchantCreated', (data) => {
console.log('New merchant created:', data);
});
// Listen for status fetches
AirXPay.events.on('merchantStatusFetched', (data) => {
console.log('Status fetched:', data);
});⚙️ Configuration
The SDK comes with default configuration:
{
baseURL: 'http://172.20.10.12:7000', // API base URL
autoRefreshToken: true // Auto-refresh auth tokens
}🛠️ Advanced Usage
With Performance Tracking
import { measureExecutionTime } from '@flixora/airxpay/performance';
const result = await measureExecutionTime(() =>
AirXPay.flixora.createMerchant(publicKey, merchantData)
);
// Output: "Execution time: 234 ms"Custom Validation
import { validateMerchantPhone } from '@flixora/airxpay/rules';
if (!validateMerchantPhone('9876543210')) {
throw new Error('Invalid phone number');
}📋 Types
import type {
MerchantData,
MerchantResponse,
KycStatus,
BankDetails
} from '@flixora/airxpay';
// Use types in your code
const merchant: MerchantData = {
merchantName: 'John Doe',
merchantEmail: '[email protected]',
// ...
};🔧 Error Handling
import { AirXPayError } from '@flixora/airxpay/errors';
try {
await AirXPay.flixora.createMerchant(publicKey, merchantData);
} catch (error) {
if (error instanceof AirXPayError) {
console.error(`SDK Error [${error.code}]:`, error.message);
} else {
console.error('Unexpected error:', error);
}
}📝 License
MIT © Flixora
🤝 Support
- 📧 Email: [email protected]
- 📚 Documentation: docs.flixora.com
- 🐛 Issues: GitHub Issues
🚦 Status
Made with ❤️ by Flixora Team
