Skip to Content

Hatalar

Her 4xx/5xx yanıtı aynı JSON zarfını taşır:

{ "code": 400, "message": "invalid_input", "details": [ { "field": "items[0].unit_price", "message": "must be a positive decimal string" } ] }
  • codesayısal HTTP durumu (400, 401, 404, …). Genel HTTP-katmanı işleme için kullanışlıdır, ancak dallanma mantığı için bunun yerine message üzerinde switch yapın — code örneğin invalid_input ile payment_method_not_supported (her ikisi de 400) arasında ayrım yapmaz.
  • message — dahili errors.go sabitinden türetilen lower-snake-case sentinel adı (örn. INVALID_INPUT → "invalid_input"). Sürümler arasında stabildir — bunun üzerinde switch yapın.
  • details — doğrulama hatalarında doldurulur. İstemcinin hataları girdilere sabitlemesi için { field, message } nesnelerinden oluşan dizi. Aksi takdirde atlanır.

Şu anda gövdede trace_id veya timestamp döndürmüyoruz. Bu sayfanın önceki taslakları her ikisini de vaat ediyordu — bu özlemdi. Bir sunucu logunu bir istekle ilişkilendirmeniz gerekirse, yanıt Date başlığını ve geçit tarafı rate-limit başlıklarını (X-RateLimit-*) yakalayın ve bunları bir destek talebinde belirtin.

