{"id":161,"date":"2026-05-24T18:30:51","date_gmt":"2026-05-24T17:30:51","guid":{"rendered":"https:\/\/lukaskoren.tech\/?page_id=161"},"modified":"2026-05-27T18:17:01","modified_gmt":"2026-05-27T17:17:01","slug":"merchant-refund-fraud-feature","status":"publish","type":"page","link":"https:\/\/lukaskoren.tech\/?page_id=161","title":{"rendered":"Merchant Refund Fraud Feature"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\"><strong>MATCHED REFUNDS LITE (MRF)<\/strong>&nbsp;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>TL;DR<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Matched Refunds Lite (MRF) at Paymentsense (Dojo) eliminated \u00a3513,000 per month in direct settlement losses &#8211; targeting a confirmed annual fraud exposure of \u00a3500,000\u2013\u00a3700,000 across the physical terminal estate. Dojo was the only card payment platform in the UK allowing unmatched refunds: any terminal operator could issue a refund to any card, at any value, with no prior transaction required. A tap-based transaction-matching mechanism, built within the existing Authorisation Gateway, closed that gap in one quarter without ML infrastructure, vendor dependency, or PCI DSS re-scoping.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>CONTEXT<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Paymentsense (rebranded Dojo) is a UK payment gateway and acquiring platform serving tens of thousands of SME merchants through physical card terminals. Dojo settles net with its merchant base &#8211; refunds issued by merchants are funded directly from Dojo&#8217;s settlement pool when merchant liquidity is exhausted. Card-user fraud was outsourced to FeatureSpace, a third-party ML provider. Merchant-initiated refund fraud sat entirely outside that arrangement. Criminal groups posing as merchants, and rogue merchants who had identified the vulnerability, had been exploiting the unmatched refund path for an extended period before detection controls were prioritised. The unmatched refund path in essence is the vulnerability where DOJO terminals would allow refunds that are not linked to a previous transaction.&nbsp;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>PROBLEM<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>User problem<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Any operator with physical access to a Dojo terminal could issue a refund to a random card at a random value &#8211; with no requirement that the card had ever transacted with that merchant. There was no verification step, no transaction history check, and no amount constraint. Legitimate merchants shared a platform with rogue operators exploiting the same infrastructure, with no isolation or detection.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Business problem<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Finance, collections, and treasury data triangulated confirmed annual losses at \u00a3500,000\u2013\u00a3700,000. Prior research mapped unmatched refunds onto cards that had never transacted with the originating merchant, on accounts that had entered debit or experienced liquidity shortages &#8211; in a limited dataset, this pattern accounted for 90% of all unmatched refund activity. Two fraud patterns drove the majority of losses: established corner-shop merchants issuing refunds that routinely exceeded their own monthly terminal revenue, and newly onboarded merchants receiving terminals and immediately issuing refunds to unknown cards before processing a single legitimate sale. Dojo was, at the time, the only card payment platform permitting unmatched refunds &#8211; a structural competitive and reputational exposure beyond the direct P&amp;L loss.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Technical \/ regulatory \/ operational problem<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The Authorisation Gateway was built for routing and approval decisioning, not stateful analysis across transaction history. Card terminal transactions carry no line-item detail &#8211; only card identifier, amount, and timestamp &#8211; so any matching logic had to operate on amount aggregates rather than itemised records. A further complication was expired card handling: a refund to an expired card is technically valid if the underlying account remains active, because the card is mapped to the account via a PAR (Payment Account Reference). Any solution had to handle the expired card scenario correctly &#8211; blocking refunds only where the account was inactive, not where the card had simply expired. This required the solution to work at the tap layer, reading the card&#8217;s PAR and transaction history at the terminal, rather than operating purely at gateway level. Finally, any new cardholder data storage would have triggered a PCI DSS scope expansion and QSA re-assessment &#8211; a constraint that ruled out a server-side transaction history database.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>APPROACH<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The programme opened by converting the fraud loss into a monthly cash drain and modelling the expected value of detection against the cost of false positives.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Dojo&#8217;s net settlement model made the loss arithmetic direct. A fraudulent refund of \u00a3X is a \u00a3X immediate cash loss &#8211; not a credit risk, not a chargeback to be recovered, but a real-time drain on settlement capital. The confirmed annual range of \u00a3500,000 \u2013 \u00a3700,000 translated to a monthly burn of \u00a342,000 \u2013 \u00a358,000. The success hypothesis was set at 80% fraud elimination:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Target monthly recovery = \u00a3500,000 \u2013 \u00a3700,000 \u00d7 80% \u00f7 12 = \u00a333,000 \u2013 \u00a347,000\/month<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">At \u00a3513,000 recovered per month post-launch, the actual fraud surface was an order of magnitude larger than the triangulated estimate &#8211; back-office reconciliation had captured roughly 8 \u201310% of true run-rate exposure.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The business case was structured around expected value of detection:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>EV(detection) = P(fraud identified) \u00d7 Average refund loss avoided \u2212 &#91;False positive rate \u00d7 LTV cost per declined legitimate refund]<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The false positive cost was the controlling variable. Declining a legitimate refund at a physical terminal creates immediate, visible merchant friction. Merchant LTV was modelled as:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>LTV(merchant) = (Average monthly net revenue per merchant \u00d7 Gross margin %) \u00f7 Monthly churn rate<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Even a 0.5% false positive rate across the terminal estate translated to meaningful LTV destruction if affected merchants churned. Phase 1 thresholds were set conservatively &#8211; maximising precision over recall &#8211; with tightening scheduled as false positive data accumulated.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The solution was designed as two tiers:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Matched Refunds Lite (MRF)<\/strong> &#8211; the Phase 1 delivery. The cardholder taps their card at the merchant terminal. The terminal reads the card&#8217;s transaction history and compares cumulative spend at that merchant against the requested refund amount. If the card has no prior transaction with the merchant, the refund is blocked. If the refund exceeds cumulative card spend over the 90-day lookback window, the refund is blocked. The PAR mechanism means this logic applies correctly to expired cards: if the underlying account is still active, the refund proceeds to the expired card and the issuer accepts it. If the account is inactive, the issuer rejects and returns the funds via positive chargeback.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Matched Refund<\/strong> (Phase 2 scope) &#8211; full transaction-level matching, where the original sales transaction is identified and the refund is issued specifically to the originating card. This was deferred: it required deeper transaction record linkage than terminal memory alone could support, and the MRF Lite mechanism was sufficient to address the primary fraud patterns within the Phase 1 timeline.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The FeatureSpace contract was reviewed and deliberately not extended. FeatureSpace held no merchant transaction history and was trained exclusively on cardholder behaviour. The MRF tap-based approach was faster, auditable, and operable within the existing PCI DSS boundary &#8211; extending FeatureSpace scope would have added at least one quarter to the timeline with no marginal accuracy gain for this fraud type. This was documented as a build-vs-buy governance decision.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The programme ran within a 9-engineer squad over one quarter.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>ARCHITECTURE<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The diagram below shows the MRF Lite refund authorisation flow &#8211; from terminal tap through transaction-history matching to the settlement or block decision, including the expired card PAR routing.<\/p>\n\n\n\n<link href=\"https:\/\/fonts.googleapis.com\/css2?family=Share+Tech+Mono&#038;display=swap\" rel=\"stylesheet\">\n\n<div class=\"tds-root\">\n\n  <div class=\"tds-header\">\n    <div class=\"tds-title\"><span class=\"tds-dot\"><\/span>MERCHANT REFUND FRAUD DETECTION \u2014 AUTHORISATION GATEWAY DECISION FLOW<\/div>\n    <div class=\"tds-meta\">PAYMENTSENSE (DOJO) \u00b7 MATCHED REFUNDS LITE (MRF) \u00b7 PHYSICAL TERMINAL ACQUIRING<\/div>\n  <\/div>\n\n  <svg viewBox=\"0 0 1400 830\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:100%;display:block;\">\n    <defs>\n      <marker id=\"tds-ah-or\"  markerWidth=\"7\" markerHeight=\"7\" refX=\"6\" refY=\"3.5\" orient=\"auto\"><polygon points=\"0 0,7 3.5,0 7\" fill=\"#FF6600\"\/><\/marker>\n      <marker id=\"tds-ah-am\"  markerWidth=\"7\" markerHeight=\"7\" refX=\"6\" refY=\"3.5\" orient=\"auto\"><polygon points=\"0 0,7 3.5,0 7\" fill=\"#FFB300\"\/><\/marker>\n      <marker id=\"tds-ah-rd\"  markerWidth=\"7\" markerHeight=\"7\" refX=\"6\" refY=\"3.5\" orient=\"auto\"><polygon points=\"0 0,7 3.5,0 7\" fill=\"#CC2200\"\/><\/marker>\n      <marker id=\"tds-ah-dm\"  markerWidth=\"7\" markerHeight=\"7\" refX=\"6\" refY=\"3.5\" orient=\"auto\"><polygon points=\"0 0,7 3.5,0 7\" fill=\"#993300\"\/><\/marker>\n    <\/defs>\n\n    <!-- LANE BANDS -->\n    <rect x=\"0\"   y=\"30\"  width=\"1400\" height=\"165\" fill=\"#0C0400\" opacity=\"0.7\"\/>\n    <rect x=\"0\"   y=\"195\" width=\"1400\" height=\"165\" fill=\"#050200\" opacity=\"0.9\"\/>\n    <rect x=\"0\"   y=\"360\" width=\"1400\" height=\"165\" fill=\"#0C0400\" opacity=\"0.7\"\/>\n    <rect x=\"0\"   y=\"525\" width=\"1400\" height=\"165\" fill=\"#050200\" opacity=\"0.9\"\/>\n\n    <!-- OUTER BORDER -->\n    <rect x=\"0\" y=\"30\" width=\"1400\" height=\"660\" fill=\"none\" stroke=\"#CC4400\" stroke-width=\"1\"\/>\n\n    <!-- LANE DIVIDERS -->\n    <line x1=\"0\" y1=\"195\" x2=\"1400\" y2=\"195\" stroke=\"#553300\" stroke-width=\"1.5\"\/>\n    <line x1=\"0\" y1=\"360\" x2=\"1400\" y2=\"360\" stroke=\"#553300\" stroke-width=\"1.5\"\/>\n    <line x1=\"0\" y1=\"525\" x2=\"1400\" y2=\"525\" stroke=\"#553300\" stroke-width=\"1.5\"\/>\n\n    <!-- HEADER COLUMN -->\n    <rect x=\"0\" y=\"30\" width=\"150\" height=\"660\" fill=\"#0D0500\"\/>\n    <line x1=\"150\" y1=\"30\" x2=\"150\" y2=\"690\" stroke=\"#CC4400\" stroke-width=\"1.5\"\/>\n\n    <!-- LANE LABELS -->\n    <text x=\"75\" y=\"106\" text-anchor=\"middle\" font-size=\"11\" font-weight=\"bold\" fill=\"#FF6600\" letter-spacing=\"2\" font-family=\"'Share Tech Mono',monospace\">MERCHANT<\/text>\n    <text x=\"75\" y=\"271\" text-anchor=\"middle\" font-size=\"11\" font-weight=\"bold\" fill=\"#FFB300\" letter-spacing=\"2\" font-family=\"'Share Tech Mono',monospace\">TERMINAL<\/text>\n    <text x=\"75\" y=\"436\" text-anchor=\"middle\" font-size=\"10\" font-weight=\"bold\" fill=\"#FF9944\" letter-spacing=\"1\" font-family=\"'Share Tech Mono',monospace\">AUTH<\/text>\n    <text x=\"75\" y=\"452\" text-anchor=\"middle\" font-size=\"10\" font-weight=\"bold\" fill=\"#FF9944\" letter-spacing=\"1\" font-family=\"'Share Tech Mono',monospace\">GATEWAY<\/text>\n    <text x=\"75\" y=\"601\" text-anchor=\"middle\" font-size=\"10\" font-weight=\"bold\" fill=\"#FFB300\" letter-spacing=\"1\" font-family=\"'Share Tech Mono',monospace\">PAR \/<\/text>\n    <text x=\"75\" y=\"617\" text-anchor=\"middle\" font-size=\"10\" font-weight=\"bold\" fill=\"#FFB300\" letter-spacing=\"1\" font-family=\"'Share Tech Mono',monospace\">ISSUER<\/text>\n\n    <!-- \u2500\u2500 LANE 0 MERCHANT mid=112 \u2500\u2500 -->\n\n    <!-- 01 cx=239 -->\n    <text x=\"239\" y=\"82\" text-anchor=\"middle\" font-size=\"8\" fill=\"#553311\" font-family=\"'Share Tech Mono',monospace\">01<\/text>\n    <rect x=\"164\" y=\"86\" width=\"150\" height=\"52\" fill=\"#0a0300\" stroke=\"#CC4400\" stroke-width=\"1\" rx=\"1\"\/>\n    <rect x=\"164\" y=\"86\" width=\"150\" height=\"2\" fill=\"#FF6600\" opacity=\"0.8\"\/>\n    <text x=\"239\" y=\"106\" text-anchor=\"middle\" font-size=\"9\" fill=\"#FFB300\" font-family=\"'Share Tech Mono',monospace\">Merchant initiates<\/text>\n    <text x=\"239\" y=\"120\" text-anchor=\"middle\" font-size=\"9\" fill=\"#FFB300\" font-family=\"'Share Tech Mono',monospace\">refund request<\/text>\n    <text x=\"239\" y=\"133\" text-anchor=\"middle\" font-size=\"8\" fill=\"#664422\" font-family=\"'Share Tech Mono',monospace\">Cardholder taps card<\/text>\n\n    <!-- 09 cx=1307 -->\n    <text x=\"1307\" y=\"82\" text-anchor=\"middle\" font-size=\"8\" fill=\"#553311\" font-family=\"'Share Tech Mono',monospace\">09<\/text>\n    <rect x=\"1232\" y=\"86\" width=\"150\" height=\"52\" fill=\"#001a00\" stroke=\"#44AA44\" stroke-width=\"1.5\" rx=\"1\"\/>\n    <rect x=\"1232\" y=\"86\" width=\"150\" height=\"2\" fill=\"#44AA44\"\/>\n    <text x=\"1307\" y=\"106\" text-anchor=\"middle\" font-size=\"9\" font-weight=\"bold\" fill=\"#44AA44\" font-family=\"'Share Tech Mono',monospace\">REFUND CONFIRMED<\/text>\n    <text x=\"1307\" y=\"120\" text-anchor=\"middle\" font-size=\"8.5\" fill=\"#336633\" font-family=\"'Share Tech Mono',monospace\">Issued to cardholder<\/text>\n\n    <!-- \u2500\u2500 LANE 1 TERMINAL mid=277 \u2500\u2500 -->\n\n    <!-- 02 cx=417 -->\n    <text x=\"417\" y=\"247\" text-anchor=\"middle\" font-size=\"8\" fill=\"#553311\" font-family=\"'Share Tech Mono',monospace\">02<\/text>\n    <rect x=\"342\" y=\"251\" width=\"150\" height=\"52\" fill=\"#0a0300\" stroke=\"#CC4400\" stroke-width=\"1\" rx=\"1\"\/>\n    <rect x=\"342\" y=\"251\" width=\"150\" height=\"2\" fill=\"#FFB300\" opacity=\"0.8\"\/>\n    <text x=\"417\" y=\"271\" text-anchor=\"middle\" font-size=\"9\" fill=\"#FFB300\" font-family=\"'Share Tech Mono',monospace\">Read card PAR +<\/text>\n    <text x=\"417\" y=\"285\" text-anchor=\"middle\" font-size=\"9\" fill=\"#FFB300\" font-family=\"'Share Tech Mono',monospace\">transaction history<\/text>\n    <text x=\"417\" y=\"298\" text-anchor=\"middle\" font-size=\"8\" fill=\"#664422\" font-family=\"'Share Tech Mono',monospace\">90-day lookback<\/text>\n\n    <!-- 08 cx=1129 -->\n    <text x=\"1129\" y=\"247\" text-anchor=\"middle\" font-size=\"8\" fill=\"#553311\" font-family=\"'Share Tech Mono',monospace\">08<\/text>\n    <rect x=\"1054\" y=\"251\" width=\"150\" height=\"52\" fill=\"#0a0300\" stroke=\"#993300\" stroke-width=\"1\" rx=\"1\"\/>\n    <rect x=\"1054\" y=\"251\" width=\"150\" height=\"2\" fill=\"#993300\" opacity=\"0.8\"\/>\n    <text x=\"1129\" y=\"271\" text-anchor=\"middle\" font-size=\"9\" fill=\"#FFDDAA\" font-family=\"'Share Tech Mono',monospace\">Relay approval<\/text>\n    <text x=\"1129\" y=\"285\" text-anchor=\"middle\" font-size=\"9\" fill=\"#FFDDAA\" font-family=\"'Share Tech Mono',monospace\">to merchant terminal<\/text>\n\n    <!-- \u2500\u2500 LANE 2 AUTH GATEWAY mid=442 \u2500\u2500 -->\n\n    <!-- 03 Rule 1 cx=595 -->\n    <text x=\"595\" y=\"412\" text-anchor=\"middle\" font-size=\"8\" fill=\"#553311\" font-family=\"'Share Tech Mono',monospace\">03<\/text>\n    <rect x=\"520\" y=\"416\" width=\"150\" height=\"52\" fill=\"#0a0300\" stroke=\"#FF6600\" stroke-width=\"1.5\" rx=\"1\"\/>\n    <rect x=\"520\" y=\"416\" width=\"150\" height=\"2\" fill=\"#FF6600\"\/>\n    <text x=\"595\" y=\"433\" text-anchor=\"middle\" font-size=\"9\" font-weight=\"bold\" fill=\"#FF9944\" font-family=\"'Share Tech Mono',monospace\">RULE 1<\/text>\n    <text x=\"595\" y=\"447\" text-anchor=\"middle\" font-size=\"8.5\" fill=\"#FFB300\" font-family=\"'Share Tech Mono',monospace\">Card match check<\/text>\n    <text x=\"595\" y=\"461\" text-anchor=\"middle\" font-size=\"8\" fill=\"#664422\" font-family=\"'Share Tech Mono',monospace\">Prior txn on this card?<\/text>\n\n    <!-- 04 Rule 2 cx=773 -->\n    <text x=\"773\" y=\"412\" text-anchor=\"middle\" font-size=\"8\" fill=\"#553311\" font-family=\"'Share Tech Mono',monospace\">04<\/text>\n    <rect x=\"698\" y=\"416\" width=\"150\" height=\"52\" fill=\"#0a0300\" stroke=\"#FF6600\" stroke-width=\"1.5\" rx=\"1\"\/>\n    <rect x=\"698\" y=\"416\" width=\"150\" height=\"2\" fill=\"#FF6600\"\/>\n    <text x=\"773\" y=\"433\" text-anchor=\"middle\" font-size=\"9\" font-weight=\"bold\" fill=\"#FF9944\" font-family=\"'Share Tech Mono',monospace\">RULE 2<\/text>\n    <text x=\"773\" y=\"447\" text-anchor=\"middle\" font-size=\"8.5\" fill=\"#FFB300\" font-family=\"'Share Tech Mono',monospace\">Amount match check<\/text>\n    <text x=\"773\" y=\"461\" text-anchor=\"middle\" font-size=\"8\" fill=\"#664422\" font-family=\"'Share Tech Mono',monospace\">Refund &lt;= 90-day spend?<\/text>\n\n    <!-- 05 Expired cx=951 -->\n    <text x=\"951\" y=\"412\" text-anchor=\"middle\" font-size=\"8\" fill=\"#553311\" font-family=\"'Share Tech Mono',monospace\">05<\/text>\n    <rect x=\"876\" y=\"416\" width=\"150\" height=\"52\" fill=\"#0a0300\" stroke=\"#FFB300\" stroke-width=\"1.5\" rx=\"1\"\/>\n    <rect x=\"876\" y=\"416\" width=\"150\" height=\"2\" fill=\"#FFB300\"\/>\n    <text x=\"951\" y=\"433\" text-anchor=\"middle\" font-size=\"9\" font-weight=\"bold\" fill=\"#FFB300\" font-family=\"'Share Tech Mono',monospace\">EXPIRED CARD?<\/text>\n    <text x=\"951\" y=\"447\" text-anchor=\"middle\" font-size=\"8.5\" fill=\"#FFB300\" font-family=\"'Share Tech Mono',monospace\">PAR lookup<\/text>\n    <text x=\"951\" y=\"461\" text-anchor=\"middle\" font-size=\"8\" fill=\"#664422\" font-family=\"'Share Tech Mono',monospace\">Account still active?<\/text>\n\n    <!-- 07 APPROVED cx=1129 -->\n    <text x=\"1129\" y=\"412\" text-anchor=\"middle\" font-size=\"8\" fill=\"#553311\" font-family=\"'Share Tech Mono',monospace\">07<\/text>\n    <rect x=\"1054\" y=\"416\" width=\"150\" height=\"52\" fill=\"#001a00\" stroke=\"#44AA44\" stroke-width=\"1.5\" rx=\"1\"\/>\n    <rect x=\"1054\" y=\"416\" width=\"150\" height=\"2\" fill=\"#44AA44\"\/>\n    <text x=\"1129\" y=\"440\" text-anchor=\"middle\" font-size=\"10\" font-weight=\"bold\" fill=\"#44AA44\" font-family=\"'Share Tech Mono',monospace\">APPROVED<\/text>\n    <text x=\"1129\" y=\"456\" text-anchor=\"middle\" font-size=\"8.5\" fill=\"#336633\" font-family=\"'Share Tech Mono',monospace\">Settlement proceeds<\/text>\n\n    <!-- BLOCKED R1 \u2014 sits just below gateway lane border cx=595 -->\n    <rect x=\"520\" y=\"494\" width=\"150\" height=\"42\" fill=\"#1a0000\" stroke=\"#CC2200\" stroke-width=\"1.5\" rx=\"1\"\/>\n    <rect x=\"520\" y=\"494\" width=\"150\" height=\"2\" fill=\"#CC2200\"\/>\n    <text x=\"595\" y=\"511\" text-anchor=\"middle\" font-size=\"9\" font-weight=\"bold\" fill=\"#FF4422\" font-family=\"'Share Tech Mono',monospace\">BLOCKED<\/text>\n    <text x=\"595\" y=\"526\" text-anchor=\"middle\" font-size=\"8\" fill=\"#993300\" font-family=\"'Share Tech Mono',monospace\">Unknown card<\/text>\n\n    <!-- BLOCKED R2 cx=773 -->\n    <rect x=\"698\" y=\"494\" width=\"150\" height=\"42\" fill=\"#1a0000\" stroke=\"#CC2200\" stroke-width=\"1.5\" rx=\"1\"\/>\n    <rect x=\"698\" y=\"494\" width=\"150\" height=\"2\" fill=\"#CC2200\"\/>\n    <text x=\"773\" y=\"511\" text-anchor=\"middle\" font-size=\"9\" font-weight=\"bold\" fill=\"#FF4422\" font-family=\"'Share Tech Mono',monospace\">BLOCKED<\/text>\n    <text x=\"773\" y=\"526\" text-anchor=\"middle\" font-size=\"8\" fill=\"#993300\" font-family=\"'Share Tech Mono',monospace\">Exceeds 90-day spend<\/text>\n\n    <!-- \u2500\u2500 LANE 3 PAR\/ISSUER mid=607 \u2500\u2500 -->\n\n    <!-- 06 PAR lookup cx=951 -->\n    <text x=\"951\" y=\"577\" text-anchor=\"middle\" font-size=\"8\" fill=\"#553311\" font-family=\"'Share Tech Mono',monospace\">06<\/text>\n    <rect x=\"876\" y=\"581\" width=\"150\" height=\"52\" fill=\"#0a0300\" stroke=\"#CC4400\" stroke-width=\"1\" rx=\"1\"\/>\n    <rect x=\"876\" y=\"581\" width=\"150\" height=\"2\" fill=\"#FFB300\" opacity=\"0.8\"\/>\n    <text x=\"951\" y=\"601\" text-anchor=\"middle\" font-size=\"9\" fill=\"#FFB300\" font-family=\"'Share Tech Mono',monospace\">PAR lookup<\/text>\n    <text x=\"951\" y=\"615\" text-anchor=\"middle\" font-size=\"9\" fill=\"#FFB300\" font-family=\"'Share Tech Mono',monospace\">Is account active?<\/text>\n\n    <!-- REJECTED \u2014 inactive account cx=1129 -->\n    <rect x=\"1054\" y=\"581\" width=\"150\" height=\"52\" fill=\"#1a0000\" stroke=\"#CC2200\" stroke-width=\"1.5\" rx=\"1\"\/>\n    <rect x=\"1054\" y=\"581\" width=\"150\" height=\"2\" fill=\"#CC2200\"\/>\n    <text x=\"1129\" y=\"599\" text-anchor=\"middle\" font-size=\"9\" font-weight=\"bold\" fill=\"#FF4422\" font-family=\"'Share Tech Mono',monospace\">REJECTED<\/text>\n    <text x=\"1129\" y=\"613\" text-anchor=\"middle\" font-size=\"8\" fill=\"#993300\" font-family=\"'Share Tech Mono',monospace\">+ve chargeback issued<\/text>\n    <text x=\"1129\" y=\"626\" text-anchor=\"middle\" font-size=\"8\" fill=\"#993300\" font-family=\"'Share Tech Mono',monospace\">Funds returned to Dojo<\/text>\n\n    <!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n         CONNECTORS\n    \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n\n    <!-- 01 \u2192 02 down-right -->\n    <line x1=\"239\" y1=\"138\" x2=\"239\" y2=\"170\" stroke=\"#FF6600\" stroke-width=\"1.5\"\/>\n    <line x1=\"239\" y1=\"170\" x2=\"417\" y2=\"170\" stroke=\"#FF6600\" stroke-width=\"1.5\"\/>\n    <line x1=\"417\" y1=\"170\" x2=\"417\" y2=\"251\" stroke=\"#FF6600\" stroke-width=\"1.5\" marker-end=\"url(#tds-ah-or)\"\/>\n    <rect x=\"272\" y=\"158\" width=\"130\" height=\"11\" fill=\"#000000\" opacity=\"0.85\"\/>\n    <text x=\"337\" y=\"168\" text-anchor=\"middle\" font-size=\"8.5\" fill=\"#FFDDAA\" font-family=\"'Share Tech Mono',monospace\">tap card at terminal<\/text>\n\n    <!-- 02 \u2192 03 down-right -->\n    <line x1=\"417\" y1=\"303\" x2=\"417\" y2=\"338\" stroke=\"#FF6600\" stroke-width=\"1.5\"\/>\n    <line x1=\"417\" y1=\"338\" x2=\"595\" y2=\"338\" stroke=\"#FF6600\" stroke-width=\"1.5\"\/>\n    <line x1=\"595\" y1=\"338\" x2=\"595\" y2=\"416\" stroke=\"#FF6600\" stroke-width=\"1.5\" marker-end=\"url(#tds-ah-or)\"\/>\n    <rect x=\"450\" y=\"326\" width=\"130\" height=\"11\" fill=\"#000000\" opacity=\"0.85\"\/>\n    <text x=\"515\" y=\"336\" text-anchor=\"middle\" font-size=\"8.5\" fill=\"#FFDDAA\" font-family=\"'Share Tech Mono',monospace\">submit for auth check<\/text>\n\n    <!-- 03 \u2192 BLOCKED R1 (drop) -->\n    <line x1=\"595\" y1=\"468\" x2=\"595\" y2=\"494\" stroke=\"#CC2200\" stroke-width=\"1.5\" marker-end=\"url(#tds-ah-rd)\"\/>\n    <rect x=\"542\" y=\"473\" width=\"66\" height=\"11\" fill=\"#000000\" opacity=\"0.85\"\/>\n    <text x=\"575\" y=\"483\" text-anchor=\"middle\" font-size=\"8\" fill=\"#CC2200\" font-family=\"'Share Tech Mono',monospace\">NO MATCH<\/text>\n\n    <!-- 03 \u2192 04 pass -->\n    <line x1=\"670\" y1=\"442\" x2=\"698\" y2=\"442\" stroke=\"#FF6600\" stroke-width=\"1.5\" marker-end=\"url(#tds-ah-or)\"\/>\n    <rect x=\"656\" y=\"430\" width=\"48\" height=\"11\" fill=\"#000000\" opacity=\"0.85\"\/>\n    <text x=\"680\" y=\"440\" text-anchor=\"middle\" font-size=\"8\" fill=\"#44AA44\" font-family=\"'Share Tech Mono',monospace\">PASS<\/text>\n\n    <!-- 04 \u2192 BLOCKED R2 (drop) -->\n    <line x1=\"773\" y1=\"468\" x2=\"773\" y2=\"494\" stroke=\"#CC2200\" stroke-width=\"1.5\" marker-end=\"url(#tds-ah-rd)\"\/>\n    <rect x=\"720\" y=\"473\" width=\"66\" height=\"11\" fill=\"#000000\" opacity=\"0.85\"\/>\n    <text x=\"753\" y=\"483\" text-anchor=\"middle\" font-size=\"8\" fill=\"#CC2200\" font-family=\"'Share Tech Mono',monospace\">EXCEEDS<\/text>\n\n    <!-- 04 \u2192 05 pass -->\n    <line x1=\"848\" y1=\"442\" x2=\"876\" y2=\"442\" stroke=\"#FF6600\" stroke-width=\"1.5\" marker-end=\"url(#tds-ah-or)\"\/>\n    <rect x=\"834\" y=\"430\" width=\"48\" height=\"11\" fill=\"#000000\" opacity=\"0.85\"\/>\n    <text x=\"858\" y=\"440\" text-anchor=\"middle\" font-size=\"8\" fill=\"#44AA44\" font-family=\"'Share Tech Mono',monospace\">PASS<\/text>\n\n    <!-- 05 \u2192 06 expired drop to PAR lane -->\n    <line x1=\"951\" y1=\"468\" x2=\"951\" y2=\"581\" stroke=\"#FFB300\" stroke-width=\"1.5\" marker-end=\"url(#tds-ah-am)\"\/>\n    <rect x=\"896\" y=\"510\" width=\"72\" height=\"11\" fill=\"#000000\" opacity=\"0.85\"\/>\n    <text x=\"932\" y=\"520\" text-anchor=\"middle\" font-size=\"8.5\" fill=\"#FFB300\" font-family=\"'Share Tech Mono',monospace\">EXPIRED<\/text>\n\n    <!-- 05 \u2192 07 not expired -->\n    <line x1=\"1026\" y1=\"442\" x2=\"1054\" y2=\"442\" stroke=\"#FF6600\" stroke-width=\"1.5\" marker-end=\"url(#tds-ah-or)\"\/>\n    <rect x=\"1006\" y=\"430\" width=\"76\" height=\"11\" fill=\"#000000\" opacity=\"0.85\"\/>\n    <text x=\"1044\" y=\"440\" text-anchor=\"middle\" font-size=\"8\" fill=\"#44AA44\" font-family=\"'Share Tech Mono',monospace\">NOT EXPIRED<\/text>\n\n    <!-- 06 \u2192 REJECTED inactive -->\n    <line x1=\"1026\" y1=\"607\" x2=\"1054\" y2=\"607\" stroke=\"#CC2200\" stroke-width=\"1.5\" marker-end=\"url(#tds-ah-rd)\"\/>\n    <rect x=\"1014\" y=\"595\" width=\"58\" height=\"11\" fill=\"#000000\" opacity=\"0.85\"\/>\n    <text x=\"1043\" y=\"605\" text-anchor=\"middle\" font-size=\"8\" fill=\"#CC2200\" font-family=\"'Share Tech Mono',monospace\">INACTIVE<\/text>\n\n    <!-- 06 \u2192 07 active account \u2014 up then right back to approved -->\n    <line x1=\"951\" y1=\"581\" x2=\"951\" y2=\"544\" stroke=\"#FFB300\" stroke-width=\"1.2\"\/>\n    <line x1=\"951\" y1=\"544\" x2=\"1129\" y2=\"544\" stroke=\"#FFB300\" stroke-width=\"1.2\"\/>\n    <line x1=\"1129\" y1=\"544\" x2=\"1129\" y2=\"468\" stroke=\"#FFB300\" stroke-width=\"1.5\" marker-end=\"url(#tds-ah-am)\"\/>\n    <rect x=\"988\" y=\"532\" width=\"92\" height=\"11\" fill=\"#000000\" opacity=\"0.85\"\/>\n    <text x=\"1034\" y=\"542\" text-anchor=\"middle\" font-size=\"8.5\" fill=\"#FFB300\" font-family=\"'Share Tech Mono',monospace\">ACTIVE \u2014 proceed<\/text>\n\n    <!-- 07 \u2192 08 approval up to terminal (dashed) -->\n    <line x1=\"1129\" y1=\"416\" x2=\"1129\" y2=\"303\" stroke=\"#993300\" stroke-width=\"1\" stroke-dasharray=\"5,4\" marker-end=\"url(#tds-ah-dm)\"\/>\n    <rect x=\"1072\" y=\"352\" width=\"110\" height=\"11\" fill=\"#000000\" opacity=\"0.85\"\/>\n    <text x=\"1127\" y=\"362\" text-anchor=\"middle\" font-size=\"8.5\" fill=\"#FFDDAA\" font-family=\"'Share Tech Mono',monospace\">approval response<\/text>\n\n    <!-- 08 \u2192 09 confirmation up to merchant (dashed) -->\n    <line x1=\"1129\" y1=\"251\" x2=\"1129\" y2=\"168\" stroke=\"#993300\" stroke-width=\"1\" stroke-dasharray=\"5,4\"\/>\n    <line x1=\"1129\" y1=\"168\" x2=\"1307\" y2=\"168\" stroke=\"#993300\" stroke-width=\"1\" stroke-dasharray=\"5,4\"\/>\n    <line x1=\"1307\" y1=\"168\" x2=\"1307\" y2=\"138\" stroke=\"#993300\" stroke-width=\"1\" stroke-dasharray=\"5,4\" marker-end=\"url(#tds-ah-dm)\"\/>\n    <rect x=\"1170\" y=\"156\" width=\"128\" height=\"11\" fill=\"#000000\" opacity=\"0.85\"\/>\n    <text x=\"1234\" y=\"166\" text-anchor=\"middle\" font-size=\"8.5\" fill=\"#FFDDAA\" font-family=\"'Share Tech Mono',monospace\">refund confirmation<\/text>\n\n  <\/svg>\n\n  <div class=\"tds-footer\">\n    <span>SWIMLANE DIAGRAM \u00b7 MATCHED REFUNDS LITE (MRF) \u00b7 DOJO AUTHORISATION GATEWAY \u00b7 PAYMENTSENSE<\/span>\n    <span>SOLID ORANGE = FORWARD &nbsp;|&nbsp; DASHED = RESPONSE &nbsp;|&nbsp; RED = BLOCKED &nbsp;|&nbsp; GREEN = APPROVED &nbsp;|&nbsp; AMBER = PAR \/ EXPIRED CARD PATH<\/span>\n  <\/div>\n\n<\/div>\n\n<style>\n  .tds-root {\n    background: #000000;\n    background-image: repeating-linear-gradient(\n      0deg,\n      transparent, transparent 2px,\n      rgba(255,102,0,0.018) 2px, rgba(255,102,0,0.018) 4px\n    );\n    font-family: 'Share Tech Mono', 'Courier New', monospace;\n    padding: 24px;\n    box-sizing: border-box;\n  }\n  .tds-root *, .tds-root *::before, .tds-root *::after {\n    box-sizing: border-box;\n    margin: 0;\n    padding: 0;\n  }\n  .tds-root .tds-header {\n    border: 1px solid #CC4400;\n    background: #080200;\n    padding: 9px 18px;\n    margin-bottom: 16px;\n    display: flex;\n    justify-content: space-between;\n    align-items: center;\n    box-shadow: 0 0 16px rgba(255,102,0,0.12);\n  }\n  .tds-root .tds-title {\n    font-size: 13px;\n    font-weight: 700;\n    letter-spacing: 0.14em;\n    color: #FFB300;\n    text-transform: uppercase;\n  }\n  .tds-root .tds-meta {\n    font-size: 9.5px;\n    color: #553311;\n    letter-spacing: 0.08em;\n  }\n  .tds-root .tds-dot {\n    display: inline-block;\n    width: 7px;\n    height: 7px;\n    border-radius: 50%;\n    background: #FF6600;\n    margin-right: 10px;\n    box-shadow: 0 0 8px #FF6600;\n    animation: tds-blink 2s step-end infinite;\n  }\n  @keyframes tds-blink { 0%,100%{opacity:1} 50%{opacity:0.15} }\n  .tds-root .tds-footer {\n    margin-top: 16px;\n    border-top: 1px solid #331100;\n    padding-top: 8px;\n    display: flex;\n    justify-content: space-between;\n    font-size: 8.5px;\n    color: #553311;\n    letter-spacing: 0.08em;\n  }\n<\/style>\n\n\n\n<p class=\"wp-block-paragraph\">This diagram shows the full MRF Lite decision flow from terminal tap to settlement outcome, including the PAR-based expired card path. The tap-based design &#8211; reading transaction history at the terminal rather than via a server-side lookup &#8211; was chosen specifically to stay within the existing PCI DSS scope boundary: no new cardholder data storage was introduced, no QSA re-assessment was triggered. The alternative, a centralised transaction history database, would have resolved the scope constraint only with significant compliance overhead and a longer delivery timeline. The expired card branch was a required addition once PAR mechanics were mapped: issuing a refund to an expired card with an inactive account produces a positive chargeback, returning funds to Dojo &#8211; a recoverable outcome, but one that needed explicit handling to prevent reconciliation noise.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>OUTCOMES<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Quantified results<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u00a3513,000 per month in fraudulent refund losses eliminated across the physical terminal estate<\/li>\n\n\n\n<li>Success hypothesis set at 80% fraud elimination &#8211; outcome exceeded the hypothesis<\/li>\n\n\n\n<li>Delivered in one quarter within a 9-engineer squad, within existing PCI DSS scope, without FeatureSpace contract extension<\/li>\n\n\n\n<li>Dojo ceased to be the only UK card payment platform permitting unmatched refunds &#8211; a structural competitive and reputational exposure closed<\/li>\n\n\n\n<li>PAR-based expired card handling defined and documented &#8211; covering a refund scenario previously unaddressed in any internal governance model<\/li>\n\n\n\n<li>FeatureSpace and Authorisation Gateway fraud responsibilities formally separated in the governance model for the first time<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>What was learned<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The gap between the triangulated annual estimate (\u00a3500,000\u2013\u00a3700,000) and the actual monthly recovery (\u00a3513,000, implying circa \u00a36 million annually) revealed that back-office reconciliation undercounted true fraud exposure by a factor of roughly eight. Losses that never escalate to collections &#8211; absorbed in settlement reconciliation &#8211; are invisible to finance reporting. Any fraud detection programme should instrument at the authorisation layer, not downstream. The 90% unmatched refund rate observed in the research dataset was confirmed by post-launch data, validating the original fraud hypothesis at scale.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>MATCHED REFUNDS LITE (MRF)&nbsp; TL;DR Matched Refunds Lite (MRF) at Paymentsense (Dojo) eliminated \u00a3513,000 per month in direct settlement losses &#8211; targeting a confirmed annual fraud exposure of \u00a3500,000\u2013\u00a3700,000 across the physical terminal estate. Dojo was the only card payment platform in the UK allowing unmatched refunds: any terminal operator could issue a refund to [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":44,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-161","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/lukaskoren.tech\/index.php?rest_route=\/wp\/v2\/pages\/161","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/lukaskoren.tech\/index.php?rest_route=\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/lukaskoren.tech\/index.php?rest_route=\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/lukaskoren.tech\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/lukaskoren.tech\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=161"}],"version-history":[{"count":3,"href":"https:\/\/lukaskoren.tech\/index.php?rest_route=\/wp\/v2\/pages\/161\/revisions"}],"predecessor-version":[{"id":196,"href":"https:\/\/lukaskoren.tech\/index.php?rest_route=\/wp\/v2\/pages\/161\/revisions\/196"}],"up":[{"embeddable":true,"href":"https:\/\/lukaskoren.tech\/index.php?rest_route=\/wp\/v2\/pages\/44"}],"wp:attachment":[{"href":"https:\/\/lukaskoren.tech\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=161"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}