kuveytturk-vpos-laravel-sdk maintained by emre-tarhan
Kuveyt Türk Virtual POS Laravel SDK
A comprehensive Laravel SDK for Kuveyt Türk Virtual POS (Sanal Pos) integration with full 3D Secure 2.0 support.
Features
- ✅ 3D Secure 2.0 Full Support — Two-phase payment flow
- ✅ Two-Phase Payment: Card verification (Kart Doğrulama) + Provision (Ödeme Alma)
- ✅ Installment (Taksit) Support — Up to 24 installments
- ✅ Deferred Payment (Harcama Öteleme) — Flexible payment scheduling
- ✅ Hash Data Validation — SHA1-based request authentication
- ✅ Test & Production Environments — Separate endpoints
- ✅ Sale / Cancel / Refund / Partial Refund Operations — Full transaction lifecycle
- ✅ WCF SOAP Service Integration — For cancel/refund operations
- ✅ Comprehensive Error Handling — All Kuveyt Türk error codes
- ✅ Laravel 12.x & 13.x Compatible
- ✅ PHP 8.1, 8.2, 8.3, 8.4 Support
Installation
composer require emre-tarhan/kuveytturk-vpos-laravel-sdk
Publish Configuration
php artisan vendor:publish --tag=kuveytturk-vpos-config
Or use the install command:
php artisan kuveytturk:install
This will publish the config file to config/kuveytturk-vpos.php.
Configuration
Add your Kuveyt Türk credentials to .env:
KUVEYTTURK_MERCHANT_ID=your_merchant_id
KUVEYTTURK_CUSTOMER_ID=your_customer_id
KUVEYTTURK_USERNAME=your_api_username
KUVEYTTURK_PASSWORD=your_api_password
KUVEYTTURK_ENVIRONMENT=test # or 'production'
Or configure in config/kuveytturk-vpos.php:
return [
'merchant_id' => env('KUVEYTTURK_MERCHANT_ID', ''),
'customer_id' => env('KUVEYTTURK_CUSTOMER_ID', ''),
'username' => env('KUVEYTTURK_USERNAME', ''),
'password' => env('KUVEYTTURK_PASSWORD', ''),
'environment' => env('KUVEYTTURK_ENVIRONMENT', 'test'),
'timeout' => env('KUVEYTTURK_TIMEOUT', 60),
'connect_timeout' => env('KUVEYTTURK_CONNECT_TIMEOUT', 30),
];
Usage
Basic Sale (Complete 3D Flow)
use EmreTarhan\KuveytTurkVPos\Services\KuveytTurkVPos;
use EmreTarhan\KuveytTurkVPos\Dto\SaleRequest;
use EmreTarhan\KuveytTurkVPos\Enums\CurrencyCode;
// Inject via service container or resolve from app
$vpos = app(KuveytTurkVPos::class);
$request = new SaleRequest(
merchantOrderId: 'ORDER-' . time(),
amount: 100.00, // 100 TL - will be converted to 10000 internally
okUrl: 'https://yoursite.com/payment/success',
failUrl: 'https://yoursite.com/payment/fail',
cardHolderName: 'John Doe',
cardNumber: '5188961939192544',
cardExpireDateYear: '2025',
cardExpireDateMonth: '06',
cardCVV2: '929',
email: 'customer@example.com',
clientIp: request()->ip(),
billAddrCity: 'Istanbul',
billAddrCountry: '792', // Turkey country code
billAddrLine1: 'Sample Street No:123',
billAddrPostCode: '34000',
billAddrState: '34',
Cc: 'John Doe',
subscriber: 'customer@example.com',
currencyCode: CurrencyCode::TRY,
installmentCount: 0, // 0 = no installment, 1-24 for installment
);
$response = $vpos->sale($request);
if ($response->isSuccessful()) {
// Payment successful
echo "Transaction approved! Order ID: " . $response->orderId;
} else {
// Payment failed
echo "Payment failed: " . $response->responseMessage;
}
Two-Phase Payment (Manual Control)
If you need more control over the payment flow:
Phase 1: Card Verification
use EmreTarhan\KuveytTurkVPos\Dto\VerifyCardRequest;
$verifyRequest = new VerifyCardRequest(
merchantOrderId: 'ORDER-' . time(),
amount: 150.00,
okUrl: 'https://yoursite.com/payment/success',
failUrl: 'https://yoursite.com/payment/fail',
cardHolderName: 'John Doe',
cardNumber: '5188961939192544',
cardExpireDateYear: '2025',
cardExpireDateMonth: '06',
cardCVV2: '929',
email: 'customer@example.com',
clientIp: request()->ip(),
billAddrCity: 'Istanbul',
billAddrCountry: '792',
billAddrLine1: 'Sample Street No:123',
billAddrPostCode: '34000',
billAddrState: '34',
Cc: 'John Doe',
subscriber: 'customer@example.com',
currencyCode: CurrencyCode::TRY,
installmentCount: 3, // 3 months installment
);
$verifyResponse = $vpos->verifyCard($verifyRequest);
// Store MD value for Phase 2
$mdValue = $verifyResponse->md; // You'll need this for provision
$orderId = $verifyResponse->orderId;
Phase 2: Provision (Complete Payment)
use EmreTarhan\KuveytTurkVPos\Dto\ProvisionRequest;
$provisionRequest = new ProvisionRequest(
merchantOrderId: 'ORDER-' . time(),
amount: 150.00,
md: $mdValueFromPhase1,
okUrl: 'https://yoursite.com/payment/success',
failUrl: 'https://yoursite.com/payment/fail',
currencyCode: CurrencyCode::TRY,
installmentCount: 3,
);
$provisionResponse = $vpos->provision($provisionRequest);
if ($provisionResponse->isSuccessful()) {
// Payment completed
echo "Provision successful! RRN: " . $provisionResponse->rrn;
}
Cancel Transaction (Same-Day)
use EmreTarhan\KuveytTurkVPos\Dto\CancelRequest;
use EmreTarhan\KuveytTurkVPos\Enums\CurrencyCode;
$cancelRequest = new CancelRequest(
merchantOrderId: 'ORDER-12345',
amount: 100.00,
provisionNumber: '123456', // From original sale
rrn: '789012345', // Reference number
stan: '654321', // System trace number
orderId: 'original-order-id',
currencyCode: CurrencyCode::TRY,
);
$cancelResponse = $vpos->cancel($cancelRequest);
if ($cancelResponse->isSuccessful()) {
echo "Transaction cancelled successfully!";
}
Refund (After Batch Close)
use EmreTarhan\KuveytTurkVPos\Dto\RefundRequest;
$refundRequest = new RefundRequest(
merchantOrderId: 'ORDER-12345',
amount: 100.00,
provisionNumber: '123456',
rrn: '789012345',
stan: '654321',
orderId: 'original-order-id',
currencyCode: CurrencyCode::TRY,
);
$refundResponse = $vpos->refund($refundRequest);
if ($refundResponse->isSuccessful()) {
echo "Refund processed successfully!";
}
Partial Refund
use EmreTarhan\KuveytTurkVPos\Dto\PartialRefundRequest;
$partialRefundRequest = new PartialRefundRequest(
merchantOrderId: 'ORDER-12345',
amount: 50.00, // Partial amount
provisionNumber: '123456',
rrn: '789012345',
stan: '654321',
orderId: 'original-order-id',
currencyCode: CurrencyCode::TRY,
);
$partialRefundResponse = $vpos->partialRefund($partialRefundRequest);
if ($partialRefundResponse->isSuccessful()) {
echo "Partial refund processed!";
}
Response Objects
SaleResponse
| Property | Description |
|---|---|
isSuccessful() |
Boolean - true if transaction approved |
responseCode |
Kuveyt Türk response code ("00" = success) |
responseMessage |
Human-readable response message |
orderId |
Bank's order ID |
provisionNumber |
Authorization number |
rrn |
Reference number |
stan |
System trace number |
transactionTime |
Transaction timestamp |
merchantOrderId |
Your order ID |
md |
3D Secure MD value |
Error Handling
use EmreTarhan\KuveytTurkVPos\Services\KuveytTurkVPos;
use EmreTarhan\KuveytTurkVPos\Exceptions\KuveytTurkVPosException;
use EmreTarhan\KuveytTurkVPos\Enums\ErrorCode;
try {
$response = $vpos->sale($request);
if ($response->isSuccessful()) {
// Handle success
} else {
// Handle business failure
$errorCode = ErrorCode::fromString($response->responseCode);
echo "Error: " . $errorCode->label();
}
} catch (KuveytTurkVPosException $e) {
// Handle connection/validation errors
echo "Error: " . $e->getMessage();
}
Error Codes
| Code | Turkish | English |
|---|---|---|
| 00 | Otorizasyon verildi | Transaction approved |
| 01 | Geçersiz kart numarası | Invalid card number |
| 05 | Yetersiz bakiye | Insufficient balance |
| 12 | Geçersiz üye işyeri | Invalid merchant |
| 14 | Geçersiz işlem / CVV | Invalid transaction / CVV |
| 17 | Kart limiti aşıldı | Card limit exceeded |
| 54 | Kart süresi dolmuş | Card expired |
| 59 | Sahtekarlık şüphesi | Fraud suspected |
| 70 | Mükerrer sipariş | Duplicate order |
| 91 | Zaman aşımı | Timeout |
| 96 | Sistem hatası | System error |
| 99 | Hashdata uyuşmazlığı | Hash mismatch |
Amount Format
All amounts must be provided as actual values (e.g., 100.50 for 100 TL 50 kurus).
The SDK automatically converts to bank's format (amount × 100, e.g., 10050 for 100.50 TL).
// Both work the same:
$request = new SaleRequest(..., amount: 100.50, ...);
$request = new SaleRequest(..., amount: '100.50', ...);
$request = new SaleRequest(..., amount: 10050, ...); // Already in bank's format
Test Environment
Use the following test card for sandbox testing:
| Field | Value |
|---|---|
| Card Number | 5188 9619 3919 2544 |
| CVV | 929 |
| Expiry | 06/25 |
| 3D Password | 123456 |
Test Endpoints:
- Card Verification:
https://boatest.kuveytturk.com.tr/boa.virtualpos.services/Home/ThreeDModelPayGate - Provision:
https://boatest.kuveytturk.com.tr/boa.virtualpos.services/Home/ThreeDModelProvisionGate
Production Endpoints:
- Card Verification:
https://sanalpos.kuveytturk.com.tr/ServiceGateWay/Home/ThreeDModelPayGate - Provision:
https://sanalpos.kuveytturk.com.tr/ServiceGateWay/Home/ThreeDModelProvisionGate
Testing
composer test
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
License
The MIT License (MIT). Please see LICENSE for more information.
Support
For issues and questions, please open an issue on GitHub:
https://github.com/emre-tarhan/kuveytturk-vpos-laravel-sdk-laravel-sdk
Email: post@emretarhan.net