PayGate

React SDK

Official React SDK for PayGate - Accept Mobile Money payments in your React web application.

React SDK

The official React SDK for PayGate provides React components and hooks to easily integrate Mobile Money payments into your web application.

Requirements: React 16.8+ (hooks support). TypeScript is recommended.

Installation

npm install @paygate/react
yarn add @paygate/react
pnpm add @paygate/react

Quick Start

Wrap your app with PayGateProvider

import { PayGateProvider } from '@paygate/react'

function App() {
  return (
    <PayGateProvider publicKey="pk_test_your_public_key">
      <YourApp />
    </PayGateProvider>
  )
}

Create a checkout session on your server

// Server-side (Node.js)
import PayGate from '@paygate/node'

const paygate = new PayGate('sk_test_your_secret_key')

app.post('/create-checkout-session', async (req, res) => {
  const session = await paygate.checkoutSessions.create({
    amount: 100.00,
    currency: 'GHS',
    success_url: 'https://yoursite.com/success',
    cancel_url: 'https://yoursite.com/cancel',
  })

  res.json({ sessionId: session.id })
})

Use PayGateButton or usePayGate hook

import { PayGateButton } from '@paygate/react'

function Checkout() {
  const [sessionId, setSessionId] = useState(null)

  const createSession = async () => {
    const res = await fetch('/create-checkout-session', { method: 'POST' })
    const { sessionId } = await res.json()
    setSessionId(sessionId)
  }

  useEffect(() => {
    createSession()
  }, [])

  return (
    <PayGateButton
      sessionId={sessionId}
      onSuccess={(data) => {
        console.log('Payment successful!', data)
        // Redirect to success page
      }}
      onCancel={() => {
        console.log('Payment cancelled')
      }}
    >
      Pay GHS 100.00
    </PayGateButton>
  )
}

Components

PayGateProvider

Wrap your application with PayGateProvider to enable PayGate functionality.

<PayGateProvider
  publicKey="pk_test_xxx"
  baseUrl="https://paygate.com" // Optional, defaults to production
>
  {children}
</PayGateProvider>
PropTypeRequiredDescription
publicKeystringYesYour PayGate public key
baseUrlstringNoBase URL for checkout pages

PayGateButton

A pre-styled button that opens the checkout popup.

<PayGateButton
  sessionId="cs_xxx"
  onSuccess={(data) => console.log('Paid!', data)}
  onCancel={() => console.log('Cancelled')}
  onError={(error) => console.error(error)}
>
  Pay Now
</PayGateButton>
PropTypeDescription
sessionIdstringCheckout session ID
paymentLinkIdstringPayment link ID (alternative to sessionId)
amountnumberAmount for dynamic payment links
onSuccessfunctionCalled when payment succeeds
onCancelfunctionCalled when user cancels
onErrorfunctionCalled on error
classNamestringCustom CSS class
styleobjectCustom inline styles
disabledbooleanDisable the button
popupOptionsobjectPopup configuration

PayGateInline

Embed the checkout form directly in your page.

<PayGateInline
  sessionId="cs_xxx"
  height="600px"
  onSuccess={(data) => console.log('Paid!', data)}
  onCancel={() => console.log('Cancelled')}
/>
PropTypeDescription
sessionIdstringCheckout session ID
paymentLinkIdstringPayment link ID
heightstring/numberHeight of the iframe
onSuccessfunctionCalled when payment succeeds
onCancelfunctionCalled when user cancels
onErrorfunctionCalled on error
onLoadfunctionCalled when iframe loads

Hooks

usePayGate

Access PayGate SDK functionality programmatically.

import { usePayGate } from '@paygate/react'

