Genel Bilgiler

Base URL

https://api.metalpay.net/api

Content-Type

Tüm isteklerde Content-Type: application/json header'ı gönderilmelidir.

Response Formatı

API, JSON formatında yanıt döner. Başarılı işlemlerde result: true, hatalı işlemlerde result: false döner.


Kimlik Doğrulama (Authentication)

MetalPay API, hash-based authentication kullanır. Her istekte aşağıdaki header'lar gönderilmelidir:

Zorunlu Header'lar

HeaderAçıklamaÖrnek
requestIdBenzersiz istek ID'sireq-1234567890
swtIdMerchant'ın Switch ID'siAB9900EFA5EA4E89AEC05D554B98297D
hashedDataHesaplanmış hash değeriA1B2C3D4E5F6...
timestampİşlem zamanı2025-01-15T10:30:00.0000000

Opsiyonel Header'lar

HeaderAçıklamaÖrnek
userIdKullanıcı ID'siuser-123

Not: Header'lar HTTP header olarak gönderilebileceği gibi, request body içinde header objesi içinde de gönderilebilir.


Hash Hesaplama

Hash değeri, aşağıdaki formül kullanılarak hesaplanır:

Hash = SHA256(requestId + swtId + userId + timestamp + switchPassword).toUpperCase()

Hash Hesaplama Adımları

  1. Değerleri birleştirin: Aşağıdaki değerleri sırayla birleştirin (aralarında boşluk veya ayırıcı karakter olmadan):

    requestId + swtId + userId + timestamp + switchPassword
    

    Birleştirilecek değerler:

    DeğerTipAçıklama
    requestIdstringBenzersiz istek ID'si
    swtIdstringMerchant'ın Switch ID'si
    userIdstringKullanıcı ID'si (boş olabilir)
    timestampstringİşlem zamanı
    switchPasswordstringMerchant'a verilen şifre
  2. Hash hesaplayın: Birleştirilmiş string'i SHA256 algoritması ile hash'leyin

  3. Büyük harfe çevirin: Hash sonucunu büyük harfe çevirin (uppercase)

Hash Hesaplama Örneği

const crypto = require('crypto');

const requestId = "req-1234567890";
const swtId = "AB9900EFA5EA4E89AEC05D554B98297D";
const userId = ""; // Boş olabilir
const timestamp = "2025-01-15T10:30:00.0000000";
const switchPassword = "your-switch-password";

const concatenated = requestId + swtId + userId + timestamp + switchPassword;
const hash = crypto.createHash('sha256').update(concatenated, 'utf8').digest('hex').toUpperCase();

console.log(hash); // Örnek: A1B2C3D4E5F6...

Önemli: Hash hesaplamasında request body içeriği kullanılmaz. Sadece header bilgileri kullanılır.


Endpoint'ler

Ödeme İşlemleri

1. 3D'siz Satış (Kart Bilgileriyle)

Kart bilgileriyle direkt ödeme işlemi yapar.

Endpoint: POST /api/payment/auth

Header'lar:

requestId: <benzersiz-istek-id>
swtId: <merchant-switch-id>
hashedData: <hesaplanmış-hash>
timestamp: <işlem-zamanı>
userId: <opsiyonel-kullanıcı-id>

Request Body:

Format 1: Standart Format

{
  "txnAmount": "100.00",
  "currencyNumber": 949,
  "card": {
    "number": "4506347052345678",
    "expireMonth": "12",
    "expireYear": "2025",
    "cvv": "123"
  },
  "orderId": "ORDER-123456"
}

Format 2: Alternatif Format

{
  "amount": "100.00",
  "currency": "TRY",
  "cardNumber": "4506347052345678",
  "expiryMonth": "12",
  "expiryYear": "2025",
  "cvv": "123",
  "orderId": "ORDER-123456"
}

Request Parametreleri:

Standart Format:

ParametreTipZorunluAçıklama
txnAmountstring/numberEvetÖdeme tutarı
currencyNumbernumberHayırPara birimi (949=TRY, 840=USD, 978=EUR)
card.numberstringEvetKart numarası (16 haneli)
card.expireMonthstring/numberEvetSon kullanma ayı (1-12)
card.expireYearstring/numberEvetSon kullanma yılı (2 veya 4 haneli)
card.cvvstringHayırCVV kodu (3-4 haneli)
orderIdstringHayırSipariş ID'si
acquirer.bankIdstringHayırVirtual POS ID'si

Alternatif Format:

