GeliştiricilerAPI v1.2

Odesin Geliştirici Merkezi

Ödeme oturumları, kart ve havale entegrasyonları, webhook bildirimleri ve kod örnekleri — mağazanızı Odesin'e bağlamak için tek referans.

x-api-keyHMAC imza

Ne bulabilirsiniz

  • Canlı API referansı
  • Hosted & whitelabel akışlar
  • Webhook akışı

Base URL

https://odesin.com

Protokol

HTTPS / REST

Format

JSON

Sanal POS (Hosted) modelinde ödeme oturumunu siz API ile oluşturursunuz; tahsilat işlemi banka sanal POS altyapısı üzerinden 3D Secure ile güvenli şekilde işlenir. Müşteri kart bilgilerini checkout_url ile verdiğimiz Odesin checkout sayfasında girer — bu adresi doğrudan yönlendirme ile açabilir veya kendi sitenizde <iframe> içinde gösterebilirsiniz. Kart verisi mağaza sistemlerinize uğramaz, doğrudan bankaya iletilir. Ödeme sonucunda müşteri return_url adresinize döner; isteğe bağlı callback_url ile sunucunuza webhook bildirimi gönderilir.

Genel Bakış

Sanal POS (Hosted) akışında ödeme oturumunu API ile açar, müşteriyi checkout_url adresine yönlendirirsiniz. Kart verisi Odesin checkout üzerinde toplanır ve 3D Secure doğrulaması banka tarafında yürür.

  • POST /api/payment/create-session ile mode: "card" gönderilir.
  • Yanıttaki checkout_url müşterinin ödeme ekranıdır; yönlendirme veya iframe ile açılır.
  • Ödeme başarılı veya başarısız olduğunda müşteri return_url adresinize otomatik yönlendirilir (5 saniyelik geri sayım ve "Mağazaya Dön" butonu ile). URL'e odesin_payment=success|failed ve odesin_ref=ISLEM_NO query parametreleri eklenir.
  • Mağazada pos_enabled açık olmalıdır; kapalıysa 403 döner.
Kart verisi yalnızca Odesin checkout akışında toplanır ve 3D Secure üzerinden bankaya iletilir; mağaza tarafında kart saklamaz veya işlemezsiniz. 3D Secure doğrulaması gerektiğinde müşteri banka doğrulama sayfasına yönlendirilir, doğrulama sonrası ödeme otomatik tamamlanır.

Kimlik Doğrulama

Tüm API isteklerinde x-api-key ile kimlik doğrulaması yapılır. API v1.2 sözleşmesine göre aynı isteklerde HMAC istek imzası da zorunludur.

İstek İmzası (HMAC)

API v1.2 ile mağaza sunucunuzdan Odesin'e giden POST /api/payment/create-session, POST /api/payment/notify, GET /api/payment/session-status ve GET /api/payment/iban-accounts çağrılarında X-Odesin-Timestamp ile X-Odesin-Signature başlıkları zorunludur. İmza anahtarı, x-api-key ile gönderdiğiniz sk_live_... değerinin ta kendisidir.

  • POST isteklerinde imzalanacak metin (UTF-8, satır sonu \n): {unixSaniye}\n{METHOD}\n{hamGövde} hamGövde, ağa giden JSON'un aynen aynısı olmalıdır (boşluk ve sıra dahil).
  • GET isteklerinde: {unixSaniye}\nGET\n{yolVeQuery} yolVeQuery örnek: /api/payment/session-status?session_id=... (baştaki slash ile).
  • İmza: HMAC-SHA256(apiKey, imzaMetni) çıktısının hex gösterimi (küçük harf önerilir).
  • X-Odesin-Timestamp: Unix saniye; sunucu saati ile fark en fazla ±5 dakika olmalıdır.
BaşlıkZorunluAçıklama
X-Odesin-TimestampEvetUnix epoch (saniye)
X-Odesin-SignatureEvetHMAC-SHA256 hex

Örnek (Node.js, POST)

import crypto from "crypto";

