Catalog npm
PACKAGE EXPLORERView in registry

9japay-nestjs

npm

A comprehensive NestJS SDK for integrating with 9jaPay Virtual Account APIs

9japayapinestjspaymentssdkvirtual-accounts
Versions collected7
Direct dependencies14From release 1.1.0
Last observed20 Oct, 21:38 UTC

README

Current package documentation

9jaPay NestJS SDK

A comprehensive NestJS SDK for integrating with 9jaPay Virtual Account APIs. This SDK provides a type-safe, easy-to-use interface for all 9jaPay API endpoints including virtual account management, transfers, and transaction handling.

Features

  • 🚀 Full API Coverage: Complete implementation of all 9jaPay API endpoints
  • 🛡️ Type Safety: Full TypeScript support with comprehensive type definitions
  • 🏗️ NestJS Integration: Native NestJS module with dependency injection support
  • 🌍 Multi-Environment: Support for both sandbox and production environments
  • 📚 Well Documented: Comprehensive documentation and examples
  • ✅ Tested: Unit tests included
  • 🔧 Configurable: Flexible configuration options

Installation

npm install 9japay-nestjs
# or
yarn add 9japay-nestjs

Quick Start

1. Module Registration

import { Module } from '@nestjs/common';
import { NineJaPayModule } from '9japay-nestjs';

@Module({
  imports: [
    NineJaPayModule.register({
      apiKey: 'your-api-key',
      secretKey: 'your-secret-key',
      environment: 'sandbox', // or 'production'
    }),
  ],
})
export class AppModule {}

2. Async Configuration

import { Module } from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { NineJaPayModule } from '9japay-nestjs';

@Module({
  imports: [
    ConfigModule.forRoot(),
    NineJaPayModule.registerAsync({
      useFactory: (configService: ConfigService) => ({
        apiKey: configService.get('NINE_JA_PAY_API_KEY'),
        secretKey: configService.get('NINE_JA_PAY_SECRET_KEY'),
        environment: configService.get('NINE_JA_PAY_ENVIRONMENT'),
      }),
      inject: [ConfigService],
    }),
  ],
})
export class AppModule {}

3. Using the Service

import { Injectable } from '@nestjs/common';
import { NineJaPayService } from '9japay-nestjs';

@Injectable()
export class PaymentService {
  constructor(private readonly nineJaPayService: NineJaPayService) {}

  async createVirtualAccount(accountName: string) {
    const response = await this.nineJaPayService.createPermanentVirtualAccount({
      requestReference: `ref-${Date.now()}`,
      accountName,
      autoPayoutEnabled: true,
    });

    return response;
  }

  async makeTransfer(transferData: any) {
    // First, validate the recipient account
    const nameEnquiry = await this.nineJaPayService.nameEnquiry({
      bankCode: transferData.bankCode,
      accountNumber: transferData.accountNumber,
    });

    if (nameEnquiry.status === 'SUCCESS') {
      // Proceed with transfer
      const transfer = await this.nineJaPayService.transfer({
        paymentReference: `pay-${Date.now()}`,
        senderAccountNumber: transferData.senderAccountNumber,
        senderAccountName: transferData.senderAccountName,
        recipientAccountNumber: transferData.accountNumber,
        recipientAccountName: nameEnquiry.data.accountName,
        recipientBankCode: transferData.bankCode,
        amount: transferData.amount.toString(),
        nameEnquiryReference: nameEnquiry.data.nameEnquiryReference,
        narration: transferData.narration,
      });

      return transfer;
    }
  }
}

API Reference

Virtual Account Management

Permanent Virtual Accounts

// Create permanent virtual account
await nineJaPayService.createPermanentVirtualAccount({
  requestReference: 'unique-ref-123',
  accountName: 'John Doe Account',
  autoPayoutEnabled: true,
});

// Update permanent virtual account
await nineJaPayService.updatePermanentVirtualAccount('9000001234', {
  accountName: 'Updated Account Name',
  blockStatus: false,
  autoPayoutEnabled: false,
});

// Get single permanent virtual account
await nineJaPayService.getPermanentVirtualAccount('9000001234');

// Get all permanent virtual accounts
await nineJaPayService.getAllPermanentVirtualAccounts({
  pageSize: 10,
  pageNumber: 1,
});

