npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@fundly.ai/payment-sdk

v1.5.3

Published

Fundly Payment SDK for seamless integration with Fundly Pay systems.

Readme

Fundly Payment SDK

A comprehensive React-based payment SDK for integrating Fundly's payment capabilities into your applications. Supports multiple payment modes including UPI, QR codes, cash, cheque, and Fundly Pay.

📦 Installation

npm install @fundly.ai/payment-sdk

🚀 Quick Start

Basic Usage (React)

import { PaymentOptionPage, sdkConfig } from '@fundly.ai/payment-sdk';
import '@fundly.ai/payment-sdk/css';

function App() {
  // Configure SDK callbacks (optional but recommended)
  React.useEffect(() => {
    sdkConfig.configure({
      onNavigateHome: () => {
        console.log('User wants to go back');
        // Handle navigation in your app
      },
      onShareText: (text) => {
        console.log('Share text:', text);
        // Handle text sharing (e.g., payment link)
      },
      onShareImage: (base64Data, fileName, fileType) => {
        console.log('Share image:', fileName);
        // Handle image sharing (e.g., receipt)
      },
      onOpenCamera: async () => {
        // Return captured image as base64
        return { name: 'photo.jpg', type: 'image/jpeg', data: 'base64...' };
      },
      onOpenGallery: async () => {
        // Return selected image as base64
        return { name: 'image.jpg', type: 'image/jpeg', data: 'base64...' };
      }
    });
  }, []);

  return (
    <PaymentOptionPage
      config={{
        environment: "production", // "production", "preprod", or "uat" (default: "production")
        partnerCredentials: {
          username: "YOUR_USERNAME",
          password: "YOUR_PASSWORD"
        },
        distributorIdnum: "YOUR_DISTRIBUTOR_ID",
        chemistId: "YOUR_CHEMIST_ID", // Either chemistId or leadId is required
        // leadId: "YOUR_LEAD_ID", // Alternative to chemistId for lead-based payments
        typeOfApp: "FUNDLY_CUSTOMER_APP", // or "FUNDLY_COLLECT_APP"
        paymentInvoice: [
          { invoiceId: "INV001", paidAmount: 1000 }
        ],
        payableValue: "1000",
        paymentType: "INVOICE_COLLECT", // or "DIRECT_COLLECT"
      }}
      onPaymentCollected={(response) => {
        console.log('Payment successful!', response);
        // Handle successful payment
      }}
      onPaymentFailed={(response) => {
        console.log('Payment failed', response);
        // Handle failed payment
      }}
    />
  );
}

🌐 Embed Script (No React / No npm)

Use the embed script to integrate Fundly Pay into Angular, Vue, plain HTML, Flutter WebView, or Android WebView — no React dependency or build system required.

Load from CDN

<!-- CSS (required) -->
<link rel="stylesheet"
  href="https://cdn.jsdelivr.net/npm/@fundly.ai/[email protected]/dist/embed.css" />

<!-- JS (self-contained — React bundled in) -->
<script
  src="https://cdn.jsdelivr.net/npm/@fundly.ai/[email protected]/dist/embed.js"
  integrity="SHA384_HASH_FROM_RELEASE_NOTES"
  crossorigin="anonymous"
></script>

Always use the versioned URL in production. The latest alias (@latest) auto-updates and may introduce breaking changes.

Quick Start (Plain HTML)

<div id="fundly-root"></div>

<script>
  FundlySDK.mount('fundly-root', {
    flow: 'collection',                  // 'collection' | 'repayment' | 'transactions'
    config: {
      environment: 'production',
      partnerCredentials: { username: 'YOUR_USER', password: 'YOUR_PASS' },
      distributorIdnum: 'DIST_001',
      chemistId: 'CHEM_001',
      payableValue: '5000',
      paymentType: 'INVOICE_COLLECT',
      typeOfApp: 'WEB',
      paymentInvoice: [{ invoiceId: 'INV-001', paidAmount: 5000 }],
    },
    onPaymentCollected: function(response) {
      console.log('Payment success', response);
      FundlySDK.unmount('fundly-root');
    },
    onNavigateHome: function() {
      window.location.href = '/dashboard';
    },
  });