ParametreTipZorunluAçıklama
amountstring/numberEvetÖdeme tutarı
currencystringHayırPara birimi (TRY, USD, EUR)
cardNumberstringEvetKart numarası (16 haneli)
expiryMonthstring/numberEvetSon kullanma ayı (1-12)
expiryYearstring/numberEvetSon kullanma yılı (2 veya 4 haneli)
cvvstringHayırCVV kodu (3-4 haneli)
orderIdstringHayırSipariş ID'si
acquirer.bankIdstringHayırVirtual POS ID'si

Response (Başarılı):

{
  "result": true,
  "transactionId": "txn-1234567890",
  "amount": "100.00",
  "currency": "TRY",
  "status": "approved",
  "timestamp": "2025-01-15T10:30:00.0000000"
}

Response (Hata):

{
  "result": false,
  "errorCode": "INSUFFICIENT_FUNDS",
  "errorMessage": "Yetersiz bakiye"
}

2. 3D'siz Satış (Token ile)

Kaydedilmiş kart token'ı ile ödeme işlemi yapar.

Endpoint: POST /api/payment/token/auth

Header'lar:

requestId: <benzersiz-istek-id>
swtId: <merchant-switch-id>
hashedData: <hesaplanmış-hash>
timestamp: <işlem-zamanı>
userId: <opsiyonel-kullanıcı-id>

Request Body:

Format 1: Standart Format

{
  "txnAmount": "150.00",
  "currencyNumber": 949,
  "card": {
    "token": "550e8400-e29b-41d4-a716-446655440000"
  },
  "orderId": "ORDER-123457"
}

Format 2: Alternatif Format

{
  "amount": "150.00",
  "currency": "TRY",
  "token": "550e8400-e29b-41d4-a716-446655440000",
  "orderId": "ORDER-123457"
}

Request Parametreleri:

Standart Format:

ParametreTipZorunluAçıklama
txnAmountstring/numberEvetÖdeme tutarı
currencyNumbernumberHayırPara birimi (949=TRY, 840=USD, 978=EUR)
card.tokenstringEvetKart token'ı
orderIdstringHayırSipariş ID'si
acquirer.bankIdstringHayırVirtual POS ID'si

Alternatif Format:

ParametreTipZorunluAçıklama
amountstring/numberEvetÖdeme tutarı
currencystringHayırPara birimi (TRY, USD, EUR)
tokenstringEvetKart token'ı
orderIdstringHayırSipariş ID'si
acquirer.bankIdstringHayırVirtual POS ID'si

Response (Başarılı):

{
  "result": true,
  "transactionId": "txn-1234567891",
  "amount": "150.00",
  "currency": "TRY",
  "status": "approved",
  "timestamp": "2025-01-15T10:31:00.0000000"
}

3. PostAuth İşlemi

Önceden yapılmış bir işlemin tutarını artırma işlemi.

Endpoint: POST /api/payment/postauth

Header'lar:

requestId: <benzersiz-istek-id>
swtId: <merchant-switch-id>
hashedData: <hesaplanmış-hash>
timestamp: <işlem-zamanı>
userId: <opsiyonel-kullanıcı-id>

Request Body:

{
  "txnAmount": "200.00",
  "currencyNumber": 949
}

Request Parametreleri:

Standart Format:

ParametreTipZorunluAçıklama
txnAmountstring/numberEvetArtırılacak tutar
currencyNumbernumberHayırPara birimi (949=TRY, 840=USD, 978=EUR)

Alternatif Format:

ParametreTipZorunluAçıklama
amountstring/numberEvetArtırılacak tutar
currencystringHayırPara birimi (TRY, USD, EUR)

Response (Başarılı):

{
  "result": true,
  "transactionId": "txn-1234567892",
  "amount": "200.00",
  "currency": "TRY",
  "status": "approved"
}

Token İşlemleri

4. Token Oluşturma (Kart Saklama)

Kart bilgilerini saklayarak token oluşturur. Bu token ile daha sonra ödeme yapılabilir.

Endpoint: POST /api/token/generate

Header'lar:

requestId: <benzersiz-istek-id>
swtId: <merchant-switch-id>
hashedData: <hesaplanmış-hash>
timestamp: <işlem-zamanı>
userId: <opsiyonel-kullanıcı-id>

Request Body:

Format 1: Standart Format

{
  "card": {
    "number": "4506347052345678",
    "expireMonth": "12",
    "expireYear": "2025",
    "holderName": "Test User",
    "cvv": "123"
  }
}

Format 2: Alternatif Format

{
  "cardNumber": "4506347052345678",
  "expiryMonth": "12",
  "expiryYear": "2025",
  "cardHolderName": "Test User",
  "cvv": "123"
}

