Case studies/FinTech & payments
Payments · platform, SDK and PCI environment

SeamlessPay

2014 - 2021

Payment optimization platform: intelligent routing, approval rates, chargeback reduction.

Overview

SeamlessPay is a payment optimization platform for high-growth businesses. It sits above payment processors to raise approval rates and reduce losses from false declines, fraud and chargebacks, combining smart routing, network tokens, account updater and intelligent retries with adaptive 3D Secure, real-time fraud scoring, Verifi and Ethoca alerts and AI-assisted dispute handling, through one integration and without locking a merchant into a single processor.

Behind that product sits the platform itself. The payment core is a set of microservices on AWS Lambda behind API Gateway, with the heavier and longer-running services in ECS Fargate containers behind a load balancer, scaling task count up and down with load. Card transactions run through a First Data integration, ACH through integrations with several different processors, and PayPal alongside them. The API is not an internal detail: physical payment terminals transact through it, so it is a public contract with hardware in the field on the other end.

On the client side there is a payment web SDK built the way Braintree builds one - card fields in an iframe, cross-frame messaging over framebus, promise wrapping - with card validation and card-type detection, and a separate package that masks and restricts what can be typed into a card field. Both are released by semantic-release, and the input package is tested in real browsers through WebdriverIO on BrowserStack rather than in a headless approximation of them.

The backend packages run on Feathers.js with socket.io and JWT authentication over MongoDB, deployed through the Serverless framework with Step Functions, run locally against localstack and fed credentials from encrypted credential storage. Infrastructure is AWS CDK v2 in TypeScript with Sentry wired in, and the whole thing is delivered by GitHub Actions: infrastructure deploys automatically, but only after the unit tests pass - a red test suite means no deploy. Exceptions and system events land in Slack channels rather than in a log nobody reads, and merchant portals are built in React and Mantine with Next.js and NestJS.

Because card data is held rather than passed through, the platform lives under audit. Card numbers are stored only encrypted; the database has no route in from the internet; CloudWatch logs are checked to make sure no card numbers and no personal data end up in them, with logging hygiene treated as its own requirement; and the cardholder data environment is a separate infrastructure stack of its own rather than a wing of the main one.

Its public site, seamlesspay.com, runs on WordPress with a site-specific theme and Genesis Blocks, hosted on WP Engine behind Cloudflare. It presents the product suite, use cases, practical guides and interactive tools such as a VAMP calculator and a chargeback cost calculator, captures audit requests through HubSpot forms, and links out to developer documentation, the merchant portal and a public status page.

What was built

Stack

Backend

AWS Lambda + API Gateway
The payment core as microservices behind one API surface
ECS Fargate
Containerised services behind a load balancer, autoscaling on load
Feathers.js
Backend services with socket.io and JWT authentication
NestJS
Backend behind the merchant portals
Serverless framework
Deployment of the functions, with Step Functions for multi-step flows

Frontend

React + Mantine
Merchant portal interfaces
Next.js
Portal application framework
Payment web SDK
Braintree-style architecture: iframed card fields, framebus messaging, promise wrapping, card validation and card-type detection
restricted-input
TypeScript package masking and constraining card entry

Data

MongoDB
Store behind the backend services
Encrypted card storage
Card numbers held only in encrypted form, in a database with no route in from the internet

Infrastructure & DevOps

AWS CDK v2 (TypeScript)
Infrastructure as code for the platform and, separately, for the cardholder data environment
GitHub Actions
Automatic deploys gated on a passing unit-test run
Sentry
Error tracking wired into the service wrapper
Slack alerting
Exceptions and system events routed to channels the team watches
localstack
Local AWS for running the serverless services without a cloud account

Integrations & Payments

First Data
Credit card transaction processing
ACH processors
Integrations with several different ACH processors
PayPal
Alternative payment method alongside cards and ACH
Payment terminals
Physical terminals transacting through the platform API

Security & Compliance

PCI cardholder data environment
Its own infrastructure stack, separate from the main platform
Log hygiene
CloudWatch logs checked for card numbers and personal data as a standing requirement
Encrypted credential storage
Service credentials pulled from an encrypted store rather than from configuration

Tooling & QA

Jest
Unit and integration tests across the backend packages and infrastructure code, with coverage reporting
WebdriverIO + BrowserStack
Real-browser tests for the card input package
semantic-release
Versioning and publishing of the SDK packages
Lerna monorepo
Package management across the platform's JavaScript packages

CMS & Commerce

WordPress on WP Engine
The marketing site, with a site-specific theme, Genesis Blocks and HubSpot forms, behind Cloudflare

Engineering highlights

The API had hardware on the other end: physical terminals in the field transacted through it, which turns every breaking change into a field problem rather than a deploy note.

Deploys are gated on tests by construction - GitHub Actions rolls out infrastructure only after the unit suite passes, so a red suite is not a judgement call.

The card SDK borrows an architecture that has already survived PCI scrutiny - Braintree's iframed fields and cross-frame messaging - instead of inventing one, and the input-masking package is tested on real browsers because card fields break in browsers, not in jsdom.

The cardholder data environment is a separate stack, so the PCI scope has an edge that can be pointed at during an audit rather than explained.