Overview
One call collects the card securely, runs 3D Secure, and authorizes. It resolves once with the final result, so it is safe to call a single time per confirm.const result = await modulus.confirmPayment({
elements,
billingDetails: {
firstName: 'Juan', lastName: 'Dela Cruz',
email: 'juan@example.com', phone: '+639171234567',
address: {
line1: 'General Luna', city: 'General Luna',
state: { code: 'SDN', name: 'Surigao del Norte' },
postalCode: '8419', country: 'PH',
},
},
onStatusChange: (s) => console.log(s), // optional lifecycle hook
});
if (result.status === 'SUCCEEDED') {
// result.receipt.transaction_id, result.receipt.approval_code, result.receipt.card_last_four ...
}
confirmPayment(options)
| Field | Type | Required | What it does |
|---|---|---|---|
elements | Elements | yes | The mounted group of card fields. |
billingDetails | object | yes | Cardholder name, email, and address. See below. |
idempotencyKey | string | no | De-duplicates a retried confirm so the customer is never double-charged. If supplied, it must match ^[A-Za-z0-9._-]{8,60}$; an invalid value resolves as FAILED with INVALID_IDEMPOTENCY_KEY. When omitted, the SDK generates one. |
acsWindowSize | string | no | 3DS challenge window size, "01" to "05" (default "05"). See 3D Secure. |
onStatusChange | function | no | Called as the payment progresses so you can update your UI. See 3D Secure. |
threeDS | object | no | 3DS rendering options, for example { container }. See 3D Secure. |
billingDetails
| Field | Type | Required | Notes |
|---|---|---|---|
firstName | string | yes | Cardholder given name. Max 60 characters. |
lastName | string | yes | Cardholder family name. Max 60 characters. |
email | string | yes | For the receipt and fraud checks. Max 255 characters. |
phone | string | no | Max 20 characters. After removing spaces, hyphens, and parentheses it must match ^\+?[1-9]\d{5,14}$ (E.164), e.g. +639171234567. |
address.line1 | string | yes | Street address. Max 60 characters. |
address.line2 | string | no | Unit / building. Max 60 characters. |
address.city | string | no | City / municipality. Max 50 characters. |
address.state | object | conditional | { code, name }, the province. Required for US, CA, and CN. When present, both code and name are required, each max 20 characters; for US/CA/CN the code must be the 2-character subdivision code (e.g. CA, ON). |
address.postalCode | string | no | ZIP / postal code. Max 10 characters. PH: exactly 4 digits. US: 12345 or 12345-6789. CA: A1B 2C3. |
address.country | string | yes | ISO 3166-1 alpha-2 code, e.g. PH. Lowercase is accepted and sent uppercase. |
Result and error handling
confirmPayment resolves with a typed status. Switch on result.status (the enum value), not on the wording of any message. Message text can be reworded in any release.
result.status | What to do |
|---|---|
SUCCEEDED | Paid. Read result.receipt and release the booking or order. |
DECLINED | Issuer declined. Show result.userMessage and let them try another card. |
PROCESSING | Outcome uncertain (network / timeout). Do not retry blindly, the payment may still complete. Show a “we’re confirming your payment” state. |
EXPIRED | The intent’s payment window lapsed before it was confirmed. Create a fresh intent and re-mount. |
FAILED | Could not complete. Branch on result.error.type (below). |
result.error
Every non-successful result carriesresult.error. It is also passed to the optional onError callback in the confirmPayment options. Branch on error.type; error.message is for your logs and can change between releases. Customer-facing text is always owned by the SDK and never repeats server or processor messages.
| Field | Type | Meaning |
|---|---|---|
type | string | One of the types below. |
code | string | Machine-readable detail code. |
message | string | Developer-facing explanation. Do not show it to the shopper. |
field | string (optional) | On validation_error, the input that was rejected: cardNumber, cardExpiry, cardCvc, or a billingDetails.* property such as billingDetails.address.postalCode. |
retryAfterSeconds | number (optional) | On rate_limited, how long to wait (1-300 seconds) before confirming again. |
error.type | Typical cause | result.status | What to do |
|---|---|---|---|
validation_error | The request input was rejected (HTTP 400/422) | FAILED | Nothing was charged. Fields stay mounted and editable. Highlight error.field and let the shopper correct and resubmit. |
rate_limited | Too many requests (HTTP 429) | FAILED | Nothing was charged. Wait error.retryAfterSeconds; the SDK refuses earlier confirms without calling the API. |
integration_error | Invalid key, access denied, unknown intent, origin not allowed, or merchant not configured | FAILED | Nothing was charged. Fix the integration; retrying will not help. |
payment_conflict | Another attempt holds this intent (HTTP 409) | PROCESSING | Do not take a second payment. Retrieve the intent to learn its final status. |
intent_closed | The intent no longer accepts payments (HTTP 410) | EXPIRED | Retrieve the intent’s final status before offering a new payment. |
card_declined | Issuer or card-eligibility decline | DECLINED | Show result.userMessage; the shopper may try another card. |
outcome_unknown | Server error, network error, or timeout | PROCESSING | Never tell the shopper the payment failed. Retrieve the intent to learn its final status. |
const result = await modulus.confirmPayment({
elements,
billingDetails,
onError: (error) => console.warn('confirm failed', error.type, error.code),
});
if (result.error?.type === 'validation_error') {
highlightField(result.error.field);
}
result.receipt
Returned onSUCCEEDED. Fields marked optional are present only when the processor returns them.
| Field | Type | Meaning |
|---|---|---|
approval_code | string | Issuer authorization code. |
transaction_id | string | Modulus transaction reference, used to track the payment in your dashboard. |
reconciliation_id | string | Settlement / reconciliation reference (the processor reference number). |
acquirer_transaction_number | string (optional) | Acquirer’s transaction reference. Present when available. |
card_scheme | string (optional) | Card brand, VISA or MASTERCARD. |
card_last_four | string (optional) | Last four digits of the card used. |
order_reference | string (optional) | Your order reference associated with the payment, echoed back when present. |
description | string (optional) | The description from the payment, echoed back. |
completed_at | string (optional) | ISO 8601 timestamp when the payment completed. |
batch_number | string (optional) | Settlement batch number. |
invoice_number | string (optional) | Modulus invoice number for this payment. |