Request Parametreleri:

Standart Format:

ParametreTipZorunluAçıklama
card.numberstringEvetKart numarası (16 haneli)
card.expireMonthstring/numberEvetSon kullanma ayı (1-12)
card.expireYearstring/numberEvetSon kullanma yılı (2 veya 4 haneli)
card.holderNamestringHayırKart sahibi adı
card.cvvstringHayırCVV kodu (PCI DSS gereği saklanmaz)

Alternatif Format:

ParametreTipZorunluAçıklama
cardNumberstringEvetKart numarası (16 haneli)
expiryMonthstring/numberEvetSon kullanma ayı (1-12)
expiryYearstring/numberEvetSon kullanma yılı (2 veya 4 haneli)
cardHolderNamestringHayırKart sahibi adı
cvvstringHayırCVV kodu (PCI DSS gereği saklanmaz)

Response (Başarılı):

{
  "header": {
    "requestId": "req-1234567890",
    "swtId": "AB9900EFA5EA4E89AEC05D554B98297D",
    "returnCode": "00",
    "reasonCode": "00",
    "message": "Başarılı",
    "timestamp": "2025-01-15T10:30:00.0000000",
    "hashedData": "A1B2C3D4E5F6..."
  },
  "card": {
    "token": "550e8400-e29b-41d4-a716-446655440000",
    "last4": "5678",
    "brand": "VISA",
    "expireMonth": "12",
    "expireYear": "2025"
  },
  "result": true
}

Response (Hata):

{
  "header": {
    "requestId": "req-1234567890",
    "swtId": "AB9900EFA5EA4E89AEC05D554B98297D",
    "returnCode": "99",
    "reasonCode": "99",
    "message": "Kart bilgileri geçersiz",
    "timestamp": "2025-01-15T10:30:00.0000000",
    "hashedData": "A1B2C3D4E5F6..."
  },
  "result": false,
  "errorMessage": "Kart bilgileri geçersiz"
}

Kart İşlemleri

5. Kart Saklama (Legacy Endpoint)

Not: Bu endpoint geriye uyumluluk için mevcuttur. Yeni entegrasyonlarda /api/token/generate kullanılmalıdır.

Endpoint: POST /api/card/save

Header'lar:

requestId: <benzersiz-istek-id>
swtId: <merchant-switch-id>
hashedData: <hesaplanmış-hash>
timestamp: <işlem-zamanı>
userId: <opsiyonel-kullanıcı-id>

Request Body:

{
  "cardNumber": "4506347052345678",
  "expiryMonth": "12",
  "expiryYear": "2025",
  "cardHolderName": "Test User",
  "cvv": "123"
}

Response: /api/token/generate ile aynı format.


6. Kaydedilmiş Kartları Listeleme

Merchant'a ait kaydedilmiş kartları listeler.

Endpoint: GET /api/card/list

Header'lar:

requestId: <benzersiz-istek-id>
swtId: <merchant-switch-id>
hashedData: <hesaplanmış-hash>
timestamp: <işlem-zamanı>
userId: <opsiyonel-kullanıcı-id>

Request Body: Yok (GET isteği)

Response (Başarılı):

{
  "result": true,
  "cards": [
    {
      "token": "550e8400-e29b-41d4-a716-446655440000",
      "last4": "5678",
      "brand": "VISA",
      "expireMonth": "12",
      "expireYear": "2025",
      "holderName": "Test User",
      "createdAt": "2025-01-15T10:30:00.000Z"
    }
  ]
}

Hata Kodları

Hata KoduAçıklama
VALIDATION_ERRORİstek validasyon hatası
MISSING_REQUEST_IDRequest ID eksik
MISSING_SWT_IDSwitch ID eksik
MISSING_HASHED_DATAHash değeri eksik
MISSING_TIMESTAMPTimestamp eksik
INVALID_SWT_IDGeçersiz Switch ID
INVALID_HASHGeçersiz hash değeri
INSUFFICIENT_FUNDSYetersiz bakiye
INVALID_CARDGeçersiz kart bilgileri
CARD_EXPIREDKartın süresi dolmuş
TRANSACTION_DECLINEDİşlem reddedildi
NO_VIRTUAL_POSAktif Virtual POS bulunamadı

Örnek İstekler

cURL Örneği - Token Oluşturma

curl -X POST https://api.metalpay.net/api/token/generate \
  -H "Content-Type: application/json" \
  -H "requestId: req-1234567890" \
  -H "swtId: AB9900EFA5EA4E89AEC05D554B98297D" \
  -H "hashedData: A1B2C3D4E5F6..." \
  -H "timestamp: 2025-01-15T10:30:00.0000000" \
  -d '{
    "card": {
      "number": "4506347052345678",
      "expireMonth": "12",
      "expireYear": "2025",
      "holderName": "Test User",
      "cvv": "123"
    }
  }'