</script>

Embed API

| Method | Description | |---|---| | FundlySDK.mount(containerId, options) | Render SDK into a DOM element. If already mounted, replaces cleanly. | | FundlySDK.unmount(containerId) | Unmount React, free all event listeners. Call before navigating away. | | FundlySDK.version | Semver string of the loaded embed script. |

Platform Guides

See EMBED_INTEGRATION.md for full integration examples including:

  • Angular (script tag + ngOnInit/ngOnDestroy)
  • Vue 3 (onMounted/onBeforeUnmount)
  • Flutter InAppWebView (Dart bridge handlers)
  • Android WebView (Kotlin @JavascriptInterface)

🔧 Configuration

Payment Config

interface PartnerCredentials {
  username: string;               // Partner username
  password: string;               // Partner password
}

interface PaymentConfig {
  environment?: 'production' | 'preprod' | 'uat'; // Environment to use (default: "production")
  partnerCredentials: PartnerCredentials; // Required: Partner authentication credentials
  distributorIdnum: string;       // Required: Distributor business ID
  chemistId?: string;             // Optional: Chemist/Retailer business ID (either chemistId or leadId required)
  leadId?: string;                // Optional: Lead ID for lead-based payments (either chemistId or leadId required)
  typeOfApp: 'FUNDLY_CUSTOMER_APP' | 'FUNDLY_COLLECT_APP';
  paymentInvoice: Array<{
    invoiceId: string;
    paidAmount: number;
  }>;
  payableValue: string;           // Total amount as string
  paymentType: 'INVOICE_COLLECT' | 'DIRECT_COLLECT';
  salesmanId?: number;            // Optional: Salesman ID
  payerMobileNumber?: string;     // Optional: Payer mobile number
  redirectionUrl?: string;        // Optional: URL to redirect after UPI payment
  transactionId?: string;         // Optional: Transaction ID to display result
  showResultOnly?: boolean;       // Optional: Skip payment options, show result only
  successButtonText?: string;     // Optional: Button text on success drawer (default: "Home")
  failureButtonText?: string;     // Optional: Button text on failure drawer (default: "Go Back")
}

Payment Callbacks

The PaymentOptionPage component accepts optional callbacks to handle payment completion:

<PaymentOptionPage
  config={paymentConfig}
  onPaymentCollected={(response) => {
    // Called when payment is successful
    // Navigate to success page, show receipt, etc.
  }}
  onPaymentFailed={(response) => {
    // Called when payment fails
    // Transaction status: FAILED, CANCELLED, or DECLINED
    // Show error message, retry option, etc.
  }}
/>

Note: For DYNAMIC_QR, PAYMENT_LINK, and UPI payment modes, the SDK automatically polls the transaction status until the payment is completed or fails.


SDK Callbacks

Configure platform-specific behaviors using sdkConfig.configure():

import { sdkConfig } from '@fundly.ai/payment-sdk';

sdkConfig.configure({
  // Called when user wants to exit the SDK
  onNavigateHome: () => void;

  // Called when user wants to share text (payment link)
  onShareText: (text: string) => void;

  // Called when user wants to share image (receipt)
  onShareImage: (base64Data: string, fileName: string, fileType: string) => void;

  // Called when user wants to share image with byte data (Android WebView)
  onShareByteImage: (byteUrl: string, receiptText: string) => void;

  // Called when user wants to capture photo (cheque/cash proof)
  onOpenCamera: () => Promise<ImageFile | null>;

  // Called when user wants to select image from gallery
  onOpenGallery: () => Promise<ImageFile | null>;
});

ImageFile Interface:

interface ImageFile {
  name: string;    // File name
  type: string;    // MIME type (e.g., 'image/jpeg')
  data: string;    // Base64 encoded image data
}

🌍 Environment Configuration

The SDK supports three environments: production, preprod (pre-production), and uat (User Acceptance Testing).

