Push notifikácie
Prenos výsledku platby na pozadí
Push notifikácie slúžia na prenos výsledku platby na pozadí z platobnej brány Comgate na server obchodníka. Táto metóda využíva HTTP požiadavku (webhook) na definovanú adresu (endpoint), ktorá upozorní na zmenu stavu platby, napríklad pri úspešnom dokončení, autorizácii, expirácii alebo zrušení platby.
Bezpečné overenie stavu platby
Skutočný stav platby je odporúčané vždy overiť prostredníctvom volania API metódy /status/. Toto overenie zaručuje spoľahlivosť a bezpečnosť, pretože informácie prijaté push notifikáciou nemusia vždy presne odrážať finálny stav platby.
Nastavenie endpointu pre push notifikácie
Adresu, na ktorú majú byť push notifikácie zasielané, je možné nastaviť v klientskom portáli. Odporúča sa nastaviť adresu, ktorá podporuje HTTPS, aby bola zabezpečená bezpečnosť komunikácie.
Parametre push notifikácie
Výsledok platby je predávaný ako HTTP POST požiadavka s nasledujúcimi parametrami:
Parameter | Typ | Povinný | Popis |
---|---|---|---|
transId | string | A | Unikátne ID transakcie |
merchant | string | A | Identifikátor e-shopu v systéme Comgate |
test | boolean | A | true pre testovaciu platbu, false pre produkčnú |
price | integer | A | Cena za produkt v halieroch alebo centoch |
curr | string | A | Kód meny podľa ISO 4217 |
label | string | A | Krátky popis produktu (1-16 znakov) |
refId | string | A | Referencia platby (napr. variabilný symbol alebo číslo objednávky) |
payerId | string | N | Identifikátor platcu v systéme e-shopu |
payerName | string | N | Názov účtu platcu |
payerAcc | string | N | Číslo účtu platcu |
method | string | N | Použitá metóda platby |
account | string | N | Identifikátor bankového účtu e-shopu |
string | A | Kontaktný e-mail platcu | |
phone | string | N | Kontaktný telefón platcu |
name | string | N | Identifikátor produktu na vyhľadávanie v štatistikách |
secret | string | A | Bezpečnostný kľúč pre komunikáciu |
status | string | A | Aktuálny stav transakcie (PAID, CANCELLED, AUTHORIZED) |
fee | string | N | Poplatok za transakciu (ak je nastavený) |
fullName | string | A | Meno a priezvisko platcu |
billingAddrCity | string | N | Fakturačná adresa - mesto |
billingAddrStreet | string | N | Fakturačná adresa - ulica |
billingAddrPostalCode | string | N | Fakturačná adresa - PSČ |
billingAddrCountry | string | N | Fakturačná adresa - krajina (ISO 3166 alpha-2) |
delivery | string | N | Spôsob doručenia (HOME_DELIVERY, PICKUP, ELECTRONIC_DELIVERY) |
homeDeliveryCity | string | N | Doručovacia adresa - mesto |
homeDeliveryStreet | string | N | Doručovacia adresa - ulica |
homeDeliveryPostalCode | string | N | Doručovacia adresa - PSČ |
homeDeliveryCountry | string | N | Doručovacia adresa - krajina (ISO 3166 alpha-2) |
category | string | N | Kategória produktu (PHYSICAL_GOODS_ONLY, OTHER) |
Výsledky predané cez notifikáciu alebo presmerovaním v URL sa neodporúča považovať za úplne dôveryhodné, keďže tieto metódy môžu byť náchylné na manipuláciu. Skutočný stav platby je odporúčané vždy overiť prostredníctvom volania API metódy /status/sk spolu s obdržaným transId.
Parametre odpovedí
Parameter | Typ | Povinný | Popis |
---|---|---|---|
code | integer | A | Návratový kód metódy a popis chyby: systém očakáva HTTP kód 200, ak bol výsledok prijatý úspešne |
Push notifikácie očakávajú potvrdenie prijatia formou HTTP kódu 200. V opačnom prípade je notifikácia opakovane zasielaná (až 1000 pokusov). Ak ani po opakovaných pokusoch nedôjde k úspešnému doručeniu, je vygenerovaná chybová správa a odoslaná na kontaktný e-mail obchodníka.
Tip: Ak nie je potvrdené prijatie notifikácie, uistite sa, že endpoint vracia kód 200. Môžete nastaviť e-mail pre zasielanie chýb v sekcii Integrácia v klientskom portáli, kde môžete definovať viac e-mailov oddelených bodkočiarkou.
Príklad prenosu výsledku platby na pozadí – HTTP požiadavka pomocou cURL
curl -X POST -i --data "merchant=merchant_com&test=false&price=10000&curr=CZK&label=Beatles%20-%20Help&refId=2010102600&method=CARD&email=info%40customer.com&phone=%2B420123456789&transId=AB12-EF34-IJ56&secret=ZXhhbXBsZS5jb206QUJDeHl6&status=PAID" https://example.com/handler.php
Príklad prenosu výsledku platby na pozadí – HTTP odpoveď
HTTP/1.1 200 OK
content-type: application/x-www-form-urlencoded; charset=UTF-8
Komunikácia medzi systémom Klienta a serverom platobnej brány je zabezpečená pomocou hesla a IP whitelistu. Prístup musí byť povolený iba z IP adresy servera platobnej brány. Rozsahy IP adries sú definované v sekcii Zabezpecenie. Je povinné používať protokol HTTPS, ktorý znemožňuje odhalenie hesla pri prípadnom odpočúvaní komunikácie. Heslo je predávané ako POST parameter (nie GET parameter) preto, aby sa neukladalo v logu komunikácie webového servera.
E-shop na svojej strane zaistí, že tovar (služba) poskytnutý v rámci zaplatenej transakcie (identifikovanej pomocou unikátneho transaction ID) bude vydaný Platcovi iba raz (aj pri opakovanom prenose výsledku tej istej platby na server Klienta).
Implementácia a Ukážka Kódu
Ukážka Endpointu na Príjem Push Notifikácií
- PHP
- Java
- Python
- C#
<?php
// Webhook endpoint for push notification
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// Load data from push notification using POST (x-www-form-urlencoded) or REST (JSON)
// POST method (x-www-form-urlencoded)
parse_str(file_get_contents('php://input'), $data);
// REST method (JSON)
// $data = json_decode(file_get_contents('php://input'), true);
if (isset($data['transId'])) {
$paymentId = $data['transId'];
// Prepare headers and parameters for payment verification
$headers = [
'Content-Type: application/x-www-form-urlencoded',
'Accept: application/x-www-form-urlencoded',
];
$request_params = [
'merchant' => '123456',
'transId' => $paymentId,
'secret' => 'gx4q8OV3TJt6noJnfhjqJKyX3Z6Ych0y',
];
// Initialize cURL for API call
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://payments.comgate.cz/v1.0/status');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($request_params));
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
try {
// Execute cURL request
$response = curl_exec($ch);
if ($response === false) {
throw new Exception(curl_error($ch), curl_errno($ch));
}
// Output API response for verification
print_r($response);
} catch (Exception $e) {
print_r($e->getMessage());
} finally {
curl_close($ch);
}
// Respond to push notification
http_response_code(200);
echo "OK";
} else {
http_response_code(400);
echo "Bad Request";
}
}
?>
import org.springframework.web.bind.annotation.*;
import org.springframework.http.ResponseEntity;
import org.json.JSONObject;
import java.net.HttpURLConnection;
import java.net.URL;
import java.io.*;
@RestController
@RequestMapping("/webhook")
public class WebhookController {
@PostMapping
public ResponseEntity<String> handlePushNotification(@RequestBody String payload) {
try {
// Load data from push notification using POST (x-www-form-urlencoded) or REST (JSON)
JSONObject data = new JSONObject(payload);
String transId = data.optString("transId", null);
if (transId != null) {
// Prepare the API URL and connection
URL url = new URL("https://payments.comgate.cz/v1.0/status");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
conn.setRequestProperty("Accept", "application/x-www-form-urlencoded");
conn.setDoOutput(true);
// Prepare the request parameters
String params = "merchant=123456&transId=" + transId + "&secret=gx4q8OV3TJt6noJnfhjqJKyX3Z6Ych0y";
// Send the request
OutputStream os = conn.getOutputStream();
os.write(params.getBytes());
os.flush();
os.close();
// Read the response
BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String inputLine;
StringBuilder content = new StringBuilder();
while ((inputLine = in.readLine()) != null) {
content.append(inputLine);
}
in.close();
conn.disconnect();
// Return success response
return ResponseEntity.ok("OK");
} else {
return ResponseEntity.badRequest().body("Bad Request: transId missing");
}
} catch (Exception e) {
e.printStackTrace();
return ResponseEntity.status(500).body("Internal Server Error");
}
}
}
from flask import Flask, request, jsonify
import requests
app = Flask(__name__)
@app.route('/webhook', methods=['POST'])
def webhook():
# Load data from push notification using POST (x-www-form-urlencoded) or REST (JSON)
# POST method (x-www-form-urlencoded)
data = request.form.to_dict()
# REST method (JSON)
# data = request.get_json()
if 'transId' in data:
payment_id = data['transId']
# Prepare headers and payload for API call
headers = {
'Content-Type': 'application/x-www-form-urlencoded',
'Accept': 'application/x-www-form-urlencoded'
}
payload = {
'merchant': '123456',
'transId': payment_id,
'secret': 'gx4q8OV3TJt6noJnfhjqJKyX3Z6Ych0y'
}
# Send POST request to API
try:
response = requests.post('https://payments.comgate.cz/v1.0/status', headers=headers, data=payload)
response.raise_for_status()
# Return success response to the webhook
return "OK", 200
except requests.exceptions.RequestException as e:
print(f"Error: {e}")
return "Internal Server Error", 500
else:
return "Bad Request: transId missing", 400
if __name__ == '__main__':
app.run(port=5000)
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading.Tasks;
[ApiController]
[Route("webhook")]
public class WebhookController : ControllerBase
{
[HttpPost]
public async Task<IActionResult> HandlePushNotification([FromBody] Dictionary<string, string> data)
{
// Check if transId is in the data
if (data.TryGetValue("transId", out var transId))
{
using (var client = new HttpClient())
{
// Prepare request parameters
var values = new Dictionary<string, string>
{
{ "merchant", "123456" },
{ "transId", transId },
{ "secret", "gx4q8OV3TJt6noJnfhjqJKyX3Z6Ych0y" }
};
var content = new FormUrlEncodedContent(values);
// Send POST request to API
var response = await client.PostAsync("https://payments.comgate.cz/v1.0/status", content);
// Check if the response was successful
if (response.IsSuccessStatusCode)
{
// Return success response to the webhook
return Ok("OK");
}
else
{
return StatusCode((int)response.StatusCode, "API call failed");
}
}
}
else
{
return BadRequest("transId missing");
}
}
}