Sanal POS API Dokümantasyonu
Payment Hub, sanal POS entegrasyonlarını tek noktadan yönetmenizi sağlayan ödeme altyapı servisidir. 3D Secure, NonSecure, PreAuth/Capture ve taksitli ödeme işlemlerini destekler. Tüm işlemler REST tabanlı JSON API üzerinden gerçekleştirilir.
Postman Workspace'i Aç →
Erişim Adresleri
Tüm API istekleri HTTPS üzerinden yapılmalıdır.
Sandbox Test Kullanıcısı
00000000-0000-0000-0000-000000000000sandbox-secret-key-for-testing-purposes-only/api/v1/vpos/payments/ prefix'i ile başlar. Tüm istek ve yanıtlar UTF-8 kodlu JSON formatındadır.Endpoint Listesi
| Metod | Endpoint | Açıklama |
|---|---|---|
| POST | /api/v1/vpos/payments/payment | Ödeme başlatma (3D / NonSecure / PreAuth) |
| POST | /api/v1/vpos/payments/capture-pre-authorization | PreAuth capture işlemi |
| POST | /api/v1/vpos/payments/refund | İade işlemi |
| POST | /api/v1/vpos/payments/void | İptal işlemi |
| GET | /api/v1/vpos/payments/query/{transaction_id} | İşlem sorgulama |
| GET | /api/v1/vpos/payments/query-history/{transaction_id} | İşlem geçmişi sorgulama |
| GET | /api/v1/payments/transactions | İşlem listeleme ve filtreleme |
| GET | /api/v1/payments/balance | Hakediş sorgulama |
Kimlik Doğrulama
Tüm API istekleri için X-API-Key header'ı zorunludur.
Ayrıca her istekte hash imzası (X-Hash) gönderilmelidir.
Zorunlu Header'lar
| Header | Zorunlu | Açıklama |
|---|---|---|
| X-API-Key | Zorunlu | Merchant servisinden alınan API anahtarı |
| X-Hash | Zorunlu | İstek gövdesinden hesaplanan hash imzası (bkz. Hash Doğrulama) |
| Content-Type | Zorunlu | application/json |
POST /api/v1/vpos/payments/payment HTTP/1.1
Host: api.payment-hub.example.com
Content-Type: application/json
X-API-Key: your-api-key-here
X-Hash: 7f83b1657ff1fc53b92dc18148a1d65dfc2d4b1fa3d677284addd200126d906
Hash Doğrulama
Payment Hub, isteğin bütünlüğünü ve kaynağını doğrulamak için HMAC-SHA512 tabanlı hash imzası kullanır.
Hash Hesaplama Adımları
İstek gövdesindeki tüm alanları string değerlerine dönüştürün:
- Sayısal (int ve float):
%.2fformatında (örn.100.00,1.00,2025.00) - Boolean:
true/falsestring - Nested obje: JSON string olarak serialize edilir; obje key'leri alfabetik sıraya göre sıralanır (örn.
{"email":"[email protected]","first_name":"John","last_name":"Doe","phone":"+90..."}) - Dizi (array): JSON array string olarak serialize edilir; dizi içindeki objelerin key'leri de alfabetik sıralanır (örn.
[{"name":"Ürün 1","price":"299.90"},{"name":"Ürün 2","price":"149.90"}]) - Null / boş string: dahil edilmez
Tüm parametreler key'lerine göre alfabetik olarak sıralanır ve kompakt (boşluksuz) JSON.stringify ile tek bir string'e dönüştürülür. Örn: {"amount":"250.00","currency":"TRY","order_id":"ORDER-001"}
Oluşturulan JSON string'i üzerinden merchant secret key ile HMAC-SHA512 hash hesaplanır. Sonuç Base64 olarak encode edilip X-Hash header'ında gönderilir.
Kod Örnekleri
function sortKeysRecursive(array $data): array {
ksort($data);
foreach ($data as $key => $value) {
if (is_array($value)) {
$data[$key] = sortKeysRecursive($value);
}
}
return $data;
}
function toHashParam(mixed $value): ?string {
if ($value === null || $value === '') return null;
if (is_float($value) || is_int($value)) return number_format((float)$value, 2, '.', '');
if (is_bool($value)) return $value ? 'true' : 'false';
if (is_array($value)) return json_encode(sortKeysRecursive($value), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
return (string)$value;
}
function calculateHash(array $params, string $secretKey): string {
$strParams = [];
foreach ($params as $key => $value) {
$v = toHashParam($value);
if ($v !== null) $strParams[$key] = $v;
}
ksort($strParams); // alfabetik sırala
// Kompakt JSON string'e çevir (boş array'i {} olarak encode et)
$jsonString = empty($strParams)
? '{}'
: json_encode($strParams, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
// HMAC-SHA512, Base64 encode
return base64_encode(hash_hmac('sha512', $jsonString, $secretKey, true));
}
// Kullanım
$requestBody = [
'transaction_type' => 'Auth',
'order_id' => 'ORDER-12345',
'amount' => 100.00,
'currency' => 'TRY',
'installment' => 1,
'card_number' => '4355084355084358',
'card_holder_name' => 'John Doe',
'exp_year' => 2025,
'exp_month' => 12,
'cvv' => '000',
'is_3d' => false,
'customer_info' => [
'first_name' => 'John',
'last_name' => 'Doe',
'email' => '[email protected]',
'phone' => '+905551234567',
],
];
$hash = calculateHash($requestBody, 'your-secret-key');
// Header: X-Hash: {$hash}
package main
import (
"crypto/hmac"
"crypto/sha512"
"encoding/base64"
"encoding/json"
"fmt"
"sort"
)
// Nested map'leri key'lere göre alfabetik sıralanmış şekilde JSON'a çevirir
func sortedJSON(v interface{}) ([]byte, error) {
switch val := v.(type) {
case map[string]interface{}:
keys := make([]string, 0, len(val))
for k := range val {
keys = append(keys, k)
}
sort.Strings(keys)
buf := []byte{'{'}
for i, k := range keys {
keyBytes, _ := json.Marshal(k)
valBytes, err := sortedJSON(val[k])
if err != nil {
return nil, err
}
buf = append(buf, keyBytes...)
buf = append(buf, ':')
buf = append(buf, valBytes...)
if i < len(keys)-1 {
buf = append(buf, ',')
}
}
return append(buf, '}'), nil
case []interface{}:
buf := []byte{'['}
for i, item := range val {
itemBytes, err := sortedJSON(item)
if err != nil {
return nil, err
}
buf = append(buf, itemBytes...)
if i < len(val)-1 {
buf = append(buf, ',')
}
}
return append(buf, ']'), nil
default:
return json.Marshal(v)
}
}
// Parametreleri string map'e dönüştüren yardımcı fonksiyon
func buildParams(body map[string]interface{}) map[string]string {
result := make(map[string]string)
for k, v := range body {
switch val := v.(type) {
case string:
if val != "" {
result[k] = val
}
case float64:
result[k] = fmt.Sprintf("%.2f", val)
case int:
result[k] = fmt.Sprintf("%.2f", float64(val))
case int32:
result[k] = fmt.Sprintf("%.2f", float64(val))
case int64:
result[k] = fmt.Sprintf("%.2f", float64(val))
case bool:
result[k] = fmt.Sprintf("%t", val)
case map[string]interface{}:
// Nested obje: key'leri alfabetik sırala, JSON string'e çevir
b, err := sortedJSON(val)
if err == nil {
result[k] = string(b)
}
case []interface{}:
// Dizi: JSON string'e çevir (içindeki objelerin key'leri sıralanır)
b, err := sortedJSON(val)
if err == nil {
result[k] = string(b)
}
}
}
return result
}
func calculateHash(params map[string]string, secretKey string) string {
// Anahtarları alfabetik sıraya göre sırala
keys := make([]string, 0, len(params))
for k := range params {
keys = append(keys, k)
}
sort.Strings(keys)
// Sıralı map oluştur ve kompakt JSON'a çevir
ordered := make(map[string]string)
for _, k := range keys {
ordered[k] = params[k]
}
jsonBytes, _ := json.Marshal(ordered)
// HMAC-SHA512 hesapla, Base64 encode et
mac := hmac.New(sha512.New, []byte(secretKey))
mac.Write(jsonBytes)
return base64.StdEncoding.EncodeToString(mac.Sum(nil))
}
func main() {
body := map[string]interface{}{
"transaction_type": "Auth",
"order_id": "ORDER-12345",
"amount": 100.00,
"currency": "TRY",
"installment": float64(1),
"card_number": "4355084355084358",
"card_holder_name": "John Doe",
"exp_year": float64(2025),
"exp_month": float64(12),
"cvv": "000",
"is_3d": false,
"customer_info": map[string]interface{}{
"first_name": "John",
"last_name": "Doe",
"email": "[email protected]",
"phone": "+905551234567",
},
}
params := buildParams(body)
hash := calculateHash(params, "your-secret-key")
fmt.Println("X-Hash:", hash)
}
using System;
using System.Collections.Generic;
using System.Security.Cryptography;
using System.Text;
using System.Text.Encodings.Web;
using System.Text.Json;
public class PaymentHashHelper
{
// JSON serialize ederken unicode escape kullanmamak için gerekli ayar
private static readonly JsonSerializerOptions JsonOptions = new()
{
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
};
// Herhangi bir değeri kompakt JSON string'e çevirir (nested obje/dizi desteği)
private static string ToJsonValue(object value)
{
if (value is Dictionary<string, object> dict)
return SortedDictToJson(dict);
if (value is List<object> list)
return ListToJson(list);
return "\"" + value + "\"";
}
// Nested Dictionary'yi key'leri alfabetik sıralı kompakt JSON string'e çevirir
private static string SortedDictToJson(Dictionary<string, object> dict)
{
var sorted = new SortedDictionary<string, object>(dict);
var sb = new StringBuilder("{");
bool first = true;
foreach (var kvp in sorted)
{
if (!first) sb.Append(",");
sb.Append("\"").Append(kvp.Key).Append("\":");
sb.Append(ToJsonValue(kvp.Value));
first = false;
}
sb.Append("}");
return sb.ToString();
}
// List'i kompakt JSON array string'e çevirir
private static string ListToJson(List<object> list)
{
var sb = new StringBuilder("[");
bool first = true;
foreach (var item in list)
{
if (!first) sb.Append(",");
sb.Append(ToJsonValue(item));
first = false;
}
sb.Append("]");
return sb.ToString();
}
private static string ToHashParam(object value)
{
if (value == null) return null;
return value switch
{
double d => d.ToString("F2", System.Globalization.CultureInfo.InvariantCulture),
float f => f.ToString("F2", System.Globalization.CultureInfo.InvariantCulture),
int i => ((double)i).ToString("F2", System.Globalization.CultureInfo.InvariantCulture),
long l => ((double)l).ToString("F2", System.Globalization.CultureInfo.InvariantCulture),
bool b => b.ToString().ToLower(),
Dictionary<string, object> dict => SortedDictToJson(dict),
List<object> list => ListToJson(list),
string s when string.IsNullOrEmpty(s) => null,
_ => value.ToString()
};
}
public static string CalculateHash(Dictionary<string, object> parameters, string secretKey)
{
// Parametreleri string'e dönüştür ve alfabetik sırala
var strParams = new SortedDictionary<string, string>();
foreach (var kvp in parameters)
{
var v = ToHashParam(kvp.Value);
if (v != null) strParams[kvp.Key] = v;
}
// Kompakt JSON string'e çevir (unicode escape olmadan)
var jsonString = JsonSerializer.Serialize(strParams, JsonOptions);
// HMAC-SHA512 hesapla, Base64 encode et
using var hmac = new HMACSHA512(Encoding.UTF8.GetBytes(secretKey));
var hashBytes = hmac.ComputeHash(Encoding.UTF8.GetBytes(jsonString));
return Convert.ToBase64String(hashBytes);
}
}
// Kullanım
var parameters = new Dictionary<string, object>
{
{ "transaction_type", "Auth" },
{ "order_id", "ORDER-12345" },
{ "amount", 100.00 },
{ "currency", "TRY" },
{ "installment", 1 },
{ "card_number", "4355084355084358" },
{ "card_holder_name", "John Doe" },
{ "exp_year", 2025 },
{ "exp_month", 12 },
{ "cvv", "000" },
{ "is_3d", false },
{ "customer_info", new Dictionary<string, object>
{
{ "first_name", "John" },
{ "last_name", "Doe" },
{ "email", "[email protected]" },
{ "phone", "+905551234567" },
}
},
};
string hash = PaymentHashHelper.CalculateHash(parameters, "your-secret-key");
// Header: X-Hash: {hash}
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.Base64;
public class PaymentHashHelper {
// Herhangi bir değeri kompakt JSON string'e çevirir (nested obje/dizi desteği)
@SuppressWarnings("unchecked")
private static String toJson(Object value) {
if (value instanceof Map) {
Map<String, Object> map = (Map<String, Object>) value;
TreeMap<String, Object> sorted = new TreeMap<>(map);
StringBuilder sb = new StringBuilder("{");
boolean first = true;
for (Map.Entry<String, Object> e : sorted.entrySet()) {
if (!first) sb.append(",");
sb.append("\"").append(e.getKey()).append("\":").append(toJson(e.getValue()));
first = false;
}
sb.append("}");
return sb.toString();
} else if (value instanceof List) {
List<?> list = (List<?>) value;
StringBuilder sb = new StringBuilder("[");
boolean first = true;
for (Object item : list) {
if (!first) sb.append(",");
sb.append(toJson(item));
first = false;
}
sb.append("]");
return sb.toString();
} else if (value instanceof String) {
return "\"" + value + "\"";
} else if (value instanceof Boolean) {
return value.toString();
} else if (value instanceof Integer || value instanceof Long) {
return String.valueOf(((Number) value).longValue());
} else if (value instanceof Double || value instanceof Float) {
double d = ((Number) value).doubleValue();
if (d == Math.floor(d) && !Double.isInfinite(d))
return String.valueOf((long) d);
return String.valueOf(d);
}
return "\"" + value + "\"";
}
@SuppressWarnings("unchecked")
private static String toHashParam(Object value) {
if (value == null) return null;
if (value instanceof Double || value instanceof Float)
return String.format("%.2f", value);
if (value instanceof Integer || value instanceof Long)
return String.format("%.2f", ((Number) value).doubleValue());
if (value instanceof Boolean)
return value.toString();
if (value instanceof Map || value instanceof List)
return toJson(value);
String s = value.toString();
return s.isEmpty() ? null : s;
}
public static String calculateHash(Map<String, Object> params, String secretKey) throws Exception {
// Parametreleri String map'e dönüştür, TreeMap alfabetik sıralar
Map<String, String> strParams = new TreeMap<>();
for (Map.Entry<String, Object> entry : params.entrySet()) {
String v = toHashParam(entry.getValue());
if (v != null) strParams.put(entry.getKey(), v);
}
// Kompakt JSON string'e çevir (value içindeki " ve \ karakterlerini escape et)
StringBuilder json = new StringBuilder("{");
boolean first = true;
for (Map.Entry<String, String> e : strParams.entrySet()) {
if (!first) json.append(",");
String escaped = e.getValue().replace("\\", "\\\\").replace("\"", "\\\"");
json.append("\"").append(e.getKey()).append("\":\"").append(escaped).append("\"");
first = false;
}
json.append("}");
String jsonString = json.toString();
// HMAC-SHA512 hesapla, Base64 encode et
Mac mac = Mac.getInstance("HmacSHA512");
SecretKeySpec keySpec = new SecretKeySpec(
secretKey.getBytes(StandardCharsets.UTF_8), "HmacSHA512"
);
mac.init(keySpec);
byte[] hashBytes = mac.doFinal(jsonString.getBytes(StandardCharsets.UTF_8));
return Base64.getEncoder().encodeToString(hashBytes);
}
public static void main(String[] args) throws Exception {
Map<String, Object> requestBody = new LinkedHashMap<>();
requestBody.put("transaction_type", "Auth");
requestBody.put("order_id", "ORDER-12345");
requestBody.put("amount", 100.00);
requestBody.put("currency", "TRY");
requestBody.put("installment", 1);
requestBody.put("card_number", "4355084355084358");
requestBody.put("card_holder_name", "John Doe");
requestBody.put("exp_year", 2025);
requestBody.put("exp_month", 12);
requestBody.put("cvv", "000");
requestBody.put("is_3d", false);
Map<String, Object> customerInfo = new LinkedHashMap<>();
customerInfo.put("first_name", "John");
customerInfo.put("last_name", "Doe");
customerInfo.put("email", "[email protected]");
customerInfo.put("phone", "+905551234567");
requestBody.put("customer_info", customerInfo);
String hash = calculateHash(requestBody, "your-secret-key");
System.out.println("X-Hash: " + hash);
}
}
const crypto = require('crypto');
// Nested objelerin key'lerini recursive olarak alfabetik sıralar
function sortObjectRecursively(obj) {
if (obj === null || typeof obj !== 'object') return obj;
if (Array.isArray(obj)) return obj.map(sortObjectRecursively);
const sorted = {};
Object.keys(obj).sort().forEach(k => { sorted[k] = sortObjectRecursively(obj[k]); });
return sorted;
}
function toHashParam(value) {
if (value === null || value === undefined || value === '') return null;
if (typeof value === 'number') return value.toFixed(2);
if (typeof value === 'boolean') return String(value);
if (typeof value === 'object') return JSON.stringify(sortObjectRecursively(value));
return String(value);
}
function calculateHash(params, secretKey) {
// Parametreleri string'e dönüştür ve null/boş değerleri çıkar
const strParams = {};
for (const [key, value] of Object.entries(params)) {
const v = toHashParam(value);
if (v !== null) strParams[key] = v;
}
// Alfabetik sıraya göre sırala ve kompakt JSON'a çevir
const sortedKeys = Object.keys(strParams).sort();
const sorted = {};
sortedKeys.forEach(k => { sorted[k] = strParams[k]; });
const jsonString = JSON.stringify(sorted);
// HMAC-SHA512 hesapla, Base64 encode et
return crypto
.createHmac('sha512', secretKey)
.update(jsonString)
.digest('base64');
}
// Kullanım
const requestBody = {
transaction_type: 'Auth',
order_id: 'ORDER-12345',
amount: 100.00,
currency: 'TRY',
installment: 1,
card_number: '4355084355084358',
card_holder_name: 'John Doe',
exp_year: 2025,
exp_month: 12,
cvv: '000',
is_3d: false,
customer_info: {
first_name: 'John',
last_name: 'Doe',
email: '[email protected]',
phone: '+905551234567',
},
};
const hash = calculateHash(requestBody, 'your-secret-key');
console.log('X-Hash:', hash);
// Fetch ile kullanım örneği
async function makePayment(body, apiKey, secretKey) {
const hash = calculateHash(body, secretKey);
const response = await fetch('https://api.payment-hub.example.com/api/v1/vpos/payments/payment', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-Key': apiKey,
'X-Hash': hash,
},
body: JSON.stringify(body),
});
return response.json();
}
Request Parametreleri
Ödeme İsteği – PaymentRequest
POST /api/v1/vpos/payments/payment endpoint'i için kullanılır.
| Alan | Tip | Zorunlu | Açıklama | Örnek |
|---|---|---|---|---|
| transaction_type | string | Evet | Auth (satış) veya PreAuth (ön otorizasyon) |
Auth |
| order_id | string | Evet | Benzersiz sipariş numarası | ORDER-12345 |
| amount | float64 | Evet | Ödeme tutarı (0'dan büyük olmalı) | 100.00 |
| currency | string | Evet | TRY, USD, EUR, GBP, CHF, JPY |
TRY |
| installment | int32 | Evet | Taksit sayısı (1 = peşin, 2-12 = taksitli) | 1 |
| card_number | string | Evet | 16 haneli kart numarası | 4355084355084358 |
| card_holder_name | string | Evet | Kart üzerindeki isim | John Doe |
| exp_year | int32 | Evet | Son kullanma yılı (4 haneli) | 2025 |
| exp_month | int32 | Evet | Son kullanma ayı (1–12) | 12 |
| cvv | string | Evet | Kart güvenlik kodu (3 hane) | 000 |
| is_3d | bool | Hayır | true = 3D Secure, false = NonSecure (varsayılan: true) |
true |
| ok_url | string | Hayır | 3D başarı dönüş URL'si (is_3d=true ise önerilir) | https://site.com/ok |
| fail_url | string | Hayır | 3D hata dönüş URL'si (is_3d=true ise önerilir) | https://site.com/fail |
| sub_merchant_id | string | Hayır | Alt üye işyeri ID'si (terminal bazı alt merchant gerektiriyorsa zorunlu) | SUBM-12345 |
| customer_info | object | Hayır | Müşteri bilgileri (detay aşağıda) | – |
Müşteri Bilgileri – CustomerInfo
customer_info objesi içinde gönderilebilecek alanlar:
| Alan | Tip | Zorunlu | Açıklama | Örnek |
|---|---|---|---|---|
| first_name | string | Hayır | Müşteri adı | John |
| last_name | string | Hayır | Müşteri soyadı | Doe |
| string | Hayır | Müşteri e-posta adresi | [email protected] |
|
| phone | string | Hayır | Müşteri telefon numarası | +905551234567 |
İptal İsteği – VoidRequest
| Alan | Tip | Zorunlu | Açıklama |
|---|---|---|---|
| order_id | string | Evet | İptal edilecek siparişin order_id değeri |
| transaction_id | string (UUID) | Evet | İptal edilecek işlem ID'si |
| sub_merchant_id | string | Hayır | Alt üye işyeri ID'si |
İade İsteği – RefundRequest
| Alan | Tip | Zorunlu | Açıklama |
|---|---|---|---|
| order_id | string | Evet | İade edilecek siparişin order_id değeri |
| transaction_id | string (UUID) | Evet | İade edilecek işlem ID'si |
| amount | float64 | Hayır | İade tutarı. Belirtilmezse tam iade yapılır |
| sub_merchant_id | string | Hayır | Alt üye işyeri ID'si |
Capture İsteği – CapturePreAuthorizationRequest
| Alan | Tip | Zorunlu | Açıklama |
|---|---|---|---|
| order_id | string | Evet | Sipariş numarası |
| transaction_id | string (UUID) | Evet | PreAuth işlem ID'si |
| amount | float64 | Evet | Capture edilecek tutar (PreAuth tutarını aşamaz) |
| sub_merchant_id | string | Hayır | Alt üye işyeri ID'si |
BIN Sorgulama
GET /api/v1/vpos/bins/query – Kartın ilk 8 hanesiyle BIN bilgisi sorgulanır.
| Alan | Tip | Zorunlu | Açıklama |
|---|---|---|---|
| bin | string | Evet | Kartın ilk 8 hanesi (query parameter) |
Taksit Seçenekleri ve Komisyonlar
POST /api/v1/vpos/payments/payment-options-with-amounts – BIN ve tutar bilgisiyle taksit seçenekleri sorgulanır.
| Alan | Tip | Zorunlu | Açıklama |
|---|---|---|---|
| bin | string | Evet | Kartın ilk 8 hanesi |
| amount | float64 | Evet | İşlem tutarı (0'dan büyük olmalı) |
| mcc_code | string | Hayır | MCC kodu filtresi |
| apply_surcharge_single | bool | Hayır | Peşin ödemede vade farkı uygula |
| apply_surcharge_installment | bool | Hayır | Taksitli ödemede vade farkı uygula |
İşlem Sorgulama
GET /api/v1/vpos/payments/query/{transaction_id} ve
GET /api/v1/vpos/payments/query-history/{transaction_id} – İşlem durumu veya geçmişi sorgulanır.
| Alan | Tip | Zorunlu | Açıklama |
|---|---|---|---|
| transaction_id | string (UUID) | Evet | Sorgulanacak işlemin ID'si (path parameter) |
İşlem Listeleme
GET /api/v1/payments/transactions – İşlemleri filtreler ve listeler. X-API-Key + X-Hash gerektirir.
| Parametre | Tip | Zorunlu | Açıklama |
|---|---|---|---|
| offset | int | Hayır | Başlangıç indeksi (varsayılan: 0) |
| limit | int | Hayır | Sayfa başına kayıt (maks 100, varsayılan: 50) |
| start_date | string (ISO 8601) | Hayır | Başlangıç tarihi filtresi |
| end_date | string (ISO 8601) | Hayır | Bitiş tarihi filtresi |
| status | string | Hayır | APPROVED, DECLINED, ERROR, CANCELLED, PENDING |
| transaction_type | string | Hayır | SALE_SECURE, SALE_NON_SECURE, PRE_AUTH_SECURE, PRE_AUTH_NON_SECURE, POST_AUTH, REFUND, VOID |
| amount_min | string | Hayır | Minimum tutar filtresi |
| amount_max | string | Hayır | Maksimum tutar filtresi |
| currency | string | Hayır | Para birimi filtresi (TRY, USD, EUR, vb.) |
| order_id | string | Hayır | Sipariş numarası ile arama |
| card_mask | string | Hayır | Maskelenmiş kart numarası ile arama |
| rrn | string | Hayır | Retrieval Reference Number ile arama |
| auth_code | string | Hayır | Provizyon kodu ile arama |
Hakediş Sorgulama
GET /api/v1/payments/balance – Merchant hakediş bilgisini sorgular. X-API-Key + X-Hash gerektirir.
| Parametre | Tip | Zorunlu | Açıklama |
|---|---|---|---|
| start_date | string | Evet | Başlangıç tarihi (YYYY-MM-DD) |
| end_date | string | Evet | Bitiş tarihi (YYYY-MM-DD) |
| currency | string | Hayır | Para birimi filtresi (TRY, USD, EUR, vb.) |
| source | string | Hayır | İşlem kaynağı filtresi (VPOS vb.) |
Oturum Oluşturma – Payment Session
POST /api/v1/sessions – Tek kullanımlık ödeme oturumu oluşturur. X-API-Key + X-Hash gerektirir.
| Alan | Tip | Zorunlu | Açıklama |
|---|---|---|---|
| amount | float64 | Evet | Ödeme tutarı |
| currency | string | Evet | TRY, USD, EUR, GBP, CHF, JPY |
| order_id | string | Evet | Benzersiz sipariş numarası |
| ok_url | string | Hayır | Başarı dönüş URL'si |
| fail_url | string | Hayır | Hata dönüş URL'si |
| customer_info | object | Hayır | first_name, last_name, email, phone |
| metadata | object | Hayır | Serbest formatta ek veri |
| installment | bool | Hayır | Taksitli ödemeye izin ver (varsayılan: false) |
| allowed_installments | array<int> | Hayır | İzin verilen taksit sayıları (ör. [2, 3, 6, 9, 12]). installment: true olduğunda geçerlidir |
Ödeme Linki Oluşturma
POST /api/v1/merchant/payment-links – Yeni ödeme linki oluşturur. X-API-Key + X-Hash gerektirir.
| Alan | Tip | Zorunlu | Açıklama |
|---|---|---|---|
| title | string | Evet | Link başlığı |
| currency | string | Evet | TRY, USD, EUR, GBP, CHF, JPY |
| products | array | Evet | En az 1 ürün zorunludur |
| products[].price | float64 | Evet | Ürün birim fiyatı |
| products[].default_quantity | int | Hayır | Varsayılan miktar (min 1) |
| products[].display_order | int | Hayır | Ürünün görüntüleme sırası |
| products[].name | string | Hayır | Ürün adı |
| products[].sku | string | Hayır | Stok kodu |
| products[].image_url | string | Hayır | Ürün görseli URL'si |
| description | string | Hayır | Link açıklaması |
| expires_at | datetime | Hayır | Son geçerlilik tarihi (ISO 8601) |
| max_uses | int | Hayır | Maksimum kullanım sayısı |
| ok_url | string | Hayır | Başarı dönüş URL'si |
| fail_url | string | Hayır | Hata dönüş URL'si |
| require_3ds | bool | Hayır | 3D Secure zorunlu mu? |
| allow_non_3ds | bool | Hayır | 3D Secure olmadan ödemeye izin ver |
| installment | bool | Hayır | Taksitli ödemeye izin ver (varsayılan: false) |
| allowed_installments | array<int> | Hayır | İzin verilen taksit sayıları (ör. [2, 3, 6, 9, 12]). installment: true olduğunda geçerlidir |
Ödeme Linki Listeleme
GET /api/v1/merchant/payment-links – Ödeme linklerini listeler. X-API-Key + X-Hash gerektirir.
| Parametre | Tip | Zorunlu | Açıklama |
|---|---|---|---|
| page | int | Hayır | Sayfa numarası (varsayılan: 1) |
| limit | int | Hayır | Sayfa başına kayıt (maks 100) |
| status | string | Hayır | ACTIVE, INACTIVE, EXPIRED, COMPLETED |
| search | string | Hayır | Başlık veya link kodu ile arama |
| currency | string | Hayır | Para birimi filtresi |
Koleksiyon Oluşturma
POST /api/v1/merchant/collections – Serbest tutarlı ödeme sayfası oluşturur. X-API-Key + X-Hash gerektirir.
| Alan | Tip | Zorunlu | Açıklama |
|---|---|---|---|
| title | string | Evet | Koleksiyon başlığı |
| currency | string | Evet | TRY, USD, EUR, GBP, CHF, JPY |
| description | string | Hayır | Açıklama metni |
| min_amount | float64 | Hayır | Minimum ödeme tutarı |
| max_amount | float64 | Hayır | Maksimum ödeme tutarı |
| expires_at | datetime | Hayır | Son geçerlilik tarihi (ISO 8601) |
| max_uses | int | Hayır | Maksimum kullanım sayısı |
| ok_url / fail_url | string | Hayır | Dönüş URL'leri |
| require_3ds | bool | Hayır | 3D Secure zorunlu mu? |
| allow_non_3ds | bool | Hayır | 3D Secure olmadan ödemeye izin ver |
| installment | bool | Hayır | Taksitli ödemeye izin ver (varsayılan: false) |
| allowed_installments | array<int> | Hayır | İzin verilen taksit sayıları (ör. [2, 3, 6, 9, 12]). installment: true olduğunda geçerlidir |
Koleksiyon Listeleme
GET /api/v1/merchant/collections – Koleksiyonları listeler. X-API-Key + X-Hash gerektirir.
| Parametre | Tip | Zorunlu | Açıklama |
|---|---|---|---|
| page | int | Hayır | Sayfa numarası (varsayılan: 1) |
| limit | int | Hayır | Sayfa başına kayıt (maks 100) |
| status | string | Hayır | ACTIVE, INACTIVE, EXPIRED |
| search | string | Hayır | Başlık veya link kodu ile arama |
| currency | string | Hayır | Para birimi filtresi |
Response Parametreleri
Ödeme Yanıtı – PaymentResponse
| Alan | Tip | Açıklama |
|---|---|---|
| success | boolean | İşlem başarı durumu |
| payload | object | Yanıt verilerini içeren ana nesne |
| payload.transaction_id | string (UUID) | Payment Hub tarafından atanan benzersiz işlem ID'si |
| payload.order_id | string | İstekte gönderilen order_id değeri |
| payload.html | string | 3D Secure işlemlerde banka 3D form HTML'i. Bu içerik sayfaya embed edilmelidir |
| payload.html_url | string | 3D Secure için yönlendirme URL'si (15 dakika geçerli) |
| payload.amount_info | object | İşlem tutar bilgileri (bkz. AmountInfo) |
| payload.gateway_response | object | Payment Hub gateway yanıtı (code, message_tr, message_en) |
| payload.bank_response | object | Banka yanıtı (code, message, auth_code, rrn) |
| payload.date | string | İşlem tarihi ve saati (ISO 8601) |
AmountInfo
| Alan | Tip | Açıklama |
|---|---|---|
| amount | float64 | İşlem tutarı |
| currency | string | İşlem para birimi |
| installment | int | Taksit sayısı |
| original_amount | float64 | Orijinal tutar |
| original_currency | string | Orijinal para birimi |
| exchange_rate | float64 | Döviz kuru (TRY bazlı) |
| base_amount | float64 | TRY cinsinden tutar |
| base_currency | string | TRY |
GatewayResponse
| Alan | Tip | Açıklama |
|---|---|---|
| code | string | Gateway yanıt kodu (00 = başarılı) |
| message_tr | string | Türkçe mesaj |
| message_en | string | İngilizce mesaj |
| detail_tr | string | Türkçe detay mesajı |
| detail_en | string | İngilizce detay mesajı |
BankResponse
| Alan | Tip | Açıklama |
|---|---|---|
| code | string | Banka yanıt kodu |
| message | string | Banka mesajı |
| auth_code | string | Provizyon / otorizasyon kodu |
| rrn | string | Retrieval Reference Number |
3D Secure Callback Parametreleri
3D doğrulama tamamlandıktan sonra aşağıdaki alanlar application/x-www-form-urlencoded olarak
ok_url (başarı) veya fail_url (başarısızlık) adresine HTTP POST ile gönderilir.
Bu yapı hem 3D Secure Ödeme hem de PreAuth 3D işlemleri için geçerlidir.
| Alan | Format | Açıklama |
|---|---|---|
| success | string | true veya false |
| transaction_id | string (UUID) | İşlem ID'si |
| order_id | string | Sipariş numarası |
| amount | string (%.4f) | İşlem tutarı — örn. 150.0000 |
| currency | string | İşlem para birimi |
| installment | string (%d) | Taksit sayısı |
| gateway_response_code | string | Gateway yanıt kodu (00 = başarılı) |
| gateway_response_message | string | Gateway mesajı (Türkçe) |
| bank_response_code | string | Banka yanıt kodu |
| bank_response_message | string | Banka mesajı |
| rrn | string | Retrieval Reference Number |
| auth_code | string | Provizyon kodu |
| bank_code | string | Banka kodu |
| date | string (RFC3339) | İşlem tamamlanma zamanı |
Oturum Oluşturma Yanıtı
POST /api/v1/sessions başarılı yanıtı.
| Alan | Tip | Açıklama |
|---|---|---|
| success | boolean | İşlem başarı durumu |
| payload | object | Yanıt verilerini içeren ana nesne |
| payload.session_id | string | Oluşturulan oturum ID'si |
| payload.session_url | string | Müşteriye gönderilecek ödeme sayfası URL'si |
| payload.expires_at | string (ISO 8601) | Oturumun son geçerlilik zamanı |
Ödeme Linki Yanıtı
POST /api/v1/merchant/payment-links ve tekil getirme endpoint'lerinin yanıt yapısı.
| Alan | Tip | Açıklama |
|---|---|---|
| id | string (UUID) | Link benzersiz ID'si |
| merchant_name | string | Merchant adı |
| link_code | string | Benzersiz link kodu (ör. PAY-XZ7Y3K) |
| link_url | string | Müşteriye gönderilecek ödeme linki URL'si |
| title | string | Link başlığı |
| description | string | Link açıklaması |
| total_amount | float64 | Toplam tutar |
| currency | string | Para birimi |
| status | string | ACTIVE, INACTIVE, EXPIRED, COMPLETED |
| expires_at | string | Son geçerlilik tarihi |
| max_uses | int | Maksimum kullanım sayısı |
| used_count | int | Kaç kez kullanıldı |
| require_3ds | boolean | 3D Secure zorunlu mu? |
| allow_non_3ds | boolean | 3D olmadan ödemeye izin var mı? |
| installment | boolean | Taksitli ödemeye izin var mı? |
| allowed_installments | array<int> | İzin verilen taksit sayıları (ör. [2, 3, 6, 9, 12]) |
| products | array | Ürün listesi (id, name, price, default_quantity, sku, subtotal) |
| qr_code_url | string | QR kod görseli URL'si |
| created_at | string | Oluşturulma tarihi (ISO 8601) |
Koleksiyon Yanıtı
POST /api/v1/merchant/collections ve tekil getirme endpoint'lerinin yanıt yapısı.
| Alan | Tip | Açıklama |
|---|---|---|
| id | string (UUID) | Koleksiyon benzersiz ID'si |
| merchant_name | string | Merchant adı |
| link_code | string | Benzersiz link kodu (ör. COL-AB3CD9) |
| link_url | string | Müşteriye gönderilecek koleksiyon URL'si |
| title | string | Koleksiyon başlığı |
| description | string | Açıklama |
| currency | string | Para birimi |
| min_amount | float64 | Minimum ödeme tutarı |
| max_amount | float64 | Maksimum ödeme tutarı |
| status | string | ACTIVE, INACTIVE, EXPIRED |
| expires_at | string | Son geçerlilik tarihi |
| max_uses | int | Maksimum kullanım sayısı |
| used_count | int | Kaç kez kullanıldı |
| require_3ds | boolean | 3D Secure zorunlu mu? |
| allow_non_3ds | boolean | 3D olmadan ödemeye izin var mı? |
| installment | boolean | Taksitli ödemeye izin var mı? |
| allowed_installments | array<int> | İzin verilen taksit sayıları (ör. [2, 3, 6, 9, 12]) |
| qr_code_url | string | QR kod görseli URL'si |
| created_at | string | Oluşturulma tarihi (ISO 8601) |
İşlem Listesi Yanıtı
GET /api/v1/payments/transactions yanıt yapısı.
Temel Bilgiler
| Alan | Tip | Açıklama |
|---|---|---|
| payload[] | array | İşlem kayıtları listesi |
| payload[].id | string (UUID) | İşlem ID'si |
| payload[].order_id | string | Sipariş numarası |
| payload[].merchant_id | string (UUID) | Merchant ID |
| payload[].merchant_name | string | Merchant adı |
| payload[].parent_id | string (UUID) | Üst işlem ID'si (iade/iptal için) |
| payload[].status | string | APPROVED, DECLINED, ERROR, CANCELLED, PENDING |
| payload[].transaction_type | string | SALE_SECURE, SALE_NON_SECURE, PRE_AUTH_SECURE, PRE_AUTH_NON_SECURE, POST_AUTH, REFUND, VOID |
| payload[].transaction_source | string | İşlem kaynağı (VIRTUAL_POS vb.) |
| payload[].transaction_channel | string | İşlem kanalı (VIRTUAL_LINK, VIRTUAL_API, VIRTUAL_COLLECTION vb.) |
| payload[].fraud_status | string | Fraud kontrol durumu (ACCEPT, REJECT vb.) |
Tutar & Döviz
| Alan | Tip | Açıklama |
|---|---|---|
| payload[].amount | float64 | İşlem tutarı |
| payload[].currency | string | İşlem para birimi |
| payload[].original_amount | float64 | Orijinal tutar (döviz çevrimi öncesi) |
| payload[].original_currency | string | Orijinal para birimi |
| payload[].base_amount | float64 | TRY cinsinden tutar |
| payload[].base_currency | string | Baz para birimi (TRY) |
| payload[].exchange_rate | float64 | Uygulanan döviz kuru |
| payload[].installment | int | Taksit sayısı |
| payload[].is_installment | boolean | Taksitli işlem mi? |
Kart Bilgileri
| Alan | Tip | Açıklama |
|---|---|---|
| payload[].card_number_masked | string | Maskelenmiş kart numarası |
| payload[].card_holder_name | string | Kart sahibi adı |
| payload[].card_brand | string | Kart markası (SHOPFLY, MAXIMUM, BONUS, AXESS, BANKART_COMBO vb.) |
| payload[].card_type | string | Kart tipi (KREDI_KARTI, BANKA_KARTI) |
| payload[].card_bank_code | string | Kartı veren banka kodu |
| payload[].card_bank_name | string | Kartı veren banka adı |
| payload[].bin_number | string | BIN numarası |
Banka & Provizyon
| Alan | Tip | Açıklama |
|---|---|---|
| payload[].rrn | string | Retrieval Reference Number |
| payload[].auth_code | string | Provizyon kodu |
| payload[].bank_response_code | string | Banka yanıt kodu |
| payload[].bank_response_message | string | Banka yanıt mesajı |
| payload[].payment_gateway_code | string | Payment gateway yanıt kodu |
| payload[].payment_gateway_message | string | Payment gateway yanıt mesajı |
Finansal Bilgiler
| Alan | Tip | Açıklama |
|---|---|---|
| payload[].merchant_commission_rate | float64 | Uygulanan komisyon oranı (%) |
| payload[].merchant_payout_amount | float64 | Merchant hakediş tutarı |
| payload[].transaction_fee | float64 | İşlem ücreti |
Müşteri & Terminal
| Alan | Tip | Açıklama |
|---|---|---|
| payload[].customer_first_name | string | Müşteri adı |
| payload[].customer_last_name | string | Müşteri soyadı |
| payload[].customer_email | string | Müşteri e-posta |
| payload[].customer_phone | string | Müşteri telefon |
| payload[].terminal_no | string | Terminal numarası |
| payload[].terminal_bank_code | string | Terminal banka kodu |
| payload[].terminal_bank_name | string | Terminal banka adı |
| payload[].webhook_status | string | Webhook gönderim durumu |
Tarihler
| Alan | Tip | Açıklama |
|---|---|---|
| payload[].created_at | string (ISO 8601) | Oluşturulma zamanı |
| payload[].updated_at | string (ISO 8601) | Son güncelleme zamanı |
| payload[].processed_at | string (ISO 8601) | İşlenme zamanı |
| payload[].completed_at | string (ISO 8601) | Tamamlanma zamanı |
Detay Objeleri (opsiyonel)
| Alan | Tip | Açıklama |
|---|---|---|
| payload[].virtual_pos_details | object | Sanal POS detayları (sub_merchant_id, ok_url, fail_url, link_code, collection_code) |
| payload[].physical_pos_details | object | Fiziksel POS detayları (device_serial_no, batch_number, entry_mode vb.) |
| payload[].soft_pos_details | object | SoftPOS detayları (device_id, sdk_version, os_type vb.) |
Hakediş Sorgulama Yanıtı
GET /api/v1/payments/balance yanıt yapısı.
| Alan | Tip | Açıklama |
|---|---|---|
| start_date | string | Sorgulanan başlangıç tarihi |
| end_date | string | Sorgulanan bitiş tarihi |
| balances[] | array | Para birimi ve kaynak bazında hakediş listesi |
| balances[].currency | string | Para birimi |
| balances[].source | string | İşlem kaynağı (VPOS vb.) |
| balances[].sale | object | Satış toplamları (count, amount, base_amount) |
| balances[].post_auth | object | Ön provizyon kapama toplamları (count, amount, base_amount) |
| balances[].refund | object | İade toplamları (count, amount, base_amount) |
| balances[].void | object | İptal toplamları (count, amount, base_amount) |
| balances[].pre_auth_pending | object | Bekleyen ön provizyon toplamları (count, amount, base_amount) |
| balances[].failed | object | Başarısız işlem toplamları (count, amount, base_amount) |
| balances[].net_amount | float64 | Net tutar (işlem para biriminde) |
| balances[].net_base_amount | float64 | Net tutar (baz para biriminde) |
| balances[].total_count | int | Toplam işlem adedi |
| balances[].success_rate | float64 | Başarı oranı (%) |
| balances[].financial | object | Finansal özet |
| balances[].financial.total_commission | float64 | Toplam komisyon |
| balances[].financial.total_merchant_payout | float64 | Toplam merchant hakediş |
| balances[].financial.total_transaction_fee | float64 | Toplam işlem ücreti |
| totals | object | Genel toplamlar |
| totals.total_count | int | Toplam işlem adedi |
| totals.net_base_amount | float64 | Toplam net tutar (baz para biriminde) |
| totals.total_merchant_payout_base | float64 | Toplam merchant hakediş (baz para biriminde) |
| totals.success_rate | float64 | Genel başarı oranı (%) |
Sayfalama (Pagination)
Liste endpoint'lerinin (GET .../payment-links, GET .../collections) yanıtında
pagination nesnesi döner.
| Alan | Tip | Açıklama |
|---|---|---|
| total | int | Toplam kayıt sayısı |
| limit | int | Sayfa başına kayıt sayısı |
| offset | int | Başlangıç kayıt indeksi |
| current_page | int | Mevcut sayfa numarası |
| total_pages | int | Toplam sayfa sayısı |
GET /api/v1/payments/transactions endpoint'i farklı bir pagination yapısı kullanır:
| Alan | Tip | Açıklama |
|---|---|---|
| total | int64 | Toplam kayıt sayısı |
| limit | int | Sayfa başına kayıt sayısı |
| offset | int | Başlangıç kayıt indeksi |
| hasNext | boolean | Sonraki sayfa var mı? |
| hasPrev | boolean | Önceki sayfa var mı? |
3D Secure Ödeme
3D Secure işlemlerde müşteri, banka tarafından kimlik doğrulamasına yönlendirilir.
İlk yanıt olarak dönen html alanı sayfaya eklenmeli veya html_url adresine yönlendirme yapılmalıdır.
Ödeme sonucu, 3D doğrulama tamamlandıktan sonra ok_url veya fail_url'e
HTTP POST (form) olarak iletilir.
ok_url ve fail_url gönderilmezse sistem varsayılan callback URL'ini kullanır.
Bu URL'lerde application/x-www-form-urlencoded POST verisi alacak şekilde hazır olunmalıdır.html_url 15 dakika geçerlidir. Süresi dolduktan sonra erişilemez.{
"transaction_type": "Auth",
"order_id": "ORDER-12345",
"amount": 150.00,
"currency": "TRY",
"installment": 1,
"card_number": "4355084355084358",
"card_holder_name": "John Doe",
"exp_year": 2026,
"exp_month": 12,
"cvv": "000",
"is_3d": true,
"ok_url": "https://yoursite.com/payment/success",
"fail_url": "https://yoursite.com/payment/fail",
"customer_info": {
"first_name": "John",
"last_name": "Doe",
"email": "[email protected]",
"phone": "+905551234567"
}
}
{
"success": true,
"payload": {
"transaction_id": "d4de0c6a-c51f-4aff-bf75-4989c9204bdc",
"order_id": "ORDER-12345",
"html": "<!DOCTYPE html><html>...3D Secure Form HTML...</html>",
"html_url": "https://payment-hub.example.com/api/v1/vpos/payments/3d-secure/a8f2e4b1-7c3d-49e5-b6a0-1d2f3e4a5b6c",
"date": "2024-01-15T14:30:00Z"
}
}
gateway_response ve bank_response bu aşamada dönmez.
Ödeme sonucu, 3D doğrulama tamamlandıktan sonra ok_url / fail_url'e iletilir.3D Secure Akış Diyagramı
1. Müşteri ödeme formunu doldurur
2. Sizin sunucunuz → POST /api/v1/vpos/payments/payment (is_3d: true, ok_url, fail_url)
3. Payment Hub → { success: true, payload: { transaction_id, html, html_url, ... } }
4. Sizin sunucunuz → html_url'e yönlendirme yapar veya html içeriğini render eder
⚠ html_url token-based'dir (15 dk geçerli), transaction ID içermez
5. Tarayıcı → Bankanın 3D sayfasına yönlendirilir
6. Müşteri → OTP / 3D doğrulamayı tamamlar
7. Payment Hub → 3D sonucunu işler ve ödemeyi tamamlar
8. Tarayıcı → ok_url veya fail_url'e HTTP POST (application/x-www-form-urlencoded)
NonSecure Ödeme
3D doğrulama olmaksızın gerçekleştirilen ödeme işlemidir. Yanıt senkron olarak döner.
{
"transaction_type": "Auth",
"order_id": "ORDER-67890",
"amount": 250.00,
"currency": "TRY",
"installment": 1,
"card_number": "4355084355084358",
"card_holder_name": "Jane Doe",
"exp_year": 2026,
"exp_month": 6,
"cvv": "000",
"is_3d": false,
"customer_info": {
"first_name": "Jane",
"last_name": "Doe",
"email": "[email protected]",
"phone": "+905551234567"
}
}
{
"success": true,
"payload": {
"transaction_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"order_id": "ORDER-67890",
"amount_info": {
"amount": 250.00,
"currency": "TRY",
"installment": 1,
"original_amount": 250.00,
"original_currency": "TRY",
"exchange_rate": 1,
"base_amount": 250.00,
"base_currency": "TRY"
},
"gateway_response": {
"code": "00",
"message_tr": "İŞLEM BAŞARILI",
"message_en": "APPROVED",
"detail_tr": "İşlem başarıyla tamamlandı",
"detail_en": "Transaction successfully completed."
},
"bank_response": {
"code": "00",
"message": "000 ONAY KODU 091322",
"auth_code": "091322",
"rrn": "603125844346"
},
"date": "2024-01-15T14:32:00Z"
}
}
PreAuth & Capture
Ön otorizasyon işlemi, müşterinin kartında belirli bir tutarı bloke eder. İşlem tamamlandığında capture ile gerçek ödeme alınır. PreAuth hem NonSecure (is_3d: false) hem de 3D Secure (is_3d: true) olarak yapılabilir.
Adım 1: PreAuth Başlatma – 3D Secure
{
"transaction_type": "PreAuth",
"order_id": "ORDER-PREAUTH-3D-001",
"amount": 500.00,
"currency": "TRY",
"installment": 1,
"card_number": "4355084355084358",
"card_holder_name": "John Doe",
"exp_year": 2026,
"exp_month": 12,
"cvv": "000",
"is_3d": true,
"ok_url": "https://yoursite.com/preauth/success",
"fail_url": "https://yoursite.com/preauth/fail",
"customer_info": {
"first_name": "John",
"last_name": "Doe",
"email": "[email protected]",
"phone": "+905551234567"
}
}
{
"success": true,
"payload": {
"transaction_id": "d4de0c6a-c51f-4aff-bf75-4989c9204bdc",
"order_id": "ORDER-PREAUTH-3D-001",
"html": "<!DOCTYPE html><html>...3D Secure Form HTML...</html>",
"html_url": "https://payment-hub.example.com/api/v1/vpos/payments/3d-secure/b7e3f5a2-9d1c-48f6-a4b8-2c6d8e0f1a3b",
"date": "2024-01-15T14:30:00Z"
}
}
gateway_response ve bank_response bu aşamada dönmez. Ödeme sonucu 3D doğrulama tamamlandıktan sonra ok_url / fail_url'e iletilir.Adım 1: PreAuth Başlatma – NonSecure
{
"transaction_type": "PreAuth",
"order_id": "ORDER-PREAUTH-001",
"amount": 500.00,
"currency": "TRY",
"installment": 1,
"card_number": "4355084355084358",
"card_holder_name": "John Doe",
"exp_year": 2026,
"exp_month": 12,
"cvv": "000",
"is_3d": false,
"customer_info": {
"first_name": "John",
"last_name": "Doe",
"email": "[email protected]",
"phone": "+905551234567"
}
}
{
"success": true,
"payload": {
"transaction_id": "d4de0c6a-c51f-4aff-bf75-4989c9204bdc",
"order_id": "ORDER-PREAUTH-001",
"amount_info": {
"amount": 500.00,
"currency": "TRY",
"installment": 1,
"original_amount": 500.00,
"original_currency": "TRY",
"exchange_rate": 1,
"base_amount": 500.00,
"base_currency": "TRY"
},
"gateway_response": {
"code": "00",
"message_tr": "İŞLEM BAŞARILI",
"message_en": "APPROVED",
"detail_tr": "İşlem başarıyla tamamlandı",
"detail_en": "Transaction successfully completed."
},
"bank_response": {
"code": "00",
"message": "000 ONAY KODU 091322",
"auth_code": "091322",
"rrn": "603125844346"
},
"date": "2024-01-15T14:30:00Z"
}
}
Adım 2: Capture
{
"order_id": "ORDER-PREAUTH-001",
"transaction_id": "d4de0c6a-c51f-4aff-bf75-4989c9204bdc",
"amount": 450.00
}
{
"payload": {
"transaction_id": "e5f6a7b8-c9d0-1234-abcd-ef5678901234",
"order_id": "ORDER-PREAUTH-001",
"original_transaction_id": "d4de0c6a-c51f-4aff-bf75-4989c9204bdc",
"amount_info": {
"amount": 450.00,
"currency": "TRY",
"installment": 1,
"original_amount": 450.00,
"original_currency": "TRY",
"exchange_rate": 1,
"base_amount": 450.00,
"base_currency": "TRY"
},
"gateway_response": {
"code": "00",
"message_tr": "CAPTURE BAŞARILI",
"message_en": "CAPTURE APPROVED"
},
"date": "2024-01-15T16:00:00Z"
}
}
Taksitli Ödeme
Taksitli ödeme akışı üç adımdan oluşur: önce kartın BIN bilgisi sorgulanır, ardından o karta özel taksit seçenekleri ve komisyon oranları alınır, son olarak seçilen taksit sayısıyla ödeme gerçekleştirilir.
ErrInstallmentNotAllowed hatası döner.Adım 1: Kart BIN Sorgulama
Kartın ilk 8 hanesi ile BIN sorgusu yapılır. Dönen yanıttaki banka (member_name),
kart şeması (scheme_name) ve marka (brand_name) bilgileri; taksit
seçeneklerini görüntülemek ve ödeme ekranını kişiselleştirmek için kullanılır.
GET /api/v1/vpos/bins/query?bin=43550843 HTTP/1.1
X-API-Key: your-api-key
X-Hash: {hash}
{
"success": true,
"payload": [
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"bin_range_min": "43550800",
"bin_range_max": "43550899",
"main": true,
"card_no_length": 16,
"validate_for_check_digit": true,
"card_type_no": "1",
"card_type_full": "DEBIT",
"scheme_name": "VISA",
"type_name": "DEBIT",
"segment_name": "CONSUMER",
"brand_name": "VISA CLASSIC",
"member_no": 15,
"member_name": "Ziraat Bankası",
"active_for_clearing": true,
"active_for_fraud": true
}
]
}
Adım 2: Taksit Seçenekleri ve Komisyonlar
BIN ve tutar bilgisiyle birlikte taksit seçenekleri sorgulandığında her taksit için
müşterinin ödeyeceği toplam tutar (customer_pays) ve aylık taksit tutarı
(installment_amount) hesaplanmış olarak döner.
{
"bin": "43550843",
"amount": 1200.00
}
{
"amount": 1200.00,
"single_payment": {
"installment_count": 1,
"merchant_commission_rate": 1.50,
"customer_pays": 1218.00,
"installment_amount": 1218.00,
"apply_surcharge": true
},
"installment_options": [
{
"bank": {
"name": "Ziraat Bankası",
"code": "0015",
"member_no": 15
},
"bank_card_brands": [
{
"card_brand": {
"name": "VISA CLASSIC",
"code": "VC"
},
"installments": [
{
"installment_count": 3,
"merchant_commission_rate": 2.50,
"customer_pays": 1230.00,
"installment_amount": 410.00,
"apply_surcharge": false
},
{
"installment_count": 6,
"merchant_commission_rate": 3.50,
"customer_pays": 1242.00,
"installment_amount": 207.00,
"apply_surcharge": false
},
{
"installment_count": 9,
"merchant_commission_rate": 4.50,
"customer_pays": 1254.00,
"installment_amount": 139.33,
"apply_surcharge": false
},
{
"installment_count": 12,
"merchant_commission_rate": 5.50,
"customer_pays": 1266.00,
"installment_amount": 105.50,
"apply_surcharge": false
}
],
"max_installment_with_mcc": 12
}
]
}
]
}
GET /api/v1/vpos/payments/payment-options endpoint'ini kullanabilirsiniz
(BIN veya tutar gerektirmez).
Adım 3: Taksitli Ödemeyi Gerçekleştir
Önceki adımda seçilen taksit sayısı installment alanına yazılarak ödeme isteği gönderilir.
3D Secure akışı için is_3d: true ve ok_url / fail_url eklenmelidir.
{
"transaction_type": "Auth",
"order_id": "ORDER-INST-001",
"amount": 1200.00,
"currency": "TRY",
"installment": 6,
"card_number": "4355084355084358",
"card_holder_name": "John Doe",
"exp_year": 2026,
"exp_month": 12,
"cvv": "000",
"is_3d": false,
"customer_info": {
"first_name": "John",
"last_name": "Doe",
"email": "[email protected]",
"phone": "+905551234567"
}
}
{
"success": true,
"payload": {
"transaction_id": "c3d4e5f6-a7b8-9012-cdef-gh3456789012",
"order_id": "ORDER-INST-001",
"amount_info": {
"amount": 1200.00,
"currency": "TRY",
"installment": 6,
"original_amount": 1200.00,
"original_currency": "TRY",
"exchange_rate": 1,
"base_amount": 1200.00,
"base_currency": "TRY"
},
"gateway_response": {
"code": "00",
"message_tr": "İŞLEM BAŞARILI",
"message_en": "APPROVED",
"detail_tr": "İşlem başarıyla tamamlandı",
"detail_en": "Transaction successfully completed."
},
"bank_response": {
"code": "00",
"message": "000 ONAY KODU 183447",
"auth_code": "183447",
"rrn": "612034912876"
},
"date": "2024-01-15T14:35:00Z"
}
}
İptal (Void)
İptal işlemi yalnızca aynı gün yapılan işlemlere uygulanabilir. Farklı günlerdeki işlemler için İade (Refund) kullanılmalıdır.
ErrVoidNotAllowedDifferentDay hatası alınır.{
"order_id": "ORDER-12345",
"transaction_id": "d4de0c6a-c51f-4aff-bf75-4989c9204bdc"
}
{
"payload": {
"transaction_id": "f1g2h3i4-j5k6-7890-mnop-qr1234567890",
"order_id": "ORDER-12345",
"original_transaction_id": "d4de0c6a-c51f-4aff-bf75-4989c9204bdc",
"amount_info": {
"amount": 150.00,
"currency": "TRY",
"installment": 1,
"original_amount": 150.00,
"original_currency": "TRY",
"exchange_rate": 1,
"base_amount": 150.00,
"base_currency": "TRY"
},
"gateway_response": {
"code": "00",
"message_tr": "İPTAL BAŞARILI",
"message_en": "VOID APPROVED"
},
"date": "2024-01-15T15:00:00Z"
}
}
İade (Refund)
İade işlemi önceki günlerde gerçekleştirilen ödemeler için kullanılır.
Kısmi iade yapmak için amount alanı gönderin; tam iade için belirtmeyebilirsiniz.
{
"order_id": "ORDER-67890",
"transaction_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}
{
"order_id": "ORDER-67890",
"transaction_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"amount": 100.00
}
{
"payload": {
"transaction_id": "g7h8i9j0-k1l2-3456-mnop-qr7890123456",
"order_id": "ORDER-67890",
"original_transaction_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"amount_info": {
"amount": 250.00,
"currency": "TRY",
"installment": 1,
"original_amount": 250.00,
"original_currency": "TRY",
"exchange_rate": 1,
"base_amount": 250.00,
"base_currency": "TRY"
},
"gateway_response": {
"code": "00",
"message_tr": "İADE BAŞARILI",
"message_en": "REFUND APPROVED"
},
"date": "2024-01-16T10:00:00Z"
}
}
İşlem Sorgulama
Bir işlemin güncel durumunu veya geçmiş kayıtlarını sorgulayabilirsiniz.
GET /api/v1/vpos/payments/query-history/d4de0c6a-c51f-4aff-bf75-4989c9204bdc HTTP/1.1
Host: api.payment-hub.example.com
X-API-Key: your-api-key-here
X-Hash: <hash-of-transaction_id>
{
"payload": [
{
"response_code": "00",
"response_message": "İşlem başarılı",
"transaction_status": "SUCCESS",
"auth_code": "091322",
"order_id": "ORDER-12345",
"amount": "150.00",
"bank_response_code": "00",
"bank_response_message": "000 ONAY KODU 091322"
}
]
}
İşlem Listesi
Geçmiş işlemlerinizi filtreler, sayfalama ile listeler. Tekil sorgulama için İşlem Sorgulama bölümüne bakınız.
GET /api/v1/payments/transactions?offset=0&limit=50&start_date=2024-01-01T00:00:00Z&end_date=2024-01-31T23:59:59Z&status=APPROVED¤cy=TRY HTTP/1.1
Host: api.payment-hub.example.com
X-API-Key: your-api-key-here
X-Hash: <hash-of-query-params>
{
"success": true,
"payload": [
{
"id": "c00970da-dcaf-4baa-9486-1ae35cd76179",
"order_id": "PL-f3f5533afe2236550280a54f-94067de0",
"merchant_id": "01997898-66c6-731b-9f00-fabaf3e470c4",
"merchant_name": "ÖRNEK İŞYERİ A.Ş.",
"amount": 3.44,
"original_amount": 3.44,
"original_currency": "TRY",
"base_amount": 3.44,
"currency": "TRY",
"installment": 1,
"is_installment": false,
"status": "APPROVED",
"transaction_type": "SALE_SECURE",
"transaction_source": "VIRTUAL_POS",
"transaction_channel": "VIRTUAL_LINK",
"fraud_status": "ACCEPT",
"card_number_masked": "5381********0019",
"card_holder_name": "John Doe",
"card_brand": "SHOPFLY",
"card_type": "KREDI_KARTI",
"card_bank_code": "62",
"card_bank_name": "T.GARANTİ BANKASI A.Ş.",
"bin_number": "53819651",
"rrn": "608925129544",
"auth_code": "797499",
"bank_response_code": "00",
"bank_response_message": "İŞLEM BAŞARILI",
"payment_gateway_code": "00",
"payment_gateway_message": "İŞLEM BAŞARILI / APPROVED",
"exchange_rate": 1,
"base_currency": "TRY",
"merchant_commission_rate": 3,
"merchant_payout_amount": 3.3368,
"transaction_fee": 0.1032,
"terminal_no": "S1804Y01",
"terminal_bank_code": "64",
"terminal_bank_name": "T.İŞ BANKASI A.Ş.",
"customer_first_name": "John",
"customer_last_name": "Doe",
"customer_phone": "05551234567",
"customer_email": "[email protected]",
"created_at": "2026-03-30T22:22:55.612003+03:00",
"updated_at": "2026-03-30T22:23:18.076433+03:00",
"processed_at": "2026-03-30T22:22:55.418741+03:00",
"completed_at": "2026-03-30T22:23:18.075784+03:00",
"virtual_pos_details": {
"ok_url": "https://example.com/callback/ok",
"fail_url": "https://example.com/callback/fail",
"link_code": "f3f5533afe2236550280a54f"
}
},
{
"id": "95cd303f-f296-4654-b1cc-4941512d8e27",
"order_id": "PL-ne5oAtv3YYV40cxM-lcNTw-a4a993d3",
"merchant_id": "01997898-66c6-731b-9f00-fabaf3e470c4",
"merchant_name": "ÖRNEK İŞYERİ A.Ş.",
"amount": 1,
"original_amount": 1,
"original_currency": "TRY",
"base_amount": 1,
"currency": "TRY",
"installment": 1,
"is_installment": false,
"status": "DECLINED",
"transaction_type": "SALE_SECURE",
"transaction_source": "VIRTUAL_POS",
"transaction_channel": "VIRTUAL_LINK",
"fraud_status": "ACCEPT",
"card_number_masked": "5381********0019",
"card_holder_name": "John Doe",
"card_brand": "SHOPFLY",
"card_type": "KREDI_KARTI",
"card_bank_code": "62",
"card_bank_name": "T.GARANTİ BANKASI A.Ş.",
"bin_number": "53819651",
"rrn": "608420206421",
"bank_response_code": "51",
"bank_response_message": "Limit Yetersiz.",
"payment_gateway_code": "51",
"payment_gateway_message": "YETERSİZ BAKİYE / INSUFFICIENT FUNDS",
"exchange_rate": 1,
"base_currency": "TRY",
"merchant_commission_rate": 3,
"merchant_payout_amount": 0.97,
"transaction_fee": 0.03,
"terminal_no": "S1804Y01",
"terminal_bank_code": "64",
"terminal_bank_name": "T.İŞ BANKASI A.Ş.",
"customer_first_name": "John",
"customer_last_name": "Doe",
"customer_phone": "+905551234567",
"customer_email": "[email protected]",
"created_at": "2026-03-25T19:41:38.682781+03:00",
"updated_at": "2026-03-25T19:42:04.143005+03:00",
"processed_at": "2026-03-25T19:41:38.557268+03:00",
"completed_at": "2026-03-25T19:41:39.648308+03:00",
"virtual_pos_details": {
"ok_url": "https://example.com/callback/ok",
"fail_url": "https://example.com/callback/fail",
"link_code": "ne5oAtv3YYV40cxM-lcNTw",
"collection_code": "adfdd7ca72b88173d124e915"
}
}
],
"pagination": {
"limit": 50,
"offset": 0,
"hasNext": true,
"hasPrev": false
}
}
Hakediş Sorgulama
Belirli bir tarih aralığında merchant hesabınıza ait hakediş bilgilerini para birimi ve kaynak bazında sorgulayabilirsiniz.
GET /api/v1/payments/balance?start_date=2024-01-01&end_date=2024-01-31¤cy=TRY HTTP/1.1
Host: api.payment-hub.example.com
X-API-Key: your-api-key-here
X-Hash: <hash-of-query-params>
{
"start_date": "2024-01-01",
"end_date": "2024-01-31",
"balances": [
{
"currency": "TRY",
"source": "VPOS",
"sale": {
"count": 100,
"amount": 50000.00,
"base_amount": 50000.00
},
"post_auth": {
"count": 5,
"amount": 2500.00,
"base_amount": 2500.00
},
"refund": {
"count": 3,
"amount": 1000.00,
"base_amount": 1000.00
},
"void": {
"count": 2,
"amount": 200.00,
"base_amount": 200.00
},
"pre_auth_pending": {
"count": 10,
"amount": 5000.00,
"base_amount": 5000.00
},
"failed": {
"count": 8,
"amount": 3000.00,
"base_amount": 3000.00
},
"net_amount": 51300.00,
"net_base_amount": 51300.00,
"total_count": 128,
"success_rate": 93.75,
"financial": {
"total_commission": 4800.00,
"total_merchant_payout": 46500.00,
"total_transaction_fee": 500.00
}
}
],
"totals": {
"total_count": 128,
"net_base_amount": 51300.00,
"total_merchant_payout_base": 46500.00,
"success_rate": 93.75
}
}
balances[] öğesi para birimi ve kaynak bazında gruplanır. İşlem tipleri:
sale (satış), post_auth (ön provizyon kapama), refund (iade),
void (iptal), pre_auth_pending (bekleyen ön provizyon), failed (başarısız).
Her birinde count, amount ve base_amount değerleri bulunur.
Link İşlemleri – Genel Bakış
Payment Link Service; ödeme oturumları, ödeme linkleri ve koleksiyonlar aracılığıyla müşterilere bağlantı tabanlı ödeme akışları sunar. Üç farklı yöntem mevcuttur:
Base URL
Sandbox Test Kullanıcısı
00000000-0000-0000-0000-000000000000sandbox-secret-key-for-testing-purposes-onlyKimlik Doğrulama Yöntemleri
| Yöntem | Endpoint Grubu | Açıklama |
|---|---|---|
| X-API-Key + X-Hash | Merchant endpoint'leri (/merchant/*, /sessions) |
Payment Hub ile aynı hash doğrulama mekanizması |
Tüm Endpoint Listesi
| Metod | Endpoint | Auth | Açıklama |
|---|---|---|---|
| POST | /api/v1/sessions | API Key + Hash | Ödeme oturumu oluştur |
| POST | /api/v1/merchant/payment-links | API Key + Hash | Ödeme linki oluştur |
| GET | /api/v1/merchant/payment-links | API Key + Hash | Ödeme linklerini listele |
| GET | /api/v1/merchant/payment-links/:id | API Key + Hash | Ödeme linkini getir |
| PATCH | /api/v1/merchant/payment-links/:id/status | API Key + Hash | Link durumunu güncelle |
| GET | /api/v1/merchant/payment-links/:id/qr | API Key + Hash | QR kod görseli (PNG) |
| POST | /api/v1/merchant/collections | API Key + Hash | Koleksiyon oluştur |
| GET | /api/v1/merchant/collections | API Key + Hash | Koleksiyonları listele |
| GET | /api/v1/merchant/collections/:id | API Key + Hash | Koleksiyonu getir |
| PATCH | /api/v1/merchant/collections/:id/status | API Key + Hash | Koleksiyon durumunu güncelle |
| GET | /api/v1/merchant/collections/:id/qr | API Key + Hash | Koleksiyon QR kodu |
Ödeme Oturumu (Payment Session)
Sunucu tarafında oluşturulan, tek kullanımlık ödeme bağlantısı. Müşteriye
session_url gönderilir; müşteri bu URL üzerinden kart bilgilerini girerek ödeme yapar.
Oturum Oluştur
{
"amount": 250.00,
"currency": "TRY",
"order_id": "ORDER-SESSION-001",
"ok_url": "https://yoursite.com/payment/success",
"fail_url": "https://yoursite.com/payment/fail",
"customer_info": {
"first_name": "John",
"last_name": "Doe",
"email": "[email protected]",
"phone": "+905551234567"
},
"metadata": {
"internal_ref": "REF-123"
},
"installment": true,
"allowed_installments": [2, 3, 6, 9, 12]
}
{
"success": true,
"payload": {
"session_id": "sess_5lnohiu4pvokvzsu",
"session_url": "http://localhost:3002/api/v1/public/session/sess_5lnohiu4pvokvzsu",
"expires_at": "2026-03-04T12:01:08.797663+03:00"
}
}
Ödeme Linki – Merchant API
Admin paneli (Keycloak) yerine doğrudan kendi sisteminizden API Key + Hash doğrulamasıyla ödeme linki yönetimi. Sadece kendi merchant'ınıza ait linkler görünür.
X-API-Key ve X-Hash header'ları zorunludur.
Hash nasıl hesaplanır: Hash Doğrulama bölümüne bakın.
X-API-Key: your-api-key
X-Hash: {hmac-sha512-signature}
Ödeme Linki Oluştur
{
"title": "Yaz Sezonu Ürünleri",
"description": "Yaz sezonu özel fiyatlı ürünler",
"currency": "TRY",
"products": [
{
"name": "Güneş Gözlüğü",
"description": "Polarize cam, UV400 koruma",
"price": 299.90,
"default_quantity": 1,
"sku": "SKU-001",
"image_url": "https://example.com/images/sunglasses.jpg",
"display_order": 1
}
],
"expires_at": "2024-09-01T00:00:00Z",
"max_uses": 100,
"ok_url": "https://yoursite.com/payment/success",
"fail_url": "https://yoursite.com/payment/fail",
"require_3ds": false,
"allow_non_3ds": true,
"installment": true,
"allowed_installments": [2, 3, 6, 9, 12]
}
{
"success": true,
"payload": {
"id": "f1a2b3c4-d5e6-7890-abcd-ef1234567890",
"merchant_name": "Örnek Mağaza",
"link_code": "PAY-XZ7Y3K",
"link_url": "https://api.payment-link.example.com/api/v1/public/payment-links/PAY-XZ7Y3K/page",
"title": "Yaz Sezonu Ürünleri",
"description": "Yaz sezonu özel fiyatlı ürünler",
"total_amount": 299.90,
"currency": "TRY",
"status": "ACTIVE",
"expires_at": "2024-09-01T00:00:00Z",
"max_uses": 100,
"used_count": 0,
"require_3ds": false,
"allow_non_3ds": true,
"installment": true,
"allowed_installments": [2, 3, 6, 9, 12],
"products": [
{
"id": "a1b2c3d4-e5f6-7890-abcd-111111111111",
"name": "Güneş Gözlüğü",
"description": "Polarize cam, UV400 koruma",
"price": 299.90,
"default_quantity": 1,
"sku": "SKU-001",
"image_url": "https://example.com/images/sunglasses.jpg",
"subtotal": 299.90
}
],
"qr_code_url": "https://api.payment-link.example.com/api/v1/merchant/payment-links/f1a2b3c4.../qr",
"created_at": "2024-01-15T10:00:00Z"
}
}
Ödeme Linklerini Listele
GET /api/v1/merchant/payment-links?page=1&limit=20&status=ACTIVE&search=yaz¤cy=TRY HTTP/1.1
X-API-Key: your-api-key
X-Hash: {hash}
{
"success": true,
"payload": {
"data": [
{
"id": "f1a2b3c4-d5e6-7890-abcd-ef1234567890",
"merchant_name": "Örnek Mağaza",
"link_code": "PAY-XZ7Y3K",
"link_url": "https://api.payment-link.example.com/api/v1/public/payment-links/PAY-XZ7Y3K/page",
"title": "Yaz Sezonu Ürünleri",
"description": "Yaz sezonu özel fiyatlı ürünler",
"total_amount": 299.90,
"currency": "TRY",
"status": "ACTIVE",
"used_count": 5,
"qr_code_url": "https://api.payment-link.example.com/api/v1/merchant/payment-links/f1a2b3c4.../qr",
"created_at": "2024-01-15T10:00:00Z"
}
],
"pagination": {
"total": 50,
"limit": 20,
"offset": 0,
"current_page": 1,
"total_pages": 3
}
}
}
Tekil Ödeme Linki Getir
{
"success": true,
"payload": {
"id": "f1a2b3c4-d5e6-7890-abcd-ef1234567890",
"merchant_name": "Örnek Mağaza",
"link_code": "PAY-XZ7Y3K",
"link_url": "https://api.payment-link.example.com/api/v1/public/payment-links/PAY-XZ7Y3K/page",
"title": "Yaz Sezonu Ürünleri",
"description": "Yaz sezonu özel fiyatlı ürünler",
"total_amount": 299.90,
"currency": "TRY",
"status": "ACTIVE",
"expires_at": "2024-09-01T00:00:00Z",
"max_uses": 100,
"used_count": 5,
"require_3ds": false,
"allow_non_3ds": true,
"installment": true,
"allowed_installments": [2, 3, 6, 9, 12],
"products": [
{
"id": "a1b2c3d4-e5f6-7890-abcd-111111111111",
"name": "Güneş Gözlüğü",
"description": "Polarize cam, UV400 koruma",
"price": 299.90,
"default_quantity": 1,
"sku": "SKU-001",
"image_url": "https://example.com/images/sunglasses.jpg",
"subtotal": 299.90
}
],
"qr_code_url": "https://api.payment-link.example.com/api/v1/merchant/payment-links/f1a2b3c4.../qr",
"created_at": "2024-01-15T10:00:00Z"
}
}
Link Durumunu Güncelle
{ "status": "INACTIVE" }
Geçerli değerler: ACTIVE, INACTIVE, EXPIRED, COMPLETED
{
"success": true,
"payload": {
"message": "Payment link status updated successfully"
}
}
QR Kod Görseli
HTTP/1.1 200 OK
Content-Type: image/png
Content-Disposition: inline; filename="qr.png"
<binary PNG data>
Koleksiyon – Merchant API
Serbest tutarlı ödeme sayfaları yönetimi. API Key + Hash doğrulamasıyla kendi sisteminizden koleksiyon oluşturup yönetebilirsiniz. Sadece kendi merchant'ınıza ait koleksiyonlar görünür.
X-API-Key ve X-Hash header'ları zorunludur.
Hash hesaplama için Hash Doğrulama bölümüne bakın.
Koleksiyon Oluştur
{
"title": "Bağış Toplama",
"description": "Okul yararına bağış kampanyası",
"currency": "TRY",
"min_amount": 10.00,
"max_amount": 10000.00,
"expires_at": "2024-12-31T00:00:00Z",
"max_uses": 500,
"ok_url": "https://yoursite.com/donation/thanks",
"fail_url": "https://yoursite.com/donation/fail",
"require_3ds": false,
"allow_non_3ds": true
}
{
"success": true,
"payload": {
"id": "c1d2e3f4-a5b6-7890-cdef-gh1234567890",
"merchant_name": "Örnek Mağaza",
"link_code": "COL-AB3CD9",
"link_url": "https://api.payment-link.example.com/api/v1/public/collections/COL-AB3CD9/page",
"title": "Bağış Toplama",
"description": "Okul yararına bağış kampanyası",
"currency": "TRY",
"min_amount": 10.00,
"max_amount": 10000.00,
"status": "ACTIVE",
"expires_at": "2024-12-31T00:00:00Z",
"max_uses": 500,
"used_count": 0,
"require_3ds": false,
"allow_non_3ds": true,
"qr_code_url": "https://api.payment-link.example.com/api/v1/merchant/collections/c1d2e3f4.../qr",
"created_at": "2024-01-15T10:00:00Z"
}
}
Koleksiyonları Listele
GET /api/v1/merchant/collections?page=1&limit=20&status=ACTIVE HTTP/1.1
X-API-Key: your-api-key
X-Hash: {hash}
{
"success": true,
"payload": {
"data": [
{
"id": "c1d2e3f4-a5b6-7890-cdef-gh1234567890",
"merchant_name": "Örnek Mağaza",
"link_code": "COL-AB3CD9",
"link_url": "https://api.payment-link.example.com/api/v1/public/collections/COL-AB3CD9/page",
"title": "Bağış Toplama",
"description": "Okul yararına bağış kampanyası",
"currency": "TRY",
"min_amount": 10.00,
"max_amount": 10000.00,
"status": "ACTIVE",
"expires_at": "2024-12-31T00:00:00Z",
"max_uses": 500,
"used_count": 42,
"require_3ds": false,
"allow_non_3ds": true,
"qr_code_url": "https://api.payment-link.example.com/api/v1/merchant/collections/c1d2e3f4.../qr",
"created_at": "2024-01-15T10:00:00Z"
}
],
"pagination": {
"total": 12,
"limit": 20,
"offset": 0,
"current_page": 1,
"total_pages": 1
}
}
}
Tekil Koleksiyon Getir
{
"success": true,
"payload": {
"id": "c1d2e3f4-a5b6-7890-cdef-gh1234567890",
"merchant_name": "Örnek Mağaza",
"link_code": "COL-AB3CD9",
"link_url": "https://api.payment-link.example.com/api/v1/public/collections/COL-AB3CD9/page",
"title": "Bağış Toplama",
"description": "Okul yararına bağış kampanyası",
"currency": "TRY",
"min_amount": 10.00,
"max_amount": 10000.00,
"status": "ACTIVE",
"expires_at": "2024-12-31T00:00:00Z",
"max_uses": 500,
"used_count": 42,
"require_3ds": false,
"allow_non_3ds": true,
"qr_code_url": "https://api.payment-link.example.com/api/v1/merchant/collections/c1d2e3f4.../qr",
"created_at": "2024-01-15T10:00:00Z"
}
}
Koleksiyon Durumunu Güncelle
{ "status": "INACTIVE" }
Geçerli değerler: ACTIVE, INACTIVE, EXPIRED
{
"success": true,
"payload": {
"message": "Collection status updated successfully"
}
}
QR Kod Görseli
HTTP/1.1 200 OK
Content-Type: image/png
Content-Disposition: inline; filename="qr.png"
<binary PNG data>
Test İşlemleri
Geliştirme ve entegrasyon testleri için aşağıdaki test kartlarını kullanabilirsiniz. Test işlemleri gerçek bankacılık sistemine gönderilmez.
Sandbox Test Kartları
Aşağıdaki kartlar sandbox ortamında farklı ödeme senaryolarını test etmek için kullanılır. Tüm kartlar için CVV: 000, SKT: 12/2026, kart sahibi herhangi bir isim olabilir.
"success": true,
başarısız işlemler "success": false ile ayrılır. Hata detayları error.details içinde
gateway_response ve bank_response olarak döner.Postman Collection
Sandbox API'lerini hızlıca test etmek için hazır Postman collection'larını kullanabilirsiniz. Collection'lar hash hesaplama script'lerini içerir, ekstra kurulum gerekmez.
Sandbox Kimlik Bilgileri
| Parametre | Değer |
|---|---|
| API Key | 00000000-0000-0000-0000-000000000000 |
| Secret Key | sandbox-secret-key-for-testing-purposes-only |
Test Ortamı Bilgileri
| Parametre | Değer |
|---|---|
| CVV | 000 (herhangi bir 3-4 haneli değer kabul edilir) |
| Son Kullanma Tarihi | 12/2026 (herhangi bir tarih kabul edilir, süresi dolmuş dahil) |
| Kart Sahibi | Herhangi bir isim |
| 3D OTP (test) | 123456 |
Örnek Test İsteği (cURL)
curl -X POST https://api.payment-hub.example.com/api/v1/vpos/payments/payment \
-H "Content-Type: application/json" \
-H "X-API-Key: 00000000-0000-0000-0000-000000000000" \
-H "X-Hash: your-calculated-hash" \
-d '{
"transaction_type": "Auth",
"order_id": "TEST-ORDER-001",
"amount": 100.00,
"currency": "TRY",
"installment": 1,
"card_number": "4000000000000001",
"card_holder_name": "Test User",
"exp_year": 2026,
"exp_month": 12,
"cvv": "000",
"is_3d": false,
"customer_info": {
"first_name": "John",
"last_name": "Doe",
"email": "[email protected]",
"phone": "+905551234567"
}
}'
Gateway Response Kodları
Bankadan dönen yanıt kodları Payment Hub tarafından ISO 8583 standardına göre normalize edilir.
Tüm ödeme yanıtlarındaki gateway_response.code ve gateway_response.message_tr
/ message_en alanları aşağıdaki tablodaki değerleri alır.
gateway_response.code değeri "00" olan işlemler başarılıdır.
Tanımlanamayan banka hata kodları "99" olarak döner.
3D Secure doğrulama başarısızlıkları "98" koduyla işaretlenir.
| Kod | Mesaj TR | Mesaj EN | Açıklama |
|---|---|---|---|
| 00 | İŞLEM BAŞARILI | APPROVED | İşlem başarıyla tamamlandı. |
| 01 | BANKADAN ONAY ALINIZ | REFER TO CARD ISSUER | Banka onayı gerekiyor; kart sahibi bankasıyla iletişime geçilmeli. |
| 02 | BANKADAN ONAY ALINIZ (ÖZEL DURUM) | REFER TO CARD ISSUER, SPECIAL CONDITION | Banka özel durum onayı gerekiyor. |
| 03 | GEÇERSİZ ÜYE İŞYERİ | INVALID MERCHANT OR SERVICE PROVIDER | Üye işyeri banka sisteminde kapalı olabilir; sanal POS bankasıyla iletişime geçilmeli. |
| 04 | KARTA EL KOYUNUZ | PICK UP CARD | Kart güvenlik nedeniyle alıkonulmalı. |
| 05 | RED | DO NOT HONOR | İşlem reddedildi; kart sahibi bankasıyla iletişime geçilmeli. |
| 07 | KARTA EL KOYUNUZ (ÖZEL DURUM) | PICK UP CARD, SPECIAL CONDITION | Kart özel durum nedeniyle alıkonulmalı. |
| 08 | ONAY VE KİMLİK DOĞRULA | HONOR WITH IDENTIFICATION | İşlem onayı için kart sahibinin kimliği doğrulanmalı. |
| 10 | KISMİ ONAY | PARTIAL APPROVAL | İşlem tutarının bir kısmı onaylandı; daha düşük tutarda işlem yapılabilir. |
| 11 | VIP ONAY | VIP APPROVAL | VIP müşteri işlemi onaylandı; özel limitler uygulandı. |
| 12 | GEÇERSİZ İŞLEM | INVALID TRANSACTION | İşlem geçersiz; işlem tipi veya parametreler kontrol edilmeli. |
| 13 | GEÇERSİZ TUTAR | INVALID AMOUNT | İşlem tutarı geçersiz; tutar formatı veya limitleri kontrol edilmeli. |
| 14 | GEÇERSİZ KART NUMARASI | INVALID CARD NUMBER | Kart numarası geçersiz. |
| 19 | GİRİŞ TEKRAR EDİNİZ | RE-ENTER TRANSACTION | Geçici sistem sorunu; işlem tekrar denenebilir. |
| 21 | İŞLEM YAPILMADI | NO ACTION TAKEN | İşlem gerçekleştirilemedi; sistem yanıt vermedi. |
| 25 | KAYIT BULUNAMADI | UNABLE TO LOCATE RECORD | İşlem kaydı sistemde bulunamadı. |
| 30 | FORMAT HATASI | FORMAT ERROR | Mesaj formatı hatalı; mesaj yapısı kontrol edilmeli. |
| 34 | SAHTEKARLIKTAN ŞÜPHELENİLİYOR | FRAUD SUSPICION | İşlem sahtekarlık şüphesi nedeniyle reddedildi. |
| 36 | KISITLI KART | RESTRICTED CARD | Kart kısıtlı; kart sahibi bankasıyla iletişime geçilmeli. |
| 38 | PIN DENEMESİ AŞILDI | ALLOWABLE PIN TRIES EXCEEDED | PIN deneme sayısı aşıldı; kart geçici olarak bloke edildi. |
| 41 | KAYIP KART | LOST CARD | Kart kayıp olarak işaretlenmiş; alıkonulmalı. |
| 43 | ÇALINTI KART | STOLEN CARD | Kart çalıntı olarak işaretlenmiş; alıkonulmalı. |
| 51 | YETERSİZ BAKİYE | INSUFFICIENT FUNDS | Hesapta yeterli bakiye yok; daha düşük tutarda denenebilir. |
| 52 | HESAP NUMARASI BULUNAMADI | NO CHECKING ACCOUNT | Vadesiz hesap bulunamadı. |
| 53 | HESAP NUMARASI BULUNAMADI | NO SAVINGS ACCOUNT | Vadeli hesap bulunamadı. |
| 54 | KART SÜRESİ DOLMUŞ / SON KULLANMA TARİHİ HATALI | EXPIRED CARD / INVALID EXPIRY DATE | Kart süresi dolmuş veya son kullanma tarihi hatalı. |
| 55 | HATALI PIN | INCORRECT PIN | PIN kodu hatalı. |
| 57 | İŞLEME İZİN YOK | TRANSACTION NOT PERMITTED TO CARDHOLDER | Kart sahibi bu işlem tipini gerçekleştiremez. |
| 58 | İŞLEME İZİN YOK | TRANSACTION NOT PERMITTED TO TERMINAL | Terminal bu işlem tipini gerçekleştiremez. |
| 59 | SAHTEKARLIK ŞÜPHESİ | SUSPECTED FRAUD | İşlem sahtekarlık riski nedeniyle reddedildi. |
| 61 | PARA ÇEKME TUTAR LİMİTİ AŞILDI | EXCEEDS WITHDRAWAL AMOUNT LIMIT | Para çekme limiti aşıldı; daha düşük tutarda denenebilir. |
| 62 | YASAKLANMIŞ KART | RESTRICTED CARD | Kart yasaklanmış; kart sahibi bankasıyla iletişime geçilmeli. |
| 63 | GÜVENLİK İHLALİ | SECURITY VIOLATION | Güvenlik ihlali tespit edildi. |
| 65 | GÜNLÜK İŞLEM LİMİTİ AŞILDI | EXCEEDS WITHDRAWAL FREQUENCY LIMIT | Günlük işlem limiti aşıldı; limit ertesi gün sıfırlanır. |
| 75 | PIN DENEMESİ AŞILDI | ALLOWABLE PIN TRIES EXCEEDED | PIN deneme sayısı aşıldı; kart geçici olarak bloke edildi. |
| 76 | HENÜZ AKTİF OLMAYAN KART | INACTIVE CARD | Kart henüz aktif değil; aktivasyon gerekiyor. |
| 77 | ORJİNAL İŞLEM VERİLERİ EŞLEŞMİYOR | ORIGINAL TRANSACTION DATA NOT MATCHED | İşlem verileri eşleşmiyor; orijinal işlem kontrol edilmeli. |
| 78 | SİSTEMDE KAYITLI OLMAYAN KART | NO ACCOUNT | Kart sistemde kayıtlı değil. |
| 82 | GEÇERSİZ CVV | INVALID CVV | CVV kodu hatalı. |
| 83 | PIN DOĞRULAMASI YAPILAMADI | CANNOT VERIFY PIN | PIN doğrulaması yapılamadı. |
| 85 | RED DEĞİL | NOT DECLINED | İşlem reddedilmedi; onay bekliyor. |
| 86 | PIN KONTROLÜ YAPILAMADI | CANNOT VERIFY PIN | PIN kontrolü yapılamadı; sistem hatası oluştu. |
| 88 | KRİPTO HATASI | CRYPTOGRAPHIC FAILURE | Şifreleme hatası; güvenlik doğrulaması başarısız. |
| 89 | KİMLİK DOĞRULAMA BAŞARISIZ | AUTHENTICATION FAILURE | Kimlik doğrulama başarısız. |
| 91 | İŞLEM BANKAYA GÖNDERİLEMEDİ | ISSUER OR SWITCH INOPERATIVE | Banka sistemi çalışmıyor; işlem tekrar denenebilir. |
| 92 | İŞLEM BANKAYA GÖNDERİLEMEDİ | FINANCIAL INSTITUTION CANNOT BE FOUND FOR ROUTING | Banka yönlendirmesi yapılamadı; sistem hatası oluştu. |
| 93 | KART ÜYESİNİN KAYDI YOK | TRANSACTION CANNOT BE COMPLETED - VIOLATION OF LAW | Kart üyesi kaydı bulunamadı veya yasal kısıtlama mevcut. |
| 95 | EŞLEŞTİRME HATASI | RECONCILE ERROR | İşlem eşleştirme hatası; sistem kontrolü gerekiyor. |
| 96 | SİSTEM HATASI | SYSTEM MALFUNCTION | Sistem hatası veya zaman aşımı; işlem tekrar denenebilir. |
| 98 | 3D DOĞRULAMA BAŞARISIZ | 3D SECURE AUTHENTICATION FAILED | Kart sahibi 3D Secure doğrulama sürecini tamamlayamadı. |
| 99 | GENEL BANKA HATASI | GENERAL BANK ERROR | Tanımlanamayan genel bir banka hatası oluştu. |
Uygulama Hata Kodları
Payment Hub'ın döndürdüğü uygulama seviyesi hata kodları. Hata yanıtı
success: false ile birlikte error.code, error.subCode ve error.message alanlarını içerir.
subCode sayesinde istemciler message string'ini parse etmeden programatik hata yönetimi yapabilir.
HTTP Durum Kodları
| HTTP Kodu | Açıklama |
|---|---|
| 200 OK | İşlem başarıyla tamamlandı |
| 400 Bad Request | Geçersiz istek parametresi veya eksik zorunlu alan |
| 401 Unauthorized | Geçersiz API key, geçersiz hash imzası veya yetkisiz erişim |
| 409 Conflict | Çakışan kayıt (ör. aynı order_id, zaten iptal edilmiş işlem) |
| 422 Unprocessable Entity | İş kuralı ihlali (ör. aynı gün iptal, limit aşımı) |
| 500 Internal Server Error | Sunucu tarafı beklenmedik hata (dahili servis hatası, gateway sorgu hatası vb.) |
| 503 Service Unavailable | Ödeme gateway'ine bağlantı kurulamadı veya uygun terminal bulunamadı |
İşlem Hataları
| error.code | subCode | error.message | HTTP | Açıklama |
|---|---|---|---|---|
| NOT_FOUND | TRANSACTION_NOT_FOUND | Transaction not found | 404 | Belirtilen transaction_id bulunamadı |
| BAD_REQUEST | INVALID_TRANSACTION_ID | Invalid transaction ID format | 400 | transaction_id geçerli bir UUID formatında değil |
| BAD_REQUEST | INVALID_MERCHANT | Invalid merchant or merchant not active | 400 | Merchant bulunamadı veya aktif değil |
| CONFLICT | DUPLICATE_ORDER_ID | Order ID already exists for this merchant | 409 | Bu order_id ile daha önce işlem yapılmış |
| BAD_REQUEST | INVALID_CARD_NUMBER | Invalid card number | 400 | Kart numarası geçersiz (Luhn kontrolü başarısız) |
| BAD_REQUEST | INVALID_EXPIRY_DATE | Invalid or expired card expiry date | 400 | Kartın son kullanma tarihi geçmiş veya geçersiz |
| BAD_REQUEST | INVALID_CVV | Invalid CVV | 400 | CVV kodu geçersiz |
| INTERNAL_SERVER_ERROR | PAYMENT_GATEWAY_ERROR | Payment gateway error | 500 | Ödeme gateway'inden hata yanıtı alındı |
| INTERNAL_SERVER_ERROR | — | An unexpected error occurred | 500 | Dahili servis hatası (gateway sorgu hatası, bağımlı servis erişilemiyor vb.); yeniden deneyin |
| SERVICE_UNAVAILABLE | PAYMENT_GATEWAY_CONNECTION_FAILED | Payment gateway connection failed | 503 | Ödeme gateway'ine bağlantı kurulamadı |
Terminal Hataları
| error.code | subCode | error.message | HTTP | Açıklama |
|---|---|---|---|---|
| SERVICE_UNAVAILABLE | NO_ELIGIBLE_TERMINALS | No eligible terminals found, please contact operations team | 503 | İsteği karşılayabilecek hiçbir terminal yok; operasyon ekibiyle iletişime geçin |
| BAD_REQUEST | TERMINAL_VOID_NOT_SUPPORTED | Terminal does not support void | 400 | İşlemin bağlı olduğu terminal iptal işlemini desteklemiyor |
| BAD_REQUEST | TERMINAL_REFUND_NOT_SUPPORTED | Terminal does not support refund | 400 | İşlemin bağlı olduğu terminal iade işlemini desteklemiyor |
| BAD_REQUEST | SUB_MERCHANT_ID_REQUIRED | sub_merchant_id is required for selected terminal | 400 | Seçilen terminal için sub_merchant_id zorunludur |
İptal (Void) Hataları
| error.code | subCode | error.message | HTTP | Açıklama |
|---|---|---|---|---|
| BAD_REQUEST | VOID_NOT_ALLOWED_DIFFERENT_DAY | Void not allowed for transactions created on different day | 400 | Farklı günde yapılan işlem iptal edilemez; iade kullanın |
| BAD_REQUEST | VOID_NOT_ALLOWED_TYPE | Transaction type not allowed for void | 400 | İşlem tipi iptal için uygun değil |
| BAD_REQUEST | VOID_NOT_ALLOWED_STATUS | Transaction status not allowed for void | 400 | İşlem durumu iptal için uygun değil |
| CONFLICT | TRANSACTION_ALREADY_VOIDED | Transaction already voided | 409 | İşlem zaten iptal edilmiş |
İade (Refund) Hataları
| error.code | subCode | error.message | HTTP | Açıklama |
|---|---|---|---|---|
| BAD_REQUEST | REFUND_NOT_ALLOWED_SAME_DAY | Refund not allowed in same day, use void | 400 | Aynı gün işlemler için iptal (void) kullanın |
| BAD_REQUEST | REFUND_NOT_ALLOWED_AFTER_30_DAYS | Refund not allowed after 30 days | 400 | 30 günden eski işlemlere iade yapılamaz |
| BAD_REQUEST | REFUND_NOT_ALLOWED_TYPE | Transaction type not allowed for refund | 400 | İşlem tipi iade için uygun değil |
| BAD_REQUEST | REFUND_NOT_ALLOWED_STATUS | Transaction status not allowed for refund | 400 | İşlem durumu iade için uygun değil |
| BAD_REQUEST | REFUND_NOT_ALLOWED_VOIDED | Voided transaction cannot be refunded | 400 | İptal edilmiş işleme iade yapılamaz |
| BAD_REQUEST | REFUND_AMOUNT_EXCEEDS_LIMIT | Refund amount exceeds available limit | 400 | İade tutarı mevcut iadesiz tutarı aşıyor |
| BAD_REQUEST | INVALID_REFUND_AMOUNT | Invalid refund amount | 400 | Geçersiz iade tutarı (0 veya negatif) |
Capture (PreAuth) Hataları
| error.code | subCode | error.message | HTTP | Açıklama |
|---|---|---|---|---|
| BAD_REQUEST | CAPTURE_NOT_ALLOWED_TYPE | Transaction type not allowed for capture | 400 | Sadece PreAuth işlemlerine capture uygulanabilir |
| BAD_REQUEST | CAPTURE_NOT_ALLOWED_STATUS | Transaction status not allowed for capture | 400 | İşlem durumu capture için uygun değil |
| BAD_REQUEST | CAPTURE_AMOUNT_EXCEEDS_LIMIT | Capture amount exceeds pre-auth amount | 400 | Capture tutarı PreAuth tutarını aşamaz |
| CONFLICT | PRE_AUTH_ALREADY_CAPTURED | Pre-authorization already captured | 409 | Bu PreAuth işlemi zaten capture edilmiş |
Limit & Kural Hataları
| error.code | subCode | error.message | HTTP | Açıklama |
|---|---|---|---|---|
| BAD_REQUEST | MIN_AMOUNT_NOT_MET | Transaction amount is below minimum limit | 400 | İşlem tutarı minimum sınırın altında |
| BAD_REQUEST | MAX_AMOUNT_EXCEEDED | Transaction amount exceeds maximum limit | 400 | İşlem tutarı maksimum sınırı aşıyor |
| BAD_REQUEST | DAILY_LIMIT_EXCEEDED | Daily transaction limit exceeded | 400 | Günlük işlem tutarı limiti aşıldı |
| BAD_REQUEST | MONTHLY_LIMIT_EXCEEDED | Monthly transaction limit exceeded | 400 | Aylık işlem tutarı limiti aşıldı |
| BAD_REQUEST | DAILY_COUNT_EXCEEDED | Daily transaction count exceeded | 400 | Günlük işlem adedi limiti aşıldı |
| BAD_REQUEST | MONTHLY_COUNT_EXCEEDED | Monthly transaction count exceeded | 400 | Aylık işlem adedi limiti aşıldı |
| BAD_REQUEST | INSTALLMENT_NOT_ALLOWED | Installment sales not allowed for this merchant | 400 | Merchant için taksitli ödeme aktif değil |
Hata Yanıtı Örneği
{
"success": false,
"error": {
"code": "BAD_REQUEST",
"subCode": "INVALID_CARD_NUMBER",
"message": "Invalid card number"
}
}
{
"success": false,
"error": {
"code": "CONFLICT",
"subCode": "DUPLICATE_ORDER_ID",
"message": "Order ID already exists for this merchant"
}
}