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

react-monnify

v1.0.0

Published

React hooks and components for accepting payments with the Monnify payment gateway

Downloads

571

Readme

react-monnify

React hooks and components for accepting payments with the Monnify payment gateway.

npm license

Monnify checkout: bank transfer, card and success states


⚠️ Upgrading from 0.0.x — read this

0.0.x had a bug where the isTestMode check in useMonnifyScript had identical URLs in both branches, so the sandbox URL was requested regardless of the flag.

In practice this had no runtime effect: sandbox.sdk.monnify.com/plugin/monnify.js and sdk.monnify.com/plugin/monnify.js are byte-for-byte the same file, and the SDK picks its environment from your API key prefix (MK_PROD_), not from the script host. Live payments were not being routed to sandbox. The fix is still worth taking — relying on two URLs staying identical is fragile — but you do not have a historical incident to investigate.

The changes most likely to affect you are the React peer range, initializePayment now throwing instead of silently doing nothing, and the new build output. See Migrating from 0.0.x.


Requirements

  • React 16.8 or later (17, 18 and 19 are supported)
  • Node 18+ to build from source

0.0.x declared support for React 15, but the library is built on hooks and has never worked below 16.8.

Install

npm install react-monnify
yarn add react-monnify

Quick start

import {MonnifyButton} from 'react-monnify';

export default function Checkout() {
  return (
    <MonnifyButton
      text="Make Payment"
      className="payButton"
      apiKey="MK_TEST_SAF7HR5F3F"
      contractCode="4934121693"
      amount={5000}
      currency="NGN"
      reference={`ref-${Date.now()}`}
      customerFullName="John Doe"
      customerEmail="[email protected]"
      customerMobileNumber="08121281921"
      paymentDescription="Test Pay"
      isTestMode
      onSuccess={(response) => console.log('paid', response)}
      onClose={(response) => console.log('closed', response)}
    />
  );
}

isTestMode controls which SDK is loaded

| isTestMode | Script loaded | | --- | --- | | true | https://sandbox.sdk.monnify.com/plugin/monnify.js | | false (default) | https://sdk.monnify.com/plugin/monnify.js |

Use your test API key with isTestMode, and your live key without it. Passing a live key while isTestMode is set will fail.

Usage

useMonnifyPayment hook

import {useMonnifyPayment} from 'react-monnify';

function DonateButton() {
  const config = {
    apiKey: 'MK_TEST_SAF7HR5F3F',
    contractCode: '4934121693',
    amount: 5000,
    currency: 'NGN',
    reference: `ref-${Date.now()}`,
    customerFullName: 'John Doe',
    customerEmail: '[email protected]',
    customerMobileNumber: '08121281921',
    isTestMode: true,
  };

  const initializePayment = useMonnifyPayment(config);

  return (
    <button onClick={() => initializePayment(onSuccess, onClose)}>
      Donate
    </button>
  );
}

initializePayment throws if it is called before the Monnify script has loaded, or if the script failed to load. To avoid that, gate your button on the script state:

import {useMonnifyScript, useMonnifyPayment} from 'react-monnify';

function PayButton(config) {
  const [ready, failed] = useMonnifyScript(config.isTestMode);
  const initializePayment = useMonnifyPayment(config);

  if (failed) return <p>Payment is unavailable right now.</p>;

  return (
    <button disabled={!ready} onClick={() => initializePayment(onSuccess, onClose)}>
      {ready ? 'Pay' : 'Loading…'}
    </button>
  );
}

MonnifyConsumer render prop

import {MonnifyConsumer} from 'react-monnify';

<MonnifyConsumer {...config} onSuccess={onSuccess} onClose={onClose}>
  {({initializePayment}) => (
    <button onClick={initializePayment}>Pay with Monnify</button>
  )}
</MonnifyConsumer>;

MonnifyConsumer forwards refs. The ref is handed to the render prop:

<MonnifyConsumer {...config} ref={myRef}>
  {({initializePayment, ref}) => (
    <button ref={ref} onClick={initializePayment}>Pay</button>
  )}
</MonnifyConsumer>

MonnifyProvider

Wrap a subtree so nested components share one payment configuration.

import {MonnifyProvider} from 'react-monnify';

