Payment providers each describe a payment differently. A failed charge can arrive as a JSON error from an API, an XML document from an older gateway, a form-encoded postback, a raw HTTP response with a plain-text body, or a series of webhook deliveries that may be duplicated or out of order. Debugging means translating all of that into one picture: which events belong to the same transaction, what the provider actually reported, and what is merely missing.
PandaPayLens takes pasted input from 40 providers, detects the provider and format, normalizes the records, rebuilds the timeline and runs a catalog of explainable rules over it. It runs in three places from the same engine: a web analyzer, a static demo on GitHub Pages, and an offline CLI published to npm as pandapaylens.
The design constraint that shapes most decisions is privacy. Payment payloads contain card data, names, emails and credentials, so the analysis must run where the data already is: in the browser or on the developer's machine.
Each adapter implements the same interface: detect, parse, normalize, decodeErrors and correlationKeys, plus a capability manifest that states what is supported, limited or experimental. A manifest capability is marked supported only when it is implemented and tested.
Normalization copies only allowlisted fields. Amounts are kept as integer strings in minor units, never floats, and an UNSAFE_INTEGER warning is raised when a value is not an exact integer. Every normalized event carries a coarse lifecycle stage, but the type documentation is explicit that this is a display aid: authorization is not settlement, and a capture is not necessarily settlement either.
Rules are pure functions of the normalized context. A rule that throws becomes a RULE_FAILED warning instead of crashing the analysis, and finding text never quotes payment identifiers, so masking in reports stays effective.