Skip to main content

Transaction registration

This guide walks you through the process of registering a transaction with the dpay.pl API step by step. We will use the simplest integration method: Simple Gateway, which redirects the customer to the payment gateway.

Prerequisites

Before you begin, make sure you have:

How it works

POST/api/v1_0/payments/registerFull registration contract: parameters, checksum, and error codes.Full contract in the API Reference

Step 1: Prepare the data

Collect the required data for the request:

Required parameters

FieldTypeDescriptionExample
servicestringService name from the panel (alternatively name)"abc123"
transactionTypestringTransaction type"transfers"
valuestringAmount (0.01-999999.99, with a decimal point)"29.99"
url_successstringURL after a successful payment"https://myshop.example/success"
url_failstringURL after a failed payment"https://myshop.example/failure"
url_ipnstringURL for IPN notifications"https://myshop.example/api/ipn"
checksumstringSHA-256 checksum(see below)

Optional parameters

FieldTypeDescription
channelstringSpecific payment channel (see dependencies below)
emailstringCustomer email address (required when channel is provided)
client_namestringCustomer first name (required when channel is provided)
client_surnamestringCustomer surname (required when channel is provided)
accept_tosbooleanConfirmation that the customer has accepted the terms and conditions (required when channel is provided)
blik_codestringBLIK code: 6 digits (for BLIK Level 0 payments); requires user_ip and user_agent
blik_aliasstringBLIK OneClick alias (max. 128 characters); requires user_ip and user_agent
register_blik_aliasobjectRegister a BLIK OneClick alias (label, type); requires blik_code, user_ip, and user_agent
register_blik_recurring_aliasobjectRegister a recurring BLIK payment alias (type PAYID; includes label, type, model, frequency, amount limits, and validity dates); requires blik_code, user_ip, and user_agent. The service is enabled per payment service; see Recurring BLIK payments
register_card_recurringobjectRegister a recurring card payment mandate (label plus optional frequency, limits, and dates); see Recurring card payments
card_recurring_aliasstringCard mandate alias for a recurring charge (max. 128 characters); see Recurring card payments
authorize_onlybooleanPre-authorize a saved token instead of charging it (used with card_recurring_alias); see Recurring card payments
alias_ipn_urlstringURL for notifications about alias status changes (max. 500 characters)
no_delaybooleanRecurring BLIK payments only: false allows the BLIK operator to hold a transaction for up to 72 hours while awaiting confirmation in the customer's app. The default is true (immediate response). Using false requires this option to be enabled for the payment service
descriptionstringTransaction description
customstringCustom data (for example, an order ID)
productsarrayProduct list
payoutobject1:1 payout instruction that routes funds to verified merchant accounts (see 1:1 payouts). Requires this option to be enabled for the payment service.
currency_codestringCurrency code (for example, PLN or EUR). Required when phone_number is provided
phone_numberstringCustomer phone number (9-15 characters)
billing_addressobjectCustomer billing address (used for deferred payments, among other methods)
shipping_addressobjectShipping address (used for deferred payments, among other methods)
device_infoobjectCustomer device and browser data; required for transactionType: mb_way_direct (see below)
user_ipstringCustomer IP address; required with blik_code, blik_alias, and recurring BLIK payments
user_agentstringCustomer browser user agent; required with blik_code, blik_alias, and recurring BLIK payments
nobanks0/1Channel flag: hide bank transfers on the gateway
paysafecard0/1Channel flag: Paysafecard
creditcard0/1Channel flag: payment cards
paypal0/1Channel flag: PayPal
blik0/1Channel flag: BLIK
installment0/1Channel flag: installments

channel parameter dependencies

warning

If you provide channel, the email, client_name, client_surname, and accept_tos fields become required. Omitting any of them results in a validation error (HTTP 422).

The values tester, paypal, installment, and paysafecard are not allowed as channel.

The device_info object (required for MB WAY)

For transactionType: mb_way_direct, the device_info object is required with the following fields: browserAcceptHeader, browserJavaEnabled (the string "true" or "false"), browserLanguage, browserColorDepth, browserScreenHeight, browserScreenWidth, browserTZ (numbers), browserUserAgent, systemFamily, deviceID, applicationName, and geoLocalization.

Transaction types

