Skip to main content

Vue Components

Use @monei-js/vue-components to add MONEI payment components to your Vue 3 app. Each component is a native Vue component with typed props and template ref submit().

Install​

npm install @monei-js/vue-components @monei-js/components

Requires Vue 3.3 or later.

Components​

ComponentDescription
CardInputSecure card input (iframe) with submit()
CardNumber / CardExpiry / CardCvcIndividually mountable card fields, coordinated by useCardGroup()
BizumBizum button + phone verification modal
PayPalPayPal checkout button
PaymentRequestApple Pay / Google Pay button

Card input​

The Card Input component collects card number, expiry, and in a single secure iframe. Use a template ref to call submit() and get a .

<template>
<div>
<CardInput ref="cardInput" :payment-id="paymentId" :on-change="handleChange" />
<button @click="handleSubmit">Pay</button>
<p v-if="error">{{ error }}</p>
</div>
</template>

<script setup lang="ts">
import {ref} from 'vue';
import {CardInput, confirmPayment} from '@monei-js/vue-components';

const props = defineProps<{paymentId: string}>();
const cardInput = ref<InstanceType<typeof CardInput>>();
const error = ref('');

function handleChange(event: {error?: string}) {
error.value = event.error ?? '';
}

async function handleSubmit() {
const result = await cardInput.value!.submit();
if (result.error) {
error.value = result.error;
return;
}
await confirmPayment({paymentId: props.paymentId, paymentToken: result.token});
}
</script>

See the API Reference for all CardInput props (style, placeholders, error messages, event callbacks).

Split card fields​

Mount the number, expiry and CVC as separate components in your own layout. Create the group with useCardGroup() inside setup() — payment identifiers live on the group, the parts take presentation props only.

<script setup>
import {ref} from 'vue';
import {
CardNumber,
CardExpiry,
CardCvc,
useCardGroup,
confirmPayment
} from '@monei-js/vue-components';

const props = defineProps({paymentId: String});
const group = useCardGroup({paymentId: props.paymentId});
const complete = ref(false);
const error = ref('');

async function handleSubmit() {
const result = await group.submit();
if (result.error) {
error.value = result.error; // the offending field is already highlighted
return;
}
await confirmPayment({paymentId: props.paymentId, paymentToken: result.token});
}
</script>

<template>
<label>Card number</label>
<CardNumber :group="group" class="card-box" :onChange="(e) => (complete = e.complete)" />
<div class="row">
<div>
<label>Expiry</label>
<CardExpiry :group="group" class="card-box" />
</div>
<div>
<label>CVC</label>
<CardCvc :group="group" class="card-box" />
</div>
</div>
<button :disabled="!complete" @click="handleSubmit">Pay</button>
<p v-if="error">{{ error }}</p>
</template>

Style that box in your own CSS — the class you pass is set on the very element each part toggles monei-component--focus, --invalid, --empty and --complete on, so .card-box.monei-component--invalid {} matches. A template ref on a part exposes focus(), blur() and clear().

See the API Reference for all options and behavior details.

Bizum​

The Bizum component renders a Bizum payment button. When the customer clicks it, a phone verification modal opens to complete the payment.

<template>
<Bizum :payment-id="paymentId" :on-submit="handleSubmit" :on-error="handleError" />
</template>

<script setup lang="ts">
import {Bizum, confirmPayment} from '@monei-js/vue-components';

const props = defineProps<{paymentId: string}>();

async function handleSubmit(result: {token?: string}) {
if (result.token) {
await confirmPayment({paymentId: props.paymentId, paymentToken: result.token});
}
}

function handleError(error: string) {
console.error(error);
}
</script>

PayPal​

The PayPal component renders a PayPal checkout button. When the customer approves, you receive a token to confirm the payment.

<template>
<PayPal :payment-id="paymentId" :on-submit="handleSubmit" :on-error="handleError" />
</template>

<script setup lang="ts">
import {PayPal, confirmPayment} from '@monei-js/vue-components';

const props = defineProps<{paymentId: string}>();

async function handleSubmit(result: {token?: string}) {
if (result.token) {
await confirmPayment({paymentId: props.paymentId, paymentToken: result.token});
}
}

function handleError(error: string) {
console.error(error);
}
</script>

PaymentRequest (Apple Pay / Google Pay)​

The PaymentRequest component renders an Apple Pay or Google Pay button depending on the customer's browser and device.

note

Apple Pay requires domain verification in both development and production.

<template>
<PaymentRequest :payment-id="paymentId" :on-submit="handleSubmit" :on-error="handleError" />
</template>

<script setup lang="ts">
import {PaymentRequest, confirmPayment} from '@monei-js/vue-components';

const props = defineProps<{paymentId: string}>();

async function handleSubmit(result: {token?: string}) {
if (result.token) {
await confirmPayment({paymentId: props.paymentId, paymentToken: result.token});
}
}

function handleError(error: string) {
console.error(error);
}
</script>

Payment modal​

Calling confirmPayment() without a paymentToken opens the MONEI Payment Modal — a full in-page checkout where the customer can select a payment method and complete the payment.

<template>
<button @click="handleClick">Pay</button>
</template>

<script setup lang="ts">
import {confirmPayment} from '@monei-js/vue-components';

const props = defineProps<{paymentId: string}>();

async function handleClick() {
const result = await confirmPayment({paymentId: props.paymentId});
// Payment completed — check result.status
console.log(result);
}
</script>
info

Apple Pay is not available in the Payment Modal. Use the PaymentRequest component instead.

See Use Payment Modal for the full integration guide.

Next steps​