Embedded Checkout can show an installment picker when the shopper pays with a card that supports installments. The SDK loads available options from the card BIN, defaults to pay in full, and updates the pay button label when the shopper chooses a multi-month plan.
Installments are available only in paymentForm() and paymentCard(). They are not available for Apple Pay, Google Pay, or headless savedCardPayment().
Installments appear only when all of the following are true:
- Installments are enabled for your site in the xMoney merchant configuration.
- The order is a standard one-time payment (not card verification and not recurring).
- The shopper enters or selects a card whose BIN supports more than one installment.
There is no merchant-side SDK flag to enable installments. When the site configuration allows them, the SDK shows the picker automatically for eligible cards.
If installments do not appear for eligible cards, ask support@xmoney.com to confirm that installments are enabled for your site.
When an eligible card is present:
- The SDK checks the first six digits of the card number (new card) or the saved-card BIN.
- If the card supports installments, the form shows a Pay in installments section.
- The shopper can choose Pay in full or a plan from 2 through the maximum number of months returned for that BIN.
- Each option shows the per-month amount for the current order total.
- The built-in submit button updates to a multi-month label such as
Pay 3 × 100.00 RON.
Pay in full remains the default. The shopper is never required to choose installments.
For returning customers, the installment picker can appear under the selected saved card. Choosing Use other card moves installments back to the new-card form when that card is eligible.
| Widget | Installments |
|---|---|
XMoney.paymentForm() | Yes |
XMoney.paymentCard() | Yes |
XMoney.savedCardPayment() | No |
XMoney.applePay() | No |
XMoney.googlePay() | No |
If you hide the built-in submit button and render your own CTA, use onPaymentChange to keep the button label and installment summary in sync.
const paymentForm = await window.XMoney.paymentForm({
container: 'xmoney-payment-form',
publicKey,
orderPayload,
orderChecksum,
card: {
submitButton: {
visible: false,
type: 'pay', // or 'saveAndPay'
},
},
onPaymentChange({ installments, button }) {
document.getElementById('custom-pay-btn').textContent = button.label
const summary = document.getElementById('installment-summary')
summary.hidden = !installments.available || installments.count <= 1
if (installments.count > 1) {
summary.textContent = `${installments.count} × ${installments.formattedAmount}`
}
},
onPaymentComplete(transaction) {
handlePaymentResult(transaction)
},
}){
installments: {
available: true, // picker is visible for the current card/BIN
count: 3, // selected months, or 1 for pay in full
amount: 100, // per-installment amount (order total / count)
formattedAmount: '100.00 RON',
},
button: {
label: 'Pay 3 × 100.00 RON',
},
}The callback fires when installment availability or selection changes, and again after updateOrder() or updateLocale() when the display state changes.
When the shopper selects more than one installment, the SDK includes an installments integer with the payment request. When the shopper pays in full, that field is omitted.
Your backend fulfillment should continue to rely on webhooks or trusted API status checks. Do not treat the client-side installment selection alone as proof of the charged plan.
Built-in button types such as pay and saveAndPay switch to installment variants when a multi-month plan is selected:
| Base type | Installment label |
|---|---|
pay | Pay {{count}} × {{amount}} |
saveAndPay | Save and pay {{count}} × {{amount}} |
{{amount}} is the per-installment amount, not the full order total.