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

mainstack-external-payments

v0.0.7

Published

A React library for integrating Mainstack's external payment system into your applications. This library provides a wrapper around the Mainstack Payments library, making it easy to integrate payment functionality into external applications.

Downloads

11

Readme

Mainstack External Payments

A React library for integrating Mainstack's external payment system into your applications. This library provides a wrapper around the Mainstack Payments library, making it easy to integrate payment functionality into external applications.

Installation

Using npm or yarn

# Using npm
npm install mainstack-external-payments

# Using yarn
yarn add mainstack-external-payments

Using CDN

You can also use the library directly via CDN:

<!-- Load React and ReactDOM from CDN -->
<script crossorigin src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>

<!-- Load the Mainstack External Payments library -->
<script src="https://assets.mainstack.co/javascript/main/mainstack-external-payments.umd.js"></script>

Usage

Using npm or yarn

import { PaymentLibrary } from 'mainstack-external-payments';

function App() {
  const paymentConfig = {
    currency: "USD",
    amount: 10,
    productId: "YOUR_PRODUCT_ID",
    baseUrl: "https://api.mainstack.io",
    postPaymentRedirectUrl: "https://your-website.com/crypto-redirect",
    embedPaymentRedirectUrl: "https://your-website.com/payment-redirect",
    metadata: {
      mainstack_product_type: "store",
      product_id: "YOUR_PRODUCT_ID",
      type: "digital_product",
      quantity: 1,
      productName: "Your Product Name",
    },
    customizations: {
      theme_color: "#6A00FF",
      showDefaultInputFields: {
        phone: true,
      },
    },

    apiKey: "YOUR_API_KEY"
  };

  return (
    <PaymentLibrary
      paymentConfig={paymentConfig}
      onGoBack={() => console.log("Go back")}
      onPaymentComplete={(payload) => console.log("Payment Complete!", payload)}
    />
  );
}

Using CDN

<div id="payment-container"></div>

<script type="text/babel">
  // Access the PaymentLibrary component from the global MainstackExternalPayments object
  const { PaymentLibrary } = MainstackExternalPayments;

  // Payment configuration
  const paymentConfig = {
    currency: "USD",
    amount: 10,
    productId: "YOUR_PRODUCT_ID",
    baseUrl: "https://api.mainstack.io",
    postPaymentRedirectUrl: "https://your-website.com/crypto-redirect",
    embedPaymentRedirectUrl: "https://your-website.com/payment-redirect",
    metadata: {
      mainstack_product_type: "store",

      product_id: "YOUR_PRODUCT_ID",

      type: "digital_product",
      productName: "Your Product Name",
    },
    customizations: {
      theme_color: "#6A00FF",
      showDefaultInputFields: {
        phone: true,
      },
    },

    apiKey: "YOUR_API_KEY"
  };

  // Render the PaymentLibrary component
  const App = () => {
    return (
      <PaymentLibrary
        paymentConfig={paymentConfig}
        onGoBack={() => console.log("Go back")}
        onPaymentComplete={(payload) => console.log("Payment Complete!", payload)}
      />
    );
  };

  // Render the App component to the DOM
  ReactDOM.createRoot(document.getElementById('payment-container')).render(<App />);
</script>

API Reference

PaymentLibrary Props

| Prop | Type | Required | Description | |------|------|----------|-------------| | paymentConfig | object | Yes | Configuration for the payment (see details below) | | summaryTitle | string | ReactNode | No | Custom title for the payment summary section | | checkoutTitle | string | ReactNode | No | Custom title for the checkout page | | defaultFormValues | object | No | Default values for the payment form fields (fullname, email, phone) | | contactForm | ReactNode | No | Custom contact form component to replace the default form | | onGoBack | function | No | Callback when the user clicks the back button | | onInitializePayment | function | No | Callback when payment is initialized. It contains an argument that has the values for the default form inputs, and must return a promise that resolves an object with a terminate boolean property. The payment initialization will terminate immediately the promise resolves depending on what the value of terminate is. | | onPaymentComplete | function | Yes | Callback when payment is completed, receives payment result payload |

paymentConfig Object

The paymentConfig object requires the following properties:

| Property | Type | Required | Description | |----------|------|----------|-------------| | currency | string | Yes | The currency code (e.g., "USD", "NGN", "GBP") | | amount | number | Yes | The payment amount | | productId | string | Yes | The ID of the product being purchased | | baseUrl | string | Yes | The base URL for API requests (e.g., "https://api.mainstack.io") | | postPaymentRedirectUrl | string | No | URL to redirect after crypto/cashapp payments completion. Will need to handle success or failure based on query parameters attached to url | | embedPaymentRedirectUrl | string | Yes | URL to redirect after payment completion (see Payment Redirect Page section below) | | metadata | object | Yes | Additional information about the transaction (see below) | | customizations | object | No | UI customization options (see below) |