Environment Options

Set the environment using the environment parameter in PaymentConfig:

| Environment | Description | Use Case | |------------|-------------|----------| | production | Production environment (default) | Live payments, production deployments | | preprod | Pre-production/staging | Testing before production release | | uat | User Acceptance Testing | QA and UAT testing |

Production Environment (Default)

By default, or when environment: "production", the SDK uses production URLs:

<PaymentOptionPage
  config={{
    environment: "production", // or omit this parameter for production
    partnerCredentials: {
      username: "YOUR_USERNAME",
      password: "YOUR_PASSWORD"
    },
    distributorIdnum: "YOUR_DISTRIBUTOR_ID",
    chemistId: "YOUR_CHEMIST_ID",
    // ... other config
  }}
/>

Pre-Production Environment

For staging and pre-production testing:

<PaymentOptionPage
  config={{
    environment: "preprod", // Pre-production environment
    partnerCredentials: {
      username: "YOUR_USERNAME",
      password: "YOUR_PASSWORD"
    },
    distributorIdnum: "YOUR_DISTRIBUTOR_ID",
    chemistId: "YOUR_CHEMIST_ID",
    // ... other config
  }}
/>

UAT Environment

For User Acceptance Testing:

<PaymentOptionPage
  config={{
    environment: "uat", // UAT environment
    partnerCredentials: {
      username: "YOUR_USERNAME",
      password: "YOUR_PASSWORD"
    },
    distributorIdnum: "YOUR_DISTRIBUTOR_ID",
    chemistId: "YOUR_CHEMIST_ID",
    // ... other config
  }}
/>

Example: Environment-based Configuration

// Automatically switch based on your app's environment
const getEnvironment = () => {
  switch (process.env.NODE_ENV) {
    case 'production':
      return 'production';
    case 'staging':
      return 'preprod';
    case 'test':
      return 'uat';
    default:
      return 'preprod';
  }
};

<PaymentOptionPage
  config={{
    environment: getEnvironment(),
    partnerCredentials: {
      username: process.env.PARTNER_USERNAME,
      password: process.env.PARTNER_PASSWORD
    },
    // ... other config
  }}
/>

Environment URLs

Each environment uses different API endpoints configured internally. The SDK automatically routes requests to the correct endpoints based on the environment parameter you provide.

Important Notes:

  • Always use uat or preprod environments during development and testing
  • Switch to production environment (default) for production deployments
  • The environment affects all API calls throughout the SDK
  • Use appropriate credentials for each environment
  • Contact Fundly support for environment-specific credentials and configurations

💳 Supported Payment Modes

The SDK automatically displays available payment options based on your configuration:

  1. Fundly Pay - One-click payment with credit line
  2. Generate QR - Dynamic UPI QR code generation for instant payments
  3. Payment Link - Generate and share payment links
  4. UPI - Direct UPI payment via payment gateway (supports all UPI apps)
  5. Scan QR - Scan distributor's static QR code
  6. Cash - Cash payment with OTP verification
  7. Cheque - Cheque payment with image upload and verification

UPI Payment Flow

The UPI payment mode provides a seamless payment experience:

  1. User selects UPI option - SDK displays UPI payment selection
  2. Redirect to payment gateway - User is redirected to a secure payment page
  3. Complete payment - User completes payment using any UPI app (Google Pay, PhonePe, Paytm, etc.)
  4. Automatic return - After payment, user is automatically redirected back to your app
  5. Status polling - SDK automatically polls for payment status and shows result

Key Features:

  • Automatic transaction status tracking
  • Supports all major UPI apps
  • Zero additional charges for UPI payments
  • Secure payment gateway integration

Display Payment Result Only

Sometimes you may want to show only the payment result (success/failure) without displaying payment options. This is useful when:

  • User returns from a payment gateway redirect
  • You want to display a transaction's current status
  • You're handling payment initiation separately

Use Case Example: User initiates UPI payment on /scan-qr page, gets redirected to payment gateway, completes payment, and returns to /scan-qr?orderId=PTXN123. Your app detects the orderId and opens the SDK to show only the result.

