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-paymentsUsing 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
- The library first verifies the API configuration by making a request to
${baseUrl}/api/payment-config?product_id=${productId}with the provided API key. - It fetches the user's IP information if not already stored in localStorage.
- It renders the payment form with the configured options.
- When User fills contact form, and call to action is clicked, the onInitializePayment function is called and payment can be terminated at this point.
- When the user completes the payment, they are redirected to the
embedPaymentRedirectUrlorpostPaymentRedirectUrlif the payment method requires it. - The
embedPaymentRedirectUrlpage sends a message back to the parent application. - The parent application receives the message and triggers the
onPaymentCompletecallback. - If the paymentMethod uses
postPaymentRedirectUrltheonPaymentCompletecallback won't be called. - If the amount for Purchase is 0 then
onPaymentCompleteis 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-cdnLicense
MIT