// Close permanent virtual account
await nineJaPayService.closePermanentVirtualAccount({
  requestReference: 'close-ref-123',
  accountNumber: '9000001234',
  reasonForClosure: 'Account no longer needed',
});

Transient Virtual Accounts

// Create transient virtual account
await nineJaPayService.createTransientVirtualAccount({
  requestReference: 'temp-ref-123',
  timeToLive: '3600', // 1 hour in seconds
  amount: 100000, // Amount in kobo (optional)
  isSinglePayment: true,
});

// Update transient virtual account
await nineJaPayService.updateTransientVirtualAccount('9000001234', {
  blockStatus: false,
});

// Get single transient virtual account
await nineJaPayService.getTransientVirtualAccount('9000001234');

// Get all transient virtual accounts
await nineJaPayService.getAllTransientVirtualAccounts({
  pageSize: 10,
  pageNumber: 1,
});

General Virtual Account Operations

// Get all virtual accounts (both permanent and transient)
await nineJaPayService.getAllVirtualAccounts({
  pageSize: 20,
  pageNumber: 1,
});

// Get single virtual account (regardless of type)
await nineJaPayService.getVirtualAccount('9000001234');

// Get account balance
await nineJaPayService.getAccountBalance('9000001234');

// Get total balance summary
await nineJaPayService.getTotalBalanceSummary();

Transfers

// Get list of banks
const banks = await nineJaPayService.getBankList();

// Perform name enquiry
const nameEnquiry = await nineJaPayService.nameEnquiry({
  bankCode: '057',
  accountNumber: '1234567890',
});

// Transfer from regular account
await nineJaPayService.transfer({
  paymentReference: 'pay-ref-123',
  senderAccountNumber: '3000001234',
  senderAccountName: 'Sender Name',
  recipientAccountNumber: '1234567890',
  recipientAccountName: 'Recipient Name',
  recipientBankCode: '057',
  amount: '100000', // Amount in kobo
  nameEnquiryReference: nameEnquiry.data.nameEnquiryReference,
  narration: 'Payment for services',
});

// Transfer from virtual account
await nineJaPayService.transferFromVirtualAccount({
  // Same parameters as above
});

// Check transaction status
await nineJaPayService.getTransactionStatus('pay-ref-123');

Transactions

// Get transactions with filters
await nineJaPayService.getTransactions({
  pageSize: 10,
  pageNumber: 1,
  accountNumber: '9000001234', // optional
  startDate: '2024-01-01', // optional
  endDate: '2024-12-31', // optional
});

// Get single transaction by ID
await nineJaPayService.getTransactionById('transaction-id-123');

// Resend failed notification for a transaction
await nineJaPayService.resendNotification({
  transactionId: 'transaction-id-123',
});

// Resend all failed notifications for an account
await nineJaPayService.resendNotificationsForAccount({
  accountNumber: '9000001234',
});

// Resend all failed notifications
await nineJaPayService.resendAllNotifications();

// Simulate deposit (sandbox only)
await nineJaPayService.simulateDeposit({
  recipientAccountNumber: '9000001234',
  amount: '100000',
  authKey: 'test-auth-key',
});

Configuration Options

interface _9JaPayConfig {
  apiKey: string;           // Your 9jaPay API key
  secretKey: string;        // Your 9jaPay secret key
  environment: 'sandbox' | 'production'; // Environment
  baseUrl?: string;         // Optional custom base URL
  rejectUnauthorized?: boolean; // Optional: Set to false for local testing to ignore SSL cert errors (default: true)
}

Local Testing Configuration

For local testing environments where you might encounter SSL certificate issues, you can disable SSL verification:

NineJaPayModule.register({
  apiKey: 'your-api-key',
  secretKey: 'your-secret-key',
  environment: 'sandbox',
  rejectUnauthorized: false, // Disable SSL verification for local testing
})

⚠️ Security Warning: Only use rejectUnauthorized: false in development/testing environments. Never use this in production!

Environment URLs

  • Sandbox: https://test.developer.9japay.com/v1/api
  • Production: https://developer.9japay.com/v1/api

Error Handling

The SDK provides comprehensive error handling with two types of exceptions:

For 9jaPay API errors, the SDK throws NineJaPayException which properly maps 9jaPay status codes to HTTP status codes:

import { NineJaPayException } from '9japay-nestjs';

