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

portalpay

v1.0.1

Published

Universal browser-based payment SDK for embedding card and mobile money payments. Zero-dependency IIFE bundle that works with any website, CMS, or framework. Supports multiple payment providers including AlexPay, Vesicash, and Portal.

Readme

PortalPay

npm version License: MIT CDN

Complete browser-based payment SDK for PortalPay. Zero-dependency IIFE bundle that works with any website or CMS.

Overview

portalpay is the standalone browser bundle of the PortalPay SDK. It provides a complete payment solution that:

  • 💳 Supports Multiple Payment Methods - Cards, Mobile Money
  • 🔒 Built-in Security - Tamper detection and fraud prevention
  • 🎨 Customizable - Style buttons to match your brand
  • 🌐 Universal - Works with any website, CMS, or framework
  • 📱 Mobile-First - Optimized for mobile payments
  • 🧪 Mock Mode - Test without real transactions

Quick Start

CDN (Recommended)

Add to your HTML <head>:

<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/portalpay.js"></script>

npm

npm install portalpay
# or
yarn add portalpay
# or
pnpm add portalpay

Basic Usage

1. Add the Script

<!DOCTYPE html>
<html>
<head>
  <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/portalpay.js"></script>
</head>
<body>
  <!-- Your content -->
</body>
</html>

2. Configure the SDK

<script>
  // Global configuration (set before the SDK loads)
  window.PORTALPAY = {
    publishableKey: 'pk_live_alexpay_xxxxxxxx',
    currency: 'GHS',
    narration: 'Order Payment',
    callback: 'https://yoursite.com/success',
    cancel: 'https://yoursite.com/cancel'
  };
</script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/portalpay.js"></script>

3. Add Payment Button

<!-- Fixed amount -->
<button data-checkout data-amount="5000">
  Pay GHS 50.00
</button>

<!-- Or read amount from page element -->
<span id="total">7500</span>
<button data-checkout data-amount-from="#total">
  Checkout
</button>

<!-- Or use JavaScript variable -->
<script>
  window.cartTotal = 10000;
</script>
<button data-checkout data-amount-var="cartTotal">
  Pay Now
</button>

Configuration Options

Global Configuration (window.EMBEDPAY)

| Option | Type | Required | Description | |--------|------|----------|-------------| | publishableKey | string | ✅ | Your publishable key from payment provider | | currency | string | ❌ | Currency code (GHS, NGN, USD, KES, ZAR) | | method | string | ❌ | Payment method: 'card' or 'mobile-money' | | narration | string | ❌ | Default payment description | | callback | string | ❌ | Success redirect URL | | cancel | string | ❌ | Cancel redirect URL | | forceMock | boolean | ❌ | Enable test mode (default: false) | | checkoutUrl | string | ❌ | Custom checkout page URL (for mock mode) |

Button Attributes

| Attribute | Description | Example | |-----------|-------------|---------| | data-checkout | Marks button as checkout trigger | <button data-checkout> | | data-amount | Fixed payment amount | data-amount="5000" | | data-amount-from | CSS selector for amount element | data-amount-from="#total" | | data-amount-var | JavaScript variable name | data-amount-var="cartTotal" | | data-currency | Override currency | data-currency="USD" | | data-narration | Override description | data-narration="Product #123" | | data-publishable-key | Use different publishable key | data-publishable-key="pk_test_..." | | data-force-mock | Enable mock mode per button | data-force-mock="true" |

Advanced Usage

WooCommerce Integration

<script>
  window.PORTALPAY = {
    publishableKey: 'pk_live_alexpay_xxxxxxxx',
    currency: 'GHS',
    narration: 'WooCommerce Order',
    amountVar: 'PORTALPAY_CART_TOTAL'  // Auto-sync with cart
  };
</script>

Custom Styling

/* Base button styles */
.portalpay-btn {
  background: #1a1714;
  color: #f5f2ee;
  padding: 12px 24px;
  border: none;
  border-radius: 8px;
  font-size: 16px;
  cursor: pointer;
  transition: background 0.15s;
}

.portalpay-btn:hover {
  background: #2d2926;
}

.portalpay-btn:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}

Event Handling

// SDK exposes PortalPay object globally
document.addEventListener('DOMContentLoaded', function() {
  // Refresh button bindings (if dynamically adding buttons)
  if (window.PortalPay) {
    window.PortalPay.refresh();
  }
});

Mock Mode (Testing)

Enable test mode to simulate payments without real transactions:

<script>
  window.PORTALPAY = {
    publishableKey: 'pk_test_alexpay_xxxxxxxx',
    forceMock: true,
    checkoutUrl: 'https://yoursite.com/checkout.html'
  };
</script>

Test Cards:

  • Success: 4084 0841 2345 6789, Exp: 12/28, CVV: 123
  • Declined: 4000 0000 0000 0002, Exp: 12/28, CVV: 456

Test Mobile Money:

  • Success: 0244 123 456, Network: MTN
  • Declined: 0244 000 000, Network: MTN

Security Features

Tamper Detection

The SDK automatically monitors for:

  • 🖥️ DevTools Detection - Blocks payments if developer tools are open
  • 📐 Window Resize - Detects suspicious window resizing
  • 💰 Amount Changes - Validates amount hasn't been manipulated

Domain Authorization

Your publishable key is restricted to specific domains. Configure allowed domains in your merchant dashboard.

CMS Integrations

WordPress

Install the PortalPay WordPress Plugin for easy integration.

// Shortcode
[portalpay_button amount="5000"]Pay Now[/portalpay_button]

// With dynamic amount
[portalpay_button amount_from="#total"]Checkout[/portalpay_button]

Shopify

Add to your theme's checkout page:

<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/portalpay.js"></script>
<script>
  window.PORTALPAY = {
    publishableKey: 'pk_live_alexpay_xxxxxxxx',
    currency: '{{ shop.currency }}',
    narration: 'Order {{ order.name }}'
  };
</script>

Browser Support

  • ✅ Chrome 80+
  • ✅ Firefox 75+
  • ✅ Safari 13+
  • ✅ Edge 80+
  • ✅ iOS Safari 13+
  • ✅ Chrome Android 80+

File Size

  • Gzipped: ~4.2 KB
  • Minified: ~10 KB

Troubleshooting

"Payment service not authorized for this site"

Your domain is not authorized. Add your domain in the merchant dashboard.

"Invalid payment key"

Check that your publishable key is correct and matches the format: pk_live_alexpay_xxxxxxxx

"Payment amount is missing or zero"

Ensure the amount element exists and contains a valid number:

<span id="total">5000</span>  <!-- Must be just the number -->

"Initialising payment service…"

The SDK is still fetching configuration. Wait a moment and try again.

API Reference

The browser bundle exposes a global PortalPay object:

interface PortalPaySDK {
  refresh(): void;  // Re-scan for buttons and bind events
}

Related Packages

License

MIT © Vesicash

Support

  • 📧 Email: [email protected]
  • 🌐 Website: https://vesicash.com/portalpay
  • 📖 Documentation: https://docs.vesicash.com/portalpay

Accept payments anywhere with PortalPay 🚀