Skip to content

Repository files navigation

react-klasha

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

npm license

Demo


⚠️ Version 0.0.x is completely non-functional — upgrade to 1.0.0

Two things were wrong with 0.0.x, and both are fatal:

  1. The script it loaded no longer exists. 0.0.x fetched https://klastatic.fra1.digitaloceanspaces.com/{test,prod}/js/klasha-integration.js. That bucket has been deleted; both URLs now return a 404. window.KlashaClient is therefore never defined and no payment can start at all. Klasha's current script is https://js.klasha.com/pay.js, which 1.0.0 loads.

  2. isTestMode was never sent to the gateway. The Klasha client takes the test flag as its 9th constructor argument; 0.0.x stopped at 8. Inside the Klasha script the flag then read as undefined, so the base URL, the iframe and the redirect URL all took the production branch. This matters now: the current pay.js serves one URL for both environments and decides which gateway to use from that argument alone, so repointing 0.0.x at the new script without adding it would route sandbox traffic to production. 1.0.0 passes it, coerced to a real boolean.

    To be clear about the past: while the old CDN still existed, 0.0.x picked /test/js/ or /prod/js/ correctly based on isTestMode, and that old script was environment-specific by URL. There is no reason to believe your historical sandbox payments went to production, and nothing to reconcile.

1.0.0 also fixes a silently dropped phone number, duplicate DOM ids, a load race that reported "ready" before the Klasha script had run, and console.log calls that printed your merchantKey to the browser console. 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-klasha
yarn add react-klasha

Quick start

import {KlashaButton} from 'react-klasha';

export default function Checkout() {
  return (
    <KlashaButton
      text="Make Payment"
      className="payButton"
      merchantKey="YOUR_MERCHANT_KEY"
      businessId="YOUR_BUSINESS_ID"
      amount={1000}
      sourceCurrency="USD"
      destinationCurrency="NGN"
      tx_ref={`tx-${Date.now()}`}
      fullname="John Doe"
      email="john@example.com"
      phone="+2348143108254"
      paymentDescription="Order #1234"
      isTestMode
      callBack={(response) => console.log('payment complete', response)}
    />
  );
}

isTestMode selects the environment

There is a single script — https://js.klasha.com/pay.js — for both test and live traffic. The environment is chosen entirely by isTestMode, which this library forwards as the 9th constructor argument:

isTestMode Gateway used
true Klasha test environment
false (default) Klasha live environment

Use your test merchant key with isTestMode, and your live key without it.

Usage

useKlashaPayment hook

import {useKlashaPayment} from 'react-klasha';

function DonateButton() {
  const config = {
    merchantKey: 'YOUR_MERCHANT_KEY',
    businessId: 'YOUR_BUSINESS_ID',
    amount: 1000,
    sourceCurrency: 'USD',
    destinationCurrency: 'NGN',
    tx_ref: `tx-${Date.now()}`,
    fullname: 'John Doe',
    email: 'john@example.com',
    phone: '+2348143108254',
    isTestMode: true,
  };

  const initializePayment = useKlashaPayment(config);
  const callBack = (response) => console.log('payment complete', response);

  return <button onClick={() => initializePayment(callBack)}>Donate</button>;
}

initializePayment throws if it is called before the Klasha script has loaded, or if the script failed to load. Gate your button on the script state:

import {useKlashaScript, useKlashaPayment} from 'react-klasha';

function PayButton({config, callBack}) {
  const [ready, failed] = useKlashaScript(config.isTestMode);
  const initializePayment = useKlashaPayment(config);

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

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

useKlashaScript returns [loaded, error]. loaded only turns true once pay.js itself has executed — never merely because a load was started.

KlashaConsumer render prop

import {KlashaConsumer} from 'react-klasha';

<KlashaConsumer {...config} callBack={callBack}>
  {({initializePayment}) => <button onClick={initializePayment}>Pay with Klasha</button>}
</KlashaConsumer>;

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

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

KlashaProvider

Wrap a subtree so nested components share one payment configuration. Nested components read initializePayment and callBack from context.

import {KlashaProvider} from 'react-klasha';

<KlashaProvider {...config} callBack={callBack}>
  <Checkout />
</KlashaProvider>;

API

Payment options

Accepted by useKlashaPayment, KlashaButton, KlashaConsumer and KlashaProvider.

Option Type Required Description
merchantKey string Merchant API key from the Klasha dashboard
businessId string | number Merchant business id
amount number Amount to charge
isTestMode boolean Use the Klasha test environment. Defaults to false
sourceCurrency string Currency the customer is charged in. Defaults to NGN
destinationCurrency string Currency the merchant is settled in. Defaults to NGN
tx_ref string Your unique transaction reference. Generated when omitted
fullname string Customer's full name
email string Customer's email
phone string Customer's phone number
phone_number string Deprecated alias of phone
callbackUrl string URL the gateway calls when the transaction completes
paymentDescription string Description of what is being paid for
metadata object Extra data to keep alongside the transaction
kit KlashaKitOptions Extra fields forwarded to the Klasha client
containerId string Render the checkout into a specific element. One is created per component when omitted

The kit object

kit is passed straight to the Klasha client. The keys pay.js actually reads are businessId, currency, redirect_url, email, phone, productType, amount, sourceAmount, callBack and tx_ref.

You rarely need to set any of them — this library fills in currency, email, fullname, phone, amount, tx_ref and callBack from the top-level options and builds a fresh kit for every payment (the Klasha script mutates the object it is given, so a shared one leaks state between transactions).

const config = {
  // …payment options…
  kit: {
    productType: 'digital',
    sourceAmount: 12,
  },
};

kit.phone is the key the gateway reads. 0.0.x set only kit.phone_number, which pay.js never looks at, so the customer's phone number was silently dropped from the exchange-rate request. 1.0.0 sets both.

KlashaButton 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'
callBack Function Called when the payment flow completes

Exports

import {
  useKlashaPayment,
  useKlashaScript,
  useKlashaContainer,
  KlashaButton,
  KlashaConsumer,
  KlashaProvider,
  ensureKlashaContainer,
  removeKlashaContainer,
  getKlashaScriptUrl,
  KLASHA_SDK_URL,
} from 'react-klasha';

TypeScript types KlashaOptionsProps, KlashaKitOptions, KlashaClientConstructor, KlashaClientInstance and KlashaRenderProps are exported too.

Migrating from 0.0.x

Change Impact
Loads https://js.klasha.com/pay.js The old CDN bucket was deleted and returns 404, so 0.0.x cannot start a payment at all.
isTestMode is forwarded to the gateway Test-mode integrations no longer hit the live environment. Use your test merchant key when isTestMode is set.
jQuery is no longer loaded pay.js does not need it. If you relied on this library to provide window.$, load jQuery yourself.
useKlashaScript reports loaded only once pay.js has executed It used to resolve on whichever of jQuery/Klasha loaded first, so loaded was frequently true while window.KlashaClient was undefined.
Script error no longer reports loaded: true useKlashaScript returns [false, true] on failure instead of [true, true].
initializePayment throws instead of silently doing nothing when the script is not ready Gate the call on useKlashaScript, or catch the error.
The checkout container has a unique per-component id The hardcoded <div id="ktest"> was appended on every effect run. Pass containerId if you need a specific element.
kit.phone is populated The phone number used to be dropped. kit.phone_number is still set for compatibility.
tx_ref is generated when omitted It is interpolated into the redirect URL and must not be empty.
console.log of the options (including merchantKey) removed Nothing is written to the console any more.
KlashaConsumer 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

Documentation

See the Klasha documentation for the full list of 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.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

Packages

Used by

Contributors

Languages