Skip to content

Architecture

Building Payment Systems With PCI DSS in Mind

Payment integration isn't just about sending a transaction to a gateway. Architecture decisions around card data, third-party scripts, failure handling and observability all affect the security and reliability of the system.

Payment processing is one of the areas of software development where small architectural decisions can have significant consequences.

I’ve worked with payment technologies including Stripe, PayPal, Cardknox, ProPay, Adyen and Authorize.Net across eCommerce and enterprise systems.

The technical integration itself is only part of the problem.

Security, reliability, compliance and failure handling need to be considered from the beginning.

Reduce Exposure to Card Data

One of the most important architectural principles is simple:

Your application should handle as little sensitive card data as reasonably possible.

Modern payment providers offer hosted fields, tokenisation and other mechanisms that can reduce direct exposure to payment information.

The more sensitive information your application touches, the larger the security and compliance responsibility becomes.

A good payment architecture starts by asking whether the application needs access to the data at all.

PCI DSS Is an Architecture Concern

PCI DSS shouldn’t be something considered only after development is complete.

The architecture of the payment flow affects the compliance scope.

Questions such as:

  • Where are payment fields rendered?
  • Which scripts can execute on the payment page?
  • Where are tokens stored?
  • What information reaches the server?
  • What gets logged?
  • Which external services participate in the transaction?

all have security implications.

Compliance is much easier when the application architecture was designed with those constraints in mind.

Treat the Browser as Part of the Payment Environment

Modern checkout experiences depend heavily on JavaScript.

That creates another area that deserves attention.

Third-party scripts, tag managers, analytics tools and compromised JavaScript can potentially affect sensitive pages.

Payment-page security therefore isn’t limited to backend code.

Understanding what executes in the customer’s browser is increasingly important as well.

Never Assume a Payment Request Will Succeed

Payment providers are external systems.

External systems fail.

Networks time out.

Requests can be retried.

Customers can close browsers.

A gateway can approve a transaction while your application fails before updating its own database.

This means payment workflows need to be designed around states rather than assuming a simple request → success sequence.

Idempotency Matters

Duplicate payment attempts are one of the risks created by retries and network failures.

Where supported, idempotent operations help ensure that retrying a request doesn’t unintentionally create a second transaction.

Applications also need their own safeguards around order and payment state.

The customer should never be charged twice simply because a request timed out at the wrong moment.

Design for Failure

For business-critical payment platforms, failure handling needs to be part of the architecture.

That can involve:

  • retry strategies
  • clear transaction states
  • gateway health monitoring
  • logging
  • alerts
  • reconciliation
  • and, in appropriate systems, routing between payment providers.

The exact architecture depends on the business requirements.

But the principle remains the same:

Payment failure should be an expected system condition, not an unexpected exception.

Logging Without Leaking Sensitive Data

Payment systems require strong observability.

When something fails, developers need enough information to understand what happened.

At the same time, logs must not become another location containing sensitive payment information.

Logging strategies should therefore capture useful operational context while deliberately excluding sensitive card data.

Good observability and good security are not competing goals.

They need to be designed together.

Reconciliation Is Part of Reliability

One difficult payment scenario is when the payment provider and the local application disagree.

For example:

  1. The gateway reports success.
  2. The application experiences a timeout.
  3. The local order remains in an uncertain state.

Systems need ways to resolve these situations.

That may involve webhooks, transaction queries, reconciliation jobs or administrative tools.

The goal is to establish a reliable source of truth and recover from partial failures.

Security Is a Continuous Process

Payment security doesn’t finish when an integration goes live.

Dependencies change.

Scripts change.

Payment providers evolve.

Compliance requirements evolve.

New vulnerabilities appear.

Security therefore needs ongoing:

  • monitoring
  • review
  • patching
  • auditing
  • and testing.

The Best Payment Architecture Is Boring

A successful payment system shouldn’t regularly surprise the development team.

Transactions should move through clearly defined states.

Failures should be observable.

Retries should be safe.

Sensitive information should be minimised.

Integrations should be documented.

Operational teams should know how to investigate problems.

When all of that works, the payment layer becomes predictable infrastructure.

And for systems responsible for real money, predictable is exactly what you want.

MoreThoughts

Have a project in mind?

Let's buildSomethingThat works.

I'm available for selected .NET, nopCommerce, eCommerce and software-development projects, as well as technical consulting and long-term collaboration.

Fields marked * are required.