Payment Orchestrator
2D Form

Kartla Ödeme — 2D

2D ödeme, kartı tek istekte çeker; banka tarafında 3D Secure doğrulaması ve yönlendirme yoktur. Alıcı formdan ayrılmaz, sonuç anında döner. Bedeli şudur: 3D doğrulaması olmadığından sorumluluk devri (liability shift) yoktur.

Bu sayfa Checkout Formu yolu içindir. POST /payments/form/2d ucunu Checkout Form SDK'sı alıcının tarayıcısından kendisi çağırır; sizin bu uca istek yazmanız gerekmez. Yazacağınız kod, sunucunuzda intent oluşturmak ve formu sayfanıza mount etmektir → Checkout Formu.

Kart verisini kendi sunucunuzdan gönderiyorsanız bu sayfa sizin için değildir → Kart — 2D.

Tüm tutarlar minor unit (kuruş) cinsinden tam sayıdır: "amount": 10050 = ₺100,50. Ondalık ya da float göndermeyin.

Nasıl çalışır

Intent oluşturun (sunucunuz)

Step-Up kimlik doğrulamasıyla POST /payments/intents çağırın. Yanıttaki form token'ı yaklaşık 15 dakika geçerlidir ve formun açılacağı origin'e bağlıdır. Bütün alanlar ve 3D ayarları → Checkout Formu.

Formu mount edin (tarayıcı)

Token'ı SDK'ya verip formu sayfanıza yerleştirin. SDK açılışta oturum kanıtını alır (POST /payments/form/session-init) ve risk analizini başlatır (POST /payments/form/live-analyze). Kanıt pg_checkout_session çerezine yazılır; karta dokunan çağrılar bu kanıt olmadan reddedilir.

Alıcı kartı girer

Form kartın marka ve ailesini çözer, taksit tablosunu gösterir ve kartı izole bir iframe'de tek kullanımlık bir token'a çevirir (POST /payments/form/tokenize). Kart numarası sayfanıza hiç açılmaz. Taksit seçilirse çekim tutarı, gösterilen teklife bağlanır → Taksit & BIN.

SDK çekimi yapar

Intent'in 3D kararı 2D ise SDK POST /payments/form/2d çağırır. İşlem risk kontrolünden geçer, uygun sağlayıcıya yönlendirilir ve anında çekilir.

Alıcı sonuç sayfanıza döner

Çekim başarılıysa ve intent'te callbackUrl verdiyseniz SDK alıcıyı imzalı bir form POST'uyla bu adrese gönderir. callbackUrl yoksa form kendi başarı ekranını gösterir. Ret durumunda form hatayı alıcıya gösterir.

Webhook ile teyit edin

payment.captured ya da payment.failed webhook endpoint'inize teslim edilir. Siparişi bu olaya ya da GET /payments/:id sorgusuna göre kapatın.

3D kararı: form 2D'yi ne zaman çağırmaz

2D bir istektir, garanti değildir. Hangi ucun çalışacağını intent'in 3D kararı belirler. Karar intent oluşturulurken aşağıdaki kaynaklardan çözülür ve intent'e sabitlenir:

KaynakDavranış
Intent'te force3D: trueHer şeyi ezer; ödeme 3D Secure ile işlenir.
Intent'te force3D: falseÖdeme politika tarafından 3D'ye zorlanmaz; panel ayarını da settings.threeD'yi de ezer.
Intent'te settings.threeD.mode: "3d"Bu intent'teki çekimler 3D Secure gerektirir.
settings.threeD.forceAmountMinor eşiğiEşik ve üzerindeki tutarlar auto modda da 3D Secure gerektirir.
Panel 3D politikasıIntent'te force3D ya da settings.threeD yoksa geçerli olan hesap varsayılanınız.

Karar 3D ise SDK doğrudan 3D Secure ucunu kullanır. Aynı intent için POST /payments/form/2d çağrısı 409 THREE_D_REQUIRED ile reddedilir; 3D'ye sessiz bir geçiş yapılmaz. SDK bu yanıtı alırsa aynı gövdeyi bir kez POST /payments/form/3d ucuna gönderir ve akış 3D Secure olarak sürer.

Bu alanları intent oluştururken verirsiniz; ayrıntılı anlatım → Checkout Formu.

Sağlayıcı 2D yapamadığında: otomatik 3D Secure

Politikanız 2D dese bile ödemeyi yönlendiren sağlayıcı, anlaşması gereği 2D (non-secure) satış yapamıyor olabilir. Checkout Formu'nda alıcı ekran başında olduğu için platform çekimi reddetmez, 3D Secure'a yükseltir:

  • POST /payments/form/2d çağrısı CAPTURED yerine bir 3D yönlendirme yanıtı döner. SDK alıcıyı banka doğrulamasına gönderir; akış oradan itibaren 3D Secure akışı gibi ilerler.
  • Ödeme escalationReason: "PROVIDER_2D_UNSUPPORTED" ile işaretlenir. Böylece ödemenin 2D istendiğini ama sağlayıcı yeteneği nedeniyle 3D'ye çıktığını ayırt edebilirsiniz.
  • Intent 3D'ye döner. Aynı intent'e yeniden POST /payments/form/2d göndermek 409 THREE_D_REQUIRED ile reddedilir.
