Ana Sayfa / Blog / Yurtiçi/MNG/Aras kargo API entegrasyonları

Yurtiçi/MNG/Aras kargo API entegrasyonları

Türkiye kargo şirketlerinin API'ları modern değil ama çalışır. 3 farklı WooCommerce entegrasyonunda öğrendiklerim, XML/SOAP workflow'u, tracking, rate comparison.

Türkiye e-ticaret kargo entegrasyonunda en sık kullanılan 3 firma: Yurtiçi, MNG, Aras Kargo. Her birinin API’sı farklı teknoloji, farklı akış, farklı özellik seti. Ortak sorunları ve çözümleri paylaşıyorum.

3 farklı WooCommerce projede bu üç kargo firmasının entegrasyonunu yaptım. Bazı noktalar benim başıma iki kere geldi, size bir kere gelsin.

Genel: SOAP/XML dünyası

Türkiye’nin kargo API’larının çoğu 2010’lar mimarisi. SOAP, XML request/response, WSDL-based. REST/JSON bekliyorsanız şok oluyorsunuz.

PHP tarafında SoapClient yerleşik. Her kargo firmasının WSDL’i farklı ama pattern ortak:

$client = new SoapClient('https://kargo.example.com/service?wsdl', [
    'trace' => true,
    'exceptions' => true,
    'connection_timeout' => 30,
    'cache_wsdl' => WSDL_CACHE_MEMORY
]);

$response = $client->createShipment([
    'username' => $username,
    'password' => $password,
    'barcode' => $order_barcode,
    'recipient' => [...]
]);

WSDL cache’lemek kritik. Her request’te WSDL fetch etmek 500ms-2sn ekliyor.

Yurtiçi Kargo

Türkiye’nin en yaygın kargo firması. API nispeten iyi dokümante edilmiş.

Ana endpointler:
createShipment: kargo oluştur, barkod al
cancelShipment: kargo iptal (sadece belirli süre içinde)
queryShipment: durum sorgula
getShipmentLabel: etiket PDF’i al

Özel dikkat:
cargoKey sizin orderId + suffix format’ında unique
barcodeNumber Yurtiçi tarafından generate edilen (siz vermiyorsunuz)
– Adres format’ı çok hassas: “il”, “ilce”, “mahalle” ayrı field’lar. Tek string olarak yazarsanız reject ediyor

Adres parse’ı için TC PTT Posta Kodu servisini kullanıyorum, il/ilçe validation’ını yaparak Yurtiçi’ye doğru format gönderiyorum. Yoksa orderlar kargo onboarding’te takılıyor.

MNG Kargo

MNG’nin API’sı daha basit ama dokümantasyon daha zayıf. Çoğu case trial-error ile öğrendim.

REST API’leri var ama temel operasyonlar için SOAP tercih ediliyor. REST’te bazı field’lar eksik dönüyor.

Ozellikler:
– Kapı önü teslimat vs şube teslimat seçeneği request’te
– Aynı gün dağıtım için özel service type
– COD (capital on delivery, kapıda ödeme) için ek endpoint

Sık hata:
– Turkish character encoding: UTF-8 encode etmezseniz “Ç”, “Ş”, “İ” karakterleri bozuluyor
– MNG’nin label PDF’i 80mm thermal printer formatında, A4’e basmak düzenleme gerektiriyor
– Cancelation time window sadece 2 saat, MNG tarafı geniş görmez, sonradan iptal edemezsiniz

Aras Kargo

Aras’ın API’sı 2022’de revize edildi, daha modern. REST endpoint’ler geldi ama SOAP hala destekli.

REST JSON örnek:

POST /api/v1/shipments
{
    "orderNumber": "WC-12345",
    "recipient": {
        "name": "Ali Müşteri",
        "phone": "05551234567",
        "address": "Örnek Mah. Test Cad. No:1",
        "city": "Ankara",
        "district": "Çankaya",
        "postalCode": "06100"
    },
    "package": {
        "weight": 1.5,
        "desi": 3,
        "count": 1
    },
    "payment": {
        "type": "SENDER_PAYS"
    }
}

Aras’ın güçlü yanları: webhook support (durum değişince bildirim), desi hesaplama otomatik, tracking daha granular detay veriyor.

WooCommerce plugin seçimi

Her kargo firmasının WooCommerce plugin’i var ama kalite farklı.

Yurtiçi Kargo plugin: resmi değil, 3rd party. 2 farklı plugin test ettim, ikisi de bug’lı. Custom implementasyon tercih ediyorum.

MNG Kargo plugin: MNG’nin kendi plugin’i var, temel entegrasyon için yeterli. Advanced case’lerde override gerekli.

Aras Kargo plugin: resmi. En iyisi. REST API üzerinden entegre.