function odesinSignPost(apiKey, rawBody) {
  const ts = Math.floor(Date.now() / 1000).toString();
  const payload = `${ts}\nPOST\n${rawBody}`;
  const sig = crypto.createHmac("sha256", apiKey).update(payload, "utf8").digest("hex");
  return { "x-odesin-timestamp": ts, "x-odesin-signature": sig };
}

function odesinSignGet(apiKey, pathWithQuery) {
  const ts = Math.floor(Date.now() / 1000).toString();
  const payload = `${ts}\nGET\n${pathWithQuery}`;
  const sig = crypto.createHmac("sha256", apiKey).update(payload, "utf8").digest("hex");
  return { "x-odesin-timestamp": ts, "x-odesin-signature": sig };
}

Örnek (bash, OpenSSL — POST)

API_KEY="sk_live_XXXXXXXXXXXX"
BODY='{"amount":250,"customer_name":"Ahmet Yılmaz","customer_email":"ahmet@email.com","customer_phone":"05321234567","description":"Sipariş #1234","callback_url":"https://yoursite.com/api/webhook","return_url":"https://yoursite.com/order/success"}'
TS=$(date +%s)
SIG=$(printf '%s\nPOST\n%s' "$TS" "$BODY" | openssl dgst -sha256 -hmac "$API_KEY" | awk '{print $2}')

curl -X POST https://odesin.com/api/payment/create-session \
  -H "Content-Type: application/json" \
  -H "x-api-key: $API_KEY" \
  -H "x-odesin-timestamp: $TS" \
  -H "x-odesin-signature: $SIG" \
  --data-binary "$BODY"

Örnek (PHP)

<?php
/** POST / GET imza başlıkları (ham gövde veya yol+query ile aynı kural). */
function odesin_sign_post(string $apiKey, string $rawBody): array {
    $ts = (string) time();
    $sig = hash_hmac('sha256', $ts . "\nPOST\n" . $rawBody, $apiKey);
    return ['x-odesin-timestamp' => $ts, 'x-odesin-signature' => $sig];
}

function odesin_sign_get(string $apiKey, string $pathWithQuery): array {
    $ts = (string) time();
    $sig = hash_hmac('sha256', $ts . "\nGET\n" . $pathWithQuery, $apiKey);
    return ['x-odesin-timestamp' => $ts, 'x-odesin-signature' => $sig];
}

// Kullanım: $h = odesin_sign_post($apiKey, $jsonBodyString);
// CURLOPT_HTTPHEADER: 'x-odesin-timestamp: '.$h['x-odesin-timestamp'], 'x-odesin-signature: '.$h['x-odesin-signature']

Kart oturumu oluştur

İstek POST /api/payment/create-session endpoint'ine gider. Kart modunda return_url zorunludur; diğer alanlar aşağıdaki tabloda özetlenmiştir.

AlanZorunluAçıklama
modeEvet"card"
amountEvetTutar (TRY)
return_urlEvetÖdeme tamamlandıktan sonra müşterinin döneceği HTTPS adresi
callback_urlHayırMağaza webhook URL'i; yoksa mağaza ayarındaki webhook kullanılır. Başarılı kart ödemesinde payment.approved benzeri bildirim gönderilir.
customer_nameEvetMüşteri adı soyadı
customer_emailEvetMüşteri e-posta adresi
customer_phoneEvetMüşteri telefon numarası
descriptionHayırSipariş / açıklama metni
API_KEY="sk_live_XXXXXXXXXXXX"
BODY='{"mode":"card","amount":199.9,"return_url":"https://magazaniz.com/siparis/tesekkur","callback_url":"https://magazaniz.com/api/odesin-webhook","customer_name":"Ali Veli","customer_email":"ali@email.com","customer_phone":"05321234567","description":"Sipariş #4521"}'
TS=$(date +%s)
SIG=$(printf '%s\nPOST\n%s' "$TS" "$BODY" | openssl dgst -sha256 -hmac "$API_KEY" | awk '{print $2}')

