Push Notifications
Payment Result Delivery in the Background
Push notifications are used to deliver the payment result in the background from the Comgate payment gateway to the merchant's server. This method utilizes an HTTP request (webhook) to a defined endpoint that notifies of a payment status change, such as successful completion, authorization, expiration, or cancellation.
Secure Verification of Payment Status
It is recommended to always verify the actual payment status by calling the API method /status. This verification ensures reliability and security, as information received via push notification may not always accurately reflect the final payment status.
Setting the Endpoint for Push Notifications
The address to which push notifications should be sent can be set in the client portal. It is recommended to set an address that supports HTTPS to ensure secure communication.
Push Notification Parameters
The payment result is delivered as an HTTP POST request with the following parameters:
Parameter | Type | Required | Description |
---|---|---|---|
transId | string | Yes | Unique transaction ID |
merchant | string | Yes | E-shop identifier in the Comgate system |
test | boolean | Yes | true for test payment, false for production |
price | integer | Yes | Product price in cents or pence |
curr | string | Yes | Currency code according to ISO 4217 |
label | string | Yes | Short product description (1-16 characters) |
refId | string | Yes | Payment reference (e.g., variable symbol or order number) |
payerId | string | No | Payer identifier in the e-shop system |
payerName | string | No | Payer account name |
payerAcc | string | No | Payer account number |
method | string | No | Payment method used |
account | string | No | E-shop's bank account identifier |
email | string | Yes | Payer's contact email |
phone | string | No | Payer's contact phone |
name | string | No | Product identifier for statistics |
secret | string | Yes | Security key for communication |
status | string | Yes | Current transaction status (PAID , CANCELLED , AUTHORIZED ) |
fee | string | No | Transaction fee (if applicable) |
fullName | string | Yes | Payer's full name |
billingAddrCity | string | No | Billing address - city |
billingAddrStreet | string | No | Billing address - street |
billingAddrPostalCode | string | No | Billing address - postal code |
billingAddrCountry | string | No | Billing address - country (ISO 3166 alpha-2) |
delivery | string | No | Delivery method (HOME_DELIVERY , PICKUP , ELECTRONIC_DELIVERY ) |
homeDeliveryCity | string | No | Delivery address - city |
homeDeliveryStreet | string | No | Delivery address - street |
homeDeliveryPostalCode | string | No | Delivery address - postal code |
homeDeliveryCountry | string | No | Delivery address - country (ISO 3166 alpha-2) |
category | string | No | Product category (PHYSICAL_GOODS_ONLY , OTHER ) |
Results delivered via notification or URL redirection should not be considered fully trustworthy, as these methods can be prone to manipulation. It is recommended to always verify the actual payment status using the API method /status together with the received transId.
Response Parameters
Parameter | Type | Required | Description |
---|---|---|---|
code | integer | Yes | Method return code and error description: the system expects HTTP code 200 if the payment result was received successfully. |
Push notifications expect an acknowledgment in the form of HTTP code 200. Otherwise, the notification is resent repeatedly (up to 1,000 attempts). If repeated attempts fail, an error message is generated and sent to the merchant's contact email.
Tip: If the notification receipt is not confirmed, ensure that the endpoint returns code 200. You can also set an email for error reporting in the Integration section of the client portal, where you can define multiple emails separated by semicolons.
Example Payment Result Delivery – HTTP request using 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
Example Payment Result Delivery – HTTP response
HTTP/1.1 200 OK
content-type: application/x-www-form-urlencoded; charset=UTF-8
Communication between the Client's system and the payment gateway server is secured using a password and IP whitelist. Access must only be allowed from the payment gateway server's IP address. IP ranges are defined in the Security section. It is mandatory to use the HTTPS protocol to prevent password exposure in case of eavesdropping. The password is passed as a POST parameter (not a GET parameter) to avoid being logged in the web server's communication log.
The e-shop must ensure that goods (services) provided in the paid transaction (identified by the unique transaction ID) are issued to the Payer only once, even if the result of the same payment is passed to the Client's server multiple times.
Implementation and Code Example
Example of an Endpoint for Receiving Push Notifications
- 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");
}
}
}