TypeDescription
transfersBank transfers (PBL)
dcb_gatewayDirect Carrier Billing
card_authPayment card authorization
mb_way_directMB WAY payment
bizum_directBizum payment (Spain, EUR)
blik_recurringRecurring BLIK charge using a registered PAYID alias (see Recurring BLIK payments)
card_recurringRecurring card charge using a registered mandate (see Recurring card payments)
info

The transfers type is the default for a simple redirect to the payment gateway (Simple Gateway), where the customer selects the payment method.

Step 2: Generate the checksum

The checksum ensures data integrity. It is generated with the SHA-256 algorithm from fields concatenated with the | character:

sha256({service}|{hash}|{value}|{url_success}|{url_fail}|{url_ipn})
Normalizing value

Before verifying the checksum, the server normalizes value to two decimal places (for example, 10 becomes 10.00 and 9.9 becomes 9.90). If you send the amount in another format, you must still use the normalized value in the checksum, or you will receive an Invalid checksum error. The simplest approach is to always send value already formatted to two decimal places.

PHP example

$service = 'abc123';
$hash = '9a8b7c6d5e4f3a2b1c0d';
$value = '29.99';
$urlSuccess = 'https://myshop.example/success';
$urlFail = 'https://myshop.example/failure';
$urlIpn = 'https://myshop.example/api/ipn';

$checksum = hash('sha256',
$service . '|' . $hash . '|' . $value . '|' .
$urlSuccess . '|' . $urlFail . '|' . $urlIpn
);

JavaScript (Node.js) example

const crypto = require('crypto');

const service = 'abc123';
const hash = '9a8b7c6d5e4f3a2b1c0d';
const value = '29.99';
const urlSuccess = 'https://myshop.example/success';
const urlFail = 'https://myshop.example/failure';
const urlIpn = 'https://myshop.example/api/ipn';

const checksum = crypto
.createHash('sha256')
.update(`${service}|${hash}|${value}|${urlSuccess}|${urlFail}|${urlIpn}`)
.digest('hex');

Python example

import hashlib

service = 'abc123'
hash_key = '9a8b7c6d5e4f3a2b1c0d'
value = '29.99'
url_success = 'https://myshop.example/success'
url_fail = 'https://myshop.example/failure'
url_ipn = 'https://myshop.example/api/ipn'

data = f'{service}|{hash_key}|{value}|{url_success}|{url_fail}|{url_ipn}'
checksum = hashlib.sha256(data.encode('utf-8')).hexdigest()

Step 3: Send the API request

Send a POST request to the payment registration endpoint:

POST https://api-payments.dpay.pl/api/v1_0/payments/register
Content-Type: application/json

Full cURL example

curl -X POST https://api-payments.dpay.pl/api/v1_0/payments/register \
-H "Content-Type: application/json" \
-d '{
"transactionType": "transfers",
"service": "abc123",
"value": "29.99",
"url_success": "https://myshop.example/success",
"url_fail": "https://myshop.example/failure",
"url_ipn": "https://myshop.example/api/ipn",
"checksum": "e3b0c44298fc1c149afb..."
}'

PHP example (cURL)

$payload = [
'transactionType' => 'transfers',
'service' => $service,
'value' => $value,
'url_success' => $urlSuccess,
'url_fail' => $urlFail,
'url_ipn' => $urlIpn,
'checksum' => $checksum,
];

$ch = curl_init('https://api-payments.dpay.pl/api/v1_0/payments/register');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

$response = curl_exec($ch);
curl_close($ch);

$result = json_decode($response, true);

Step 4: Handle the response

The dpay.pl API returns a JSON response:

Success response

{
"error": false,
"msg": "https://secure.dpay.pl/transfer@pay@A75AEBB4-4B89-4834-AD43-EF442C133769",
"status": true,
"transactionId": "A75AEBB4-4B89-4834-AD43-EF442C133769"
}
FieldTypeDescription
errorbooleanfalse if the request was processed successfully
msgstringPayment gateway URL; redirect the customer to this address
statusbooleantrue on success, false on error
transactionIdstringUnique transaction identifier

Successful response without a gateway URL: "Internal processing" (HTTP 200)

For payments processed in the background without redirecting the customer (for example, BLIK Level 0, BLIK OneClick, or MB WAY), the msg field does not contain a URL. Instead, it contains the fixed text Internal processing:

{
"error": false,
"msg": "Internal processing",
"status": true,
"transactionId": "A75AEBB4-4B89-4834-AD43-EF442C133769"
}

