how to pair this app-to-app flow with a Viva Wallet Webhook (Transaction Payment Created) sent from Viva’s servers directly to your backend server to securely finalize the order processing?
Pairing a local browser-to-app checkout with an asynchronous backend webhook is the industry gold standard for payment security. It bridges the gap between a fragile client-side environment (the mobile browser, which can be closed mid-transaction) and a secure server-side database.
The synchronization pattern relies on a unique identifier that ties the in-app terminal payment payload to your specific order record.
The Secure Architecture
[ Mobile Browser ] --(1. Deep Link)--> [ Viva.com Terminal App ]
| | (2. Physical Tap)
(4. Returns App-to-Browser) [ Viva Servers ]
| |
v v (3. Asynchronous HTTP POST)
[ Frontend Callback ] [ Your Backend Server ]
(Polling/Waiting) <--(5. Finalized)-- (Verifies & Saves Order)
Step 1: Generate an Order Tracking ID
Before launching the vivapayclient:// deep link, your system must generate an internal, unique tracking reference for the pending payment.
Viva doesn't allow custom pass-through metadata strings inside the basic app-to-app link payload, but you can repurpose the merchantTrns parameter or pass a tracking parameter inside your custom callback URL.
Option A (Recommended): Store your order ID directly inside the url-encoded
callbackfield:callback=https%3A%2F%2Fyourwebsite.com%2Fapi%2Fviva-return%3ForderRef%3DORD-99824Option B: If supported by the specific version of the local terminal application, append
&merchantTrns=ORD-99824directly to the deep link query parameters.
Step 2: Configure the Webhook in Viva's Dashboard
To catch the payment notification on your backend server:
Log into your live or demo Viva account dashboard.
Navigate to Settings > API Access > Webhooks.
Click Create Webhook and paste your backend listener URL (e.g.,
[https://api.yourwebsite.com/v1/webhooks/viva](https://api.yourwebsite.com/v1/webhooks/viva)).Click Verify (Viva will send an empty test validation payload to your endpoint; ensure your endpoint returns an HTTP 200).
Set the Event Type dropdown explicitly to
Transaction Payment Created.Check Active and click Save.
Step 3: Handle the Webhook Backend Logic
When the terminal successfully captures the card data and authorizes the funds, Viva's servers dispatch an HTTP POST request containing a JSON body to your backend.
Your listener endpoint should match the transaction back to the database, verify the parameters, and update the state securely.
The Webhook Payload Structure
Viva wraps the core data inside an EventData object. Here is the structure to expect:
{
"Url": "https://api.yourwebsite.com/v1/webhooks/viva",
"ContentType": "application/json",
"EventTypeId": 1796,
"EventData": {
"Amount": 12.50,
"CurrencyCode": "978",
"StatusId": "F",
"TransactionId": "e3da21b4-7b9c-44fa-96de-0c15ce664bad",
"OrderCode": 561234987120,
"MerchantTrns": "ORD-99824",
"Message": "Success"
}
}
Backend Processing Checklist (Implementation Blueprint)
Your backend code should handle incoming POST operations using a workflow that guarantees data safety:
// 1. Instantly respond with a 200 OK status to acknowledge receipt
// Viva retries 24 times if you time out or throw a 5xx error.
http_response_code(200);
$payload = json_decode(file_get_contents('php://input'), true);
if ($payload['EventTypeId'] === 1796) { // Transaction Payment Created
$data = $payload['EventData'];
$transactionId = $data['TransactionId'];
$amountReceived = $data['Amount']; // Check your currency scaling rules
$status = $data['StatusId']; // "F" stands for Finalized/Success
$orderRef = $data['MerchantTrns'];
// 2. Security Check: Validate State
if ($status !== 'F') {
exit('Transaction not successfully finalized.');
}
// 3. Database Check: Guard against duplicate hook executions
$alreadyProcessed = checkDbForTransactionId($transactionId);
if ($alreadyProcessed) {
exit('Transaction already handled.');
}
// 4. Match and Compare Values
$order = fetchOrderFromDatabase($orderRef);
if ($order && $order->total_minor_units === ($amountReceived * 100)) {
// 5. Finalize the state safely
markOrderAsPaid($order->id, $transactionId);
dispatchFulfillmentSystems($order->id);
}
}
Step 4: Reconciling the Frontend User Experience
While your backend securely handles the webhook, the user is still interacting with the browser frontend. Tie them together cleanly with these best practices:
The Waiting Screen: When Viva finishes processing and triggers your frontend redirect
callback, display a loading spinner stating "Confirming payment processing..." instead of an immediate confirmation screen.Database Polling: Have your frontend JavaScript poll an internal API endpoint (
/api/orders/ORD-99824/status) every two seconds to check if the backend has flipped the flag topaid.Fallback Resolution: If after 15 seconds the webhook hasn't arrived (due to extreme network latency), use Viva's Retrieve Transaction Details API manually from your backend using the
transactionIdprovided in the frontend URL query string to actively pull the final status.
Reacties
Een reactie posten