VMTech
Discuss a project
← All capabilities
SYSTEMS & INTEGRATIONS · 09

Online payments

Payment is the one place in a system where a mistake costs money directly. So it is designed as if the connection will drop at the worst possible moment: it will.

Discuss a project
WHAT CAN GO WRONG

Six places where a payment usually gets lost

Every step can fail — and at each one the system has to stay in a state you can reason about.

checkout.example.rs
Transaction for order #4821
LIVE
no differences
A double click one transaction
The amount is tampered with signature valid
The customer closed the tab callback received
The gateway did not answer status pending
A refund refunded
The daily reconciliation no differences
WHAT CAN GO WRONG
  1. A double clickAn idempotency key makes retries safe: two requests create one payment, not two charges
  2. The amount is tampered withThe amount comes from the order on the server, not the form — the request signature is verified
  3. The customer closed the tabThe result arrives as a separate gateway notification — the order updates without the customer returning
  4. The gateway did not answerThe transaction is marked unknown and polled: its status is requested until it resolves
  5. A refundFull or partial, tied to the original transaction; a repeated request does not create a second refund
  6. The daily reconciliationThe statement is matched to transactions: differences are listed rather than hunted by hand
A FAMILIAR PICTURE

What happens when payments are wired up “by the manual”

The bare-minimum integration

  • The customer is charged twice because they pressed the button twice
  • The order status changes only if the customer returns to the site after paying
  • If the gateway times out, the transaction hangs in limbo forever
  • Refunds are issued in the bank's portal and the system never hears about it
  • Reconciliation is an accountant, a statement and an evening with a calculator

An engineered integration

  • A repeated request with the same key returns the same transaction instead of creating another
  • The result reaches the server directly and is processed independently of the browser
  • Unresolved transactions are polled automatically until they reach a final status
  • Refunds go through the system, so the order, the stock and the report all learn about it at once
  • Reconciliation is daily and automatic: the list of differences arrives in the morning
SCOPE OF WORK

What the payments work covers

Transaction model

Order and payment are separate entities with their own states; the transitions are written down.

Gateway integration

Initialisation, request signing, response handling and authenticated bank callbacks.

Idempotent operations

Idempotency keys, so a retried request never becomes a second charge.

Declines and timeouts

A clear message to the customer, the order preserved and automatic resolution of unclear statuses.

Refunds and voids

Full and partial operations from the admin panel, with permission checks and a record of who did it.

Reconciliation

Daily matching of transactions against the statement and a report of what does not add up.

Logging and observability

Every attempt is stored with the gateway's response; a rise in declines is visible at once, not through complaints.

Test scenarios

We test not only a successful payment but a decline, a drop, a double click and a refund.

TECHNOLOGY LANDSCAPE

What reliability is made of

The bank's formCard details are entered on the bank's side and never reach your server
Request signingThe amount and parameters are signed — they cannot be altered in the browser
Idempotency keysA repeated request returns the earlier result instead of a new transaction
Callback queueGateway callbacks are processed one at a time and survive a server restart
Background pollingTransactions without a final status are polled until they resolve
Reconciliation reportA daily match against the statement and a list of mismatches

The acquiring contract and the rates are between you and the bank. We are responsible for money and orders agreeing, and for disputes being settled from the log rather than from memory.

QUESTIONS

What people usually ask

A customer was charged twice. How does that happen?

Usually a missing idempotency key: the user clicked twice, or the browser retried after a drop, and two transactions were created. The right fix is not hiding the button for a second but making a repeat with the same key return the earlier transaction.

What about payments stuck in limbo?

They appear when the gateway did not answer in time although the result already exists on its side. We mark such transactions as unresolved and poll their status until it is final. Without that mechanism the money is taken while the order stays unpaid, and someone sorts it out by hand.

Do we need to store card data for recurring charges?

No. For recurring charges the bank issues a token tied to the card: you store that instead of the details, and it works only for your transactions. The card numbers themselves never appear on your server, so the storage requirements do not apply to you.

How do we know the decline rate has risen?

From the transaction log and watching it. Every attempt is stored with the bank's response code, so you see not just “fewer payments” but why: insufficient funds, a limit rejection, a failed confirmation. Those are different problems with different fixes.

Can several payment methods run at once?

Yes, and it is the normal case: card, bank transfer and cash on delivery coexist. What matters is that each method has its own chain of statuses: cash on delivery is confirmed by the carrier's report rather than the bank statement, otherwise reconciliation stops adding up.