• October 16, 2024

Platba na Back Market: jeden formulář, který jim všem vládne / Paul Guilbert / Duben, 2023

Vydání plakátu Pána Prstenu se zprávou

Přiznejme si to-právě jste strávili hodiny výzkumu své další znovuzrozené technické položky a nyní jste ji našli na Zpět Na Trh. S málo času nazbyt, ocitnete se na platební stránce zpět na trhu, netrpělivý dokončit svůj nákup a nechat si ho poslat k vám. Ať už dáváte přednost platbě ve splátkách pomocí Affirm, přeskočte zadání karty pomocí PayPal, použijte francouzštinu “carte bancaire“, nebo dokonce platit v hotovosti v japonském samoobsluze, máme vás kryté.

Ve skutečnosti jsme na Back Market integrovali celkem 15 různých platebních metod v 17 zemích do jedné jediné stránky formuláře.

V tomto příspěvku, podrobně popíšu náš front-end přístup ke konsolidaci těchto platebních metod do jednotné komponenty formuláře, s cílem zachovat jednoduchost a umožnit budoucí expanzi.

Jako front-end vývojáři v platebním týmu na Back Market je jedním z našich cílů udržovat platební komponentu, kterou může snadno integrovat tým odpovědný za celý zážitek z pokladny (od stránky košíku po potvrzovací e-mail, který obdržíte po zakoupení). Rozhraní komponenty je proto jednoduché: vezme částku nákupu a zemi jako vstup a vrátí jasný signál úspěchu, zrušení nebo chyby jako výstup.

Jak vidíte, s touto komponentou děláme dvě věci: ukážeme vám seznam platebních metod a umožníme vám platit zvolenými platebními metodami.

Krok 1: Seznam dostupných platebních metod

Počátečním úkolem platební složky je získat seznam dostupných platebních metod. To se provádí prostřednictvím webové služby, která určuje dostupnost na základě kontextových parametrů, jako je aktuální země, možnosti prodejce a částka nákupu.

Kromě tohoto prvního filtru nám druhý umožňuje provádět experimenty s testováním A/B nebo postupné zavádění. To nám umožňuje povolit, zakázat nebo znovu objednat platební metody pro předem určené procento našeho publika. Proto můžeme snadno porovnat výkony různých metod nebo představit nový způsob platby malému procentu uživatelů.

Nakonec musíme filtrovat načtené platební metody na základě schopností zařízení uživatele. Pokud například používáte zařízení Android nebo iOS bez konfigurace Apple Pay, neuvidíte možnost Apple Pay.

Vývojový diagram shrnující 3 filtry: metody filtrování nedostupné pro tento košík; odfiltrovat metody, které jsou ovlivněny AB testy nebo progresivním zaváděním; odfiltrovat metody nedostupné pro toto zařízení
Proces určení seznamu platebních metod, které se mají zobrazit v platebním formuláři.

Krok 2: Vyberte a zaplaťte

Toto je forma součástí platební složky. Jakmile si uživatel vybere platební metodu, zobrazí se mu uživatelské rozhraní specifické pro danou metodu a bude moci pokračovat ověřením formuláře.

Pro zajištění jednoduchosti je veškerá specifická logika pro různé platební metody skryta za společným rozhraním, které následuje po návrhový vzor adaptéru.

Ve skutečnosti je adaptér v podstatě formulář HTML se specifickým obslužným programem odeslání. Používáme malý HTML trik k vykreslení společného tlačítka Odeslat mimo adaptér (více informací o atributech tlačítka “formulář” najdete v Prvek tlačítka-HTML: HyperText Markup Language / MDN).

Zde je zjednodušená verze kódu naší komponenty” PaymentForm”:

// Payment form Vue template 
<component
:is="adapter"
:formId="formId"
:amount="amount"
:country="country"
@error="onError"
@success="onSuccess"
/>

<button :form="formId">Confirm and pay</button>

// Payment form Vue script
adapter() {
switch(selectedPaymentMethod) {
case 'card':
return CardAdapter
case 'paypal':
return PaypalAdapter
...
}
}

Jak jste si možná všimli, používá se stejný “formId” bez ohledu na zvolený způsob platby. Níže můžete vidět, jak to vypadá na straně adaptéru karty, kde je umístěna skutečná logika podání.

// Credit card adapter

<form onSubmit="handleSubmit":id="formId">
<input type="text" name="cc-number" />
<input type="text" name="cc-exp" />
...
</form>

//...

async handleSubmit() {
try {
await submitCreditCard()
this.$emit('success')
} catch (e) {
this.$emit('error', e)
}
}

