@flopay/vue
Vue 3 components and composables for FloPay checkout, card setup and one-click payments: the Vue counterpart of @flopay/react, with the same props, events and behaviour.
Installation
npm install @flopay/vue
vue (>=3.3.0) is a peer dependency. @flopay/js and @flopay/shared are installed with the package.
Usage
Render FloPayCheckout with a session the merchant server created, or with an inline createSession draft. Notification callbacks are Vue events: React's onComplete is @complete in templates and onComplete in h().
import { FloPayCheckout } from '@flopay/vue';
import { h } from 'vue';
export default {
setup() {
return () =>
h(FloPayCheckout, {
sessionId: 'sess_123',
nonce: 'nonce_123',
onComplete: (result) => console.log(result.status),
onDecline: (decline) => console.log(decline.message),
});
},
};
Browser work (session reads, SDK loading, the hosted card widget) starts in onMounted, so server rendering never touches window and renders the loading state.
Examples
Card setup from the Stripe-free subpath:
import { FloPayCardSetup } from '@flopay/vue/card-setup';
import { h } from 'vue';
const render = () =>
h(FloPayCardSetup, {
sessionId: 'sess_setup_123',
nonce: 'nonce_setup_123',
onComplete: (event) => console.log(event.sessionId),
});
One-click payment with the buyer's saved payment method:
import { FloPayAutomaticPaymentButton } from '@flopay/vue';
import { h } from 'vue';
const render = () =>
h(FloPayAutomaticPaymentButton, {
clientId: 'client_123',
account: { userId: 'user_123', email: '[email protected]' },
products: [{ code: 'pro-monthly', quantity: 1 }],
successUrl: 'https://example.com/success',
cancelUrl: 'https://example.com/cancel',
onSuccess: (event) => console.log(event.autoCompleted),
});
Public API
Every @flopay/react component and hook has a same-name Vue export. React's notification callbacks are Vue events with the same payloads.
| Export | React (@flopay/react) | Vue (@flopay/vue) |
|---|---|---|
FloPayProvider | <FloPayProvider> | FloPayProvider, provided to descendants; @instrument |
FloPayCheckout | <FloPayCheckout> | FloPayCheckout: @complete, @decline, @cancel, @error, @button-click |
SplitCardForm | <SplitCardForm> | SplitCardForm: @complete, @decline, @cancel, @error |
VaultCardFields | <VaultCardFields> | VaultCardFields: @ready, @error, @validation |
DirectPayPalButton | <DirectPayPalButton> | DirectPayPalButton: @complete, @decline, @cancel, @error |
FloPayAutomaticPaymentButton | <FloPayAutomaticPaymentButton> | FloPayAutomaticPaymentButton: @success, @error, @decline |
FloPayCardSetup | <FloPayCardSetup> | FloPayCardSetup: @ready, @complete, @decline, @cancel, @error |
FloPayPaymentMethodSetup | <FloPayPaymentMethodSetup> | FloPayPaymentMethodSetup |
useFloPay | useFloPay() | useFloPay(): a ref, null until loadFloPay() resolves |
usePayPalFloPay | usePayPalFloPay() | usePayPalFloPay(): a ref |
useCheckout | useCheckout() | useCheckout(): a reactive checkout state |
FloPayCardSetupError | FloPayCardSetupError | FloPayCardSetupError |
dropThirdPartyOnlyError | dropThirdPartyOnlyError | dropThirdPartyOnlyError |
React children and custom layouts are slots. FloPayCheckout's layout slot replaces the built-in form, and a SplitCardForm inside it receives the session, nonce and submitLabel unless it sets them itself.
Entry points: @flopay/vue, @flopay/vue/card-setup and @flopay/vue/payment-method-setup.
PayPal buyer cancel
FloPayCheckout, SplitCardForm and DirectPayPalButton emit cancel (@cancel, React's onCancel) once per click when the buyer closes the PayPal pop-up, or returns from PayPal's app switch, without approving. The payload is a FloPayPaymentCancelEvent: { status: 'cancelled', sessionId, provider: 'paypal', paymentMethodType }. sessionId is the attempt's session (the click-time patch's, otherwise the checkout's), and paymentMethodType is paypal_vaulted when the session advertises an order or setup_token, otherwise paypal.
It is never emitted for an approval, a decline (that stays @decline), a blocked pop-up, a load, render or eligibility failure, or a click your runBeforeButtonClick gate stopped, and a repeated cancel for the same click is ignored. It covers the direct PayPal button only (sessions with gateways.paypal). The button stays rendered for the next click, and nothing changes if you don't listen for it.
A "Didn't work? Pay another way" prompt that moves the buyer to the card form:
import { FloPayCheckout, type FloPayPaymentCancelEvent } from '@flopay/vue';
import { defineComponent, h, ref } from 'vue';
export default defineComponent({
setup() {
const cancelled = ref<FloPayPaymentCancelEvent | null>(null);
const cardForm = ref<HTMLElement | null>(null);
return () => [
cancelled.value
? h('div', { role: 'status' }, [
"Didn't work? Pay another way. ",
h(
'button',
{ type: 'button', onClick: () => cardForm.value?.focus() },
'Pay by card or Google Pay',
),
])
: null,
h('div', { ref: cardForm, tabindex: -1 }, [
h(FloPayCheckout, {
sessionId: 'sess_123',
nonce: 'nonce_123',
onCancel: (event: FloPayPaymentCancelEvent) => {
cancelled.value = event;
},
}),
]),
];
},
});
Errors
Errors are FloPayError instances from @flopay/shared, emitted through @error.
| Code | Meaning |
|---|---|
UnsupportedBackendVaultCapability | The session has no hosted vault card form and no other usable method. |
stored_payment_method_unsupported | The buyer's saved method cannot be charged; ask for another method. |
MissingCheckoutSessionToken | A session id was given without its nonce. |
network_request_failed | Type network_error. FloPayCheckout could not start because creating or reading the session never got a response, after the SDK's retries. cause holds the original error; sessionId is set when the session already existed. |
CheckoutInitializationFailed | Type api_error. FloPayCheckout could not start for a reason that is not a network failure, with sessionId set once the session exists. |
Setup surfaces emit FloPayCardSetupError, whose retryable says whether trying again can help.