<MonnifyProvider {...config} onSuccess={onSuccess} onClose={onClose}>
  <Checkout />
</MonnifyProvider>;

API

Payment options

Accepted by useMonnifyPayment, MonnifyButton, MonnifyConsumer and MonnifyProvider.

| Option | Type | Required | Description | | --- | --- | --- | --- | | apiKey | string | ✅ | Merchant API key from the Monnify dashboard | | contractCode | string | ✅ | Merchant contract code | | amount | number | ✅ | Amount to charge | | reference | string | ✅ | Your unique reference for this transaction | | currency | string | ✅ | Defaults to NGN | | customerFullName | string | ✅ | Customer's full name | | customerEmail | string | ✅ | Customer's email | | customerMobileNumber | string | ✅ | Customer's phone number | | isTestMode | boolean | | Load the sandbox SDK. Defaults to false | | paymentDescription | string | | Used as the account name for bank-transfer payments | | redirectUrl | string | | Where to send the customer after payment | | metadata | object | | Extra data passed through to the API | | incomeSplitConfig | MonnifySplitOptions[] | | Split-payment configuration | | transactionHash | object | | Transaction hash, for response verification |

MonnifyButton props

Everything above, plus:

| Prop | Type | Description | | --- | --- | --- | | text | string | Button label | | children | ReactNode | Used when text is absent | | className | string | CSS class | | disabled | boolean | Disable the button | | type | 'button', 'submit' or 'reset' | Defaults to 'button' | | onSuccess | Function | Called on completion | | onClose | Function | Called when the modal closes |

Exports

import {
  useMonnifyPayment,
  useMonnifyScript,
  MonnifyButton,
  MonnifyConsumer,
  MonnifyProvider,
  getMonnifyScriptUrl,
  MONNIFY_SANDBOX_SDK_URL,
  MONNIFY_PRODUCTION_SDK_URL,
} from 'react-monnify';

TypeScript types MonnifyProps, MonnifySplitOptions, MonnifySDK and MonnifyRenderProps are exported too.

Migrating from 0.0.x

| Change | Impact | | --- | --- | | The correct host is now requested per isTestMode | No behavioural change — both hosts serve the same file (see above). Cosmetic in the Network tab. | | customerName is now sent to Monnify | The SDK builds its transaction payload from customerName, but the library only ever set customerFullName, so the customer's name never reached Monnify. It does now. | | initializePayment throws instead of silently doing nothing when the script is not ready | Gate the call on useMonnifyScript, or catch the error. | | Script error no longer reports loaded: true | useMonnifyScript returns [false, true] on failure instead of [true, true]. | | MonnifyConsumer ref actually reaches the render prop | It was always undefined before. | | Peer range is now react@^16.8 || ^17 || ^18 || ^19 | React 15 was never actually supported. | | react-dom peer dependency removed | The library never imported it. | | Build output is dist/index.cjs + dist/index.mjs with an exports map | Deep imports into dist/ are no longer supported. |

Development

npm install
npm run typecheck
npm test
npm run build

Running the example app

npm run build                 # the example consumes the built library
cd example
cp .env.example .env          # add your sandbox API key + contract code
npm install
npm run dev                   # http://localhost:3000

Monnify's current public sandbox credentials are on the developer docs. Note that the demo key and contract code printed in this README before v1.0.0 have been retired — Monnify's API now answers Could not find specified contract for them.

Only the API key and contract code belong in a frontend integration. Never put your Secret Key in browser code — anything in a VITE_-prefixed variable is compiled into the public bundle. The Secret Key is for server-to-server calls such as verifying a transaction.

Each payment attempt needs a fresh reference; Monnify rejects one it has already seen. The example regenerates it per attempt.

Documentation

See the Monnify developer documentation for the full list of SDK options and for how to verify a transaction server-side.

Always verify a payment on your server before fulfilling an order. Never trust the browser callback alone.

Contributing

  1. Fork it
  2. Create your feature branch: git checkout -b feature-name
  3. Commit your changes: git commit -am 'Some commit message'
  4. Push to the branch: git push origin feature-name
  5. Submit a pull request 😉

How can I thank you?

Star the repo, and share it! Don't forget to follow me on twitter.

Thanks! Adekanbi Dansteve.

License

MIT — see LICENSE.md.