curl -X POST https://odesin.com/api/payment/create-session \
  -H "Content-Type: application/json" \
  -H "x-api-key: $API_KEY" \
  -H "x-odesin-timestamp: $TS" \
  -H "x-odesin-signature: $SIG" \
  --data-binary "$BODY"

Örnek yanıt

{
  "session_id": "uuid",
  "mode": "card",
  "checkout_url": "https://odesin.com/checkout/uuid",
  "reference_code": "ODSN-XXXX",
  "amount": 199.9,
  "currency": "TRY",
  "expires_at": "2025-01-01T12:00:00.000Z"
}

Checkout ve 3D Secure

Müşteri checkout_url üzerindeki Odesin checkout sayfasında kart bilgilerini (PAN, SKT, CVV) girer. Form gönderildiğinde Odesin sunucusu kart verisini banka sanal POS altyapısı üzerinden 3D Secure akışına sokar.

Akış

  1. Müşteri Odesin checkout sayfasında kartını girer ve "Öde" butonuna tıklar.
  2. Odesin, kart verisi ile gt3dengine formunu oluşturup bankaya POST eder (3D_PAY).
  3. Banka, müşterinin tarayıcısını 3D Secure doğrulama sayfasına yönlendirir (SMS / mobil onay).
  4. Doğrulama sonrası banka, Odesin callback adresine sonucu POST eder.
  5. Oturum durumu paid veya failed olur; müşteri her iki durumda da return_url adresinize otomatik yönlendirilir (?odesin_payment=success|failed&odesin_ref=ISLEM_NO).
