embedpay-vue
v3.0.9
Published
Vue 3 composables and components for EmbedPay payment processing. Provides useEmbedPay composable and EmbedPayButton component with full TypeScript support. Compatible with Vue 3, Nuxt 3, and Vite.
Readme
EmbedPay Vue
Vue 3 composables and components for EmbedPay payment processing. Build seamless payment flows in your Vue applications.
Overview
embedpay-vue provides Vue 3-specific bindings for the EmbedPay SDK:
- 🎣 Vue Composables -
useEmbedPaycomposition function - 🧩 Components - Pre-built checkout button component
- ⚡ Reactive - Vue reactivity system integration
- 🔒 Type-Safe - Full TypeScript support with Vue types
- 🧪 Mock Mode - Built-in testing support
Installation
npm install embedpay-vue
# or
yarn add embedpay-vue
# or
pnpm add embedpay-vuePeer Dependencies
npm install vue@^3.0.0Quick Start
1. Install the Plugin
// main.ts
import { createApp } from 'vue';
import { EmbedPayPlugin } from 'embedpay-vue';
import App from './App.vue';
const app = createApp(App);
app.use(EmbedPayPlugin, {
key: 'pk_live_alexpay_xxxxxxxx',
currency: 'GHS',
narration: 'Order Payment',
callback: 'https://yoursite.com/success',
cancel: 'https://yoursite.com/cancel'
});
app.mount('#app');2. Use the Composable
<template>
<div>
<div v-if="state === 'fetching'">Loading...</div>
<div v-else-if="state === 'error'" class="error">
⚠️ {{ error }}
<button @click="retry">Retry</button>
</div>
<button
v-else
@click="initPayment"
:disabled="state !== 'ready'"
>
Pay GHS {{ (amount / 100).toFixed(2) }}
</button>
</div>
</template>
<script setup lang="ts">
import { useEmbedPay } from 'embedpay-vue';
import { ref } from 'vue';
const amount = ref(5000);
const { state, initPayment, error, retry } = useEmbedPay({
amountSource: {
type: 'prop',
getter: () => amount.value
}
});
</script>3. Or Use the Component
<template>
<EmbedPayButton
:amount="5000"
currency="GHS"
narration="Product Purchase"
@success="handleSuccess"
@error="handleError"
>
Pay Now
</EmbedPayButton>
</template>
<script setup lang="ts">
import { EmbedPayButton } from 'embedpay-vue';
const handleSuccess = () => {
console.log('Payment initiated!');
};
const handleError = (err: Error) => {
console.error('Payment error:', err);
};
</script>API Reference
EmbedPayPlugin
Vue plugin for global configuration.
import { EmbedPayPlugin } from 'embedpay-vue';
app.use(EmbedPayPlugin, {
key: 'pk_live_alexpay_xxxxxxxx',
currency: 'GHS',
method: 'card',
narration: 'Order Payment',
callback: 'https://yoursite.com/success',
cancel: 'https://yoursite.com/cancel',
forceMock: false
});Options:
| Option | Type | Required | Description |
|--------|------|----------|-------------|
| key | string | ✅ | Publishable key |
| currency | string | ❌ | Currency code (GHS, NGN, USD) |
| method | 'card' \| 'mobile-money' | ❌ | Payment method |
| narration | string | ❌ | Default description |
| callback | string | ❌ | Success URL |
| cancel | string | ❌ | Cancel URL |
| forceMock | boolean | ❌ | Test mode |
useEmbedPay
Main composable for payment processing.
const result = useEmbedPay(options);Options:
interface UseEmbedPayOptions {
amountSource: AmountSource;
autoInitialize?: boolean;
}
type AmountSource =
| { type: 'prop'; getter: () => number | Promise<number> }
| { type: 'var'; varName: string }
| { type: 'dom'; selector: string };Return Value:
interface UseEmbedPayResult {
state: Ref<'idle' | 'fetching' | 'ready' | 'error' | 'retrying'>;
config: Ref<EmbedPayConfig | null>;
error: Ref<string | null>;
initPayment: () => Promise<void>;
retry: () => Promise<void>;
}Example with DOM source:
<template>
<div>
<span id="cart-total">5000</span>
<button
@click="initPayment"
:disabled="state !== 'ready'"
>
Checkout
</button>
</div>
</template>
<script setup>
import { useEmbedPay } from 'embedpay-vue';
const { state, initPayment } = useEmbedPay({
amountSource: {
type: 'dom',
selector: '#cart-total'
}
});
</script>EmbedPayButton
Pre-built checkout button component.
<template>
<EmbedPayButton
:amount="5000"
currency="GHS"
narration="Order #123"
:disabled="false"
class="custom-button"
@success="onSuccess"
@error="onError"
>
Pay GHS 50.00
</EmbedPayButton>
</template>Props:
| Prop | Type | Required | Description |
|------|------|----------|-------------|
| amount | number | ✅ | Payment amount |
| currency | string | ❌ | Override currency |
| narration | string | ❌ | Override description |
| disabled | boolean | ❌ | Disable button |
| class | string | ❌ | CSS class |
Events:
| Event | Payload | Description |
|-------|---------|-------------|
| success | void | Payment initiated |
| error | Error | Payment failed |
Advanced Usage
Reactive Amount
<template>
<div>
<input
v-model.number="quantity"
type="number"
min="1"
/>
<p>Total: GHS {{ totalAmount / 100 }}</p>
<button
@click="initPayment"
:disabled="state !== 'ready'"
>
Pay Now
</button>
</div>
</template>
<script setup lang="ts">
import { useEmbedPay } from 'embedpay-vue';
import { ref, computed } from 'vue';
const quantity = ref(1);
const unitPrice = 5000;
const totalAmount = computed(() => quantity.value * unitPrice);
const { state, initPayment } = useEmbedPay({
amountSource: {
type: 'prop',
getter: () => totalAmount.value
}
});
</script>Mock Mode Testing
<template>
<div>
<h2>Test Checkout</h2>
<EmbedPayButton
:amount="5000"
@success="showSuccess"
>
Test Payment
</EmbedPayButton>
</div>
</template>
<script setup>
// In your main.ts for testing:
// app.use(EmbedPayPlugin, {
// key: 'pk_test_alexpay_xxxxxxxx',
// forceMock: true,
// checkoutUrl: '/checkout'
// });
const showSuccess = () => {
alert('Test payment initiated!');
};
</script>Error Handling
<template>
<div>
<div v-if="state === 'error'" class="error-card">
<h3>⚠️ Payment Error</h3>
<p>{{ error }}</p>
<button @click="retry">Try Again</button>
</div>
<button
v-else
@click="initPayment"
:disabled="state === 'fetching'"
>
<span v-if="state === 'fetching'">Loading...</span>
<span v-else>Pay GHS 50.00</span>
</button>
</div>
</template>
<script setup>
import { useEmbedPay } from 'embedpay-vue';
const { state, error, initPayment, retry } = useEmbedPay({
amountSource: {
type: 'prop',
getter: () => 5000
}
});
</script>
<style scoped>
.error-card {
background: #ffebee;
padding: 16px;
border-radius: 8px;
border: 1px solid #ef5350;
}
</style>Custom Button with Composable
<template>
<button
@click="initPayment"
:disabled="state !== 'ready'"
class="custom-checkout-btn"
:class="{ 'is-loading': state === 'fetching' }"
>
<span v-if="state === 'fetching'" class="spinner" />
<span v-else-if="state === 'ready'">
Pay {{ formattedAmount }}
</span>
<span v-else-if="state === 'error'">Try Again</span>
</button>
</template>
<script setup lang="ts">
import { useEmbedPay } from 'embedpay-vue';
import { computed } from 'vue';
const props = defineProps<{
amount: number;
currency?: string;
}>();
const formattedAmount = computed(() => {
const currency = props.currency || 'GHS';
const value = (props.amount / 100).toFixed(2);
return `${currency} ${value}`;
});
const { state, initPayment } = useEmbedPay({
amountSource: {
type: 'prop',
getter: () => props.amount
}
});
</script>
<style scoped>
.custom-checkout-btn {
background: #1a1714;
color: white;
padding: 12px 24px;
border-radius: 8px;
border: none;
cursor: pointer;
transition: opacity 0.2s;
}
.custom-checkout-btn:disabled {
opacity: 0.6;
cursor: not-allowed;
}
.is-loading {
cursor: wait;
}
.spinner {
display: inline-block;
width: 16px;
height: 16px;
border: 2px solid rgba(255,255,255,0.3);
border-top-color: white;
border-radius: 50%;
animation: spin 0.7s linear infinite;
}
@keyframes spin {
to { transform: rotate(360deg); }
}
</style>TypeScript Support
Full TypeScript definitions included:
import type {
EmbedPayConfig,
UseEmbedPayOptions,
UseEmbedPayResult,
AmountSource
} from 'embedpay-vue';Nuxt 3 Integration
// plugins/embedpay.ts
import { EmbedPayPlugin } from 'embedpay-vue';
export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.vueApp.use(EmbedPayPlugin, {
key: useRuntimeConfig().public.embedpayKey,
currency: 'GHS'
});
});<!-- pages/checkout.vue -->
<template>
<div>
<h1>Checkout</h1>
<EmbedPayButton :amount="5000">
Complete Order
</EmbedPayButton>
</div>
</template>Vite Integration
// main.ts
import { createApp } from 'vue';
import App from './App.vue';
import { EmbedPayPlugin } from 'embedpay-vue';
createApp(App)
.use(EmbedPayPlugin, {
key: import.meta.env.VITE_EMBEDPAY_KEY
})
.mount('#app');Testing
npm test
# or
yarn testBrowser Support
- ✅ Chrome 80+
- ✅ Firefox 75+
- ✅ Safari 13+
- ✅ Edge 80+
Related Packages
embedpay- Browser bundleembedpay-core- Core functionalityembedpay-react- React integration
License
MIT © Vesicash
Support
- 📧 Email: [email protected]
- 🌐 Website: https://vesicash.com/embedpay
Build better payment experiences with Vue + EmbedPay 💚
