← All posts
BEST PRACTICESFebruary 26, 2026 · 5 min read

Payment Processing Best Practices

From idempotency keys to retry logic, the engineering habits that prevent lost revenue.

By Cenoa Team

Payments code is unforgiving. A bug in your blog renders a typo; a bug in your payments code charges customers twice. The good news is that the discipline required to write reliable payments code is well-understood and largely the same across processors.

Always use idempotency keys

Every modern payments API supports idempotency keys. They turn a "charge this card" request into "charge this card, but only once." If your network call times out and you retry, the second request returns the same result as the first instead of double-charging.

const charge = await stripe.charges.create(
  { amount: 4500, currency: "usd", source: tokenId },
  { idempotencyKey: `order-${orderId}` },
);

The key should be deterministic for the operation. Use the order ID, not a UUID generated at request time.

Webhooks are the source of truth

It is tempting to read the response of your charge call and update your database from there. Resist. Use the response only to confirm the request was accepted, then wait for the webhook (charge.succeeded or payment_intent.succeeded) to mark the order paid in your database.

Why? Because some payment methods (SEPA, ACH, BACS) confirm minutes or hours after the initial request. Modeling those as synchronous will quietly corrupt your data.

Build for replay

Webhooks fail. Your endpoint goes down for two minutes; the processor retries with an exponential backoff. Make sure your handler:

  • Uses the event ID as an idempotency key on your side too.
  • Handles the same event arriving twice.
  • Handles events arriving slightly out of order (charge.refunded arriving before charge.succeeded is rare but happens).

A simple pattern: store every event in a table, mark it processed only after side-effects succeed, replay unprocessed events nightly.

Reconcile daily, not monthly

Every night, pull your payouts from the processor and reconcile against your internal ledger. Even a tiny mismatch — a refund recorded in your DB that the processor never confirmed — should produce an alert. Catching it the same day is cheap; catching it during a quarterly close is expensive.

Test the unhappy paths

The happy path is easy. The bugs live in:

  • Network timeouts mid-charge.
  • Duplicate webhooks.
  • Refunds that fail.
  • Disputes opened on a charge you already refunded.
  • Customers who change their card mid-subscription.
  • Currency mismatches between presentment and settlement.

Write integration tests for each. Most processors offer test cards specifically designed to trigger these scenarios.

Security baseline

  • Never log full card data. Most processors will revoke your API key if they see it in your logs.
  • Validate webhook signatures. Anyone on the internet can POST to your webhook URL.
  • Use restricted API keys with the minimum scope needed for each service.
  • Rotate keys at least annually, and immediately after any staff departure with access.

Observability

Treat payments code with the same seriousness as your authentication code. Tag every metric and log line with the order ID, customer ID, and processor reference ID. When something breaks at 2am on a Saturday, those tags determine whether you fix it in 10 minutes or 10 hours.

How Cenoa Payment Helps

Cenoa Payment was built to remove the friction this article describes. Whether you are a freelancer collecting your first international invoice or a fast-growing merchant accepting payments in dozens of currencies, Cenoa gives you wallet, checkout, and payouts under one roof — backed by regulated payment and banking partners.

  • Open a multi-currency wallet in minutes, no minimum balance.
  • Accept cards, Apple Pay, SEPA, iDeal, bank transfers, and crypto from 195 countries.
  • Pay and get paid by username, link, or QR code — no IBAN gymnastics.
  • Real-time fraud and KYC tooling so your account stays in good standing.

If you are evaluating processors, sign up for free and try a real transaction end-to-end. Most teams know within an hour whether Cenoa fits their workflow.

#engineering#reliability#payments

Ready to accept payments globally?

Open a free Cenoa Payment account and start collecting in minutes.

Get Started with Cenoa Payment