Tento modulární design nám umožňuje spojit kód každé platební metody samostatně a sloužit klientovi pouze dostupné platební metody. Tento přístup přináší výhody výkonu, protože některé metody mohou potřebovat načíst své vlastní knihovny, což může být v některých případech těžké.

Jedním z přímých důsledků tohoto návrhu je, že máme jednu společnou komponentu formuláře pro všechny země, kde se používá Back Market. Pokud země potřebuje místní platební metodu, stačí vyvinout nový adaptér a nakonfigurovat jej bez obav o globální velikost balíčku komponenty.

Další výhodou naší modulární konstrukce je, že nám umožňuje nezávisle testovat každou platební metodu. To znamená, že můžeme identifikovat a opravit jakékoli problémy s konkrétní platební metodou, aniž by to ovlivnilo ostatní metody. To je důležité, protože nám to umožňuje udržovat nejvyšší úroveň spolehlivosti našeho platebního systému.

Nyní, když rozumíme tomu, jak platební formulář funguje, pojďme se ponořit do toho, co používáme k vytvoření každé z 15 platebních metod. Tyto metody jsou samozřejmě odlišné. Například neplatíte přes PayPal se stejným rozhraním jako kreditní karta. A ze stejného důvodu obsahuje technické základy těchto metod mnoho rozdílů. Nicméně, zaměstnáváme několik sdílených cihel k vytvoření platebního zážitku.

Za tímto účelem jsme vytvořili “platební knihovnu”, která přeskupuje všechny nástroje, které potřebujeme jako front-end vývojář k vytvoření/údržbě adaptéru různých metod. Zde je rychlý přehled klíčových komponent naší sdílené platební knihovny:

  • Zavaděč knihoven třetích stran: zjednodušte načítání metod s velkými závislostmi, včetně načítání, opakování a správy chyb
  • Podvod: vyhodnocuje riziko podvodu na přední straně pomocí hlavně výpočtu otisků prstů prohlížeče
  • Testovací nástroje: zajišťuje spolehlivost platebního systému
  • Monitorování a výstraha: sjednocuje protokoly odeslané každým adaptérem metody
  • Nástroje pro přesměrování: zpracovává přesměrování 3DS nebo externí platební toky

Nyní se ponoříme hlouběji do tří z těchto komponent: testování, monitorování a přesměrování.

Testovací nástroje hrají klíčovou roli při zajišťování spolehlivosti našeho platebního systému. Dodáváme tři různé typy testů:

  • Test pro každou součást a funkci Vue, aby bylo zajištěno, že každá jednotka systému funguje správně
  • Integrační testy Chcete-li zkontrolovat, zda každý adaptér platební metody funguje jako celek
  • End-to-end testy ověření spolehlivosti systému v reálných scénářích, napodobování skutečného chování uživatelů

Za tímto účelem obsahuje platební knihovna sdílené výsměchy a testovací nástroje pro simulaci chování externích systémů a služeb, což zajišťuje, že platební systém zvládne různé scénáře a podmínky. Výsledkem je, že pro každou knihovnu třetích stran, kterou používáme, jsme vyvinuli její falešnou verzi. Například, zde je část falešného pro knihovnu Apple Pay:

const USER_EVENTS = {
AUTHORIZE: 'AUTHORIZE',
CANCEL: 'CANCEL',
}

const controllerBus = mitt()

export class ApplePaySessionMock {
static STATUS_SUCCESS = 0
static STATUS_FAILURE = 1

static canMakePaymentsWithActiveCard = jest.fn()
static constructorSpy = jest.fn()

static install() {
this.canMakePaymentsWithActiveCard.mockClear()
this.canMakePaymentsWithActiveCard.mockResolvedValue(true)
this.constructorSpy.mockClear()
this.constructorSpy.mockImplementation(() => {})
window.ApplePaySession = this
}

static uninstall() {
delete window.ApplePaySession
this.canMakePaymentsWithActiveCard.mockClear()
this.constructorSpy.mockClear()
Object.values(USER_EVENTS).forEach((eventType) =>
controllerBus.off(eventType),
)
}

static async triggerUserAuthorize(
authorizedEvent = applePayAuthorizedEventBuilder(),
) {
controllerBus.emit(USER_EVENTS.AUTHORIZE, authorizedEvent)
await flushPromises()
}

static async triggerUserCancel() {
controllerBus.emit(USER_EVENTS.CANCEL)
await flushPromises()
}

constructor(...args) {
this.constructor.constructorSpy(...args)
this.oncancel = () => {}
this.onpaymentauthorized = () => {}

controllerBus.on(USER_EVENTS.AUTHORIZE, (event) => {
this.onpaymentauthorized(event)
})

controllerBus.on(USER_EVENTS.CANCEL, () => {
this.oncancel()
})
}

begin() {
window.setTimeout(() => {
this.onvalidatemerchant()
}, 0)
}
}

