Card Payment
xperise issues a closed-group card to employees. A card can be issued in physical form, in the app (virtual), or both at once, and is valid only inside the xperise network. It can be accepted three ways at a vendor:
- Tap the card (NFC contactless) — best security and UX.
- Vendor scans a printed QR on the card.
- Manual entry of the card details (card-not-present).
What a card payment deducts
The xperise card follows the two-layer model. Each card carries a card balance. On a successful payment, xperise deducts atomically:
- Layer 1 — spending authority: the card balance — plus the cost center only if the company runs the cost-center model (a company uses monthly limit or cost center, never both; a card payment never draws the monthly limit).
- Layer 2 — funding (optional): the company wallet (backed by company credit) — only when the card's funding source is set to the company wallet. A card may instead have no funding source, in which case the card balance is stored value (prepaid) and is the money — no wallet is drawn.
If the card balance (or the cost center, under the cost-center model) is exhausted — or, when the card is wallet-funded, the company wallet/credit is insufficient — the payment is declined and nothing is deducted. The operating model and the card's funding source are set in the Corporate Portal.
The golden rule: the card is an identifier, not a credential
Whatever is printed, tapped, or scanned identifies which account to charge — it must never be enough to move money on its own. Every payment also needs the cardholder's verification — the Cardholder Verification Method (CVM) — scaled to the risk of the transaction. This is what makes a photographed card or a copied number harmless on its own.
Accordingly, the card's stored/printed data is a token, never the real account number, and never a secret:
| On the card | What it is | Sensitivity |
|---|---|---|
| Printed number / QR | A card token (maps to the account server-side) | Identifier — safe to see, useless alone |
| NFC chip | A secret key in a secure element that signs each tap | Secret — never leaves the chip |
| PIN | Chosen by the user; verified as a salted hash / in an HSM | Secret — never printed, never stored in clear |
CVV-style codes are never stored by xperise; full card numbers are held only in a
tokenization vault (stored as token + last4 + hash).
Transaction authentication (CVM)
Every card transaction is authenticated by the Cardholder Verification Method (CVM) — a PIN or an OTP, one of the two, never both. The CVM is configured per card/company:
- PIN — a secret the cardholder sets; verified as a salted hash / in an HSM.
- OTP — a one-time code from the shared OTP service, delivered to the cardholder's registered channel.
Low-value tap transactions may be authorized below the contactless floor limit with no CVM; above that limit the card's configured CVM (PIN or OTP) is required.
Card lifecycle
Cards ship inactive (ISSUED) and can move money only once ACTIVE. Activation binds the card
and captures its verification — see Card activation below.
Card assignment
A card is assigned to one employee or to no-one:
- Assigned to an employee — the card inherits all the employee's cost center(s) and stays in sync (if the employee is removed from a cost center, the card is removed from it too); the employee's default cost center is used for card payments, and the cost-center picker is hidden.
- Unassigned = a bearer card — anyone who holds the card and knows the PIN can use it (so its CVM is PIN). A bearer card may optionally be linked to one cost center. Good for shared/pool cards; pair with a low balance and tight limits.
Users can freeze/unfreeze instantly and report lost to permanently kill the token — a lost card cannot be reused because the token alone can't authorize. See the Card Management spec for the full assignment rules.
Card activation
Activation is the security gate that turns a physical card (ISSUED) into a spendable one
(ACTIVE). Its job is to confirm two independent things before any money can move:
- Possession — the activator physically holds this card (proved by the printed activation code / QR, or an NFC tap).
- Identity / authority — the activator is the rightful cardholder (a logged-in user + OTP) or an authorized corporate admin (elevated, MFA-protected role).
xperise supports two flows, matching the two ways cards are distributed.
Common rules
| Rule | Why |
|---|---|
Cards are shipped ISSUED (inactive) | A card lost in the mail can't be used until activated. |
| Activation code / QR is single-use with an attempt lockout | Prevents brute-forcing card tokens. |
| Activation always needs possession + identity | One stolen factor is never enough. |
| The PIN is set by the cardholder, never shared | Keeps the tap/terminal secret private, even from admins. |
| Every activation is audit-logged (who, when, which card) | Traceability and reconciliation. |
Flow 1 — User self-activation
The cardholder activates their own card. This works in the app (best security) or without the app via an activation web page + OTP (for users who don't or can't install it). Recommended for individual customers.
1a — In the app (recommended)
- User signs in (reuses the existing xperise session + account OTP channels).
- Possession: user scans the card's printed QR, taps it (NFC), or types the activation code from the sealed mailer.
- Identity: an OTP — from the shared xperise OTP service — is sent to the account's registered email / SMS / Zalo and entered back.
- User sets a PIN (used for tap-and-terminal payments above the no-PIN threshold).
- Server binds the card token to the user, stores the PIN as a salted hash, and flips
ISSUED → ACTIVE.
1b — Without the app (activation web page + OTP)
For users who can't or won't install the app, activation runs on a web page (or SMS/IVR) using the same shared OTP service — no app, no login session required. The two factors are preserved by pairing the printed activation code (possession) with an OTP to the registered phone/email (identity).
- Possession: user enters the activation code / card number printed on the card or sealed mailer.
- Identity: an OTP (
scope: card_activation, bound to that card) is sent to the account's registered phone/email and entered back. - User sets a PIN, and the card flips
ISSUED → ACTIVE.
An OTP proves control of the registered contact (identity) — it does not prove the person holds the card. Keep both the printed activation code and the OTP. If you want a truly code-free "OTP-only" activation, the possession factor becomes "the card was mailed to the customer's verified address", which is weaker — acceptable only for low-limit cards and paired with a first-use step-up (confirm the first payment with another OTP). Never activate on an OTP sent to a contact the user just typed in — always the pre-registered channel.
Because the app-less path drops device binding and biometrics, lean harder on the other controls: conservative limits until first successful use, velocity/anomaly checks, and the freeze/report-lost self-service (also reachable from the web page).
Flow 2 — Corporate admin activation
A corporate customer's admin activates cards for employees — the closed-group corporate case where the company issues staff cards funded by the company wallet, each card carrying an allocated card balance. There are two variants; the design recommends the employee-claim variant.
- Admin signs in to the corporate console with an elevated, MFA-protected role (RBAC).
- Admin uploads a batch of card tokens (from the delivery manifest) and maps each to an employee account.
- Server validates the cards belong to this organization's card pool and the employees belong to the org.
- Admin sets policy per card/group: spend limits, allowed vendors, and the corporate funding source.
- Cards move
ISSUED → ASSIGNED. Final activation then takes one of two paths:
| Variant | How ASSIGNED → ACTIVE happens | Security | UX | Recommendation |
|---|---|---|---|---|
| Employee claim | Employee proves possession and sets their own PIN — in the app or via the app-less web + OTP path | Strong — keeps possession + private PIN with the cardholder | One extra step for the employee | Default. Preserves segregation of duties; a card intercepted in transit stays unusable. |
| Admin full-activation | Admin activates with a temporary PIN, forced change on first use | Weaker — admin briefly knows the PIN; no possession check | Fastest; cards work on hand-out | Only for low-limit cards or when employees can't self-serve. |
Prefer the employee-claim variant: the admin assigns and sets policy, but the cardholder completes activation and owns the PIN. This limits insider risk and keeps the possession factor intact even for bulk corporate issuance.
Mode 1 — Tap (NFC contactless) — recommended
The card (or the phone acting as a card via HCE) has a secret key in a secure element. On each tap it computes a dynamic cryptogram — an EMV-style MAC over a transaction counter + amount + terminal nonce. The server verifies the cryptogram and the counter, so a captured tap can't be replayed and the card can't be cloned.
Small amounts can be tap-and-go below the contactless floor limit (no CVM); above it, the card's configured CVM (PIN or OTP) is required. See the trade-off table in Security.
Mode 2 — Vendor scans printed QR on the card
The printed QR is a static card token. Because a static code can be photographed, scanning it must always be paired with a second factor:
Because a static token isn't a credential, the transaction is authenticated by the card's CVM (PIN or OTP) — an in-app approval showing the amount and merchant, a PIN entered on the vendor terminal, or an OTP to the cardholder. Never approve on the token alone.
A printed QR never changes, so treat it strictly as an identifier and lean on the second factor and the risk engine (velocity, geo, amount). Prefer tap where the hardware allows it.
Mode 3 — Manual entry (card-not-present)
The vendor types the card number + expiry (+ CVV). This is the highest-risk mode and should be restricted to trusted vendors and lower limits, always with a step-up:
Rules for this mode: tokenize the PAN immediately, never log PAN or CVV, never store CVV, rate-limit attempts per card/terminal, and always require the step-up.
Illustrative endpoint
{
"amountMinor": 150000,
"currency": "VND",
"acceptance": "tap", // tap | qr | manual
"cardToken": "CT_a1b2...", // present for tap/qr
"cryptogram": "9f8e...", // present for tap
"counter": 42, // present for tap
"orderRef": "INV-2026-0714"
}
| Field | Type | Required | Description |
|---|---|---|---|
amountMinor | number | Yes | Amount in minor units. |
acceptance | string | Yes | tap, qr, or manual — selects the auth factor required. |
cardToken | string | Conditional | Required for tap/qr; the vaulted identifier, not the PAN. |
cryptogram / counter | string / number | Conditional | Required for tap; verified server-side to block replay/cloning. |
orderRef | string | Yes | Vendor order reference for reconciliation. |
Error responses (illustrative)
| Status | Body | Reason |
|---|---|---|
402 | {"error":"insufficient_balance"} | Card balance exhausted, or (when wallet-funded) company wallet/credit too low. |
409 | {"error":"card_frozen"} | Card is frozen or reported lost. |
401 | {"error":"bad_cryptogram"} | Tap cryptogram/counter failed verification (possible replay/clone). |
403 | {"error":"cvm_required"} | Cardholder Verification Method (PIN or OTP) not completed. |
429 | {"error":"velocity_exceeded"} | Too many attempts / amount over the risk threshold. |
See Security & Trade-offs for how these factors are chosen per transaction.