klc/tami-laravel
Composer 安装命令:
composer require klc/tami-laravel
包简介
Tami sanal POS için Laravel-native paket — tip-güvenli, test edilebilir, güvenli
README 文档
README
Tami sanal POS için Laravel-native paket. Tip-güvenli, test edilebilir, güvenli.
Kurulum
composer require klc/tami-laravel
Laravel 10.x+ ve PHP 8.1+ gerektirir. Paket auto-discovery ile otomatik yüklenir.
Konfigürasyon
php artisan vendor:publish --tag=tami-config
.env dosyasına aşağıdaki değişkenleri ekleyin:
TAMI_ENVIRONMENT=sandbox TAMI_MERCHANT_ID=77006950 TAMI_TERMINAL_ID=84006953 TAMI_SECRET_KEY=your-secret-key TAMI_JWK_KID=your-jwk-kid TAMI_JWK_K=your-jwk-k # Normal API response securityHash doğrulaması, Tami algoritması netleşene kadar kapalı kalmalıdır. TAMI_RESPONSE_HASH_ENABLED=false
Canlı ortam için:
TAMI_ENVIRONMENT=production TAMI_MERCHANT_ID=your-production-merchant TAMI_TERMINAL_ID=your-production-terminal TAMI_SECRET_KEY=your-production-secret TAMI_JWK_KID=your-production-kid TAMI_JWK_K=your-production-k
Kullanım
Ödeme (Payment)
use Klc\Tami\Facades\Tami; use Klc\Tami\DTOs\CardDto; use Klc\Tami\DTOs\AddressDto; use Klc\Tami\DTOs\BuyerDto; use Klc\Tami\DTOs\BasketItemDto; use Klc\Tami\DTOs\BasketDto; use Klc\Tami\DTOs\Payment\AuthRequestDto; use Klc\Tami\Enums\ItemType; use Klc\Tami\Enums\PaymentChannel; // Kart $card = new CardDto( number: '4824910501747014', holderName: 'Örnek Kullanıcı', cvv: '123', expireMonth: 12, expireYear: 2026, ); // Adres $address = new AddressDto( address: 'Örnek Mah. Test Sk. No:1', city: 'İstanbul', companyName: 'Örnek Firma', country: 'Türkiye', district: 'Kadıköy', contactName: 'Örnek İletişim', phoneNumber: '05555555555', zipCode: '34700', ); // Alıcı $buyer = new BuyerDto( ipAddress: '127.0.0.1', buyerId: 'buyer-001', name: 'Örnek', surName: 'Kullanıcı', emailAddress: 'ornek@eposta.com', phoneNumber: '05555555555', // Aşağıdaki alanlar Tami dokümanında opsiyonel/senaryoya bağlıdır. identityNumber: '11111111111', city: 'İstanbul', country: 'Türkiye', zipCode: '34700', registrationAddress: 'Örnek Mah. Test Sk. No:1', registrationDate: '2023-01-01T10:00:00', lastLoginDate: '2023-06-01T10:00:00', ); // Sepet $item = new BasketItemDto( itemId: 'item-001', name: 'Örnek Ürün', itemType: ItemType::Physical, numberOfProducts: 1, totalPrice: '100.00', unitPrice: '100.00', category: 'Elektronik', subCategory: 'Bilgisayar', ); $basket = new BasketDto('basket-001', [$item]); // Ödeme isteği $dto = new AuthRequestDto( orderId: 'order-' . uniqid(), amount: '100.00', currency: 'TRY', installmentCount: 1, paymentGroup: 'PRODUCT', paymentChannel: PaymentChannel::Web, card: $card, billingAddress: $address, shippingAddress: $address, buyer: $buyer, basket: $basket, ); // Ödemeyi gerçekleştir $response = Tami::payment()->auth($dto); if ($response->isSuccess()) { echo "Ödeme başarılı! Sipariş: " . $response->getOrderId(); } else { echo "Hata: " . $response->getErrorCode() . " - " . $response->getErrorMessage(); }
3D Secure Ödeme
// Geri dönüş URL'si ile 3DS başlatma $authDto = new AuthRequestDto( orderId: 'order-' . uniqid(), amount: '100.00', currency: 'TRY', installmentCount: 1, paymentGroup: 'PRODUCT', paymentChannel: PaymentChannel::Web, card: $card, billingAddress: $address, shippingAddress: $address, buyer: $buyer, basket: $basket, callbackUrl: 'https://example.com/tami/callback', ); $response = Tami::payment()->auth($authDto); if ($response->is3dsRequired()) { echo $response->getHtmlContent(); // Banka 3DS sayfasına yönlendir }
3DS Callback Yönetimi
Paket otomatik olarak POST /tami/callback ve GET /tami/callback route'larını kaydeder. Callback payload'ında hashedData varsa paket Tami'nin 3DS HMAC-SHA256 formülüne göre doğrular; doğrulama başarısızsa /payment/complete-3ds çağrısı yapılmadan hata event'i yayınlanır. Başarılı/başarısız durumlar için event dinleyicileri:
// EventServiceProvider.php use Klc\Tami\Events\TamiPaymentSucceeded; use Klc\Tami\Events\TamiPaymentFailed; protected $listen = [ TamiPaymentSucceeded::class => [ // Siparişi tamamla, stok düş, vs. ], TamiPaymentFailed::class => [ // Hata logla, kullanıcıyı bilgilendir ], ];
Ön Otorizasyon (Pre-Auth)
$preAuthResponse = Tami::payment()->preAuth($authDto); // Daha sonra kapama (capture) use Klc\Tami\DTOs\Payment\PostAuthRequestDto; $postAuthDto = new PostAuthRequestDto( orderId: $preAuthResponse->getOrderId(), amount: '100.00', // Kısmi kapama için daha düşük tutar ); $captureResponse = Tami::payment()->postAuth($postAuthDto);
İptal / İade
use Klc\Tami\DTOs\Payment\ReverseRequestDto; // Tam iade $reverseDto = new ReverseRequestDto(orderId: 'order-123'); $reverseResponse = Tami::payment()->reverse($reverseDto); // Kısmi iade $reverseDto = new ReverseRequestDto( orderId: 'order-123', amount: '50.00', reason: 'Kısmi iade', ); $reverseResponse = Tami::payment()->reverse($reverseDto);
Sipariş Sorgulama
use Klc\Tami\DTOs\Payment\QueryRequestDto; $queryDto = new QueryRequestDto( orderId: 'order-123', isTransactionDetail: true, ); $queryResponse = Tami::payment()->query($queryDto); echo "Sipariş Durumu: " . $queryResponse->getOrderStatus(); echo "Ödeme Durumu: " . $queryResponse->getPaymentStatus(); echo "Taksit Sayısı: " . $queryResponse->getInstallmentCount();
Taksit ve Kart Bilgisi
use Klc\Tami\DTOs\Installment\BinInfoRequestDto; use Klc\Tami\DTOs\Installment\InstallmentInfoRequestDto; // BIN sorgulama $binDto = new BinInfoRequestDto('48249105'); $binResponse = Tami::installment()->binInfo($binDto); echo "Banka: " . $binResponse->getBankName(); echo "Kart Tipi: " . $binResponse->getCardType(); // CREDIT/DEBIT echo "Kart Ağı: " . $binResponse->getCardOrg(); // VISA/MASTERCARD/TROY/AMEX // Taksit seçenekleri $installmentDto = new InstallmentInfoRequestDto('48249105'); $installmentResponse = Tami::installment()->installmentInfo($installmentDto); $installments = $installmentResponse->getInstallments(); // [1, 3, 5] $requires3ds = $installmentResponse->isForce3ds(); $requiresCvv = $installmentResponse->isForceCvc();
Bonus / Puan Sorgulama
use Klc\Tami\DTOs\Vas\BonusInquiryRequestDto; $bonusDto = new BonusInquiryRequestDto( ipAddress: '127.0.0.1', emailAddress: 'ornek@eposta.com', cardNumber: '4824910501747014', expireMonth: 12, expireYear: 2026, currencyCode: 949, // TRY için 949 amount: '100.00', ); $bonusResponse = Tami::vas()->bonusInquiry($bonusDto); if ($bonusResponse->isApproved()) { foreach ($bonusResponse->getRewardList() as $reward) { echo $reward['type'] . ': ' . $reward['amount']; } }
Puanlı Satış
use Klc\Tami\DTOs\RewardDto; use Klc\Tami\DTOs\RewardToBeUsedDto; $reward = new RewardDto(type: 'BNS', amount: '20.00'); $rewardToBeUsed = new RewardToBeUsedDto([$reward]); $dto = new AuthRequestDto( // ... diğer alanlar orderId: 'order-' . uniqid(), amount: '100.00', currency: 'TRY', installmentCount: 1, paymentGroup: 'PRODUCT', paymentChannel: PaymentChannel::Web, card: $card, billingAddress: $address, shippingAddress: $address, buyer: $buyer, basket: $basket, isRewardToBeUsed: true, rewardToBeUsed: $rewardToBeUsed, ); $response = Tami::payment()->auth($dto);
Ortak Ödeme Sayfası (Hosted Payment)
Tami'nin sunduğu ortak ödeme sayfası entegrasyonu — işyerinin kart bilgisi toplamasına gerek kalmadan, ödeme sayfası Tami tarafından sunulur. Masterpass ile kayıtlı kartlarla veya yeni kart bilgisiyle ödeme yapılabilir.
Token geçerlilik süresi: Test ortamında 15 dakika, prod ortamda 6 dakika. Token alınır alınmaz kullanıcı sayfaya yönlendirilmelidir.
use Klc\Tami\Facades\Tami; use Klc\Tami\DTOs\HostedToken\HostedTokenRequestDto; // 1. Token oluştur $dto = new HostedTokenRequestDto( amount: 150.00, orderId: 'order-' . uniqid(), successCallbackUrl: 'https://example.com/odeme/basarili', failCallbackUrl: 'https://example.com/odeme/basarisiz', mobilePhoneNumber: '905343000201', // 905xxxxxxxxx formatında zorunlu data: ['key-1' => 'extra-info'], // opsiyonel ); $response = Tami::hosted()->createToken($dto); // 2. Kullanıcıyı ortak ödeme sayfasına yönlendir return redirect($response->getPaymentUrl()); // → https://portal.tami.com.tr/hostedPaymentPage?token=...
Callback yönetimi: Başarılı ödemede Tami, successCallbackUrl'e yönlendirme yapar. Callback verisi taşımadığı için işlem durumunu Query servisi ile sorgulayın:
// successCallbackUrl handler'ında: $queryResponse = Tami::payment()->query(new QueryRequestDto( orderId: $orderId, isTransactionDetail: true, )); if ($queryResponse->getPaymentStatus() === 'SUCCESS') { // Siparişi tamamla }
Not: failCallbackUrl şu an için Tami tarafından kullanılmamaktadır, successCallbackUrl ile aynı değer verilebilir. Hata durumunda kullanıcıya Tami sayfasında hata mesajı gösterilir.
Hata Yönetimi
use Klc\Tami\Exceptions\TamiConnectionException; use Klc\Tami\Exceptions\TamiAuthException; use Klc\Tami\Exceptions\TamiApiException; use Klc\Tami\Exceptions\TamiValidationException; use Klc\Tami\Exceptions\TamiSecurityException; try { $response = Tami::payment()->auth($dto); } catch (TamiValidationException $e) { // DTO validasyon hatası $errors = $e->errors; // MessageBag } catch (TamiConnectionException $e) { // Bağlantı hatası } catch (TamiAuthException $e) { // Kimlik doğrulama hatası (HTTP 401) } catch (TamiApiException $e) { // API hatası echo $e->errorCode; echo $e->errorMessage; echo $e->errorGroup; } catch (TamiSecurityException $e) { // Security hash doğrulama hatası }
Route Konfigürasyonu
# Route'ları kapat TAMI_ROUTES_ENABLED=false # Route ön eki TAMI_ROUTES_PREFIX=payment # Başarı/başarısızlık URL'leri TAMI_SUCCESS_URL=/odeme/basarili TAMI_FAILURE_URL=/odeme/basarisiz
Güvenlik Notları
Paket, Tami'ye gönderilen request body için securityHash değerini Tami PHP örneğiyle uyumlu JWK/HS512 JWT algoritmasıyla üretir. securityHash, request body'ye eklenmeden önceki JSON üzerinden hesaplanır.
Normal API response'larında dönen securityHash için Tami PHP örneklerinde doğrulama algoritması bulunmadığı için bu paket o alanı yanlış algoritmayla doğrulamaya çalışmaz. TAMI_RESPONSE_HASH_ENABLED=true yapılırsa paket fail-closed davranır ve TamiSecurityException fırlatır. Bu ayarı ancak normal API response hash algoritması netleşip pakette ayrıca implemente edildikten sonra açın.
3DS callback payload'ında hashedData varsa paket bu değeri secretKey ile HMAC-SHA256 kullanarak doğrular. Callback payload'ına güvenip siparişi doğrudan tamamlamayın; paket callback sonrası server-to-server /payment/complete-3ds çağrısı yapar.
Test
# Docker ile (önerilen) make test # veya doğrudan docker compose run --rm php vendor/bin/phpunit
3DS Callback ve CSRF
3DS callback route'u varsayılan olarak api middleware ile kaydedilir — banka callback'i
CSRF token taşımadığı için web middleware altında 419 hatası alabilir.
Eğer web middleware kullanmak isterseniz VerifyCsrfToken middleware'ine
tami/callback yolunu ekleyin:
// app/Http/Middleware/VerifyCsrfToken.php protected $except = [ 'tami/callback', ];
Lisans
MIT
统计信息
- 总下载量: 150
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 0
- 点击次数: 0
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2026-05-19