Bütçe varsa plugin + small customization, yoksa custom. Orta ölçek projelerde plugin + WooCommerce hook’larıyla customization yeterli oluyor.

Tracking: kullanıcıya durumu göstermek

Her kargo firması farklı status code veriyor:

  • Yurtiçi: “Kargo Şubede”, “Dağıtıma Çıktı”, “Teslim Edildi”, vs
  • MNG: “ACCEPTED”, “IN_TRANSIT”, “OUT_FOR_DELIVERY”, “DELIVERED”
  • Aras: yine kendi code’ları

Kullanıcıya göstermek için normalize ediyorum:

function normalize_cargo_status($provider, $raw_status) {
    $map = [
        'yurtici' => [
            'Kargo Şubede' => 'processing',
            'Dağıtıma Çıktı' => 'out_for_delivery',
            'Teslim Edildi' => 'delivered'
        ],
        'mng' => [
            'ACCEPTED' => 'processing',
            'OUT_FOR_DELIVERY' => 'out_for_delivery',
            'DELIVERED' => 'delivered'
        ],
        'aras' => [...]
    ];
    return $map[$provider][$raw_status] ?? 'unknown';
}

WooCommerce order notes’a da raw status log’luyorum ops team için.

Tracking update frequency

Kargo durumunu ne sıklıkla güncellesin?

Polling: Her saat order tablosundan “shipped” durumdaki order’ları çekip status sorgulama. CRON ile. Günde 24 sorgu/order.

Webhook: Aras webhook veriyor, MNG ve Yurtiçi’de webhook yok. Aras için webhook + diğerleri için polling hybrid.

Kullanıcı-tetikli: kullanıcı “kargom nerede?” butonuna tıklarsa fresh fetch. Cache’le 15 dakikalık window.

Ben hybrid approach kullanıyorum: webhook + 2 saatlik polling (tüm in-transit orders) + user-triggered fresh fetch (cache miss için).

Rate comparison: 3 firmayı paralel sorgula

Müşteri checkout’ta “en ucuz kargo hangisi?” göstermek için 3 API’yi paralel çağırmak gerekli. Tek tek seri çağrı toplamda 9 saniye sürebiliyor.

Parallel call pattern:

$promises = [
    'yurtici' => $yurtici_client->getRateAsync($package),
    'mng' => $mng_client->getRateAsync($package),
    'aras' => $aras_client->getRateAsync($package)
];

$results = Promise\Utils::unwrap($promises);

Her API’nin async wrapper’ı var (Guzzle, Swoole, ReactPHP). 3 saniyede 3 quote alınıyor.

Cache’leyin: aynı ağırlık/destination için quote 1 saat geçerli, DB/Redis cache yeterli.

Hata durumu

Kargo API’si down olduğunda ne yapacaksınız? Order işlem süresi kritik.

Pattern:
1. Try primary: Yurtiçi default. Fail olursa:
2. Try fallback: MNG yedek
3. Queue for retry: Her ikisi de fail ise order’ı queue’ya al, 15 dakika sonra tekrar dene
4. Manual intervention: 3 saat geçse hala fail, ops’a alarm

Bu pattern sayesinde kargo API outage’ında sipariş kaybı yaşamadık. 2 saatlik Yurtiçi outage’ında 150 sipariş MNG’ye düştü, kimse fark etmedi.

Testing

Test environment her kargo firmasında var:
– Yurtiçi: ayrı test credentials, test barcode’ları gerçek taşıma ürettirmez
– MNG: test endpoint’i, sandbox mode request flag’i
– Aras: dedicated sandbox

Ama test environment’lar production’un tam replica’sı değil. Bazı edge case production’a ulaşana kadar görülmez. Staging’den önce küçük bir production shipment ile smoke test yapın.

Label printing

Kargo etiketi PDF olarak geliyor. A4 vs thermal (80mm) farkı:
– A4: 6-8 label per sheet (manuel kesim)
– Thermal: direkt barcode printer’a

Operations ekibi thermal printer kullanıyorsa label PDF’ini 80mm format’a dönüştürmeniz gerekebilir. PDF manipulation: ghostscript veya ImageMagick ile crop.

Son tavsiye

Kargo entegrasyonu sanıldığından daha zaman alıyor. Her firma için 1 hafta planlayın. Test senaryoları: create, cancel, query, tracking update, label generation, rate comparison. Hepsini manuel test ettikten sonra production.

Bir lokal entegrasyon iyi yapıldığında e-ticaretin conversion’ına doğrudan etki ediyor. Kargo seçimi zamanı / fiyatı / güvenilirliği müşteri checkout friction’ını belirliyor.

Bu konuda bir projeniz mi var?

Kısa bir özet bırakın, 24 saat içinde size dönüş yapayım.

İletişime Geç