JavaScript (Node.js) Örneği

const crypto = require('crypto');
const axios = require('axios');

// Hash hesaplama fonksiyonu
function calculateHash(requestId, swtId, userId, timestamp, switchPassword) {
  const concatenated = requestId + swtId + (userId || '') + timestamp + switchPassword;
  return crypto.createHash('sha256').update(concatenated, 'utf8').digest('hex').toUpperCase();
}

// Token oluşturma örneği
async function generateToken() {
  const requestId = `req-${Date.now()}`;
  const swtId = 'AB9900EFA5EA4E89AEC05D554B98297D';
  const userId = '';
  const timestamp = new Date().toISOString().replace(/[-T:]/g, '').substring(0, 15);
  const switchPassword = 'your-switch-password';
  
  const hashedData = calculateHash(requestId, swtId, userId, timestamp, switchPassword);
  
  try {
    const response = await axios.post(
      'https://api.metalpay.net/api/token/generate',
      {
        card: {
          number: '4506347052345678',
          expireMonth: '12',
          expireYear: '2025',
          holderName: 'Test User',
          cvv: '123'
        }
      },
      {
        headers: {
          'Content-Type': 'application/json',
          'requestId': requestId,
          'swtId': swtId,
          'hashedData': hashedData,
          'timestamp': timestamp
        }
      }
    );
    
    console.log('Token:', response.data.card.token);
    return response.data;
  } catch (error) {
    console.error('Hata:', error.response?.data || error.message);
    throw error;
  }
}

Python Örneği

import hashlib
import requests
from datetime import datetime

def calculate_hash(request_id, swt_id, user_id, timestamp, switch_password):
    """Hash hesaplama fonksiyonu"""
    concatenated = request_id + swt_id + (user_id or '') + timestamp + switch_password
    return hashlib.sha256(concatenated.encode('utf-8')).hexdigest().upper()

# Token oluşturma örneği
def generate_token():
    request_id = f"req-{int(datetime.now().timestamp() * 1000)}"
    swt_id = 'AB9900EFA5EA4E89AEC05D554B98297D'
    user_id = ''
    timestamp = datetime.now().strftime('%Y%m%d%H%M%S')
    switch_password = 'your-switch-password'
    
    hashed_data = calculate_hash(request_id, swt_id, user_id, timestamp, switch_password)
    
    headers = {
        'Content-Type': 'application/json',
        'requestId': request_id,
        'swtId': swt_id,
        'hashedData': hashed_data,
        'timestamp': timestamp
    }
    
    data = {
        'card': {
            'number': '4506347052345678',
            'expireMonth': '12',
            'expireYear': '2025',
            'holderName': 'Test User',
            'cvv': '123'
        }
    }
    
    response = requests.post(
        'https://api.metalpay.net/api/token/generate',
        json=data,
        headers=headers
    )
    
    if response.status_code == 200:
        result = response.json()
        print(f"Token: {result['card']['token']}")
        return result
    else:
        print(f"Hata: {response.json()}")
        raise Exception(f"API hatası: {response.status_code}")

Önemli Notlar

Güvenlik

  • CVV bilgisi kart saklama işlemlerinde saklanmaz (PCI DSS uyumluluğu)
  • Tüm kart bilgileri şifrelenmiş olarak saklanır
  • Hash hesaplamasında switch password asla açık metin olarak gönderilmez

Para Birimi Kodları

  • 949 = TRY (Türk Lirası)
  • 840 = USD (Amerikan Doları)
  • 978 = EUR (Euro)
  • 826 = GBP (İngiliz Sterlini)
  • 392 = JPY (Japon Yeni)

Timestamp Formatı

  • ISO 8601 formatı: 2025-01-15T10:30:00.0000000
  • Unix timestamp (milisaniye): 1705315800000
  • Her iki format da kabul edilir

Request ID

  • Her istek için benzersiz olmalıdır
  • Aynı request ID ile tekrar istek gönderilmemelidir
  • UUID veya timestamp-based ID kullanılabilir

Virtual POS

  • Eğer acquirer.bankId parametresi gönderilmezse, merchant'a ait aktif Virtual POS otomatik seçilir
  • Öncelik sırası: Ziraat > İş Bankası > Diğer

Destek

Sorularınız için lütfen destek ekibi ile iletişime geçin.

Son Güncelleme: 2025-01-15