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:
- A verified account at panel.dpay.pl (see Registration)
- A payment service created with a service name and Hash key (see Configuration)
How it works
/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
| Field | Type | Description | Example |
|---|---|---|---|
service | string | Service name from the panel (alternatively name) | "abc123" |
transactionType | string | Transaction type | "transfers" |
value | string | Amount (0.01-999999.99, with a decimal point) | "29.99" |
url_success | string | URL after a successful payment | "https://myshop.example/success" |
url_fail | string | URL after a failed payment | "https://myshop.example/failure" |
url_ipn | string | URL for IPN notifications | "https://myshop.example/api/ipn" |
checksum | string | SHA-256 checksum | (see below) |
Optional parameters
| Field | Type | Description |
|---|---|---|
channel | string | Specific payment channel (see dependencies below) |
email | string | Customer email address (required when channel is provided) |
client_name | string | Customer first name (required when channel is provided) |
client_surname | string | Customer surname (required when channel is provided) |
accept_tos | boolean | Confirmation that the customer has accepted the terms and conditions (required when channel is provided) |
blik_code | string | BLIK code: 6 digits (for BLIK Level 0 payments); requires user_ip and user_agent |
blik_alias | string | BLIK OneClick alias (max. 128 characters); requires user_ip and user_agent |
register_blik_alias | object | Register a BLIK OneClick alias (label, type); requires blik_code, user_ip, and user_agent |
register_blik_recurring_alias | object | Register 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_recurring | object | Register a recurring card payment mandate (label plus optional frequency, limits, and dates); see Recurring card payments |
card_recurring_alias | string | Card mandate alias for a recurring charge (max. 128 characters); see Recurring card payments |
authorize_only | boolean | Pre-authorize a saved token instead of charging it (used with card_recurring_alias); see Recurring card payments |
alias_ipn_url | string | URL for notifications about alias status changes (max. 500 characters) |
no_delay | boolean | Recurring 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 |
description | string | Transaction description |
custom | string | Custom data (for example, an order ID) |
products | array | Product list |
payout | object | 1: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_code | string | Currency code (for example, PLN or EUR). Required when phone_number is provided |
phone_number | string | Customer phone number (9-15 characters) |
billing_address | object | Customer billing address (used for deferred payments, among other methods) |
shipping_address | object | Shipping address (used for deferred payments, among other methods) |
device_info | object | Customer device and browser data; required for transactionType: mb_way_direct (see below) |
user_ip | string | Customer IP address; required with blik_code, blik_alias, and recurring BLIK payments |
user_agent | string | Customer browser user agent; required with blik_code, blik_alias, and recurring BLIK payments |
nobanks | 0/1 | Channel flag: hide bank transfers on the gateway |
paysafecard | 0/1 | Channel flag: Paysafecard |
creditcard | 0/1 | Channel flag: payment cards |
paypal | 0/1 | Channel flag: PayPal |
blik | 0/1 | Channel flag: BLIK |
installment | 0/1 | Channel flag: installments |
channel parameter dependencies
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
| Type | Description |
|---|---|
transfers | Bank transfers (PBL) |
dcb_gateway | Direct Carrier Billing |
card_auth | Payment card authorization |
mb_way_direct | MB WAY payment |
bizum_direct | Bizum payment (Spain, EUR) |
blik_recurring | Recurring BLIK charge using a registered PAYID alias (see Recurring BLIK payments) |
card_recurring | Recurring card charge using a registered mandate (see Recurring card payments) |
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})
valueBefore 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"
}
| Field | Type | Description |
|---|---|---|
error | boolean | false if the request was processed successfully |
msg | string | Payment gateway URL; redirect the customer to this address |
status | boolean | true on success, false on error |
transactionId | string | Unique 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
}
}
| Field | Type | Description |
|---|---|---|
error | boolean | true: an error occurred |
msg | string | Error description |
status | boolean | false: the transaction failed |
transactionId | string | Transaction identifier |
additionalInfo | object | Optional 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"
}
}
| Field | Type | Description |
|---|---|---|
status | string | "failed" |
message | string | Specific error message (for example, "Invalid checksum" or "Amount is less than 0.01 PLN") |
errors | object | Key-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
| Error | Cause | Solution |
|---|---|---|
Invalid checksum | Invalid checksum | Check the field order, Hash key, and normalization of value to two decimal places |
Service not found | Unknown service name | Check the service field in the panel |
Amount is less than 0.01 PLN | Amount below the minimum | The minimum transaction amount is 0.01 |
What's next?
- IPN handling - learn how to receive and verify payment notifications
- BLIK Level 0 - integrate direct BLIK payments
- BLIK OneClick - offer one-click payments with a saved alias
- Cards S2S - add Server-to-Server card payments