// Detect payment return in your app
useEffect(() => {
  const urlParams = new URLSearchParams(window.location.search);
  const orderIdFromUrl = urlParams.get("orderId") || urlParams.get("transactionId");

  if (orderIdFromUrl) {
    // User returned from payment gateway - show SDK with result only
    setShowPaymentSDK(true);
    setTransactionId(orderIdFromUrl);
  }
}, []);

// Render SDK in result-only mode
{showPaymentSDK && (
  <PaymentOptionPage
    config={{
      // ... your config
      transactionId: transactionId,        // Transaction ID to fetch
      showResultOnly: true,                // Skip payment options UI
      redirectionUrl: window.location.href // For consistency
    }}
    onPaymentCollected={(response) => {
      console.log('Payment successful!', response);
      // Handle success, navigate, etc.
    }}
    onPaymentFailed={(response) => {
      console.log('Payment failed', response);
      // Handle failure
    }}
  />
)}

How it works:

  1. SDK fetches transaction status using the provided transactionId
  2. If status is SUCCESS/COMPLETED → Shows success drawer and calls onPaymentCollected
  3. If status is FAILED/CANCELLED/DECLINED → Shows failure drawer and calls onPaymentFailed
  4. If status is still PENDING/PROCESSING → Shows UPI drawer with polling until completion

👤 Customer Types: Chemist vs Lead

The SDK supports two types of customers for payment collection:

Chemist-based Payments (Existing Customers)

For registered chemists/retailers with established accounts:

<PaymentOptionPage
  config={{
    partnerCredentials: { username: "...", password: "..." },
    distributorIdnum: "DIST123",
    chemistId: "CHEM456", // Use chemistId for registered customers
    typeOfApp: "FUNDLY_CUSTOMER_APP",
    // ... other config
  }}
/>

Lead-based Payments (New/Prospective Customers)

For leads or new customers who don't have a chemist account yet:

<PaymentOptionPage
  config={{
    partnerCredentials: { username: "...", password: "..." },
    distributorIdnum: "DIST123",
    leadId: "LEAD789", // Use leadId for leads/new customers
    typeOfApp: "FUNDLY_CUSTOMER_APP",
    // ... other config
  }}
/>

Important Notes:

  • You must provide either chemistId or leadId (not both)
  • If both are provided, chemistId takes precedence
  • Lead-based payments support the same payment modes as chemist-based payments
  • Analytics events are tracked with the appropriate customer identifier

🎨 UI Customization

Custom Button Text

You can customize the button text shown on success and failure drawers to better match your app's navigation behavior:

<PaymentOptionPage
  config={{
    // ... your config
    successButtonText: "Close",    // Custom text for success drawer button
    failureButtonText: "Close",    // Custom text for failure drawer button
  }}
/>

Common Use Cases:

1. Web Applications with Tab Closing

When your app opens the SDK in a new tab that should be closed after payment:

config={{
  successButtonText: "Close",
  failureButtonText: "Close",
}}

sdkConfig.configure({
  onNavigateHome: () => {
    window.close(); // Close the tab/window
  }
});

2. Single Page Applications (SPA)

When navigating back to a specific page in your app:

config={{
  successButtonText: "Back to Dashboard",
  failureButtonText: "Retry Payment",
}}

sdkConfig.configure({
  onNavigateHome: () => {
    navigate('/dashboard'); // Use your router
  }
});

3. Default Behavior

If you don't specify custom text, the defaults are used:

  • Success drawer: "Home"
  • Failure drawer: "Go Back"

🎨 Styling

Import the CSS file in your application:

import '@fundly.ai/payment-sdk/css';

The SDK uses Tailwind CSS internally and provides a clean, mobile-first UI.


🔐 Authentication & Security

Partner Credentials

The SDK requires partner credentials for authentication. Important security considerations:

import { PaymentOptionPage } from '@fundly.ai/payment-sdk';