try {
  const result = await nineJaPayService.createPermanentVirtualAccount({
    requestReference: 'duplicate-ref',
    accountName: 'Test Account',
    autoPayoutEnabled: true,
  });
} catch (error) {
  if (error instanceof NineJaPayException) {
    console.log('9jaPay Status Code:', error.nineJaPayStatusCode); // "26"
    console.log('HTTP Status Code:', error.getStatus()); // 409
    console.log('Message:', error.message); // "Duplicate record found."
    console.log('Full Response:', error.nineJaPayResponse);
    
    // Handle specific 9jaPay errors
    switch (error.nineJaPayStatusCode) {
      case '26':
        // Handle duplicate record
        console.log('Duplicate record detected');
        break;
      case '25':
        // Handle no record found
        console.log('Record not found');
        break;
      case '09':
        // Handle validation error
        console.log('Validation failed');
        break;
      default:
        console.log('Other 9jaPay error');
    }
  }
}

2. Standard _9JaPayError

For network errors or other issues:

try {
  const result = await nineJaPayService.createPermanentVirtualAccount({
    requestReference: 'ref-123',
    accountName: 'Test Account',
    autoPayoutEnabled: true,
  });
} catch (error) {
  console.error('Error:', error.message);
  console.error('9jaPay Status Code:', error.nineJaPayStatusCode);
  console.error('HTTP Status Code:', error.httpStatusCode);
  console.error('Response:', error.response);
}

Error Response Structure

When using NineJaPayException, the error response structure is:

{
  statusCode: 409,              // HTTP status code (for proper REST API responses)
  message: "Duplicate record found.",
  nineJaPayStatusCode: "26",    // 9jaPay's business logic status code
  nineJaPayResponse: {          // Full 9jaPay response
    status: "FAILED",
    message: "Duplicate record found.",
    statusCode: "26"
  }
}

Response Codes

The SDK maps 9jaPay status codes to appropriate HTTP status codes:

9jaPay CodeDescriptionHTTP StatusHTTP Code
00SuccessOK200
01ProcessingAccepted202
06General errorInternal Server Error500
09Validation errorBad Request400
25No record foundNot Found404
26Duplicate recordConflict409

Status Code Usage

  • 9jaPay Code: Used for business logic and specific error handling
  • HTTP Status: Used for REST API responses and proper HTTP semantics
  • Both codes are available in the NineJaPayException for comprehensive error handling

Development

Building the Package

npm run build

Running Tests

npm test
npm run test:watch
npm run test:coverage

Linting

npm run lint
npm run lint:fix

Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Add tests
  5. Run the test suite
  6. Submit a pull request

License

This project is licensed under the MIT License - see the LICENSE file for details.

Support

For support and questions:

Changelog

v1.0.2

  • Enhanced Error Handling: Added NineJaPayException class with proper HTTP status code mapping
  • Fixed Status Code Conflict: Separated 9jaPay status codes from HTTP status codes to prevent ERR_HTTP_INVALID_STATUS_CODE
  • Improved Error Structure: Better error response format with both business logic and HTTP codes
  • Status Code Mapping: Automatic mapping of 9jaPay codes (e.g., "26") to appropriate HTTP codes (e.g., 409)

v1.0.1

  • Global Module: Made module global to resolve dependency injection issues
  • Fix: Service now available throughout application without additional imports

v1.0.0

  • Initial release
  • Complete API coverage
  • TypeScript support
  • NestJS integration
  • Unit tests
  • Comprehensive documentation

Downloads & popularity

Awaiting observations

No metric observations yet

Download counts and popularity will appear here as the collector receives them.

Versions 7

Collected releases
VersionPublishedDirect dependenciesOpen version
1.1.0Registry latest26 Nov 202514
1.0.526 Nov 202514
1.0.46 Sept 202514
1.0.36 Sept 202514
1.0.26 Sept 202514
1.0.16 Sept 202514
1.0.06 Sept 202514

Package advisories

0
No matching advisories collected

This describes our collected data; it is not a security assessment.

Repository

PENDING
evidenze/9japay-nestjs

Shared repository data · GitHub

License detected in repository
Not collected

Metadata history

Meaningful changes
Current collected state Current

Observed since 20 Oct, 21:38 UTC

No superseded metadata states collected. Unchanged observations do not create new revisions.

Record identity

package:ed0371bb2db1d1e166735f83370b1cc560a66d3a2590200ab0a0bd58cb536ea1