function CustomCheckout() {
  const { openCheckout, openPaymentLink, closePopup, isOpen, isLoading } = usePayGate()

  const handlePay = async () => {
    // Get session from your server
    const { sessionId } = await createCheckoutSession()

    openCheckout(sessionId, {
      onSuccess: (data) => {
        console.log('Payment successful!', data)
      },
      onCancel: () => {
        console.log('Payment cancelled')
      },
      onError: (error) => {
        console.error('Payment error:', error)
      },
    })
  }

  return (
    <button onClick={handlePay} disabled={isOpen || isLoading}>
      {isLoading ? 'Loading...' : 'Pay Now'}
    </button>
  )
}
Return ValueTypeDescription
openCheckoutfunctionOpen checkout popup
openPaymentLinkfunctionOpen payment link popup
closePopupfunctionClose any open popup
isOpenbooleanWhether popup is open
isLoadingbooleanWhether SDK is loading
publicKeystringYour public key

useCheckoutSession

Fetch checkout session data.

import { useCheckoutSession } from '@paygate/react'

function SessionInfo({ sessionId }) {
  const { session, isLoading, error, refetch } = useCheckoutSession(sessionId)

  if (isLoading) return <div>Loading...</div>
  if (error) return <div>Error: {error.message}</div>

  return (
    <div>
      <p>Amount: {session.amount} {session.currency}</p>
      <p>Status: {session.status}</p>
    </div>
  )
}

You can also use payment links for simpler integrations:

// Using PayGateButton
<PayGateButton
  paymentLinkId="pl_xxx"
  amount={25.00}  // Optional: for dynamic amount links
  onSuccess={(data) => console.log('Paid!', data)}
>
  Donate GHS 25.00
</PayGateButton>

// Using the hook
const { openPaymentLink } = usePayGate()

openPaymentLink('pl_xxx', {
  amount: 25.00,
  email: 'customer@example.com',
  phone: '0241234567',
  onSuccess: (data) => console.log('Paid!', data),
})

Customize the checkout popup appearance:

<PayGateButton
  sessionId="cs_xxx"
  popupOptions={{
    position: 'center',        // 'center' | 'right'
    showBackdrop: true,
    closeOnBackdropClick: true,
    zIndex: 9999,
  }}
  onSuccess={(data) => console.log('Paid!')}
>
  Pay Now
</PayGateButton>

TypeScript

The SDK includes full TypeScript definitions:

import type {
  PayGateConfig,
  CheckoutOptions,
  PaymentLinkOptions,
  PaymentResult,
  PayGateError,
  CheckoutSession,
} from '@paygate/react'

Error Handling

<PayGateButton
  sessionId="cs_xxx"
  onError={(error) => {
    switch (error.type) {
      case 'validation_error':
        console.error('Invalid input:', error.message)
        break
      case 'payment_error':
        console.error('Payment failed:', error.message)
        break
      case 'network_error':
        console.error('Network issue:', error.message)
        break
      default:
        console.error('Unknown error:', error.message)
    }
  }}
>
  Pay Now
</PayGateButton>

Test Mode

Use test mode keys (pk_test_xxx) during development. In test mode, you can simulate different payment outcomes without processing real transactions.

<PayGateProvider publicKey="pk_test_xxx">
  {/* Test mode enabled */}
</PayGateProvider>

In test mode, the checkout page will show simulation controls to test success, failure, and cancellation flows.

Complete Example

import { PayGateProvider, PayGateButton, usePayGate } from '@paygate/react'
import { useState, useEffect } from 'react'

function App() {
  return (
    <PayGateProvider publicKey="pk_test_xxx">
      <Checkout />
    </PayGateProvider>
  )
}

function Checkout() {
  const [sessionId, setSessionId] = useState(null)
  const [loading, setLoading] = useState(true)

  useEffect(() => {
    fetch('/api/create-checkout-session', {
      method: 'POST',
      body: JSON.stringify({ amount: 100 }),
    })
      .then(res => res.json())
      .then(data => {
        setSessionId(data.sessionId)
        setLoading(false)
      })
  }, [])

  if (loading) return <div>Loading...</div>

  return (
    <div>
      <h1>Complete your purchase</h1>
      <PayGateButton
        sessionId={sessionId}
        onSuccess={(data) => {
          alert('Payment successful!')
          window.location.href = '/success'
        }}
        onCancel={() => {
          alert('Payment cancelled')
        }}
        onError={(error) => {
          alert(`Error: ${error.message}`)
        }}
      >
        Pay GHS 100.00
      </PayGateButton>
    </div>
  )
}

export default App