Platobná brána v aplikácii
Integrácia platobnej brány do mobilnej alebo desktopovej aplikácie (ďalej len ako Aplikácia) je veľmi podobná ako integrácia do webového rozhrania. Aj v tomto prípade sa využíva štandardný API protokol. Jediným rozdielom je, že na webe je možné zvoliť buď presmerovanie na platobnú bránu, alebo zobrazenie brány v iframe, zatiaľ čo v aplikácii je potrebné platbu otvoriť v komponentne určenej na zobrazenie webovej stránky, typicky WebView, alebo využiť možnosť presmerovania pomocou Android Intent prípadne Apple URL Schemes a Universal Links.
WebView
Pre Android, .Net a Xamarin je dostupná komponenta WebView, zatiaľ čo Apple používa vo svojom Swifte WKWebView.
Rozhranie WebView by malo byť zobrazené na čo najväčšej časti obrazovky, aby mala platobná brána dostatok priestoru na zobrazenie a maximalizovala užívateľský komfort.
Priebeh spracovania platby
- Aplikácia kontaktuje svoj Server a vytvorí objednávku.
- Server vykoná HTTP request na Comgate API (/create), čím založí platbu. Comgate API vráti odpoveď obsahujúcu informácie o platbe.
- Server si informácie získané z Comgate API uloží a odovzdá ich aj Aplikácii (ako parsovať query string v PHP, JavaScripte, Kotline, Jave a Swifte).
- Aplikácia vytvorí cez čo najväčšiu časť displeja WebView komponentu a v nej načíta URL platobnej brány (parameter redirect).
- Platiteľovi sa načíta platobná brána vo WebView.
- Počas toho, čo sa platiteľ pokúša zaplatiť, je potrebné spustiť status watcher. Ten sa snaží čo najrýchlejšie synchronizovať stav platby zo Servera do Aplikácie. Dostupné metódy:
- Polling - krátke opakované requesty na server (cca každé 3 sekundy),
- Long Polling - server drží requesty otvorené, kým nie sú dáta dostupné alebo nedôjde k timeout. Ak ešte nie je známy status, request sa opakuje,
- WebSocket - poskytuje full-duplex komunikačný kanál, kde je server schopný aplikácii v reálnom čase poslať informáciu o stave platby.
- Platiteľ zaplatí objednávku.
- Po tom, čo platiteľ vykoná úhradu, je Server pomocou Push notifikácie informovaný o novom stave platby. Túto informáciu si uloží.
- Server si overí stav platby tým, že sa dotáže Comgate API (/status), či je platba skutočne zaplatená.
- Ak nie, dotazuje sa periodicky každé cca 3 sekundy znova. Po 10 dotazoch (cca 30 sekundách) je vhodné dotazovanie ukončiť a na pozadí sa dotázať Servera na stav raz za 30 minút.
Venujte zvýšenú pozornosť
V niektorých prípadoch môže spracovanie platby trvať až do 12:00 nasledujúceho pracovného dňa.
- V opakovaní dotazovania je možné pokračovať podľa stavov platieb.
- Ak nie, dotazuje sa periodicky každé cca 3 sekundy znova. Po 10 dotazoch (cca 30 sekundách) je vhodné dotazovanie ukončiť a na pozadí sa dotázať Servera na stav raz za 30 minút.
- Brána zobrazená vo WebView zistí, že došlo k zaplateniu:
- a tesne pred presmerovaním zasiela post message, ktorú je možné zachytiť a na jej základe WebView skryť,
- prípadne dôjde k presmerovaniu platiteľa na URL definovanú v prepojení obchodu - na túto URL by mala Aplikácia reagovať a WebView skryť.
- Aplikácia kontaktuje svoj Server a overí si stav platby.
- Aplikácia sprístupní zaplatenú službu.
Sekvenčný diagram
Ako zistiť okamih, kedy je potrebné skryť WebView
Ako už bolo naznačené v bode 10, existujú v zásade 2 spôsoby, ako zistiť, že je platba zaplatená a je potrebné skryť WebView:
- zachytenie zaslanej post message,
- presmerovanie platiteľa na URL definovanú v prepojení obchodu.
Post message
Pred presmerovaním platiteľa preč z brány je zasielaná post message, ktorá informuje o stave platby. Túto správu je možné zachytiť a na jej základe WebView skryť.
Štruktúra post message:
{
"value":{
"id": "XXXX-XXXX-XXXX",
"status": "PAID", // PAID, CANCELLED, AUTHORIZED, PENDING
"refId": "hodnota-refId"
},
"scope": "comgate-to-eshop",
"action": "status"
}
Pri prijatí message je potrebné overovať, že scope
je "comgate-to-eshop"
a action
je "status"
. Ostatné post messages by mali byť ignorované.
Zároveň je potrebné venovať zvýšenú pozornosť overeniu stavu platby. Stavy získané pomocou post messages nie sú dôveryhodné a je vždy potrebné si stav overiť na API Comgate.
Presmerovanie platiteľa
Platiteľa je možné presmerovať na nejakú URL vlastného servera. V tomto prípade je nutné zabezpečiť automatické zistenie tohto presmerovania v Aplikácii a skrytie WebView.
URL je možné nastaviť v klientskom portáli (alebo cez API pri zakladaní platby):
- URL zaplatený (
url_paid
) - zaplatené platby (PAID
,AUTHORIZED
), - URL zrušený (
url_cancelled
) - zrušené a expirované platby (CANCELLED
), - URL nevybavený (
url_pending
) - stále prebiehajúce platby (PENDING
), - URL pre odovzdanie výsledku platby - je nutné nastaviť iba v klientskom portáli v prepojení obchodu.
Detekcia zmeny URL vo WebView
Java kód
WebViewClient webViewClient = new WebViewClient() {
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
if(url.equals("your link...")){
finish();
}
}
};
Zaujímavé odkazy:
- https://stackoverflow.com/questions/6908369/how-to-exit-a-webview-android
- https://stackoverflow.com/questions/3149216/how-to-listen-for-a-webview-finishing-loading-a-url
- https://medium.com/nerd-for-tech/androids-webview-common-challenges-and-it-s-solution-part-1-9b970b95a482
- https://stackoverflow.com/questions/20305612/closing-webview-in-android
Zjednodušená implementácia v Kotline
Kotlin kód
package com.comgate.webviewtest
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.webkit.WebView
import java.net.URLDecoder
import java.nio.charset.StandardCharsets
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// TODO: Create a payment
// Request the mobile app server to create a payment using the Comgate API
// Server returns payment data
val cloudResponseFromComgate = "code=0&message=OK&transId=XXXX-XXXX-XXXX&redirect=https%3A%2F%2Fpay1.comgate.cz%2Finit%3Fid%3DXXXX-XXXX-XXXX";
// Parse the response
val paymentData = this.parseQuery(cloudResponseFromComgate)
val comgateMessage = paymentData["message"]
val paymentUrl = paymentData["redirect"]
val transId = paymentData["transId"]
if (comgateMessage == "OK" && paymentUrl?.isNotEmpty() == true && transId?.isNotEmpty() == true) {
val paymentView: WebView = findViewById(R.id.comgatePaymentFrame)
paymentView.visibility = View.VISIBLE
// The URL can change over time, so always use the URL returned by the Comgate API
paymentView.loadUrl(paymentUrl)
// Start the status watcher
runStatusWatcher(transId)
} else {
// TODO: Handle payment error
}
}
private fun runStatusWatcher(transId: String) {
// TODO: Implement a payment status watcher
// Options for implementation:
// - Polling: Send repeated requests every 3 seconds
// - Long polling: Keep the request open until new data is available
// - WebSockets: Establish a full-duplex communication channel
// - Other methods
}
/**
* Parses a query string into a Map (Key -> Value)
*/
private fun parseQuery(input: String): Map<String, String> {
return input.split("&")
.map { pair ->
pair.split("=").let {
URLDecoder.decode(it[0].trim(), StandardCharsets.UTF_8.toString()) to
URLDecoder.decode(it.getOrElse(1) { "" }.trim(), StandardCharsets.UTF_8.toString())
}
}
.toMap()
}
}
Android Intent
Comgate tiež umožňuje integráciu návratov z platobnej brány pomocou Intent. Výhodou je, že nemusíte implementovať WebView a na zobrazenie platby sa použije predvolený prehliadač, ktorý následne aplikácii vráti focus.
Priebeh spracovania platby
- Aplikácia kontaktuje svoj Server a vytvorí objednávku.
- Server vykoná HTTP request na Comgate API (/create), čím založí platbu. Comgate API vráti odpoveď obsahujúcu informácie o platbe.
- Server si informácie získané z Comgate API uloží a odovzdá ich aj Aplikácii (ako parsovať query string v PHP, JavaScripte, Kotline, Jave a Swifte).
- Aplikácia otvorí platbu v predvolenom prehliadači platiteľa (použije URL na platobnú bránu z parametra "redirect"). Tým aplikácia stratí focus.
- Platiteľovi sa načíta platobná brána v predvolenom prehliadači.
- Platiteľ zaplatí objednávku.
- Po tom, čo platiteľ vykoná úhradu, je Server pomocou Push notifikácie informovaný o novom stave platby. Túto informáciu si uloží.
- Server si overí stav platby tým, že sa dotáže Comgate API (/status), či je platba skutočne zaplatená.
- Ak nie, dotazuje sa periodicky každé cca 3 sekundy znova. Po 10 dotazoch (cca 30 sekundách) je vhodné dotazovanie ukončiť a na pozadí sa dotázať Servera na stav raz za 30 minút.
Venujte zvýšenú pozornosť
V niektorých prípadoch môže spracovanie platby trvať až do 12:00 nasledujúceho pracovného dňa.
- V opakovaní dotazovania je možné pokračovať podľa stavov platieb.
- Ak nie, dotazuje sa periodicky každé cca 3 sekundy znova. Po 10 dotazoch (cca 30 sekundách) je vhodné dotazovanie ukončiť a na pozadí sa dotázať Servera na stav raz za 30 minút.
- Platiteľ je následne presmerovaný späť do Aplikácie a tá získa "focus".
- Aplikácia kontaktuje svoj Server a overí si stav platby.
- Aplikácia sprístupní zaplatenú službu.
Sekvenčný diagram
Nastavenie návratových URI pre Intent
V súčasnosti je možné Android Intent použiť iba ako parametre pri zakladaní platby cez Comgate API (/create). Jedná sa o parametre:
url_paid
- URI pre presmerovanie platiteľa po zaplatení platby,url_cancelled
- URI pre presmerovanie platiteľa po zrušení platby,url_pending
- URI pre presmerovanie platiteľa, ak platba ešte nie je vybavená.
Platobná brána sa následne bude snažiť použiť tento Intent v predvolenom prehliadači a presmerovať tak platiteľa späť do vašej aplikácie.
Android Intent nie je v súčasnosti možné nastaviť v klientskom portáli.
Android Intent formát
Je možné používať prakticky ľubovoľný formát Intentu. Veľmi často sa stretávame s obecným zápisom v tvare:
intent://host/path?transactionId=XXXX-XXXX-XXXX&status=PAID#Intent;package=com.example.package;end
Je možné sa tiež stretnúť s viac špecifickými Intentami napr.:
myapp://payment/success?transactionId=XXXX-XXXX-XXXX&status=PAID
V oboch prípadoch sú Intenty úzko späté s konkrétnou aplikáciou. Ich funkčnosť je potrebné implementovať v rámci samotnej aplikácie.
Apple URL Schemes a Universal Links
Apple na svojich zariadeniach poskytuje mechanizmy, ktoré umožňujú aplikáciám efektívne spracovať presmerovanie. Medzi tieto mechanizmy patria URL Schemes a Universal Links.
URL Schemes
Vlastné URL schémy umožňujú aplikáciám registrovať jedinečné odkazy, pomocou ktorých môže platobná brána presmerovať platiteľa späť do aplikácie.
myapp://payment/success?transactionId=XXXX-XXXX-XXXX&status=PAID
Universal Links
Universal Links sú štandardné HTTP/HTTPS odkazy, ktoré automaticky otvoria aplikáciu. Tento mechanizmus je preferovaný kvôli lepšej bezpečnosti a používateľskej prívetivosti.
https://example.com/payment/success?transactionId=XXXX-XXXX-XXXX&status=PAID
Návratové URL
Pri nastavovaní platieb cez Comgate API je možné definovať návratové URL, ktoré určujú, kam bude platiteľ presmerovaný v rôznych situáciách:
url_paid
: presmerovanie po úspešnej platbe (PAID
,AUTHORIZED
)url_cancelled
: presmerovanie po zrušenej alebo expirovanej platbe (CANCELLED
)url_pending
: presmerovanie pre prebiehajúce platby (PENDING
)
Návratové URL vo formáte Universal Links je možné definovať ako cez Comgate API, tak aj v klientskom portáli.
URL Schemes je momentálne možné nastaviť iba cez Comgate API.