Vue SDK

npm version GitHub Vue 3 SDK for integrating Reevit unified payments with Composition API support.

Installation

npm install @reevit/vue @reevit/core

Quick Start

The simplest way to integrate Reevit is using the ReevitCheckout component.
<script setup lang="ts">
import { ReevitCheckout } from '@reevit/vue';
import '@reevit/vue/styles.css';

const handleSuccess = (result: any) => {
  console.log('Payment success!', result);
};

const handleError = (error: any) => {
  console.error('Payment failed:', error);
};
</script>

<template>
  <ReevitCheckout
    publicKey="pfk_test_xxx.secret"
    :amount="10000"
    currency="GHS"
    email="customer@example.com"
    reference="ORD-12345"
    @success="handleSuccess"
    @error="handleError"
  >
    <template #default="{ open, isLoading }">
      <button 
        class="my-pay-button" 
        :disabled="isLoading" 
        @click="open"
      >
        {{ isLoading ? 'Loading...' : 'Pay GHS 100.00' }}
      </button>
    </template>
  </ReevitCheckout>
</template>

Props Reference

PropTypeRequiredDescription
publicKeystringYour project’s public key
amountnumberAmount in smallest unit
currencystring3-letter currency code
emailstringCustomer’s email
phonestringCustomer’s phone number
referencestringYour transaction reference
metadataobjectOptional key-value pairs for your own tracking
paymentMethodsstring[]Enabled payment methods
themeReevitThemeCustomization options
isOpenbooleanControl modal visibility manually
initialPaymentIntentPaymentIntentPre-created intent for controlled mode
apiBaseUrlstringCustom API URL

Events

EventPayloadDescription
@successPaymentResultCalled on successful payment
@errorPaymentErrorCalled on error
@closevoidCalled when widget is closed

Theming

<ReevitCheckout
  :theme="{
    primaryColor: '#00D1B2',
    backgroundColor: '#FFFFFF',
    darkMode: false,
    borderRadius: '4px'
  }"
  publicKey="pfk_test_xxx.secret"
  :amount="5000"
  currency="GHS"
>
  <button>Pay Now</button>
</ReevitCheckout>

Controlled Mode

If you prefer to create the payment intent on your backend before opening the checkout, you can use Controlled Mode.
<template>
  <ReevitCheckout
    publicKey="pfk_test_xxx.secret"
    :initialPaymentIntent="myPreCreatedIntent"
    @success="handleSuccess"
  >
    <template #default="{ open }">
      <button @click="open">Open Pre-paid Checkout</button>
    </template>
  </ReevitCheckout>
</template>
In this mode, the SDK skips the initial intent creation step and proceeds directly to payment method selection or provider confirmation.
For full control over the payment flow, use the useReevit composable.
<script setup lang="ts">
import { useReevit } from '@reevit/vue';

const { 
  status, 
  paymentIntent,
  error,
  initialize, 
  selectMethod,
  processPayment,
  reset,
  isLoading 
} = useReevit({
  config: {
    publicKey: 'pfk_test_xxx.secret',
    amount: 5000,
    currency: 'GHS',
    email: 'customer@example.com',
  },
  apiBaseUrl: 'http://localhost:8080',
  onSuccess: (res) => console.log('Payment done!', res),
  onError: (err) => console.error('Payment failed:', err),
});
</script>

<template>
  <div>
    <button v-if="status === 'idle'" @click="initialize">
      Start Payment
    </button>
    
    <div v-if="status === 'ready'">
      <h3>Select Payment Method</h3>
      <button @click="selectMethod('card')">💳 Card</button>
      <button @click="selectMethod('mobile_money')">📱 Mobile Money</button>
    </div>
    
    <div v-if="status === 'success'">
      ✅ Payment successful!
    </div>
    
    <div v-if="error" class="error">
      {{ error.message }}
      <button @click="reset">Try Again</button>
    </div>
  </div>
</template>

PSP Bridge Functions

For advanced use cases, use PSP bridge functions directly.

Stripe

import { createStripeInstance, confirmStripePayment } from '@reevit/vue';

// Create Stripe instance
const stripe = await createStripeInstance('pfk_test_xxx.secret');
const elements = stripe.elements({ clientSecret: 'pi_xxx_secret_xxx' });
const paymentElement = elements.create('payment');
paymentElement.mount('#payment-element');

// Later, confirm the payment
await confirmStripePayment({
  publishableKey: 'pfk_test_xxx.secret',
  clientSecret: 'pi_xxx_secret_xxx',
  elements,
  onSuccess: (result) => console.log('Paid:', result.paymentIntentId),
  onError: (err) => console.error(err.message),
});

Monnify (Nigeria)

import { openMonnifyModal } from '@reevit/vue';

await openMonnifyModal({
  apiKey: 'MK_TEST_xxx',
  contractCode: '1234567890',
  amount: 5000,
  currency: 'NGN',
  reference: 'TXN_12345',
  customerName: 'John Doe',
  customerEmail: 'john@example.com',
  onSuccess: (result) => console.log('Paid:', result.transactionReference),
  onClose: () => console.log('Closed'),
});

M-Pesa (Kenya/Tanzania)

import { initiateMPesaSTKPush } from '@reevit/vue';

const result = await initiateMPesaSTKPush(
  {
    phoneNumber: '254712345678',
    amount: 500,
    reference: 'TXN_12345',
    onInitiated: () => console.log('STK Push sent'),
    onSuccess: (result) => console.log('Paid:', result.transactionId),
    onError: (err) => console.error(err.message),
  },
  '/api/mpesa/stk-push' // Your backend endpoint
);

Nuxt.js Integration

For Nuxt 3 applications, wrap the component in <ClientOnly>:
<template>
  <ClientOnly>
    <ReevitCheckout
      publicKey="pfk_test_xxx.secret"
      :amount="5000"
      currency="GHS"
      @success="handleSuccess"
    >
      <button>Pay Now</button>
    </ReevitCheckout>
  </ClientOnly>
</template>

Supported Providers

ProviderCountriesPayment Methods
PaystackNG, GH, ZA, KECard, Mobile Money, Bank
FlutterwaveNG, GH, KE, ZA+Card, Mobile Money, Bank
HubtelGHMobile Money
StripeGlobal (50+)Card, Apple Pay, Google Pay
MonnifyNGCard, Bank Transfer, USSD
M-PesaKE, TZMobile Money (STK Push)