Kart verisi yalnızca Odesin checkout sayfasında toplanır ve doğrudan bankaya iletilir; mağaza sunucunuz kart numarası veya CVV görmez. 3D Secure doğrulaması banka tarafında yapılır.
Checkout sayfasını iframe içinde gösterirken, çerçeve ve üst sayfa kaynağının güvenilir olduğundan emin olun (ör. yalnızca kendi domain'inizden embed). Bazı bankalar iframe içinde 3D doğrulama sayfasını engelleyebilir; bu durumda tam sayfa yönlendirme (window.location.href) önerilir.

Dönüş ve webhook

Ödeme sonrası (başarılı veya başarısız) müşteri return_url adresinize otomatik yönlendirilir. URL'e eklenen query parametreleri ile ödeme durumunu anlık kontrol edebilirsiniz:

ParametreDeğerAçıklama
odesin_paymentsuccess / failedÖdeme sonucu
odesin_refMetinİşlem no (session ID kısaltması)
odesin_detailMetinBanka hata mesajı (red durumunda)
odesin_hash_ok1 / 0Banka yanıt hash doğrulaması

Sunucu tarafında, oturum oluştururken verdiğiniz callback_url veya mağaza panelinde tanımlı webhook adresine JSON bildirim gönderilir:

{
  "event": "payment.approved",
  "session_id": "uuid",
  "reference_code": "ODSN-XXXX",
  "amount": 199.9,
  "currency": "TRY",
  "status": "paid",
  "transaction_id": "uuid",
  "payment_method": "card",
  "provider": "bank_pos",
  "timestamp": "2025-01-01T12:00:00.000Z"
}
Webhook URL'inizin HTTPS ve erişilebilir olduğundan emin olun. Yanıtta dönen reference_code ve session_id ile kendi sisteminizde mutabakat yapın. Ödeme başarısız olduğunda olay tipi payment.rejected olur.

Kod örnekleri

JavaScriptOturum oluştur ve müşteriyi checkout'a yönlendir

const BASE = "https://odesin.com";
const API_KEY = "sk_live_XXXXXXXXXXXX";

function odesinSignPost(apiKey, rawBody) {
  const ts = Math.floor(Date.now() / 1000).toString();
  const enc = new TextEncoder();
  const payload = enc.encode(`${ts}\nPOST\n${rawBody}`);
  return crypto.subtle.importKey("raw", enc.encode(apiKey), { name: "HMAC", hash: "SHA-256" }, false, ["sign"])
    .then((key) => crypto.subtle.sign("HMAC", key, payload))
    .then((buf) => ({
      "x-odesin-timestamp": ts,
      "x-odesin-signature": Array.from(new Uint8Array(buf), (b) => b.toString(16).padStart(2, "0")).join(""),
    }));
}

async function startHostedCardCheckout(order) {
  const rawBody = JSON.stringify({
    mode: "card",
    amount: order.total,
    currency: "TRY",
    return_url: order.successUrl,
    callback_url: order.webhookUrl,
    customer_name: order.customerName,
    customer_email: order.customerEmail,
    customer_phone: order.customerPhone,
    description: order.description ?? "",
  });
  const sig = await odesinSignPost(API_KEY, rawBody);
  const res = await fetch(`${BASE}/api/payment/create-session`, {
    method: "POST",
    headers: { "Content-Type": "application/json", "x-api-key": API_KEY, ...sig },
    body: rawBody,
  });
  const data = await res.json();
  if (!res.ok) throw new Error(data.error ?? res.statusText);
  window.location.href = data.checkout_url;
}

Pythoncreate-session (kart / hosted)

import hashlib, hmac, time, json, requests

BASE = "https://odesin.com"
API_KEY = "sk_live_XXXXXXXXXXXX"

def odesin_sign_post(api_key: str, raw_body: str) -> dict:
    ts = str(int(time.time()))
    msg = f"${ts}\nPOST\n${raw_body}".encode("utf-8")
    sig = hmac.new(api_key.encode("utf-8"), msg, hashlib.sha256).hexdigest()
    return {"x-odesin-timestamp": ts, "x-odesin-signature": sig}

body = {
    "mode": "card",
    "amount": 199.90,
    "return_url": "https://magazaniz.com/tesekkur",
    "callback_url": "https://magazaniz.com/api/webhook",
    "customer_name": "Ali Veli",
    "customer_email": "ali@email.com",
    "customer_phone": "05321234567",
}
raw = json.dumps(body, separators=(",", ":"), ensure_ascii=False)
sig_h = odesin_sign_post(API_KEY, raw)
r = requests.post(
    f"{BASE}/api/payment/create-session",
    headers={"Content-Type": "application/json", "x-api-key": API_KEY, **sig_h},
    data=raw.encode("utf-8"),
)
r.raise_for_status()
checkout_url = r.json()["checkout_url"]

PHPcreate-session (kart / hosted)

<?php
$base = "https://odesin.com";
$apiKey = getenv('ODESIN_API_KEY') ?: '';
$payload = [
    'mode' => 'card',
    'amount' => 199.90,
    'currency' => 'TRY',
    'return_url' => 'https://magazaniz.com/tesekkur',
    'callback_url' => 'https://magazaniz.com/api/webhook',
    'customer_name' => 'Ali Veli',
    'customer_email' => 'ali@email.com',
    'customer_phone' => '05321234567',
    'description' => 'Sipariş #4521',
];
$body = json_encode($payload, JSON_UNESCAPED_UNICODE);
$ts = (string) time();
$sig = hash_hmac('sha256', $ts . "
POST
" . $body, $apiKey);
$ch = curl_init($base . '/api/payment/create-session');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => $body,
    CURLOPT_HTTPHEADER => [
        'Content-Type: application/json',
        'x-api-key: ' . $apiKey,
        'x-odesin-timestamp: ' . $ts,
        'x-odesin-signature: ' . $sig,
    ],
]);
$raw = curl_exec($ch);
curl_close($ch);
$data = json_decode($raw, true);
Kart girişi ve 3DS yönlendirmesi checkout_url üzerindeki Odesin sayfasında tamamlanır; sunucunuz kart PAN/CVV görmez.

Sık görülen hatalar

HTTPDurum
403Mağazada Sanal POS kapalı (pos_enabled)
400mode: "card" iken return_url eksik veya geçersiz gövde
401İstek imzası geçersiz, zaman damgası ±5 dk dışında veya imza başlıklarından yalnızca biri gönderildi
401API anahtarı eksik veya geçersiz
402 / 409 / 410Kart reddi, oturum uygun değil veya süre dolmuş