Refunds
dpay.pl enables refund processing for completed transactions. Both full refunds and partial refunds are supported. Refunds can be issued programmatically via the API or manually from the admin panel.
Supported payment methods
| Method | Full refund | Partial refund |
|---|---|---|
| BLIK | Yes | Yes |
| BLIK BNPL | Yes | Yes |
| Bank transfers (PBL) | Yes | Yes |
| Payment cards (Visa / Mastercard) | Yes | Yes |
| MB WAY | Yes | Yes |
| PayPo | Yes | No |
| Twisto | Yes | No |
A refund can be issued within 180 days of the transaction date. After this period, refunds are no longer possible.
API endpoint
POST https://api-payments.dpay.pl/api/v1/pbl/refund
Content-Type: application/json
Request parameters
| Field | Type | Required | Description |
|---|---|---|---|
service | string | Yes | Service name from the panel |
transaction_id | string | Yes | Transaction ID to refund |
value | string | No | Refund amount (e.g. "15.00"). If omitted - full refund |
checksum | string | Yes | SHA-256 checksum |
To issue a partial refund, pass the value parameter with an amount less than the transaction value. The amount must be a non-negative number (e.g. "15.00").
Generating the checksum
The checksum format depends on the refund type.
Full refund
sha256({service}|{transaction_id}|{secret_hash})
Partial refund (with value parameter)
sha256({service}|{transaction_id}|{value}|{secret_hash})
When passing the value parameter, you must include it in the checksum. Using a checksum without value for a partial refund will result in an Invalid checksum error.
PHP
$service = 'abc123';
$transactionId = 'abc-def-123-456';
$secretHash = '9a8b7c6d5e4f3a2b1c0d';
// Full refund
$checksum = hash('sha256',
$service . '|' . $transactionId . '|' . $secretHash
);
// Partial refund
$value = '15.00';
$checksumPartial = hash('sha256',
$service . '|' . $transactionId . '|' . $value . '|' . $secretHash
);
JavaScript (Node.js)
const crypto = require('crypto');
const service = 'abc123';
const transactionId = 'abc-def-123-456';
const secretHash = '9a8b7c6d5e4f3a2b1c0d';
// Full refund
const checksum = crypto
.createHash('sha256')
.update(`${service}|${transactionId}|${secretHash}`)
.digest('hex');
// Partial refund
const value = '15.00';
const checksumPartial = crypto
.createHash('sha256')
.update(`${service}|${transactionId}|${value}|${secretHash}`)
.digest('hex');
Python
import hashlib
service = 'abc123'
transaction_id = 'abc-def-123-456'
secret_hash = '9a8b7c6d5e4f3a2b1c0d'
# Full refund
data = f'{service}|{transaction_id}|{secret_hash}'
checksum = hashlib.sha256(data.encode('utf-8')).hexdigest()
# Partial refund
value = '15.00'
data_partial = f'{service}|{transaction_id}|{value}|{secret_hash}'
checksum_partial = hashlib.sha256(data_partial.encode('utf-8')).hexdigest()
Request examples
Full refund - cURL
curl -X POST https://api-payments.dpay.pl/api/v1/pbl/refund \
-H "Content-Type: application/json" \
-d '{
"service": "abc123",
"transaction_id": "abc-def-123-456",
"checksum": "e3b0c44298fc1c149afb..."
}'
Partial refund - cURL
curl -X POST https://api-payments.dpay.pl/api/v1/pbl/refund \
-H "Content-Type: application/json" \
-d '{
"service": "abc123",
"transaction_id": "abc-def-123-456",
"value": "15.00",
"checksum": "a1b2c3d4e5f6..."
}'
PHP
<?php
$service = getenv('DPAY_SERVICE');
$secretHash = getenv('DPAY_SECRET_HASH');
$transactionId = 'abc-def-123-456';
$value = '15.00'; // null for a full refund
// Generate checksum
if ($value !== null) {
$checksum = hash('sha256',
$service . '|' . $transactionId . '|' . $value . '|' . $secretHash
);
} else {
$checksum = hash('sha256',
$service . '|' . $transactionId . '|' . $secretHash
);
}
$payload = [
'service' => $service,
'transaction_id' => $transactionId,
'checksum' => $checksum,
];
if ($value !== null) {
$payload['value'] = $value;
}
$ch = curl_init('https://api-payments.dpay.pl/api/v1/pbl/refund');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode($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['status'] === 'success') {
echo 'Refund processed successfully';
} else {
echo 'Refund error: ' . $result['message'];
}
API response
Success
{
"status": "success",
"refund": true,
"message": "Refund processed successfully"
}
Error
{
"status": "error",
"refund": false,
"message": "Transaction not found"
}
Multiple partial refunds
For methods that support partial refunds (BLIK, cards, MB WAY), you can issue multiple refunds for a single transaction, as long as the total refunded amount does not exceed the original transaction amount.
dpay.pl tracks the cumulative refunded amount in the refunded_amount field. Example:
| Operation | Amount | refunded_amount | Remaining |
|---|---|---|---|
| Transaction | 100.00 PLN | 0.00 | 100.00 |
| Refund #1 | 30.00 PLN | 30.00 | 70.00 |
| Refund #2 | 25.00 PLN | 55.00 | 45.00 |
| Refund #3 | 45.00 PLN | 100.00 | 0.00 |
Attempting to refund an amount that exceeds the remaining transaction value will result in an error.
Common errors
| Error | Cause | Solution |
|---|---|---|
Transaction not found | The provided transaction_id does not exist | Verify the transaction ID |
Invalid checksum | Invalid checksum | Check the field order and Secret Hash. For partial refunds, include value in the checksum |
Transaction not eligible for refund | The transaction is not eligible for a refund | Check whether the payment method supports refunds |
Refund period expired | The 180-day refund period has been exceeded | Refunds are no longer possible after the time limit |
Refund amount exceeds remaining value | The refund amount exceeds the remaining value | Reduce the refund amount |
Refunds in the admin panel
You can also issue a refund manually:
- Log in to panel.dpay.pl.
- Go to the Transactions section.
- Find the transaction to refund (use filters or the search bar).
- Click on the transaction to open its details.
- Click the Refund button.
- Select the refund type - full or partial (if available for the given payment method).
- For a partial refund, enter the amount.
- Confirm the refund.