Poskytujeme také sadu nástrojů, které umožňují ostatním týmům provádět integrační testy plateb v rámci jejich toků využití. Cílem je zajistit, aby integrace platebního formuláře fungovala podle očekávání, aniž by přenesla břemeno integrace a udržování sady testů na druhý tým.

Níže zjednodušené používání našich nástrojů” PaymentTest”:

tconst paymentTest = new PaymentTest(testOptions)

paymentTest.expect.toBeOnThePaymentPage();
paymentTest.expect.toHavePaymentMethod(CARD);

await paymentTest.form.selectPaymentMethod(CARD);
await paymentTest.form.fill(SANDBOX_CARDS.AMERICAN_EXPRESS);
await paymentTest.form.submit();

paymentTest.expect.toBeRedirectedToTheConfirmationPage()
paymentTest.expect.toHaveASuccessfulPayment();

Přesměrování utils je součástí knihovny plateb, která zpracovává přesměrování 3DS nebo externí platební toky hostované poskytovatelem plateb. Nic fantastického. Jedinou specifičností je, že musíme také spravovat přesměrování pomocí metody HTTP POST:

type Method = 'GET' | 'POST';
type PaymentRedirection {
method: Method;
href: string;
data?: Data;
}

export function proceedPaymentRedirection(
{ method, href, data }: PaymentRedirection,
) {
switch (method) {
case 'GET':
// If method is GET, redirect using the vue router
$navigation.push(href);
break;

case 'POST':
// If method is POST, create a form element with hidden input elements for the data,
// add it to the DOM, submit it, and then remove it from the DOM.
processPostRedirection(href, data);
break;

default:
throw new Error(`Unknown redirection type: ${method}`);
}
}

function processPostRedirection(href: string, data?: Data): void {
const form = document.createElement('form');
form.method = METHODS.POST;
form.action = href;

Object.entries(data || {}).forEach(([name, value]) => {
const input = document.createElement('input');
input.type = 'hidden';
input.name = name;
input.value = String(value);
form.appendChild(input);
});

document.body.appendChild(form);
form.submit();
form.remove();
}

Monitorování a výstraha vyžadují pečlivé zvážení, pokud jde o protokolování konkrétních událostí. I když je důležité sledovat konkrétní události z platebních metod, naším primárním cílem je získat komplexní přehled o tom, jak si náš platební systém celkově vede. Abychom toho dosáhli, máme jednotné schéma protokolování, které přesahuje rozdíly mezi jednotlivými metodami.

Například se nutíme používat následující typy událostí, bez ohledu na metodu:

"FORM_SUBMIT_START" 
"FORM_SUBMIT_SUCCESS"
"FORM_SUBMIT_CANCEL"
"FORM_SUBMIT_ERROR"
"RESULT_SUCCESS"
"RESULT_FAILURE"

Obsah protokolů se samozřejmě může lišit, ale díky harmonizaci protokolů můžeme mít jednotný řídicí panel, který lze snadno přizpůsobit tak, aby zahrnoval nové platební metody.

Výpis z našeho formuláře dashboard, každý sloupec je založen na jednom typu události
Výpis z našeho formuláře dashboard, každý sloupec je založen na jednom typu události

Závěrem lze říci, že front-endový přístup Back Market konsolidující různé platební metody do jednotné komponenty formuláře je výsledkem modulárního designu a sdílené platební knihovny.

Tento přístup umožňuje nejen snadnou integraci platební komponenty jinými týmy, ale také zjednodušuje proces přidávání nových platebních metod do formuláře. Při použití společného rozhraní je specifická logika pro každou platební metodu skryta za adaptérem, který sleduje návrhový vzor adaptéru. Tento design umožňuje nezávislé testování každé platební metody a zajišťuje nejvyšší úroveň spolehlivosti platebního systému Back Market.

Protože integrujeme nové platební metody, aktivně udržujeme platební knihovnu s cílem učinit každý adaptér co nejobecnějším. Testování a monitorování zaujímají v této knihovně obrovské místo, protože chceme zajistit dobré zdraví platebního systému. Jsme také nadšeni z rozšíření knihovny v budoucnu, například pomocí nedávno představeného API žádosti o platbu.

Leave a Reply

Your email address will not be published. Required fields are marked *