Geçit-kenarı reddetmeleri farklı bir şekil kullanır. Yukarıdaki zarf, backend servislerinin yaydığı şeydir. Bir servise ulaşmadan önce geçidde reddedilen istekler — bir /b2b/v1/* çağrısında eksik/geçersiz X-Signature, bilinmeyen X-Client-ID veya eski X-Timestamp{ "error": "...", "message": "..." } olarak geri gelir; burada error kaba bir slug’tır (unauthorized / bad_request / service_unavailable) ve message ayrıntıları taşır. Sayısal code ve details yoktur. Bu yüzden bir doğrulayıcı önce HTTP durumu üzerinde dallanmalı, ardından message’ı okumalı ve code/details’i yalnızca istek geçidi geçtikten sonra mevcut olarak değerlendirmelidir. Örnek geçit gövdesi (401):

{ "error": "unauthorized", "message": "invalid signature" }

HTTP durumu → tipik kodlar

HTTPTipik code değerleriNe anlama gelir
400INVALID_INPUT, MISSING_REQUIRED, INVALID_FORMAT, INVALID_LENGTH, INVALID_VALUE, INVALID_USER_STATUS, INVALID_USER_ROLE, PAYMENT_METHOD_NOT_SUPPORTED, AMOUNT_BELOW_MINIMUMHatalı istek — details’e bakın
401INVALID_CREDENTIALS, INVALID_TOKEN, TOKEN_EXPIRED, INVALID_SIGNATURE (B2B); INVALID_OTP, OTP_EXPIRED, SESSION_EXPIRED (yalnızca panel / JWT)Auth başarısız — hatalı anahtar, süresi dolmuş timestamp, yanlış imza. OTP/SESSION_EXPIRED kodları yalnızca panel-JWT rotalarında (/payment/v1/*) yüzeye çıkar; saf B2B entegrasyonları bunları görmez.
402INSUFFICIENT_CREDITSatıcının ön ödemeli bakiyesi tükendi — yeniden denemeden önce yükleyin
403FORBIDDEN, IP_BLOCKEDAnahtar geçerli ama bu çağrı için scope/IP iznine sahip değil
404NOT_FOUND, RECORD_NOT_FOUND, USER_NOT_FOUND, SESSION_NOT_FOUNDKaynak yok (veya bu satıcı için yok)
409ALREADY_EXISTS, USER_ALREADY_EXISTS, SESSION_ALREADY_EXISTSFarklı bir gövde ile idempotency replay, ya da durum makinesi geçişi reddetti
429TOO_MANY_REQUESTS, TOO_MANY_ATTEMPTSRate limit’e ulaşıldı; geri çekilin ve yeniden deneyin
500INTERNAL_SERVER_ERROR, DATABASE_CONNECTION_ERROR, DATABASE_QUERY_ERROR, DATABASE_TRANSACTION_ERROR, REDIS_CONNECTION_ERROR, REDIS_OPERATION_ERROR, EXTERNAL_SERVICE_ERRORBizim hatamız; geri çekilmeyle yeniden denemek güvenli. (TWILIO_SERVICE_ERROR / SENDGRID_SERVICE_ERROR gibi provider’a özgü kodlar dahili olarak vardır ama yalnızca panel tarafı bildirim akışlarında yüzeye çıkar, B2B uç noktalarında değil.)
503SERVICE_UNAVAILABLEBir alt bağımlılık çalışmıyor. Geri çekilme ile yeniden deneyin

Tam kod referansı

Görebileceğiniz code değerlerinin tam kümesi (payment-service/pkg/errors/errors.go ile eşleşir):

Auth ve oturumlar (401)

  • INVALID_CREDENTIALS — kullanıcı adı/şifre veya API anahtarı kombinasyonu reddedildi
  • INVALID_TOKEN — JWT/oturum token’ı ayrıştırılamadı veya değiştirilmiş
  • TOKEN_EXPIRED — JWT exp’i geçti
  • INVALID_OTP — OTP eşleşmiyor
  • OTP_EXPIRED — OTP tolerans penceresi öncesinde verildi
  • SESSION_EXPIRED — panel oturumu süresi doldu
  • INVALID_SIGNATURE — B2B / webhook çağrılarında HMAC imza uyumsuzluğu

Yetkilendirme (403)

  • FORBIDDEN — doğrulandı ama rol/scope/satıcı sınırı eylemi engelliyor
  • IP_BLOCKED — IP suistimal listesinde

Bulunamadı (404)

  • NOT_FOUND — genel
  • RECORD_NOT_FOUND — verilen ID için satır eksik
  • USER_NOT_FOUND — kullanıcı araması başarısız
  • SESSION_NOT_FOUND — panel oturum id’si tanınmıyor

Çakışma (409)

  • ALREADY_EXISTS — genel
  • USER_ALREADY_EXISTS — kayıt benzersizlik kısıtlamasına çarptı
  • SESSION_ALREADY_EXISTS — yinelenen oturum eklemesi

Doğrulama (400)

  • INVALID_INPUT — genel; details’i kontrol edin
  • MISSING_REQUIRED — gerekli bir alan eksik
  • INVALID_FORMAT — değer beklenen formatla eşleşmedi (örn. UUID, URL, e-posta)
  • INVALID_LENGTH — değer çok kısa veya çok uzun
  • INVALID_VALUE — değer izin verilen enum/aralığın dışında
  • INVALID_USER_STATUS — kullanıcı eylemi yasaklayan bir durumda
  • INVALID_USER_ROLE — rol eylem için izinden yoksun
  • PAYMENT_METHOD_NOT_SUPPORTED — provider/varlık kombinasyonu satıcı için etkin değil
  • AMOUNT_BELOW_MINIMUM — sipariş tutarı ağ başına veya env-seviyesi zemininin altında. Yanıtın details.floor_usd alanı yapılandırılmış zemini (USD) taşır, böylece onu doğrudan yüzeye çıkarabilirsiniz; message metni de bunu belirtir.
  • INSUFFICIENT_BALANCE — alıcının cüzdanı, transferi karşılamak için yeterli ödeme varlığını tutmuyor.
  • INSUFFICIENT_GAS — alıcının cüzdanında transferi yaymak için yerel gas eksik.

Ödeme / faturalama (402)

  • INSUFFICIENT_CREDIT — satıcı ön ödemeli bakiyesi gas / platform ücretini karşılayamaz. Panel üzerinden yükleyin, ardından yeniden deneyin

Rate limit (429)

  • TOO_MANY_REQUESTS — geçit IP rate-limit
  • TOO_MANY_ATTEMPTS — aynı kaynak üzerinde (örn. OTP) tekrar eden başarısız denemeler bir throttle’ı tetikledi

Depolama / altyapı (500)

  • DATABASE_CONNECTION_ERROR — DB’ye ulaşılamadı
  • DATABASE_QUERY_ERROR — query plan runtime’da başarısız oldu
  • DATABASE_TRANSACTION_ERROR — commit/rollback başarısız oldu
  • REDIS_CONNECTION_ERROR — Redis’e ulaşılamadı
  • REDIS_OPERATION_ERROR — Redis komutu başarısız oldu
  • EXTERNAL_SERVICE_ERROR — genel üçüncü taraf hatası (aşağıda kovaya alınmamış provider)
  • TWILIO_SERVICE_ERROR — Twilio SMS / Verify çağrısı başarısız oldu
  • SENDGRID_SERVICE_ERROR — SendGrid posta gönderimi başarısız oldu
  • INTERNAL_SERVER_ERROR — beklenmedik fall-through; yanıt Date başlığı + X-RateLimit-*’ı yakalayın ve ulaşın

Kullanılabilirlik (503)

  • SERVICE_UNAVAILABLE — kritik bir alt bağımlılık sağlıksız raporluyor; geri çekilme + yeniden deneme

Doğrulama hataları (400)

Sorun hatalı biçimlendirilmiş bir istek gövdesi olduğunda, details bir dizidir, böylece hataları alanlara geri eşleyebilirsiniz:

{ "code": 400, "message": "invalid_input", "details": [ { "field": "items[0].unit_price", "message": "must be a positive decimal string" }, { "field": "success_url", "message": "must be a valid https URL" } ] }

Auth hataları (401)

INVALID_SIGNATURE üç farklı arıza modunu kapsar — onları ayırt etmenin tek yolu ikileştirmektir:

  • Yanlış secret anahtar (env var’ı yeniden kontrol edin)
  • Timestamp sapması > 5 dk (NTP senkronize edin)
  • Yanlış kanonik dize (en sık: \n ayraçlarını unutmak veya ayrıştırılıp-sonra-yeniden-stringleştirilmiş, gönderdiğinizden farklı bir gövdeyi imzalamak)

Tam imzalama algoritması için Kimlik doğrulama sayfasına bakın.

Rate limit’ler (429)

YüzeyLimit
Her geçit rotası (/b2b/v1/* dahil)Geçidde IP başına — 500 req/dk, paylaşımlı kova. Satıcı başına değil.
Public checkout (/checkout/*)Daha sıkı alt kova — IP başına 20 req/dk

X-RateLimit-Limit ve X-RateLimit-Remaining, her geçit-rate-limitli yanıtta yayılır (yalnızca başarılarda değil). Bunları IP’niz için canlı bütçe olarak değerlendirin.

Rate-limit’li yanıtlar bir Retry-After başlığı içerir (pencerenin sıfırlanmasına kalan saniye) — buna uyun. Yedek olarak, jitter ile geri çekilin — 1s temel + 30s’ye üstel artan bekleme süresi.

Rate limit’ler değişebilir. Onlara meşru bir şekilde ulaşıyorsanız (örn. büyük bir tarihsel aralığı mutabık kılıyorsanız), ulaşın — toplu uç noktalar yol haritasında.

Yetersiz kredi (402)

INSUFFICIENT_CREDIT (HTTP 402 Payment Required), satıcının ön ödemeli bakiyesinin, gerçekleştirmeye çalıştığınız işlem için bir sonraki gas-ve-platform ücretini karşılayamadığı anlamına gelir — tipik olarak bir kripto ödemesi tahsil etme veya gas-sponsorlu bir zincir üstü eylem yürütme. Satıcı panelinden (Faturalama → Kredi ekle) yükleyin, ardından işlemi yeniden deneyin; uçuştaki iş bekler ve bakiye temizlenir temizlenmez otomatik olarak devam eder.

Sunucu hataları (5xx)

Bir 500, isteği işleyemediğimiz anlamına gelir. Geri çekilme ile yeniden deneyin — idempotency_key’iniz, orijinal istek kısmen başarılı olmuş olsa bile çift ücretlendirme yapmamanızı sağlar.

Yeniden denemeler bir dakika içinde kurtarılmazsa, alıcıya genel bir “ödeme geçici olarak kullanılamıyor” gösterin ve başarısız uç noktayı, satıcı ID’nizi, yanıt Date başlığını ve X-RateLimit-* değerlerini ve yaklaşık istek zamanını destek ekibine iletin — bu, loglarımızda ilgili isteğe geçmemiz için yeterlidir.

Webhook teslim hataları

Webhook teslimleri ayrı bir başarısızlık kanalıdır — API hatası olarak yüzeye çıkmazlar çünkü sunucunuz çağrı yapan taraf değildir. Bir teslim 2xx-olmayan bir yanıt döndürdüğünde (veya zaman aşımına uğradığında), 0s, 1dk, 5dk, 15dk, 1s, 6s aralıklarında üstel artan bekleme süresi ile yeniden denemek üzere kuyruğa alınır (toplam altı deneme — bkz. Webhook’lar → Genel bakış ile aynı program). Tam teslim başına geçmiş, panelin Geliştiriciler → Webhook’lar → [uç nokta] → Teslim günlüğü altında görünür. Altıncı denemeden sonra teslim dead-letter’a gönderilir — panel sunucunuz sağlıklı olduğunda manuel olarak yeniden oynatabileceğiniz bir “Başarısız” rozeti gösterir.