The transaction is waiting for confirmation, for example in the customer's banking app. You will receive the result through an IPN or by querying the transaction status.

Successful response: "Transaction paid" (HTTP 200)

If the transaction has already been paid while the request is being processed (for example, an immediate charge using an alias), the response also contains an object with transaction data:

{
"error": false,
"msg": "Transaction paid",
"status": true,
"transactionId": "A75AEBB4-4B89-4834-AD43-EF442C133769",
"additionalInfo": {
"transaction": { "...": "transaction data" }
}
}

Transaction error response (HTTP 200)

Returned, for example, for an invalid BLIK code or a canceled transaction:

{
"error": true,
"msg": "Transaction canceled",
"status": false,
"transactionId": "42191111-A7AE-392E-8C09-7965C1DC6B0B",
"additionalInfo": {
"error": "ER_WRONG_TICKET",
"error_description": null
}
}
FieldTypeDescription
errorbooleantrue: an error occurred
msgstringError description
statusbooleanfalse: the transaction failed
transactionIdstringTransaction identifier
additionalInfoobjectOptional error details (for example, a BLIK error code)

Merchant-side error (HTTP 400)

Returned for merchant-side errors such as an invalid checksum, a disabled channel, or an invalid amount:

{
"status": "failed",
"message": "Invalid checksum",
"errors": {
"checksum": "Invalid checksum"
}
}
FieldTypeDescription
statusstring"failed"
messagestringSpecific error message (for example, "Invalid checksum" or "Amount is less than 0.01 PLN")
errorsobjectKey-to-message object containing error details (for example, {"value": "Invalid value"})

Field validation error (HTTP 422)

Missing fields or invalid request field formats (for example, a missing url_success, an invalid blik_code format, or a missing email when channel is provided) return a 422 status in the standard format:

{
"message": "The url_success field is required.",
"errors": {
"url_success": ["The url_success field is required."]
}
}

In the 422 format, errors is an object that maps each field to an array of messages.

Step 5: Redirect the customer

After receiving a response with error: false, redirect the customer to the URL in the msg field:

PHP

if (!$result['error']) {
// Save transactionId in the database
saveTransaction($orderId, $result['transactionId']);

// Redirect the customer to the payment gateway
header('Location: ' . $result['msg']);
exit;
} else {
// Handle the error
echo 'Payment registration error: ' . $result['msg'];
}

JavaScript (Express.js)

if (!result.error) {
// Save transactionId in the database
await saveTransaction(orderId, result.transactionId);

// Redirect the customer
res.redirect(result.msg);
} else {
res.status(400).json({ error: result.msg });
}

Step 6: Receive the IPN

After the payment is completed, dpay.pl sends an IPN notification to url_ipn. For details on handling IPN notifications, see IPN handling.

Full example: PHP

<?php
// Configuration
$service = getenv('DPAY_SERVICE');
$hash = getenv('DPAY_HASH');

// Order data
$value = '29.99';
$urlSuccess = 'https://myshop.example/success';
$urlFail = 'https://myshop.example/failure';
$urlIpn = 'https://myshop.example/api/ipn';

// Generate the checksum
$checksum = hash('sha256',
$service . '|' . $hash . '|' . $value . '|' .
$urlSuccess . '|' . $urlFail . '|' . $urlIpn
);

// Register the payment
$payload = json_encode([
'transactionType' => 'transfers',
'service' => $service,
'value' => $value,
'url_success' => $urlSuccess,
'url_fail' => $urlFail,
'url_ipn' => $urlIpn,
'checksum' => $checksum,
]);

$ch = curl_init('https://api-payments.dpay.pl/api/v1_0/payments/register');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $payload,
CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
]);

$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

$result = json_decode($response, true);

if ($httpCode === 200 && !$result['error']) {
// Redirect the customer to the gateway
header('Location: ' . $result['msg']);
exit;
} else {
http_response_code(500);
echo 'Error: ' . ($result['msg'] ?? 'Unknown error');
}

Common errors

ErrorCauseSolution
Invalid checksumInvalid checksumCheck the field order, Hash key, and normalization of value to two decimal places
Service not foundUnknown service nameCheck the service field in the panel
Amount is less than 0.01 PLNAmount below the minimumThe minimum transaction amount is 0.01

What's next?