@authvia/payment-method-create
v0.6.0
Published
Authvia Payment Method Form Web Component - Payment method form built with Vue 3 and Vuetify 3
Readme
Authvia Payment Method Form
Vue 3 + Vuetify 3 component and standalone web component for adding a saved payment method (card, ACH, PayPal, Venmo, Paze, and related options). You choose which methods to expose; only enabled methods appear. On success the host receives a payment method id.
Full prop and behavior notes live in Storybook (AuthviaPaymentMethodForm story docs) and in exported TypeScript types.
Requirements
- Vue
>= 3.4.0 - Vuetify
3.x(your app creates the Vuetify instance; this package does not) - MDI font CSS on the host page (Material Design Icons)
If Vue, Vuetify, or styles are missing in a web-component embed, the element may emit authvia:dependency-missing.
Installation
npm install @authvia/payment-method-createExports:
- Vue plugin / module:
@authvia/payment-method-create(default build) - Standalone web component:
@authvia/payment-method-create/web-component
Features (summary)
- Token: A valid JWT is required for the inner form to render. The token must include
https://authvia.com/uuidandpayment_methods:createinscope. Missing, empty, invalid, or expired tokens keep the form hidden; the wrapper emitserroras{ phase: 'init', error }and logs a warning, and does not emitready.readyis emitted only after the token passes validation. - Enabled methods: Props such as
card,ach,paypal,venmo, andpazecontrol what appears. Methods you do not configure stay off the list. - Runtime errors: Failures while saving emit
errorwith a payload that usually includes amessagestring (shape is not{ phase: 'init', … }). Incomplete Paze or PayPal/Venmo (for non-payoutsintent) config hides those methods in the list instead of erroring on open. The embed usually stays mounted so the user can retry. - Sentry: Supports standalone widget ownership (
VITE_WIDGET_SENTRY_DSN) and host-owned ownership (VITE_SENTRY_EMBED_MODE=lockorwindow.__AUTHVIA_EMBED__.sentry='host') without double-init. - Success:
successcarries payment method details (see Events). The host decides navigation or hiding the embed. - Styling: Accent color, border radius, and field
variantare configurable; CSS variables use the--avwc-*prefix on the form root.
Vue: register the plugin
Your application must call createVuetify() (and load Vuetify styles + MDI) before registering this plugin.
import { createApp } from 'vue';
import { createVuetify } from 'vuetify';
import AuthviaPaymentMethodFormPlugin from '@authvia/payment-method-create';
import App from './App.vue';
const app = createApp(App);
const vuetify = createVuetify();
app.use(vuetify);
app.use(AuthviaPaymentMethodFormPlugin);
app.mount('#app');Named export AuthviaPaymentMethodFormPlugin is also available for explicit imports.
Vue: use the component
<template>
<AuthviaPaymentMethodForm
:token="token"
merchant-id="demo-merchant"
customer-ref="demo-customer"
intent="payments"
:card="{ demoMode: false }"
:ach="{ demoMode: false, online: true }"
@ready="onReady"
@success="onSuccess"
@error="onError"
/>
</template>
<script setup lang="ts">
import { AuthviaPaymentMethodForm } from '@authvia/payment-method-create';
function onReady(): void {
/* JWT passed validation; inner form can render */
}
function onSuccess(detail: unknown): void {
/* includes paymentMethodId — see types */
}
function onError(detail: unknown): void {
/* init: { phase: 'init', error }; runtime: often { message } */
}
</script>Web component
Load Vue 3, Vuetify CSS, and MDI before the bundle. Use the data- prefix for attributes; object props are JSON strings on the element.
See demo.html in this repo for a full page example.
<script src="https://cdn.jsdelivr.net/npm/vue@3/dist/vue.global.prod.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/vuetify.min.css" data-vuetify />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@mdi/[email protected]/css/materialdesignicons.min.css" data-mdi /><authvia-create-payment-method-form
data-token="YOUR_JWT"
data-merchant-id="demo-merchant"
data-customer-ref="demo-customer"
data-intent="payments"
data-card='{"demoMode":false,"submitBtnText":"Add card"}'
data-color="#4CAF50"
data-border-radius="1rem"
></authvia-create-payment-method-form>Load the built script after Vue (for example the output of npm run build:wc):
<script type="module" src=".https://cdn.authvia.com/web-components/authvia-payment-method-create/authvia-payment-method-create.js"></script>Web component events
Listen on the custom element for:
| Event | detail |
|--------|----------|
| ready | Emitted only when the JWT passes validation (non-empty, parseable, not expired, required scope). Not emitted for missing, invalid, expired, or under-scoped tokens; use error with { phase: 'init', error } instead. |
| submit | Emitted from some inner flows (for example ACH / PayPal) with form-related payloads. |
| success | Saved payment method; includes paymentMethodId in the normalized payload. |
| error | Init failures: { phase: 'init', error }. Runtime: often { message: string } or similar. |
| authvia:dependency-missing | Host is missing Vue, Vuetify, or required styles. |
<script>
const component = document.querySelector('authvia-create-payment-method-form');
component?.addEventListener('ready', () => { /* … */ });
component?.addEventListener('success', (e) => { console.log(e.detail); });
component?.addEventListener('error', (e) => { console.log(e.detail); });
</script>Sentry behavior
The package uses a single-client ownership model:
- Standalone widget mode: set
VITE_WIDGET_SENTRY_DSN; the widget callsSentry.initonce and tags events withcomponent=payment-method-createandintegration=standalone-web-component. - Embedded host mode (Lock or another host): set
VITE_SENTRY_EMBED_MODE=lockat build time, or setwindow.__AUTHVIA_EMBED__.sentry = 'host'before widget mount; the widget skipsSentry.initand attaches handlers to the active host client. - No active Sentry client: capture helpers are safe no-ops.
Supported Sentry env vars:
| Variable | Purpose | Default |
|----------|---------|---------|
| VITE_WIDGET_SENTRY_DSN | DSN for standalone widget ownership | unset |
| VITE_SENTRY_EMBED_MODE | Set to lock to force host-owned mode | unset |
| VITE_SENTRY_RELEASE | Optional release version sent to Sentry | unset |
| VITE_SENTRY_REPLAY_SESSION_SAMPLE_RATE | Session replay sample rate (0..1) | 0 |
| VITE_SENTRY_REPLAY_ON_ERROR_SAMPLE_RATE | Replay-on-error sample rate (0..1) | 1 |
Props (overview)
Details and examples match Storybook (src/components/AuthviaPaymentMethodForm.stories.ts).
| Area | Props |
|------|--------|
| Auth / context | token, merchantId, customerRef, intent |
| Methods | card, ach, paypal, venmo, paze |
| List UI | paymentMethodDisplay (titles, subtitles, order; optional root gap) |
| Legal / footer | terms (privacy + terms links) |
| Behavior | forgetHidden, forgetDefault, restrictions |
| Styling | color (default #4CAF50, from DEFAULT_AVWC_PRIMARY_COLOR), borderRadius (default 1rem, from DEFAULT_AVWC_BORDER_RADIUS), variant (default outlined, from DEFAULT_AVWC_FIELD_VARIANT), vuetifyOverrides (web component: plain CSS string for Shadow DOM) |
paymentMethodDisplay
Controls the payment method picker list (labels and order). It does not turn methods on or off; use card, ach, paypal, etc. for that.
| Field | Description |
|--------|-------------|
| gap (root, optional) | Vertical space between option rows. Any CSS length (1rem, 12px, …). If omitted, this prop does not add spacing; layout matches the previous behavior (no list-level gap from this object). |
| card, ach, paypal, venmo, paze | Optional title, subtitle, and order. Lower order values appear higher in the list. |
Vue
:payment-method-display="{
gap: '1rem',
card: { title: 'Credit / debit card', subtitle: '…', order: 1 },
ach: { title: 'Bank account', subtitle: '…', order: 2 }
}"Web component (data-payment-method-display): pass a single JSON object string. Use commas between properties. Invalid JSON is ignored (check the console).
data-payment-method-display='{"gap":"1rem","card":{"title":"Card","order":1},"ach":{"title":"Bank","order":2}}'Paze (paze)
Requires amount, clientId, profileId, and name on the object you pass; all must be non-empty (after trim). If any are missing or blank, Paze is not shown in the picker (including when restrictions list Paze but the paze prop is incomplete). The inner flow runs in two steps: Initializing Paze (SDK load) then Processing Paze payment (checkout → complete → create). Failures emit error and return the user to the payment method list without an inline error banner on that step; details are logged for developers.
PayPal / Venmo
intent="payouts":paypalandvenmocan be booleans; PayPal and Venmo stay listed even whenmerchantIdis incomplete (same as before for payouts).intent="payments"(and any intent other thanpayouts): PayPal and Venmo appear in the picker only whenmerchantIdis non-empty on the resolved wallet settings and the build definesVITE_APP_PAYPAL_CLIENT_ID. Otherwise those rows are hidden (same rules as the former click-timeerror, without showing a dead option). Userestrictionsonly when you intend to allow those methods; incomplete wallet config still strips PayPal/Venmo from the list.- Pass
merchantIdand optionalredirectUrlon thepaypal/venmoobject when you want the payments flow to succeed.
Stable styling hook classes (overrides)
Use these hooks in data-vuetify-overrides (web component) or host CSS. Canonical strings live in src/constants/avwcStylingHooks.ts (avwcPaymentMethodFormHooks).
| Class | Where |
|--------|--------|
| avwc-payment-method-form__root | Main form wrapper (AuthviaPaymentMethodForm) |
| avwc-payment-method-form__options-root | Options container (AuthviaPaymentMethodOptions v-container) |
| avwc-payment-method-form__options-card | Payment method selection v-card |
| avwc-payment-method-form__options-list | List area wrapping picker rows |
| avwc-payment-method-form__method-dialog | Each payment-method v-dialog content v-card |
| avwc-payment-method-form__method-row | Each picker row (AuthviaPaymentMethodCard) |
| avwc-payment-method-form__credit-card-section | Credit card block inside the card/PayPal dialog |
| avwc-payment-method-form__ach-root | ACH add-bank flow root (AuthviaPaymentMethodAddAch) |
Inside each picker row (data-vuetify-overrides): combine with the row hook, e.g. .avwc-payment-method-form__method-row .payment-method-card__title { color: #1565c0 !important; } for title text, .payment-method-card__logo-slot for icon tint, .payment-method-card__subtitle for the description line.
CSS variables
The form root sets theming variables, including:
--avwc-color(accent; mirrorscolorprop, default#4CAF50fromDEFAULT_AVWC_PRIMARY_COLOR)--avwc-border-radius(mirrorsborderRadius, default1remfromDEFAULT_AVWC_BORDER_RADIUS)
Additional tokens (for example --avwc-text-color-light) are documented in variables.css and Storybook.
Development
Prerequisites: Node.js 18+, npm 9+.
npm install
npm run dev # app dev server
npm run build # Vue module
npm run build:wc # web component
npm run type-check
npm run lint
npm testBundle and assets
- The Vue module expects Vue and Vuetify as peer dependencies; your app supplies Vuetify and MDI.
- The standalone web component bundles Vuetify JavaScript but expects Vuetify CSS + MDI from the host (same as
demo.html). - Component styles ship with the JS; add Vuetify + MDI at the app level.
Browser support
Chrome 88+, Firefox 85+, Safari 14+, Edge 88+.
Changelog
Version 1.0.3
Added Storybook stories and expanded unit tests; fixed duplicate tender-type filtering in useWalletMerchantService. See git history for details.
Version 1.0.2
Unified success payloads for ACH and card ({ type, paymentMethodId, use }), --avwc-* CSS variables with backward-compatible fallbacks, and named plugin export.
Documentation (current)
README aligned with AuthviaPaymentMethodForm.stories.ts (including paymentMethodDisplay.gap), demo.html, and package exports (@authvia/payment-method-create).
License
MIT License — see the LICENSE file.
Support
For support and questions, contact the Authvia UI Team.