⚠️

Intent'te açıkça force3D: false göndermiş olsanız da sağlayıcının 2D yapamaması bu tercihi ezer ve ödeme 3D Secure'a yükseltilir. 2D seçtiğiniz bir intent'in de 3D Secure ile tamamlanabileceğini varsayın; sonuç sayfanız ve webhook işleyiciniz iki durumu da karşılamalıdır.

Uç başvurusu — POST /payments/form/2d

Bu bölüm başvuru içindir: gövdeyi SDK kurar ve gönderir.

Kimlik doğrulama Authorization başlığıyla değil, iki parçayla yapılır:

  • Gövdedeki token: intent yanıtındaki form token'ı.
  • Oturum kanıtı: pg_checkout_session çerezi. Çerez taşınamayan ortamlarda (WebView, üçüncü taraf çerez engeli) aynı kanıt gövdede checkoutSessionProof alanıyla gönderilir.

Alanlar

POST /payments/form/3d aynı gövdeyi kullanır.

AlanTipZorunluAçıklama
tokenstringEvetIntent yanıtındaki form token'ı.
installmentintegerEvetTaksit sayısı; peşin için 1.
paymentCardsobjectEvetKart. Ham kart alanları (cardHolderName, cardNumber, expireMonth, expireYear, cvcNumber) ya da POST /payments/form/tokenize yanıtındaki tek kullanımlık token (secureCardToken). Alıcı kartını kaydetmek isterse cardSave: true.
paymentChannelenumEvetWEB, WEEMOBILE, MOBILE, MOBILE_WEB, MOBILE_ANDROID, MOBILE_WINDOWS, MOBILE_TABLET, MOBILE_PHONE, MOBILE_IOS
browserFingerprintstringEvetTarayıcı parmak izi; SDK üretir.
installmentQuoteTokenstringTaksitte evetTaksit tablosundan dönen bağlayıcı teklif token'ı. installment 1'den büyükse sunucu bu token'ı ister.
checkoutSessionProofstring (en çok 2048)HayırOturum kanıtı; çerez taşınamayan ortamlarda gövdede gönderilir.
liveSessionTraceIdstringHayırRisk analizinin döndürdüğü iz kimliği.
gsmNumberstringHayırAlıcı Koruması seçildiğinde alıcının telefon numarası.
buyerProtectedbooleanHayırAlıcının Alıcı Koruması'nı seçip seçmediği.

2D çekimde kart kaydedilmez. Alıcı "kartımı kaydet" kutusunu işaretlese de ödeme etkilenmez; kart kaydı yalnız 3D Secure ile yapılır.

Örnek gövde

SDK'nın gönderdiği gövde (secure-fields modunda):

{
  "token": "<intent yanıtındaki form token'ı>",
  "installment": 1,
  "paymentCards": {
    "secureCardToken": "<tokenize yanıtındaki cardToken>"
  },
  "paymentChannel": "WEB",
  "browserFingerprint": "<parmak izi>"
}

Gövdeyi Checkout Form SDK'sı kurar. SDK, alıcıya gösterdiği toplamı da formun iç alanı olarak ekler; bu sizin göndereceğiniz bir tutar değildir. Çekilen tutarı sunucu, intent'teki amount'tan ve taksitte bağlayıcı teklifteki vade farkından hesaplar.

Yanıt

Başarılı çekim 200 döner:

{
  "status": "success",
  "code": "PAYMENT_CAPTURED",
  "message": "Payment processed",
  "data": {
    "id": "9c6f2b1a-4e8d-4a3f-b5e6-2d7c1a9b8e30",
    "orderId": "ORD-9988",
    "amount": 10050,
    "currency": "TRY",
    "status": "CAPTURED"
  },
  "statusCode": 200,
  "requestId": "…"
}
  • data.status 2D'de normalde nihaidir: başarıda CAPTURED, retde FAILED.
  • data.amount çekilen tutardır: intent'teki amount, taksitli ödemede sistemin eklediği vade farkıyla birlikte.
  • callbackUrl verdiyseniz yanıt, alıcıyı sonuç sayfanıza taşıyan imzalı formu da içerir. SDK bu formu kendisi gönderir. Gelen alanlar 3D Secure dönüşüyle aynıdır → Sonuç sayfanıza gelen imzalı POST.
  • Sağlayıcı yeteneği nedeniyle 3D'ye yükseltilen çekim, 3D Secure ucunun yanıtını döner (status: "partial", AWAITING_3D) → Kartla Ödeme — 3D Secure › Yanıt.
  • Sonucu henüz kesinleşmemiş bir işlem status: "partial" (HTTP 202) ile döner; nihai durumu webhook teslim eder.