<PaymentOptionPage
  config={{
    partnerCredentials: {
      username: process.env.PARTNER_USERNAME, // Use environment variables
      password: process.env.PARTNER_PASSWORD  // NEVER hardcode credentials
    },
    // ... other config
  }}
/>

Security Best Practices:

  • Never commit credentials to version control
  • Store credentials in environment variables or secure vaults
  • Use different credentials for sandbox and production environments
  • Rotate credentials periodically
  • Implement proper access controls in your application

Access Token (Optional)

You can also set a JWT token for additional authentication:

import { setAccessToken } from '@fundly.ai/payment-sdk';

// Set token before rendering PaymentOptionPage
setAccessToken('your-jwt-token');

📊 Analytics & Tracking

The SDK automatically tracks payment events using CleverTap analytics. No manual configuration needed - analytics is initialized automatically when you render the PaymentOptionPage component.

Automatic Analytics Initialization

When the SDK mounts, it automatically initializes analytics with the appropriate environment settings based on the environment parameter in your PaymentConfig.

Tracked Events (v2)

The SDK tracks exactly two events in the payment lifecycle:

1. Payment_SDK_Launched

Fires when the payment options screen fully loads.

Key fields included:

  • invoice_count, payment_amount, payment_type, partial_payment
  • supplier_id, supplier_name, user_type, user_uuid
  • session_id, platform, sdk_version, sdk_entry_point
  • is_payment_enabled, status
  • All 9 payment_option_* availability booleans
  • scan_channel, scan_origin, salesman_name
  • Carry-forward fields from upstream: view_id, scan_id, bill_id, bill_type, bill_status, bill_total_amount, outstanding_amount, notification_id, notification_channel (null for non-QR/non-notification flows)

2. Payment_Initiated

Fires when the user selects a payment method and proceeds.

Key fields included:

  • fundly_transaction_id, invoice_count, partial_payment
  • payment_amount, payment_type, payment_method, payment_mode
  • payment_channel, payment_gateway, otp_required, retry_count
  • supplier_id, supplier_name, user_type, user_uuid
  • session_id, platform, mobile_changed
  • FUNDLY_PAY loan fields where applicable

Note: Payment_Transaction is not fired by the SDK. It is owned by the backend.

Analytics Failures

All analytics calls are wrapped in try/catch. A tracking failure will never block or interrupt the payment flow.


📚 API Reference

Components

PaymentOptionPage

Main payment UI component with all payment options.

Props:

  • config: PaymentConfig - Payment configuration object

Utilities

sdkConfig.configure(callbacks: SDKCallbacks)

Configure platform-specific callbacks for SDK behavior.

setAccessToken(token: string)

Set authentication token for API calls.

getAccessToken(): string | null

Get current authentication token.


🛠️ Development

Building the SDK

npm run build          # Build React npm package + embed script
npm run build:embed    # Build embed script only (faster)

Testing

npm run test:embed     # Run Playwright integration tests for embed.js

Requires npm run build first to produce dist/embed.js.

SRI Hash (for release notes)

npm run sri            # Compute SHA-384 hash + print CDN URLs

Local Testing

# Link locally
npm link

# In your test project
npm link @fundly.ai/payment-sdk

Unlink

npm unlink @fundly.ai/payment-sdk

📝 TypeScript Support

The SDK is written in TypeScript and provides full type definitions. Import types:

import type {
  PaymentConfig,
  PartnerCredentials,
  PaymentInvoice,
  SDKCallbacks,
  ImageFile,
  Environment
} from '@fundly.ai/payment-sdk';

🐛 Troubleshooting

Payment options not showing

  • Verify authentication token is set
  • Check that typeOfApp matches your use case
  • Ensure paymentInvoice array is properly formatted

Camera/Gallery not working

  • Implement onOpenCamera and onOpenGallery callbacks
  • Return image data in the correct format (base64 string)

SDK not closing

  • Implement onNavigateHome callback
  • Handle navigation in your application's routing system

📄 License

MIT License © Fundly Developers


🤝 Support

For issues and questions: