vnpay Node.js Library

repository·main·Indexed 43 days ago

https://github.com/lehuygiang28/vnpay

An open-source Node.js library for integrating the VNPay payment gateway. Version 2.5.0 supports TypeScript, modular imports for reduced bundle size, and provides a simplified API for generating payment URLs, verifying return URLs, retrieving supported bank lists, and generating payment QR codes. Designed exclusively for Node.js backends (Node.js 18.0+).

Tokens
26.3K
Snippets
71
Records
100
Agent score
55%

What's inside vnpay

  1. Overview of the vnpay library

    main

    The vnpay library is an open-source project designed to facilitate easy and fast integration of the VNPay online payment gateway. It provides a simplified API for handling VNPay transactions and supports both sandbox and production environments.

    Key features include:

    • TypeScript Support: Full type definitions for enhanced developer experience.
    • Modular Imports (v2.4.0+): Allows importing specific modules to reduce bundle size by up to 80%.
    • Optimized Builds: Supports tree-shaking and code splitting.
    • Customizable Endpoints: Ability to configure endpoints for various VNPay services.
    • Minimal Dependencies: Only depends on dayjs for time processing.
  2. How to architect VNPay integration in Full-stack applications

    main

    The vnpay library is strictly for Node.js backend environments. It cannot be used directly in frontend frameworks (React, Vue, Angular) because it relies on Node.js-specific modules like fs, crypto, and path, and contains sensitive logic for secureSecret.

    To use VNPay correctly, you must implement a client-server pattern:

    1. Frontend: Handles UI and user interaction. It should only import types from the library. It communicates with your backend via API calls.
    2. Backend: A Node.js server that hosts the vnpay library. It handles payment URL generation, transaction verification, and IPN (Instant Payment Notification) processing.

    Data Flow:

    • Frontend $\rightarrow$ API Call $\rightarrow$ Backend (Generates Payment URL)
    • Backend $\rightarrow$ JSON Response $\rightarrow$ Frontend (Redirects user to VNPay)
    • VNPay $\rightarrow$ IPN Webhook $\rightarrow$ Backend (Updates database)
  3. Important: Backend vs Frontend usage

    main

    The vnpay library is designed for Node.js backends only. It relies on server-side modules like fs and crypto.

    • Backend (Node.js): Use standard imports (e.g., import { VNPay } from 'vnpay') for payment processing.
    • Frontend (React/Vue/Angular): DO NOT import the main library, as it will cause errors (e.g., Module not found: Can't resolve 'fs'). Instead, only import types using vnpay/types-only for type checking and call your backend APIs to handle payments.
  4. Use vnpay types in Frontend applications

    main

    ⚠️ IMPORTANT: Backend Only

    The vnpay library is designed exclusively for Node.js backends. It uses Node.js modules like fs, crypto, and path, which are not available in browsers. Do not import the main vnpay package into frontend code (React, Vue, Angular, etc.), as it will cause build errors.

    How to use in Frontend

    To maintain type safety in your frontend without breaking the build:

    1. Only import types: Use import type from vnpay/types-only or the main package.
    2. Call Backend APIs: Instead of running VNPay logic in the browser, call your own backend API to handle payment creation and redirection.
    // ✅ CORRECT: Only import types for type checking
    import type {
      VNPayConfig,
      BuildPaymentUrl,
      Bank,
      VerifyReturnUrl
    } from 'vnpay/types-only';
    
    // ✅ CORRECT: Call your backend API to get the payment URL
    const handleCreatePayment = async () => {
      const response = await fetch('/api/create-payment', {
        method: 'POST',
        body: JSON.stringify({ amount: 100000 }),
        headers: { 'Content-Type': 'application/json' }
      });
    
      const { paymentUrl } = await response.json();
      window.location.href = paymentUrl;
    };
  5. Generate a VNPay payment QR code

    main

    Use the generateQr method to request a QR code from VNPay. This method sends a signed GET request to the VNPay payment gateway with vnp_Command = genqr.

    Key behaviors:

    • Amount Handling: Unlike the raw VNPay specification which requires the amount to be multiplied by 100, this library accepts the "normal" amount (e.g., 10000) and automatically handles the multiplication for you.
    • Environment: This must be executed on a Server (requires secureSecret) in a Node.js environment that supports fetch (Node 18+).
    • Response: Returns a JSON object containing a status code, a message, and the qrcontent string used to render the QR code or initiate a deep-link.

    Important Note: For specific field lengths, error codes, and merchant conditions, always refer to the official "Merchant hosted QR" documentation provided by VNPay.

    import { ProductCode, VnpLocale, dateFormat } from 'vnpay';
    
    const start = new Date();
    const end = new Date(start.getTime() + 15 * 60 * 1000); // expires after 15 minutes
    
    const result = await vnpay.generateQr({
        vnp_Amount: 10000,
        vnp_IpAddr: '192.168.1.1',
        vnp_TxnRef: 'ORD-123456',
        vnp_OrderInfo: 'Thanh toan don hang ORD-123456',
        vnp_OrderType: ProductCode.Other,
        vnp_ReturnUrl: 'https://merchant.example.com/return',
        vnp_Locale: VnpLocale.VN,
        vnp_CreateDate: dateFormat(start),
        vnp_ExpireDate: dateFormat(end),
    });
    
    if (result.code === '00' && result.qrcontent) {
        // Use result.qrcontent to draw the QR code or use as a deep-link
    } else {
        // Handle error: result.qrcontent is typically empty when code is not '00'
    }
  6. Configure custom logging for payment URL generation

    main

    You can provide a logger object in the options argument of buildPaymentUrl to track the generation process.

    • Use type: 'all' to log everything.
    • Use type: 'pick' with a fields array to log only specific keys.
    • Use type: 'omit' to log everything except specific keys.
    • Provide a custom loggerFn to direct logs to your own systems (e.g., a database or external logging service).
    import { ProductCode, VnpLocale } from 'vnpay';
    
    const paymentUrl = vnpay.buildPaymentUrl(
        {
            vnp_Amount: 10000,
            vnp_IpAddr: '1.1.1.1',
            vnp_TxnRef: '123456',
            vnp_OrderInfo: 'Thanh toan don hang 123456',
            vnp_OrderType: ProductCode.Other,
            vnp_ReturnUrl: returnUrl,
        },
        {
            logger: {
                type: 'pick', // Modes: 'pick', 'omit', or 'all'
                fields: ['createdAt', 'method', 'paymentUrl'],
                loggerFn: (data) => logToDatabase(data), // Implement your own logging logic
            },
        },
    );
  7. Security best practices for VNPay integration

    main

    To ensure a secure integration, follow these security guidelines:

    • Protect your secureSecret: Never expose your secureSecret in client-side code. It must remain strictly on your server.
    • Validate Client IP: Always validate and audit the customer's IP address before sending requests to VNPay.
    • Verify Webhooks and Redirects: Always use the verifyIpnCall and verifyReturnUrl methods to verify the integrity of data received from VNPay.
    • Use IPN for Business Logic: Critical business operations (e.g., updating order status, completing orders) must be handled via the IPN (Instant Payment Notification) callback. The Return URL is primarily for UI feedback and can be bypassed by users.
    • Verify Transaction Amounts: Always verify that the amount returned by VNPay matches the expected amount stored in your database.
  8. Full-stack Project Examples

    main

    For complete reference implementations, check the following repositories:

    • Next.js 15 Full-stack Example: Uses Next.js 15 App Router, Server Actions, and API Routes. Features server-side integration and an IPN handler.
      • GitHub: lehuygiang28/vnpay-nextjs-fullstack-example
    • Express MVC Example: Uses Express, TypeScript, Bootstrap 5, and Handlebars.
      • GitHub: lehuygiang28/vnpay-mvc-example
  9. Error handling and transaction management

    main

    Error Handling

    • Use try-catch blocks: Wrap all VNPay API calls in try-catch blocks to handle potential errors gracefully.
    • Implement Logging: Enable logging to track API calls and facilitate debugging. Store logs for auditing and troubleshooting.
    • Handle Network Errors: Implement specific logic to handle network-related failures when calling VNPay APIs.

    Transaction Management

    • Unique Transaction References: Ensure every vnp_TxnRef is unique. A recommended pattern is combining an Order ID with a timestamp.
    • Store Transaction Details: Save all transaction details in your database for reconciliation and customer support.
    • Handle Duplicate IPN Notifications: VNPay may send the same IPN notification multiple times. Implement idempotent processing to ensure a transaction is not processed more than once.
  10. Enable logging for debugging

    main

    Use the built-in logging feature to capture detailed information about requests and responses. You can pass a loggerFn to the VNPay constructor to handle the log data.

    const vnpay = new VNPay({
        // ... other configuration
        enableLog: true,
        loggerFn: (data) => {
            console.log(JSON.stringify(data, null, 2));
            // Or save to a file/database
        },
    });