Backend integrations

Payment integrations are a state-management problem

Checkout, capture, webhooks, and retries through the lens of my payment-service experience.

More than a gateway request

My Java and Spring work at Prokoders included payment services covering checkout, capture, webhooks, payment links, validation, and resilient error handling. These are connected stages rather than independent API calls. A browser can close after checkout, a provider can reply late, and an event can arrive while another request is still being handled. The application needs a clear account of the payment state throughout those transitions.

Model uncertainty explicitly

A timeout does not prove that a payment failed. It can mean the application did not receive the result. Distinguish a confirmed failure from an unresolved operation, then define how reconciliation works. Keep provider references alongside internal identifiers so that events and follow-up checks can be linked to the same operation. The names and transitions should follow the actual provider contract and the business workflow.

Make duplicate handling testable

Before relying on webhooks, define how their authenticity is checked and how repeated delivery is handled. Test the same notification twice and verify that it does not create two business actions. Also test a late notification after an earlier timeout. A useful acceptance check inspects the stored transaction and related business record, not only the HTTP response. This keeps integration testing focused on correctness across the whole workflow.

Back to all articles