Appearance
Viva Wallet Integration
Overview
Viva Wallet is Upvendo's kiosk / in-person card-terminal payment provider. Online ordering always uses Stripe (and when Square POS is connected, Square handles everything). A merchant's Viva Wallet connection lives on a payment profile: you set it up once on the profile detail page, which creates a Viva Wallet connected account through Upvendo's ISV (Independent Software Vendor) integration. The merchant then completes onboarding on Viva Wallet's own dashboard.
There are no merchant-entered Viva credentials in the back office (no API key, API secret, merchant ID, or source-code fields). Authentication is handled at the platform level using Upvendo's ISV OAuth credentials; the back office only shows read-only Viva account details once the account is created.
Key purpose: Process card payments on physical Viva terminals at kiosks / point of sale.
Note: When Square POS is connected, Square Payments is used instead of Viva Wallet for kiosk/in-person payments.
Purpose
This page (the payment profile detail page) lets you set up a Viva Wallet connected account for kiosk/in-person card payments and view its read-only account details. Terminals themselves are assigned per device in Device Management, not here.
Key Concepts
- ISV model (config-level OAuth): Upvendo connects to Viva Wallet as an ISV partner ("Upvendo"). All Viva API calls authenticate with platform-level ISV/reseller credentials (
services.viva.{eu|us}.client_id/secret_key/reseller_id/reseller_secret) selected by country (US vs EU). There is no per-profile API key. - Connected account: Setting up Viva on a payment profile calls Viva's ISV "create account" endpoint, stores the result under
external_data.viva_wallet, and returns a redirect URL where the merchant finishes onboarding on Viva's dashboard. - Account ID / Merchant ID:
viva_wallet.accountIdis the ISV connected-account identifier;viva_wallet.merchantIdscopes payment/terminal API calls to that merchant. Both are displayed read-only in the back office. - Terminal sale (Cloud ECR API): A kiosk payment creates a terminal session identified by an idempotency key (used as the
sessionId), sent to the assigned physical terminal via Viva's Cloud ECR API; the session status is then polled until the customer taps/inserts their card. - Source codes (deprecated): Per-location Viva
online/physicalsource codes are no longer generated. Existing values are preserved; new locations use the source code'Default'. - Pre-authorization / capture: Some flows create a pre-auth and capture later. Whether a transaction is a pre-auth is read from the transaction's
payment_snapshot['preauth'](isVivaWalletPreauth()); when true, the verification step captures the transaction.
Actions
Set Up Viva Wallet Account
On the payment profile detail page, click Setup Viva Wallet Account. This creates a Viva Wallet connected account via Upvendo's ISV integration and opens Viva's onboarding/signup page (a redirect URL returned by Viva). No credentials are entered in Upvendo.
View / Edit Viva Wallet Account
Once created, the profile shows a read-only Viva Wallet Account section (Account ID, Merchant ID, Email, Acquiring Enabled, Legal Name, VAT Number, and a verified/not-verified status). The Edit action opens a dialog that displays the Account ID (with copy) and a link to the Viva Wallet dashboard (accounts.vivapayments.com) — it does not edit credentials in Upvendo; account changes are made on Viva's side.
Assign a Terminal to a Device
Physical terminals are assigned per device (kiosk), not on the payment profile. In Device Management → Devices, open the device's Reader / Terminal section and Add Terminal → Assign Viva Terminal, then pick a terminal from the list available on the merchant's Viva account. (See the Payments feature for the full per-provider pairing flow.)
When Viva Wallet is Used
| Channel | Payment provider | Notes |
|---|---|---|
| Online Ordering | Stripe | Customer web payments through the profile's Stripe connected account (Viva is not the online provider) |
| Kiosk / In-Person (terminal) | Viva Wallet | Card payment on the physical Viva terminal assigned to the kiosk device |
| Any channel when Square POS connected | Square Payments | Square overrides both Stripe and Viva Wallet |
A legacy Viva "web payment order" path (
createPaymentOrder) still exists in the backend and can drive a hosted Viva checkout (with a country-default method — iDEAL for NL, Bancontact QR for BE, Klarna for DE, Multibanco for PT), but the primary online-ordering provider is Stripe.
Location
- Backoffice route: payment profile detail page —
/settings/payments/profiles/:id(Viva is set up here, not at a dedicated/settings/payments/viva-walletpage) - Setup endpoint:
POST /payment-profiles/{id}/viva-wallet/account→PaymentProfileController::createVivaWalletAccount - Backend service:
app/Services/Common/VivaWalletService.php - Account model accessors:
app/RawModels/PaymentProfile.php(getVivaWalletAccountId(),retrieveVivaWalletData()) - Back-office components:
src/views/settings/Payments/PaymentProfileDetail.vue,EditVivaWalletAccountDialog.vue,VivaAccountIdDialog.vue; terminal assignment insrc/views/devices/components/setup-device/reader-section/ReaderSection.vue
Fields
There are no Viva credential or toggle fields in the back office. Setting up Viva is a single Setup Viva Wallet Account action that creates a connected account; everything else is read-only and is sourced from Viva.
Read-only Viva Wallet account details (shown after setup)
| Field | Source | Notes |
|---|---|---|
| Account ID | viva_wallet.accountId | ISV connected-account ID (copyable) |
| Merchant ID | viva_wallet.merchantId | Scopes payment/terminal API calls |
viva_wallet.email | Onboarding email | |
| Acquiring Enabled | viva_wallet.acquiringEnabled | Shown as Enabled/Disabled |
| Legal Name | viva_wallet.legalName | Shown if present |
| VAT Number | viva_wallet.vatNumber | Shown if present |
| Verified | viva_wallet.verified | Drives the verified / not-verified status badge |
Onboarding (and any credential / business-detail changes) happens on Viva Wallet's dashboard, not in Upvendo.
Test mode (per location, not a Viva field)
Test/simulation is not a Viva Wallet setting. It is the per-location payment_test_mode flag (toggled from the profile detail page's Locations list) that simulates payments for both Stripe and Viva without real charges. See the Payments feature.
Business Logic
Kiosk terminal payment flow
Customer completes kiosk order
|
v
Provider check: Square integrated?
Yes -> route to Square Terminal
No -> Viva Wallet terminal sale
|
v
initiateTerminalSale (Cloud ECR API)
sessionId = idempotency key
terminalId = device's assigned Viva terminal
amount + tipAmount, merchant/source from location
|
v
Card terminal activated -> customer taps/inserts card
|
v
Status polled / webhook received -> payment verified
|
v
Order confirmedOnline ordering (for contrast)
Online ordering creates a Stripe PaymentIntent on the profile's Stripe connected account (or Square when connected). The Viva createPaymentOrder web-checkout path is a fallback, not the primary online flow.
Webhook capture and retention
Every inbound Viva webhook is persisted losslessly at ingestion — before the duplicate guard and before location resolution — because Viva offers no dashboard resend. If an event cannot be matched to a location, or arrives as a duplicate, the raw payload is still on file and replayable.
- Stored in the shared
logscollection undertype: 'viva_webhook'. - The capture is an idempotent upsert keyed on
{webhook_id, type}, wherewebhook_idis a content hash. A redelivery incrementsoccurrencesrather than inserting a second row, andcreated_atis written only on insert because it anchors the TTL. - Capture failures are swallowed — the payment path is never blocked by a logging problem (a warning is logged instead).
- Retention is a partial TTL index scoped to
type: 'viva_webhook', 90 days (expireAfterSeconds: 7776000), so it prunes only these PII-bearing receipts and never touches other documents in the shared collection.
This is platform behaviour, not a merchant-facing setting. It does not contradict compliance.md's statement that there are no merchant-configurable data-retention settings — there still are none.
Business Rules
- Kiosk only: Viva Wallet is the kiosk/in-person provider. Online ordering uses Stripe; the provider is chosen at payment time (
isSquareIntegrated()→ Square, otherwise Viva for kiosk / Stripe for online). - Square overrides Viva: When Square POS is connected, kiosk payments route to Square Terminal instead of Viva.
- ISV / config-level auth: All Viva calls use platform ISV/reseller credentials selected by country (
usvseu); there is no per-profile/per-location API key. ISV partner name is "Upvendo". - One connected account per profile: Setting up Viva when an account already exists is rejected (
Viva Wallet account already exists for this payment profile). - Default profile needs verification: A profile can be set as default only when Viva-verified (or its Stripe online ordering is ready).
- Source codes deprecated: New locations use the
'Default'source code; existing per-locationonline/physicalsource codes are preserved but no longer generated. - Idempotency / 409 retry: Each terminal sale uses an idempotency key as the
sessionId; on a409conflict the system generates a new idempotency key and retries. The device'slatest_idempotency_keyis updated after each initiation, and the transaction tracksall_idempotency_keys. - Amounts in cents: Amounts are normalized to the smallest currency unit before being sent to Viva; currency is sent as Viva's numeric code (EUR 978, GBP 826, USD 840, CHF 756).
- Environment URLs: Base URLs switch by
isProduction(derived from! isTestEnv()): production usesapi.vivapayments.com/www.vivapayments.com/accounts.vivapayments.com; non-production uses thedemo-api/demo/demo-accountsequivalents. - Webhook security: Viva webhooks are received at
/api/viva-webhook/{countryCode}/{eventTypeId}. There is no per-request signature; GET returns the verification key, and POST is protected by IP allowlisting (verify.viva-webhookmiddleware, production vs demo Viva IP ranges). (Verified:routes/api/guest.phplines 44-47 — the file appliesguestas middleware, not as a URL prefix —required fromroutes/api.phpline 38 outside any prefix group, under Laravel's/apiprefix frombootstrap/app.phpline 14. The comment atroutes/api.phpline 15 still says/api/guest/...and is stale.) - Every webhook is captured for 90 days: Each inbound Viva webhook is persisted to the shared
logscollection (type: 'viva_webhook',status: 'received') before the duplicate guard and before location resolution, so every event stays replayable — Viva offers no dashboard resend. Retention is a partial TTL of 90 days (7,776,000s) scoped to that type. (Verified:app/Services/Orchestrators/VivaWebhookOrchestrator.phplines 41-45 and 196-207;app/Repositories/RequestLogRepository.phplines 67-96 and 105-133.)
FAQs
"Is Viva Wallet used for online ordering?" No. Online ordering uses Stripe (or Square when connected). Viva Wallet is the kiosk / in-person card-terminal provider. (A legacy Viva web-checkout path exists in the backend but is not the primary online flow.)
"Where do I enter my Viva Wallet API key / merchant ID / source code?" You don't. Upvendo authenticates with Viva at the platform level (ISV OAuth). Setup is a single Setup Viva Wallet Account button that creates a connected account; the back office then shows read-only details (Account ID, Merchant ID, etc.). You finish onboarding on Viva's dashboard.
"How do I connect Viva Wallet?" On the payment profile detail page, click Setup Viva Wallet Account. Upvendo creates the connected account and opens Viva's onboarding page. Complete onboarding there; the profile then shows your Viva account details and a verified status.
"How do I add a Viva terminal to a kiosk?" In Device Management → Devices, open the device, go to the Reader / Terminal section, choose Add Terminal → Assign Viva Terminal, and pick a terminal from your Viva account. Terminals are assigned per device, not on the payment profile.
"Can I use Viva Wallet and Square at the same location?" No. At payment time the system checks
isSquareIntegrated()and routes to one provider. If Square POS is connected, kiosk payments go through Square instead of Viva."What happens if the customer doesn't tap their card?" The terminal session stays pending until it times out; the session can be aborted (its idempotency key is tracked), and a retry generates a fresh idempotency key.
"What countries / currencies are supported?" ISV credentials are chosen by region (US vs EU). Currency is mapped per country (EUR for BE/NL/DE/FR/IT/ES/PT, GBP for GB, CHF for CH) and sent to Viva as a numeric code.
"How are tips handled?" The tip is sent as a separate
tipAmounton the terminal sale, captured as part of the same transaction. Whether tips are collected (and the percentage options) is configured at the location/device Collect Tips settings, not on Viva.
Troubleshooting
Kiosk/terminal payments failing
Causes:
- No Viva terminal assigned to the device
- Viva connected account not verified / onboarding incomplete
- Location is in test mode (
payment_test_mode) and being simulated - Square is connected, so payments route to Square instead
Solutions:
- Assign a terminal in Device Management → Devices → Reader/Terminal
- Complete onboarding on Viva's dashboard until the account shows verified
- Check the location's test-mode setting on the profile detail page
- If using Square, manage kiosk payments through Square
Terminal not responding
Causes:
- Terminal offline or powered down
- Wrong terminal assigned to the device
- Network issue between terminal and Viva Cloud
Solutions:
- Check terminal power and connectivity
- Re-assign the correct Viva terminal to the device
- Check network; the system retries on session conflicts (409) with a new idempotency key
"Viva Wallet account already exists for this payment profile"
A profile can hold only one Viva connected account. The account is already set up — view/edit it from the profile detail page rather than creating a new one.
Assistant Guidance
When answering questions about Viva Wallet:
- Viva Wallet is the kiosk / in-person provider. Online ordering uses Stripe; Square overrides both when connected.
- There are no Viva credential fields (API key/secret, merchant ID, source code) in the back office — auth is platform-level ISV OAuth. Do not describe a credentials form.
- Setup is the Setup Viva Wallet Account button on the payment profile detail page; onboarding finishes on Viva's dashboard. Back-office Viva details are read-only.
- Terminals are assigned per device (kiosk) in Device Management, not on the payment profile.
- Per-location source codes are deprecated (new locations use
'Default'). - Test mode is a per-location setting (
payment_test_mode), not a Viva setting.
Relations
Depends On
- Payment Profiles: The Viva connected account lives on a payment profile (
external_data.viva_wallet). - Locations: A profile is assigned to locations; the location carries the Viva merchant ID and (deprecated) source codes.
- Devices: A physical Viva terminal is assigned per device for kiosk payments.
Affects
- Kiosk payments: Terminal sales, refunds, and pre-auth/capture.
- Transactions: Viva order/session records and payment verification.
- Commission / Reporting: Viva terminal IDs are tracked on the merchant for commission attribution.
Storefront / payment-proxy behavior (how the hosted Viva checkout or the kiosk app surface the terminal prompt to the customer) is not verified here.