Skip to content
3toggles Contact
payments 3-D Secure security

Why 3-D Secure payments fail intermittently, and how to fix the signature

Short answer: intermittent “invalid signature” declines under 3-D Secure are almost never a 3-D Secure problem. They are a determinism problem. If two systems can serialize the same payment data in two slightly different ways before signing it, their signatures will differ, the gateway will reject the request, and the failure will look random.

The failure mode

3-D Secure requires that the signature on a request match exactly what the gateway recomputes on its side. The signature is a hash of the request, so it is exquisitely sensitive: change one byte of the signed payload and the hash changes completely. That is the whole point of a cryptographic signature, and it is also the trap.

The data is usually correct. What differs is the serialization: the order of the fields, the casing of a value, an encoding choice, an extra whitespace character. Any of those produces a different byte string, a different hash, and a rejected payment.

Why it looks intermittent

In a single-terminal integration you would notice immediately. The problem hides in fleets. In a multi-branch POS estate, terminals get provisioned at different times with subtly different firmware and configuration, so two terminals can hold identical order data and still build a different request body to sign. One signs fields in the order amount, currency, ref; another uses ref, amount, currency. Both look fine in logs. One passes, one fails, and which is which drifts as terminals are updated.

Because it is data-dependent and config-dependent, it presents as “random” declines, and it quietly corrupts settlement reconciliation in the background.

The fix: canonicalize before you sign

Stop trusting whatever a client happens to emit. Build the signed string yourself, deterministically:

  • Fixed field order. Define one canonical order and sort into it every time.
  • Normalized casing and encoding. Decide on case and character encoding and apply them uniformly.
  • A strong hash with the right secret. Sign the canonical string with HMAC-SHA512 against the acquirer’s shared secret.
  • Idempotent signing. A retried request must reproduce the same signature, never a second divergent one.

Once canonicalization is in place, terminal-specific quirks become irrelevant: identical data produces an identical signature everywhere.

Catch it before reconciliation does

A signature bug you cannot see is one you cannot fix. Alert on settlement exceptions whose reason codes indicate signature mismatch, so drift surfaces in minutes instead of showing up weeks later as a reconciliation gap. Roll the fix out terminal by terminal with no downtime and watch reconciliation return to balance as each one migrates.

Takeaways

  • Treat the signed payload as a canonical artifact you construct, not as whatever the client serializes.
  • Determinism is the feature: same input, same signature, every terminal, every time.
  • Make money-moving operations idempotent so retries are safe.
  • Alert on settlement exceptions; do not let reconciliation be your monitoring.

Got a system like this to build?

An experienced engineer, not a salesperson, will scope it with you and reply within 24 hours.