Příklady implementace
Checkout SDK lze implementovat více způsoby v závislosti na prostředí a použitých technologiích e-shopu.
Následující příklady ilustrují základní scénáře implementace, které mohou sloužit jako výchozí bod pro integraci.
1. Vložením scriptu z Comgate CDN
Checkout SDK je možné načíst přímo z Comgate CDN pomocí vloženého <script>
tagu.
Stáhnout ukázkový projekt
Příklad je rozsáhlý, proto je zobrazen ve sbalitelném bloku.
<!DOCTYPE html>
<html lang="cs">
<head>
<meta charset="UTF-8" />
<title>Comgate Checkout – CDN example integration</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
body {
background: #FFFFFF;
}
.container {
width: 240px;
background: #DDDDDD;
border: solid 1px #d0d0d0;
padding: 5px;
}
.container .button {
background: #808080;
width: 100%;
height: 50px;
}
.container .button:first-child {
margin-bottom: 5px;
}
</style>
</head>
<body>
<div class="container">
<div class="button" id="apple-pay-button-box"></div>
<div class="button" id="google-pay-button-box"></div>
</div>
<!-- Vlož script @comgate/checkout-js (Loaderu) z Comgate CDN (nikdy nepoužívejte jsDelivr, unpkg a další) -->
<!-- Pokud lze, doporučujeme použít NPM balíček @comgate/checkout-js (https://www.npmjs.com/package/@comgate/checkout-js) -->
<script src="https://checkout.comgate.cz/sdk/@2/checkout-js.min.js"></script>
<script>
// kde získat checkoutId: https://apidoc.comgate.cz/checkout/konfigurace#aktivace-checkout-sdk
const checkoutId = 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'; // PŘED
const transactionId = 'XXXX-XXXX-XXXX';
const checkoutJsRef = window.comgateCheckoutJs;
const APPLE_PAY_BUTTON_TYPE = 'plain';
const APPLE_PAY_BUTTON_COLOR = 'white';
const GOOGLE_PAY_BUTTON_TYPE = 'short';
const GOOGLE_PAY_BUTTON_COLOR = 'white';
const APPLE_PAY_BUTTON_BOX_SELECTOR = '#apple-pay-button-box';
const GOOGLE_PAY_BUTTON_BOX_SELECTOR = '#google-pay-button-box';
let isCheckoutReadyTmp = false;
/**
* Spustí tok: kontrola verze → přednačtení → vlastní kód → načtení Checkoutu.
*/
function run() {
if (!isCheckoutReady()) {
console.warn('Comgate Checkout: Loader není dostupný.');
return;
}
checkUpdate(); // zkontroluj major update
preloadCheckout(); // proveď přednačtení modulů
// ===================
// === DIY: vlastní kód ===
// ===================
loadCheckout(); // načti Checkout
}
run();
/**
* Ověří, že je Loader pro Checkout SDK připraven k použití.
* @returns {boolean} Vrací true, pokud je Loader připraven, jinak false.
*/
function isCheckoutReady() {
return isCheckoutReadyTmp ||= (
!!checkoutJsRef &&
typeof checkoutJsRef === 'object' &&
typeof checkoutJsRef.loadComgateCheckout === 'function'
);
}
/**
* Zkontroluje implementovanou major verzi vůči aktuálně preferované verzi Checkout SDK.
* Pokud není použita preferovaná verze, zaloguje upozornění.
*/
function checkUpdate() {
if (!isCheckoutReady()) return;
if (checkoutJsRef.VERSION_2 !== checkoutJsRef.VERSION_PREFERRED) {
// DIY: napojte na vlastní logger, případně odstraňte
console.warn(
'Comgate Checkout: Dostupná nová major verze Checkout SDK. ' +
'Aktualizujte kód, abyste získali nejnovější funkce.'
);
}
}
/**
* Provádí přednačtení potřebných modulů do cache prohlížeče,
* aby plátce nečekal ve chvíli, kdy se Checkout začne používat.
*/
function preloadCheckout() {
if (!isCheckoutReady()) {
console.error('Comgate Checkout: Přednačtení modulů se nezdařilo – Loader není k dispozici.');
return;
}
// Pozn.: „fire-and-forget“ – výsledek se dále nezpracovává, stačí ošetřit chybu.
checkoutJsRef.preloadComgateCheckout({
checkoutId,
version: checkoutJsRef.VERSION_2,
modules: [checkoutJsRef.MODULE_GOOGLEPAY, checkoutJsRef.MODULE_APPLEPAY],
})
.catch((error) => {
console.error('Comgate Checkout: Chyba při přednačtení modulů.', error);
});
}
/**
* Spustí (případně i stáhne) potřebné moduly, aby byly připraveny k použití.
*/
function loadCheckout() {
if (!isCheckoutReady()) {
console.error('Comgate Checkout: Načtení modulů se nezdařilo – Loader není k dispozici.');
return;
}
checkoutJsRef.loadComgateCheckout({
checkoutId,
version: checkoutJsRef.VERSION_2,
modules: [checkoutJsRef.MODULE_GOOGLEPAY, checkoutJsRef.MODULE_APPLEPAY],
// debug: true,
})
.then(async (result) => {
let coreInstance = null;
let applePayInstance = null;
let googlePayInstance = null;
if(result.error) {
console.error('Comgate Checkout: Detaily chyb při načítání modulů:', result.error);
return;
}
// Core
coreInstance = await prepareCore(result.core);
if(!coreInstance) {
console.error("Comgate Checkout: Instanci Core se nepodařilo vytvořit");
return;
}
applePayInstance = await prepareApplePay(coreInstance, result.applepay);
if(applePayInstance) {
const apMountResult = await mountApplePay(applePayInstance, APPLE_PAY_BUTTON_BOX_SELECTOR);
if(apMountResult) {
console.log(`Comgate Checkout: Tlačítko Apple pay je připraveno pro plátce.`);
}
}
googlePayInstance = await prepareGooglePay(coreInstance, result.googlepay);
if(googlePayInstance) {
const gpMountResult = await mountGooglePay(googlePayInstance, GOOGLE_PAY_BUTTON_BOX_SELECTOR);
if(gpMountResult) {
console.log(`Comgate Checkout: Tlačítko Google pay je připraveno pro plátce.`);
}
}
})
.catch((error) => {
// Nečekaná chyba (Promise byla rejectnuta)
console.error('Comgate Checkout: Neočekávaná chyba při načítání modulů.', error);
});
}
/**
* Připraví instanci modulu Core
* @param loaderCore
* @return {Promise<CheckoutCore>}
*/
async function prepareCore(loaderCore) {
if(!loaderCore || typeof loaderCore !== 'object' || typeof loaderCore.create !== 'function') {
console.error('Comgate Checkout: Chyba načítání modulu Core. Očekávaná funkce core.create() neexistuje.');
return null;
}
console.log(`Comgate Checkout: modul Core v${loaderCore.version()} je připraven.`);
const coreConfig = {
checkoutId,
transactionId,
locale: "cs",
onPaid: onPaidHandler, // mapování handleru
onCancelled: onCancelledHandler, // mapování handleru
onPending: onPendingHandler, // mapování handleru
onError: onErrorHandler, // mapování handleru
onPaymentStarted: onPaymentStartedHandler, // mapování handleru
onPaymentStopped: onPaymentStoppedHandler, // mapování handleru
debug: true, // v produkci vypnout
//env: 'prod'
}
return loaderCore.create(coreConfig)
// then není potřeba stejně by jen udělal `return instance`
// .then((instance) => { return instance; })
.catch((error) => {
console.error("Comgate Checkout: chyba při vytváření instance CORE", error);
return null;
});
// alternativní zápis
// try {
// return await loaderCore.create(coreConfig);
// } catch (error) {
// console.error("Comgate Checkout: chyba při vytváření instance CORE", error);
// return null;
// }
}
/**
* Připraví instanci modulu Apple Pay
* @param coreInstance
* @param loaderApplePay
* @return {Promise<ModuleApplePay|null>}
*/
async function prepareApplePay(coreInstance, loaderApplePay) {
if(!loaderApplePay || typeof loaderApplePay !== 'object' || typeof loaderApplePay.create !== 'function') {
console.error('Comgate Checkout: Chyba načítání modulu Apple Pay. Očekávaná funkce applepay.create() neexistuje.');
return null;
}
console.log(`Comgate Checkout: modul Apple Pay v${loaderApplePay.version()} je připraven.`);
const apConfig = {
ui: {
type: APPLE_PAY_BUTTON_TYPE,
color: APPLE_PAY_BUTTON_COLOR
},
actions: {
onButtonClick: () => onButtonClickHandler('applepay')
}
};
return loaderApplePay.create(coreInstance, apConfig)
// then není potřeba stejně by jen udělal `return instance`
// .then((instance) => { return instance; })
.catch((error) => {
console.error("Comgate Checkout: chyba při vytváření instance APPLEPAY", error);
return null;
})
// alternativní zápis
// try {
// return await loaderApplePay.create(coreInstance, {ui: {type: APPLE_PAY_BUTTON_TYPE, color: APPLE_PAY_BUTTON_COLOR}});
// } catch (error) {
// console.error("Comgate Checkout: chyba při vytváření instance APPLEPAY", error);
// return null;
// }
}
/**
* Mount tlačítka Apple Pay
* @param apInstance
* @param selector string
* @return {Promise<boolean>}
*/
async function mountApplePay(apInstance, selector) {
const can = await apInstance.canMakePayments()
.catch(() => {
console.warn('Comgate Checkout: ApplePay canMakePayments said no.');
return false;
});
if(!can) {
return false;
}
const apMountPoint = document.querySelector(selector);
if(!apMountPoint) {
console.warn(`Comgate Checkout: ApplePay element pro mountování s id="${selector}" nebyl nalezen.`)
return false;
}
return await apInstance.mount([apMountPoint])
// then není potřeba stejně by jen udělal `return true`
// .then((result) => { return true; }) // result je na then vždy true
.catch((error) => {
console.error("Comgate Checkout: chyba při mount tlačítka APPLEPAY", error);
return false;
});
}
/**
* Připraví instanci modulu Google Pay
* @param coreInstance
* @param loaderGooglePay
* @return {Promise<ModuleGooglePay|null>}
*/
async function prepareGooglePay(coreInstance, loaderGooglePay) {
if(!loaderGooglePay || typeof loaderGooglePay !== 'object' || typeof loaderGooglePay.create !== 'function') {
console.error('Comgate Checkout: Chyba načítání modulu Google Pay. Očekávaná funkce googlepay.create() neexistuje.');
return null;
}
console.log(`Comgate Checkout: modul Google Pay v${loaderGooglePay.version()} je připraven.`);
const gpConfig = {
ui: {
type: GOOGLE_PAY_BUTTON_TYPE,
color: GOOGLE_PAY_BUTTON_COLOR
},
actions: {
onButtonClick: () => onButtonClickHandler('googlepay')
}
};
return loaderGooglePay.create(coreInstance, gpConfig)
// then není potřeba stejně by jen udělal `return instance`
// .then((instance) => { return instance; })
.catch((error) => {
console.error("Comgate Checkout: chyba při vytváření instance GOOGLEPAY", error);
return null;
})
// alternativní zápis
// try {
// return await loaderGooglePay.create(coreInstance, {ui: {type: GOOGLE_PAY_BUTTON_TYPE, color: GOOGLE_PAY_BUTTON_COLOR}});
// } catch (error) {
// console.error("Comgate Checkout: chyba při vytváření instance GOOGLEPAY", error);
// return null;
// }
}
/**
* Mount tlačítka Google Pay
* @param gpInstance
* @param selector string
* @return {Promise<boolean>}
*/
async function mountGooglePay(gpInstance, selector) {
const can = await gpInstance.canMakePayments()
.catch(() => {
console.warn('Comgate Checkout: GooglePay canMakePayments said no.');
return false;
});
if(!can) {
return false;
}
const gpMountPoint = document.querySelector(selector);
if(!gpMountPoint) {
console.warn(`Comgate Checkout: GooglePay element pro mountování s id="${selector}" nebyl nalezen.`)
return false;
}
return await gpInstance.mount([gpMountPoint])
// then není potřeba stejně by jen udělal `return true`
// .then((result) => { return true; }) // result je na then vždy true
.catch((error) => {
console.error("Comgate Checkout: chyba při mountování tlačítka GOOGLEPAY", error);
return false;
});
}
// =================================================================================
// Sekce handlerů určených pro instance Core, ApplePay a GooglePay
// =================================================================================
function onPaidHandler(payload) {
console.log("onPaid", payload);
// DIY: vistory screen - platba provedena
}
function onCancelledHandler(payload) {
console.log("onCancelled", payload);
// DIY: defeat screen - platba byla zrušena
}
function onPendingHandler(payload) {
console.log("onPending", payload);
// DIY: retry payment screen - pokus se nezdařil, zkusit znovu
}
function onErrorHandler(payload) {
console.log("onError", payload);
// DIY: failure screen - vznikla chyba, opakuje později
// refresh stránky?
}
function onPaymentStartedHandler() {
console.log("onPaymentStarted");
// DIY: zobrazit animaci zpracování platby
}
function onPaymentStoppedHandler() {
console.log("onPaymentStopped");
// DIY: skrýt animaci zpracování platby
}
function onButtonClickHandler(service) {
console.log("onButtonClick", service);
//=============================================================================================//
// Pokud je tento handler v configu modulu definován, čeká Checkout na dokončení této funkce. //
// Jako návratový typ očekává void nebo promise! //
//=============================================================================================//
// DIY: libovolná logika, která by neměla být příliš dlouhá
// nedoporučuje se zde dělat requesty a trvající akce
// Google Pay i Apple Pay ověřují fyzické kliknutí a když uplyně příliš času, platbu odmítnou realizovat
// A) standardním koncem je nedefinovaný return
// B) Také je možné vrátit libovolnou hodnotu na kterou se však nebere ohled a považuje se za potvrzení pokračování
// return false;
// C) přímý resolve dovolí taktéž pokračování
// return Promise.resolve();
// D) zatímco, pokud dojde k vrácení reject, tak dojde k zastavení procesu a je nutné znovu kliknout na tlačítko
// (nedochází také k notifikaci plátce, protože tuto akci má eshop pod kontrolou sám)
// return Promise.reject();
// E) pokud dojde k vrácení nevyřešeného promise, čeká na resolve / reject a chová se jako C nebo D
// return new Promise((resolve, reject) => {
// setTimeout(() => {
// resolve();
// // reject();
// }, 2000);
// });
}
</script>
</body>
</html>
2. Integrace pomocí NPM v Reactu
Checkout SDK lze nainstalovat jako závislost v projektu a následně jej využít přímo v komponentách Reactu.
Z důvodu rozsahu nebylo možné zpřístupnit ukázku jako jeden soubor. Kompletní projekt postavený na Vite.js je k dispozici ke stažení (viz odkaz níže).
Upozornění
Ukázkový projekt pro integraci Checkout SDK v Reactu zatím není k dispozici. Bude doplněn brzy.
Jak projekt spustit lokálně?
- Stáhnout archiv a rozbalit do pracovní složky.
- Nainstalovat závislosti.
- Spustit vývojový server.
# 2) instalace závislostí
npm ci
# 3) lokální vývoj
npm run dev