| apiKey | string | Yes | Your Mainstack API key | | discountAmount | number | No | Amount to discount from the total | | paymentOptions | array | No | Available payment methods (wallet, startbutton, stripe, paystack, crypto, cashapp) | | itemsList | array | No | List of items in the order (see TItemList below) | | isFreeTrial | boolean | No | Whether this is a free trial payment |

metadata Object

The metadata object requires the following properties:

| Property | Type | Required | Description | |----------|------|----------|-------------| | type | string | Yes | Type of product (e.g., "digital_product") | | product_id | string | Yes | The product ID (same as productId) | | mainstack_product_type | string | Yes | The Mainstack product type (store, editor, bookings, mediakit, invoicing, hosted_courses) | | productName | string | Yes | The name of the product |

Additional custom fields can be added to the metadata object as needed.

customizations Object

The customizations object allows you to customize the appearance of the payment form:

| Property | Type | Description | |----------|------|-------------| | theme_color | string | Primary color for buttons and UI elements (hex code) | | button_label | string | Custom label for the payment button | | back_button_label | string | Custom label for the back button | | font_family | string | Custom font family for the payment form | | hideDetails | boolean | Whether to hide payment details | | showDefaultInputFields | object | Configure which input fields to show (email, phone, fullname) | | hideBackButton | boolean | Whether to hide the back button | | padding | string | Custom padding for the payment form | | isSingleColumn | boolean | Whether to use a single column layout |

defaultFormValues Object

The defaultFormValues object allows you to pre-fill the payment form:

| Property | Type | Description | |----------|------|-------------| | fullname | string | Pre-filled full name | | email | string | Pre-filled email address | | phone | string | Pre-filled phone number |

itemsList Array

Each item in the itemsList array should have the following structure:

| Property | Type | Required | Description | |----------|------|----------|-------------| | name | string | Yes | Name of the item | | price | number | Yes | Price of the item | | currency | string | Yes | Currency code for the item | | quantity | number | Yes | Quantity of the item | | image | string | No | URL to the item's image |

Payment Redirect Page

The embedPaymentRedirectUrl should point to a page that handles the payment completion notification. This page should contain specific code to communicate the payment completion back to the parent window or application.

React Implementation

For React applications, your redirect page should look like this:

import { useEffect } from "react";

const PostMessagePage = () => {
  useEffect(() => {
    if (window.self !== window.top) {
      // If the page is in an iframe, send message to parent
      (() => {
        window.parent.postMessage({ type: "Payment Completed" }, "*");
      })();
    } else {
      // If the page is in a new tab/window
      (() => {
        const channel = new BroadcastChannel("app-channel");
        channel.postMessage({
          type: "Payment Completed",
          message: "Payment tab is closed",
        });
        window.close();
      })();
    }
  }, []);

  return <div></div>;
};

export default PostMessagePage;

HTML-only Implementation

For HTML-only applications, your redirect page should look like this:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Payment Redirect</title>
</head>
<body>
  <div id="payment-complete-message">Payment Completed</div>

  <script>
    // Execute when the page loads
    document.addEventListener('DOMContentLoaded', function() {
      if (window.self !== window.top) {
        // If the page is in an iframe, send message to parent
        window.parent.postMessage({ type: "Payment Completed" }, "*");
      } else {
        // If the page is in a new tab/window
         const channel = new BroadcastChannel("app-channel");
          channel.postMessage({
            type: "Payment Completed",
            message: "Payment tab is closed",
          });

          // Attempt to close the window
          window.close();
      }
    });
  </script>
</body>
</html>

Payment Flow

  1. The library first verifies the API configuration by making a request to ${baseUrl}/api/payment-config?product_id=${productId} with the provided API key.
  2. It fetches the user's IP information if not already stored in localStorage.
  3. It renders the payment form with the configured options.
  4. When User fills contact form, and call to action is clicked, the onInitializePayment function is called and payment can be terminated at this point.
  5. When the user completes the payment, they are redirected to the embedPaymentRedirectUrl or postPaymentRedirectUrl if the payment method requires it.
  6. The embedPaymentRedirectUrl page sends a message back to the parent application.
  7. The parent application receives the message and triggers the onPaymentComplete callback.
  8. If the paymentMethod uses postPaymentRedirectUrl the onPaymentComplete callback won't be called.
  9. If the amount for Purchase is 0 then onPaymentComplete is called immediately.

Supported Payment Methods

The Mainstack External Payments library supports the following payment methods:

  • wallet - Apple Pay and Google Pay Wallet
  • startbutton - Start Button payments (for KES and GHS)
  • stripe - Credit/Debit Cards (via Stripe)
  • paystack - Paystack payments (for NGN)
  • crypto - Cryptocurrency payments (only supports USD)
  • cashapp - Cash App payments (only supports USD)

The available payment methods are determined by the account settings and can be further restricted using the paymentOptions array.

Error Handling

The library provides built-in error handling for common payment issues. If an error occurs during the API configuration verification, an error message will be displayed to the user.

Development

# Install dependencies
yarn install

# Start development server
yarn dev

# Build for production
yarn build

# Test CDN build
yarn test-cdn

License

MIT