Skip to main content

Migrate from Stripe Elements

MONEI Components mirror the Stripe Elements integration model: hosted iframes collect card data on your page, your PCI DSS scope stays at SAQ A, and your JavaScript never sees a card number. This page maps each Stripe concept to its MONEI equivalent.

Concept mapping

StripeMONEI
Stripe(publishableKey)No global constructor — Components take paymentId or accountId directly.
stripe.elements()monei.CardGroup({...})
elements.create('card')monei.CardInput({...})
elements.create('cardNumber')monei.CardNumber({group})
elements.create('cardExpiry')monei.CardExpiry({group})
elements.create('cardCvc')monei.CardCvc({group})
element.mount('#id')component.render('#id')
stripe.createToken(cardElement)cardGroup.submit() / cardInput.submit()
stripe.confirmCardPayment(clientSecret)monei.confirmPayment({paymentId, paymentToken})
element.on('change', handler)onChange prop
element.focus() / blur() / clear()Same methods on a mounted part
StripeElement--focus etc.monei-component--focus etc.
style option (per element)style object
fonts optionfonts: FontConfig[]

Key structural difference: MONEI has no element factory. The group travels as a plain group prop on each part — every Component is created with monei.X({...}) and mounted with .render().

Split card fields

Stripe:

const elements = stripe.elements();
elements.create('cardNumber').mount('#number');
elements.create('cardExpiry').mount('#expiry');
elements.create('cardCvc').mount('#cvc');
const {token} = await stripe.createToken(elements.getElement('cardNumber'));

MONEI:

const cardGroup = monei.CardGroup({paymentId});
monei.CardNumber({group: cardGroup}).render('#number');
monei.CardExpiry({group: cardGroup}).render('#expiry');
monei.CardCvc({group: cardGroup}).render('#cvc');
const {token, error} = await cardGroup.submit();

Differences that work in your favor:

  • Aggregate onChange on the groupCardGroup({onChange: ({complete}) => ...}) tells you when all fields are valid. With Stripe you track each element's complete yourself.
  • Automatic focus advance — number → expiry → CVC as the customer types, with Backspace walking back. Stripe's split elements do not advance focus.
  • Submit-time highlighting — a failed submit() marks the offending part invalid; you only render the returned error string.

Events

Stripe's change event payload maps almost one-to-one:

Stripe eventMONEI CardPartChangeEvent
event.emptyevent.empty
event.completeevent.complete
event.error.messageevent.error (already a display-ready string)
event.brandevent.brand (CardNumber only)

ready → use onLoad. focus/bluronFocus/onBlur (no payload).

Framework packages

StripeMONEI
@stripe/react-stripe-js <Elements> provider + useElements()useCardGroup() — no provider needed
<CardNumberElement /> etc.<CardNumber group={group} /> etc.

Vue, Angular and Svelte packages follow the same shape — see Vue, Angular and Svelte.

Server side

Replace PaymentIntents with MONEI payments: create a payment on your server, pass its id as paymentId to the group, then submit() + confirmPayment on the client — or confirm server-side with the token. Test with MONEI test cards.