payline-qnb-driver maintained by x-laravel
payline-qnb-driver
QNB Finansbank VPOS driver for x-laravel/payline.
Requirements
- PHP ^8.3
- Laravel ^12.0 | ^13.0
- x-laravel/payline ^1.0
Installation
composer require x-laravel/payline-qnb-driver
Configuration
Add the qnb block to config/payline.php under gateways:
'gateways' => [
'qnb' => [
'mbr_id' => env('QNB_MBR_ID', '5'),
'merchant_id' => env('QNB_MERCHANT_ID'),
'user_name' => env('QNB_USER_NAME'),
'password' => env('QNB_PASSWORD'),
'merchant_pass' => env('QNB_MERCHANT_PASS'),
'endpoint' => env('QNB_ENDPOINT', 'https://vpostest.qnbfinansbank.com/Gateway/Default.aspx'),
'lang' => env('QNB_LANG', 'TR'),
],
],
Set the corresponding environment variables in .env:
PAYLINE_DRIVER=qnb
QNB_MBR_ID=5
QNB_MERCHANT_ID=your-merchant-id
QNB_USER_NAME=your-user-name
QNB_PASSWORD=your-password
QNB_MERCHANT_PASS=your-merchant-pass
QNB_ENDPOINT=https://vpos.qnbfinansbank.com/Gateway/Default.aspx
Sandbox endpoint:
https://vpostest.qnbfinansbank.com/Gateway/Default.aspx
Production endpoint:https://vpos.qnbfinansbank.com/Gateway/Default.aspx
Usage
Charging a payment
use XLaravel\Payline\DTOs\Card;
use XLaravel\Payline\DTOs\PaymentRequest;
$data = PaymentRequest::fromPayable(
payable: $order,
card: new Card(
holderName: 'John Doe',
number: '4111111111111111',
expiryMonth: '12',
expiryYear: '2030',
cvv: '123',
),
installments: 1,
customerIp: $request->ip(),
);
$response = $order->pay('qnb')->charge($data);
QNB uses a 3DS HTML form flow. On success, pay() returns a PaymentResponse with status = Pending and a redirectForm containing a self-submitting HTML form that forwards the customer to their bank's 3DS page:
if ($response->requiresRedirect()) {
return response($response->redirectForm); // renders and auto-submits the form
}
Handling the callback
Payline handles the callback automatically via its built-in route (/payline/callbacks/qnb). After 3DS completes, QNB POSTs back to this URL. The driver verifies the response hash and the user is redirected to payline.callback_success_url or payline.callback_failure_url.
You can listen to the dispatched events for any post-payment logic:
use XLaravel\Payline\Events\PaymentSucceeded;
use XLaravel\Payline\Events\PaymentFailed;
class HandlePaymentSucceeded
{
public function handle(PaymentSucceeded $event): void
{
$event->payment; // Payment model
$event->transaction; // Transaction model
$event->response; // PaymentResponse DTO
}
}
Pre-authorization & Capture
use XLaravel\Payline\DTOs\CaptureData;
use XLaravel\Payline\Facades\Payline;
// 1. Pre-authorize (TxnType=PreAuth, 3DS flow)
$response = $order->pay('qnb')->authorize($data);
// 2. Capture later
Payline::via('qnb')->capture(
new CaptureData(
gatewayTransactionId: $transaction->gateway_transaction_id,
amount: $transaction->amount,
currency: $transaction->currency,
),
$payment,
$transaction,
);
Refund
use XLaravel\Payline\DTOs\RefundData;
Payline::via('qnb')->refund(
new RefundData(
gatewayTransactionId: $transaction->gateway_transaction_id,
amount: 5000, // kuruş
currency: 'TRY',
),
$payment,
$transaction,
);
Void (Cancel)
use XLaravel\Payline\DTOs\VoidData;
Payline::via('qnb')->void(
new VoidData(gatewayTransactionId: $transaction->gateway_transaction_id),
$payment,
$transaction,
);
Supported Currencies
| ISO Code | QNB Code |
|---|---|
| TRY | 949 |
| USD | 840 |
| EUR | 978 |
| GBP | 826 |
Supported Operations
| Operation | Supported | Notes |
|---|---|---|
| Pay (3DS) | ✓ | Returns self-submitting HTML form (redirectForm) |
| Authorize | ✓ | PreAuth + 3DS flow |
| Capture | ✓ | PostAuth via OrgOrderId |
| Refund | ✓ | Partial or full |
| Void/Cancel | ✓ | |
| Webhooks | ✗ | QNB uses callback-only flow |
Testing
# Build first (once per PHP version)
DOCKER_BUILDKIT=0 docker compose --profile php83 build
# Run tests
docker compose --profile php83 up
docker compose --profile php84 up
docker compose --profile php85 up
Or directly:
composer test
License
This package is open-sourced software licensed under the MIT license.