Embedded Checkout
Pridajte do svojej vlastnej pokladne zabezpečené polia pre kartu a Apple Pay alebo Google Pay.
Vložte zabezpečené polia pre kartu priamo do svojej pokladne. Formulár aj odosielacie tlačidlo máte vo svojej réžii; Tapaya zabezpečuje validáciu karty, tokenizáciu a 3-D Secure. Vložené platby sú dostupné v ostrej prevádzke pre schválených obchodníkov a na testovanie je k dispozícii sandbox. Tento sprievodca používa Tapaya.js 0.2.0 a Node.js SDK 0.3.0.
- 1. Your frontend to Your backend: Prepare payment.
- 2. Your backend to Tapaya: Create or resume payment.
- 3. Tapaya to Your backend: Payment and client secret.
- 4. Your backend to Your frontend: Client secret and status.
- 5. Your frontend to Tapaya: Confirm card and 3-D Secure.
- 6. Tapaya to Your frontend: Payment outcome.
- 7. Your backend to Tapaya: Read order's payment.
- 8. Tapaya to Your backend: Payment status.
- 9. Your backend to Your frontend: Show verified result.
Platobné metódy
Embedded Checkout podporuje karty, Apple Pay a Google Pay. Pre karty použite vlastné tlačidlo Pay a pre Apple Pay a Google Pay oficiálne tlačidlá peňaženiek. Pozrite si Pridanie Apple Pay a Google Pay.
Skôr ako začnete
Inštalácia SDK
Jeden balík obsahuje serverového klienta, SDK pre prehliadač aj React hook:
npm install @tapayadot/checkout| Import | Kde |
|---|---|
@tapayadot/checkout | Iba na vašom serveri. Import v zostavení pre prehliadač vyhodí chybu, takže sa váš API kľúč nikdy nedostane na stránku. |
@tapayadot/checkout/client | Vaša stránka pokladne. |
@tapayadot/checkout/react | Vaša stránka pokladne, ak používate React. |
Konfigurácia servera
Vložené platby nepotrebujú návratové URL. Serverové príklady nižšie sú vo verziách HTTP (fetch), Node.js SDK a cURL. Všetky volajú to isté API obchodníka a polia pre kartu v prehliadači nechávajú bez zmeny.
| Node.js SDK | HTTP (fetch) a cURL | |
|---|---|---|
| Kľúč | TAPAYA_SECRET_KEY, ktorý načíta new Tapaya() | TAPAYA_CHECKOUT_API_KEY |
| Prostredie | TAPAYA_ENVIRONMENT=sandbox alebo production. Bez tejto premennej kľúč tapaya_live_ zvolí produkčné prostredie a pri ostatných kľúčoch sa predvolene použije sandbox. | TAPAYA_CHECKOUT_API_URL: https://api.sandbox.tapaya.com alebo https://api.tapaya.com |
| Režim platformy | Odovzdávajte merchantToken objednávky v každom volaní alebo ho nastavte pomocou new Tapaya(key, { merchantToken }) | Posielajte X-Tapaya-Merchant-Token v každej požiadavke. Pomocná funkcia pre fetch ho načítava z TAPAYA_MERCHANT_TOKEN. |
Checkout kľúč obchodníka nič ďalšie nepotrebuje. V režime platformy použite Secret key organizácie a backend, ktorý obsluhuje viacerých obchodníkov, nechajte vyberať token podľa objednávky z autentifikovanej relácie zákazníka. Pozrite si Autentifikácia Checkoutu. Client secrets sú špecifické pre každú platbu.
Dokončite onboarding s online platbami a overte, že je obchodník v nastaveniach Checkoutu v stave Ready.
Povolenie Tapaya vo vašej CSP
Loader sťahuje Tapaya.js 0.2.0 z https://js.tapaya.com/checkout/0.2.0/checkout.js; verzia skriptu pre prehliadač
je nezávislá od verzie Node.js SDK. Pridajte origin assetov Tapaya do svojej existujúcej Content Security
Policy:
script-src https://js.tapaya.com
frame-src https://js.tapaya.comPrehliadač dostane publishable key a client secret špecifický pre danú platbu. Váš tajný API kľúč obchodníka
zostáva na vašom serveri a údaje o karte aj skripty poskytovateľa platieb zostávajú vnútri rámca Tapaya. Na lokálne testovanie
hostujte Tapaya.js sami a jeho origin odovzdajte loaderu, napríklad
loadTapaya(publishableKey, { apiOrigin, origin: 'http://localhost:4191' }).
Ako to funguje
- Vaša stránka pripojí polia pre kartu od Tapaya a nasmeruje ich na endpoint na vašom serveri.
- Pri načítaní stránky a pri platbe zákazníka volajú polia pre kartu tento endpoint. Ten vráti platbu objednávky
ako
clientSecret: prihlasovací údaj pre jednu platbu, pomocou ktorého polia pre kartu potvrdia platbu priamo v Tapaya. Kód vašej stránky ho nikdy nečíta. - Vaša stránka sleduje
outcomeplatby. Keď sa platba dokončí, váš server ju overí a až potom objednávku vybavíte.
Prijatie platby
Získanie nastavení pre prehliadač
Načítajte nastavenia pre prehliadač raz na serveri a pridajte ich do konfigurácie svojho frontendu.
Túto pomocnú funkciu majte na serveri. Kontroluje chyby HTTP, na požiadanie považuje chýbajúcu platbu objednávky za null
a požiadavky automaticky neopakuje.
const apiOrigin = new URL(process.env.TAPAYA_CHECKOUT_API_URL).origin;
const apiKey = process.env.TAPAYA_CHECKOUT_API_KEY;
const merchantToken = process.env.TAPAYA_MERCHANT_TOKEN;
export async function paymentRequest(path, { method = 'GET', body, key, allowMissing = false } = {}) {
const response = await fetch(new URL(path, apiOrigin), {
method,
headers: {
Authorization: `Bearer ${apiKey}`,
...(merchantToken ? { 'X-Tapaya-Merchant-Token': merchantToken } : {}),
...(body === undefined ? {} : { 'Content-Type': 'application/json' }),
...(key ? { 'Idempotency-Key': key } : {}),
},
...(body === undefined ? {} : { body: JSON.stringify(body) }),
redirect: 'error',
cache: 'no-store',
signal: AbortSignal.timeout(35000),
});
if (allowMissing && response.status === 404) return null;
if (!response.ok) throw new Error(`Payment request failed (${response.status})`);
return response.json();
}
const { publishableKey } = await paymentRequest('/merchant/payments/configuration');
export const config = { publishableKey, apiOrigin };API vracia publishableKey a environment. Hodnotu apiOrigin nastavte podľa URL API, ktoré ste volali; nie je to pole
odpovede s konfiguráciou.
Obe hodnoty môžete bezpečne vložiť do stránky. Publishable key má predponu pk_test_ pri testovacích kľúčoch brány a pk_live_
pri ostrých kľúčoch brány. Loaderu vždy odovzdávajte apiOrigin vrátený vaším serverom, aby prehliadač aj server
zostali v tom istom prostredí.
Pridanie polí pre kartu
Pridajte kontajner do svojho existujúceho formulára pokladne:
<form id="checkout">
<!-- Your other checkout inputs go here. -->
<div id="card-fields"></div>
<button type="submit" disabled>Pay</button>
<p id="message" role="status"></p>
</form>Načítajte Tapaya a pripojte polia. prepare je endpoint, ktorý pridáte v ďalšom kroku.
import { loadTapaya } from '@tapayadot/checkout/client'
import { config } from './config' // { publishableKey, apiOrigin } from your server
const form = document.querySelector<HTMLFormElement>('#checkout')!
const button = form.querySelector<HTMLButtonElement>('button')!
const message = document.querySelector<HTMLElement>('#message')!
const tapaya = await loadTapaya(config.publishableKey, { apiOrigin: config.apiOrigin })
const payment = tapaya.createPayment({
prepare: '/api/payments',
onChange: ({ canSubmit, outcome }) => {
button.disabled = !canSubmit
if (outcome === 'completed') location.assign('/checkout/confirmation')
if (outcome === 'ended') message.textContent = 'This payment cannot be completed. Start a new checkout.'
},
})
await payment.mount('#card-fields')Po pripojení polia zavolajú prepare, aby nadviazali na existujúcu platbu objednávky. Opätovné načítanie stránky počas platby
nikdy nevedie k ďalšiemu zaťaženiu karty: stránka namiesto toho zobrazí aktuálny stav platby.
Vrátenie platby objednávky
Pripojte tento handler k POST /api/payments. getCheckoutOrder() je funkcia vašej vlastnej aplikácie: autentifikuje
zákazníka, skontroluje jeho prístup k objednávke a vráti jej uložené id, amount, currency a status. Na túto routu
uplatnite svoju obvyklú ochranu proti CSRF.
Skôr ako vytvoríte pokus, načítajte existujúcu platbu. Nevyriešenú platbu použite znova a ďalší pokus vytvorte
iba po zamietnutí alebo zrušení s retryAllowed: true.
import { paymentRequest } from './tapaya.js';
import { getCheckoutOrder } from './orders.js';
export async function findPayment(order) {
const query = new URLSearchParams({ merchantOrderId: order.id });
const payment = await paymentRequest(`/merchant/payments?${query}`, { allowMissing: true });
if (payment && (payment.merchantOrderId !== order.id ||
payment.amount !== order.amount || payment.currency !== order.currency)) {
throw new Error('Payment does not match the order');
}
return payment;
}
export function browserStatus(payment) {
if (payment.status === 'successful') return 'completed';
if (['declined', 'cancelled'].includes(payment.status) && !payment.retryAllowed) return 'ended';
return 'open';
}
export async function POST(request) {
const order = await getCheckoutOrder(request);
const payable = order.status === 'pending_payment';
let payment = await findPayment(order);
if (payable && (!payment ||
(['declined', 'cancelled'].includes(payment.status) && payment.retryAllowed))) {
// Derive the same key on retries, including after a lost creation response.
let key = `${order.id}:${payment ? `after:${payment.id}` : 'initial'}`;
if (/[^\x21-\x7e]/.test(key)) {
const digest = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(key));
key = `prepare:${Array.from(new Uint8Array(digest), byte => byte.toString(16).padStart(2, '0')).join('')}`;
}
payment = await paymentRequest('/merchant/payments', {
method: 'POST', key,
body: { merchantOrderId: order.id, amount: order.amount, currency: order.currency },
});
if (payment.merchantOrderId !== order.id || payment.amount !== order.amount || payment.currency !== order.currency) {
throw new Error('Payment does not match the order');
}
}
if (!payment) return Response.json({ error: 'Order cannot accept payment' }, { status: 409 });
return Response.json(
{ clientSecret: payable ? payment.clientSecret : null, status: browserStatus(payment) },
{ headers: { 'Cache-Control': 'no-store' } },
);
}Používajte kód meny veľkými písmenami a uložené ID objednávky s dĺžkou najviac 200 znakov. Po začatí platby údaje objednávky nemeňte. Pri vypršaní časového limitu znova načítajte platbu objednávky a až potom rozhodnite, či je potrebný nový pokus. Nikdy negenerujte nový kľúč len preto, že sa stratila odpoveď.
REST API vracia stavy platby. Node SDK ich prevádza na status, ktorý polia pre kartu očakávajú; integrácie cez fetch a cURL
používajú rovnaký prevod vo svojom vlastnom endpointe prepare:
status v API | status endpointu prepare |
|---|---|
successful | completed |
declined alebo cancelled s retryAllowed: false | ended |
ready, pending, action_required alebo zamietnutie či zrušenie, ktoré možno opakovať | open |
Odoslanie z vášho handlera
Pridajte toto do toho istého skriptu. Váš handler zvaliduje formulár a zavolá submit():
form.addEventListener('submit', async (event) => {
event.preventDefault()
if (!form.reportValidity() || !payment.snapshot.canSubmit) return
await payment.submit().catch(() => {
// The card fields show the reason. The shopper can try again when canSubmit allows it.
})
})submit() zavolá pre platbu prepare, potom zvaliduje kartu, vykoná 3-D Secure a potvrdí platbu
v Tapaya.
Zobrazenie výsledku
onChange dostane snapshot platby pri každej jeho zmene, vrátane načítania stránky s platbou, ktorá
je už dokončená. Riaďte sa hodnotou snapshot.outcome:
outcome | Čo zobraziť |
|---|---|
open | Tlačidlo Pay, aktívne, kým je canSubmit true. Po zamietnutí zostáva open a ďalšie submit() dostane nový pokus. |
pending | Indikátor priebehu. Výsledok zatiaľ nie je známy, takže nemožno nič zaplatiť znova. SDK kontroluje stav automaticky, kým je stránka viditeľná. |
completed | Vašu potvrdzovaciu stránku. Tam váš server objednávku overí. |
ended | Novú pokladňu. Pre túto objednávku už nie je možný žiadny ďalší pokus. |
Keď sa zobrazenie vašej pokladne odpája (unmount), zavolajte payment.destroy(). V Reacte použite usePayment() z
@tapayadot/checkout/react. Prijíma rovnaké možnosti a navyše publishableKey a apiOrigin a vracia
fieldRef pre kontajner, aktuálny snapshot a submit().
Overenie pred vybavením
Výsledok v prehliadači slúži iba na zobrazenie. Na potvrdzovacej stránke načítajte platbu objednávky na svojom serveri a objednávku vybavte iba vtedy, keď je platba dokončená:
import { findPayment } from './payments.js';
const order = await getCheckoutOrder(request);
const payment = await findPayment(order); // Checks order ID, amount, and currency.
if (payment?.status === 'successful') await markOrderPaid(order.id, payment.id);Zabezpečte, aby markOrderPaid() zaznamenala platbu iba raz, aj keď sa volá opakovane, a vybavenie spúšťajte z tohto
uloženého stavu.
Odsúhlasenie objednávok, ktoré zákazník opustil
Zákazník môže zatvoriť kartu prehliadača skôr, ako sa otvorí potvrdzovacia stránka. Spustite plánovanú úlohu, ktorá pre nezaplatené objednávky volá verify() alebo
číta GET /merchant/payments?merchantOrderId=..., s rovnakými kontrolami. Zamietnuté a
zrušené pokusy umožňujú nový pokus, takže nezaplatená objednávka zostáva open: uvoľnite ju podľa vlastného harmonogramu, a
to iba vtedy, keď jej paymentStatus nie je pending. Neúspešná požiadavka alebo vypršanie časového limitu nie je zamietnutie, preto objednávku nechajte
rezervovanú, kým platba nemá známy výsledok.
Pridanie Apple Pay a Google Pay
Peňaženky sa zobrazujú vnútri rámca Tapaya vedľa polí pre kartu. Aby sa zobrazili, overte, že:
- Peňaženky sú povolené v nastaveniach Checkoutu.
- Apple Pay: obchod má aktívnu doménu obchodu.
- Google Pay v produkčnom prostredí: je nakonfigurované Google Pay merchant ID.
- Zariadenie, prehliadač a peňaženka zákazníka danú metódu podporujú.
Odovzdajte wallets s celkovou sumou pokladne v najmenších jednotkách meny. Tapaya zobrazí dostupné metódy a nepodporované alebo
vypnuté peňaženky zostanú skryté. Použite tento kód namiesto príkladu createPayment() iba pre karty:
const payment = tapaya.createPayment({
prepare: '/api/payments',
wallets: { amount: order.totalInMinorUnits, currency: order.currency },
onWalletClick: async () => {
if (!form.reportValidity()) throw new Error('Complete the checkout details.')
// Validate the cart and reserve the order on your server.
const response = await fetch('/api/payments', { method: 'POST' })
if (!response.ok) throw new Error('Could not prepare the payment.')
return response.json() // { clientSecret, status }
},
onChange: (snapshot) => {
button.hidden = snapshot.paymentMethod !== 'card'
button.disabled = !snapshot.canSubmit
if (snapshot.outcome === 'completed') location.assign('/checkout/confirmation')
},
})
await payment.mount('#card-fields')Celková suma zobrazená v prehliadači musí pochádzať z vášho servera, ktorý ju pri príprave platby aj tak sám vypočíta a overí.
Kliknutia na peňaženku
Oficiálne tlačidlo peňaženky otvorí natívne platobné okno peňaženky na základe kliknutia zákazníka. onWalletClick zvaliduje vašu
pokladňu a rezervuje jej platbu vo chvíli, keď sa na toto tlačidlo klikne, nikdy pri pripojení ani pri výbere metódy. Bez tohto
callbacku používajú peňaženky prepare alebo clientSecret. Ak objednávku rezervujete až pri kliknutí, zabezpečte, aby callback
prepare volaný pri pripojení nadviazal na existujúcu objednávku bez toho, aby vytvoril novú.
Vlastné tlačidlo Pay nechajte viditeľné iba vtedy, keď je snapshot.paymentMethod rovné card; peňaženky namiesto
payment.submit() používajú svoje značkové tlačidlá. Výsledky platieb peňaženkou prechádzajú rovnakým postupom overenia a obnovy ako karty. Zatvorenie
platobného okna peňaženky ponechá pokladňu dostupnú; neistá platba zostane čakajúca a zablokuje ďalšie zaťaženie karty.
Aktualizácia celkovej sumy
Kým nie sú vyplnené povinné údaje pokladne, odovzdávajte wallets: { amount, currency, disabled: true }. Celkovú sumu
aktualizujte alebo tlačidlá povoľte bez opätovného pripojenia:
payment.update({ wallets: { amount: 2450, currency: 'EUR', disabled: false } })Odovzdaním wallets: null peňaženky skryjete, kým nebude celková suma pripravená. Tapaya odmietne potvrdenie, ak sa pripravená platba
líši od celkovej sumy peňaženky. React hook usePayment() tieto možnosti prijíma a celkovú sumu aktualizuje, keď sa
wallets zmení.
Vlastný výber metódy
Ak výber metódy spravuje vaša stránka, odovzdajte paymentMethod: 'card', 'apple_pay' alebo 'google_pay', aby sa vykreslila
iba táto metóda. Nedostupná vybraná peňaženka zobrazí popisok walletUnavailable a nahlási
snapshot.error.code: 'wallet_unavailable', ak možno bezpečne začať inú platbu; ponúknite vo svojom
výbere inú metódu. Výber zamknite, kým je snapshot.busy true alebo je platba v stave pending či action_required.
Rámce a CSP
SDK pridáva k svojmu rámcu allow="payment". Ak je váš obchod vnútri iného rámca, musí platby povoliť aj tento vonkajší
rámec. Apple Pay naprieč originmi vyžaduje Safari 17 alebo novší. Skripty poskytovateľov peňaženiek zostávajú vnútri rámca Tapaya, takže
vaša stránka nepotrebuje vo svojej CSP žiadne ďalšie originy poskytovateľov.
Spracovanie vypršaného prístupu prehliadača
Client secret vyprší po 24 hodinách a clientSecret je potom null. Platba, ktorá nebola nikdy odoslaná, sa
potom zruší a ďalšie prepare() začne pre tú istú objednávku nový pokus. Čakajúca platba zostáva v prehliadači pending
a SDK naďalej volá váš endpoint, kým váš server nenahlási jej výsledok ako status. Čítanie na serveri
stále funguje, takže ju vaša plánovaná úloha v každom prípade dokončí.
Diagnostika chýb servera
Node SDK pri odmietnutých požiadavkách na API vyhadzuje PaymentsApiError. Na svojom serveri skontrolujte jeho status, code, message,
fieldErrors a requestId. Prihlasovacie údaje a client secrets nezapisujte do logov a zákazníkovi zobrazujte vlastné
texty.
Prispôsobenie vašej značke
Polia pre kartu používajú ako farbu zvýraznenia pri fokuse (colorFocus) výslednú farbu pokladne obchodníka z nastavení
Checkoutu.
Hodnoty, ktoré odovzdáte v appearance.variables, ju prepíšu, a posielajú sa iba premenné, ktoré nastavíte.