⚠️

Tarayıcıdan gelen sonuç bilgilendiricidir. Siparişi payment.captured webhook'una ya da GET /payments/:id sorgusuna göre ödenmiş sayın.

Ön provizyon

Formda ön provizyonu ayrıca istemezsiniz: intent'i POST /payments/intents ile oluştururken "preauth": true gönderin. Form çekimi bu karara göre yapar; ödeme başarılı olursa CAPTURED yerine AUTHORIZED olur ve payment.authorized gönderilir. Ön provizyonu desteklemeyen sağlayıcılar adaylardan çıkarılır; uygun sağlayıcı kalmazsa ödeme FAILED olur ve ret kodu PREAUTH_NOT_SUPPORTED'dır.

Capture, void ve 7 günlük süre: Ön Provizyon, Capture & İptal.

Hatalar

Hata yanıtları ortak hata zarfını kullanır; message'a göre değil code'a göre dallanın → Hata Yönetimi.

DurumKodNe yapmalı
Gövde doğrulamadan geçmedi400 VALIDATION_ERRORGüncel SDK'yı kullanın; gövdeyi SDK kurar.
Intent'in 3D kararı 3D409 THREE_D_REQUIRED2D'yi yeniden denemeyin. SDK aynı gövdeyi POST /payments/form/3d ucuna gönderir.
Form token'ı geçersiz401 payment.checkout.session_invalidYeni intent oluşturup formu yeniden mount edin.
Form token'ının süresi doldu (yaklaşık 15 dakika)401 payment.checkout.session_expiredYeni intent oluşturup formu yeniden mount edin.
Form, intent'in bağlı olduğu origin dışında açıldı401 payment.checkout.origin_mismatchIntent'i, formu açtığınız sayfanın origin'iyle oluşturun → Checkout Formu.
Oturum kanıtı yok ya da geçersiz401 payment.checkout.proof_missingFormu SDK ile açın. Çerez taşınamayan ortamlarda kanıt checkoutSessionProof ile gövdede gönderilir.
Oturum kanıtı bu oturuma ait değil401 payment.checkout.proof_mismatchFormu yeniden açın.
Form token'ı bu ödemeye ait değil401 payment.checkout.token_mismatchFormu intent yanıtındaki token'la yeniden açın.
Tek kullanımlık kart token'ı geçersiz ya da kullanılmış401 payment.secure_card.invalid_tokenAlıcı kartı yeniden girer; SDK yeni token alır.
İşlem güvenlik kontrolünden geçemedi409 payment.intent.live_risk_blockedYeniden deneme sonucu değiştirmez.
Bu ödeme denemesi kapandı (ödeme sonuçlandı)409 payment.intent.attempt_closedYeni intent oluşturup formu yeniden açın.
Intent kart dışı bir yöntemle açılmış (ör. paymentMethod: "WALLET")409 payment.method.intent_not_cardBu intent kartla ödenemez; intent'i paymentMethod göndermeden ya da "CARD" ile oluşturun. Intent'e dokunulmadı, kendi yönteminden ödenebilir → Checkout Formu — Payment.
Ön provizyonu destekleyen sağlayıcı yokÖdeme FAILED, kod PREAUTH_NOT_SUPPORTEDPara bloke edilmedi; bkz. Ön Provizyon.
Taksit teklifi geçersiz ya da süresi dolduÖdeme FAILED, kod INSTALLMENT_QUOTE_REJECTEDYeni intent oluşturun; alıcı taksiti güncel tablodan yeniden seçer.
Formun alıcıya gösterdiği toplam, sunucunun hesapladığı çekim tutarıyla eşleşmiyorÖdeme FAILED, kod CLIENT_PRICE_DIVERGENCEFormun güncel SDK ile açıldığından emin olun ve yeni intent oluşturun.
Sağlayıcı reddi (yetersiz bakiye, geçersiz kart …)Ödeme FAILEDForm reddi alıcıya gösterir. Aynı intent'le yeniden çekim yapılamaz; alıcı yeniden ödemek isterse yeni intent oluşturun.
Geçici altyapı hatası503 payment.dependency.unavailable, payment.credential.resolution_failed, payment.lock.unavailableGeçicidir; alıcı kısa süre sonra yeniden deneyebilir.

Webhook'lar

EventNe zaman
payment.capturedÇekim tamamlandı, para çekildi
payment.failedÇekim reddedildi
payment.authorizedÖn provizyonlu intent'te tutar bloke edildi (AUTHORIZED); para henüz çekilmedi

Teslimat ve imza doğrulaması → Webhook'lar.

Sonraki adımlar