Skip to main content

Card (Purse vault)

The card method renders the Android Secure Fields form: card number, expiry, CVV and holder. Card data is tokenized by the Purse vault and never reaches your code.

Setup​

Artifacteu.purse:headless-checkout-android, nothing else
DashboardA card method whose vault is Purse (vault.vendor = purse) activated on the entity, with any acquiring partner
ManifestNothing. 3-D Secure opens in an Activity the SDK declares
KeysNone in the app. The vault tenant travels in the client session
Cards outside the Purse vault

A card method hosted by a PSP's own form (Adyen, Stripe, Checkout.com, a pci_proxy vault…) has no native form and is not rendered by this SDK. Configure the method in redirection mode to offer it through the redirection guide.

Render and pay​

val element = rememberPaymentElement(checkout, cardMethod, listener)
LaunchedEffect(cardMethod.id) { checkout.setPrimary(cardMethod) }
PaymentElementUi(element, Modifier.fillMaxWidth())
Button(onClick = { element.submit() }, enabled = element.ready) { Text("Pay") }

An empty or invalid form is never payable: element.ready and isPaymentFulfilled stay false until every field validates, and submit() on an invalid form is a no-op, not an error (the fields show their own messages). submit() tokenizes the card, runs /init and /validate, then follows 3-D Secure in the SDK's Activity.

checkout.schemeAssets(cardMethod) gives the accepted schemes with icon and label, to show above the form. Co-badged cards default to the first scheme the BIN lookup matches.

Outcomes​

OutcomeWhen
Completed/validate answered without a challenge. status is the API's verdict
ReturnedFromRedirectThe shopper came back from 3-D Secure. Not an outcome. Show a processing state; your backend confirms the payment
CanceledThe 3-D Secure page was dismissed
FailedTokenization refused, /init or /validate failed. error.code says which

Save the card​

When the method allows it (save_token_mode PREFER or PREFER_NO in the dashboard), canBeRegistered is true and the shopper can keep the card for the next session:

if (cardMethod.canBeRegistered) {
checkout.register(cardMethod, registered = true, name = "holiday card")
}
val decision = checkout.registrationOf(cardMethod) // observable before and after submit

register throws WalletOperationFailed with METHOD_NOT_REGISTERABLE when the method cannot save cards, INVALID_TOKEN_NAME or TOKEN_NAME_EXISTS on a bad label. Saving needs a wallet session in the client session: see Saved cards and accounts.

Customize the form​

Locale, texts and theme come from PluginOptions at init: Customization.

Troubleshooting​

SymptomCause
The Pay button never enablesA field is invalid. The form shows which; element.ready mirrors it
The form loses its input on recompositionYou built your own coordinator without remembering the host. Use rememberPaymentElement, or remember(method.id) { checkout.host(method) }
Failed with API_ERROR on submit, message creditcard init not successfulThe /init was refused for this item. Check the method's configuration on the entity
The form does not initialize at allThe session carries no vault tenant: the card method is not vaulted by Purse
A 3-D Secure page refuses to renderSome issuers block embedded WebViews. Report the issuer to Purse support