Esc
Aramaya başlamak için yazın...

Ödeme Değişiklikleri

Ödeme Değişiklikleri Genel Bakış #

Pazaryeri sisteminde gerçekleşen ödemeleri iptal edebilir veya iade yapabilirsiniz. Bu sayfada aşağıdaki işlemleri öğreneceksiniz:

  • PaymentRefund - Kısmi veya tam iade işlemleri
  • PaymentCancel - Ödeme iptali (aynı gün içinde)

İptal vs İade #

İşlemNe Zaman?Açıklama
CancelAynı günÖdeme işlemi aynı gün içinde iptal edilir, müşteriden para çekilmez
RefundErtesi gün ve sonrasıÇekilen para müşteriye iade edilir, 2-10 iş günü sürer

1. PaymentRefund #

Gerçekleşmiş bir ödemeyi tamamen veya kısmen iade eder.

Endpoint #

TEST:

POST https://apitest.paynkolay.com.tr/marketplace/v1/payment/refund

PROD:

POST https://api.paynkolay.com.tr/marketplace/v1/payment/refund

İstek Parametreleri #

{
  "apiKey": "calculated_api_key_for_refund",
  "apiSecretKey": "sx_iptal_value",
  "mpCode": "MP12345",
  "refCode": "REF123456789",
  "trxType": "refund",
  "trxDate": "2025-01-20",
  "totalTrxAmount": 150.00,
  "trxCurrency": "TRY",
  "sellerList": [
    {
      "sellerExternalId": "SELLER_001",
      "trxAmount": 100.00,
      "refundedCommissionAmount": 5.00,
      "withholdingTax": 0.80
    },
    {
      "sellerExternalId": "SELLER_002",
      "trxAmount": 50.00,
      "refundedCommissionAmount": 2.50,
      "withholdingTax": 0.40
    }
  ]
}

Parametre Detayları #

ParametreTipZorunluAçıklama
apiKeyStringİptal/iade için hesaplanmış API anahtarı
apiSecretKeyStringİptal işlemleri için özel SX değeri
mpCodeStringPazaryeri kodu
refCodeStringOrijinal işlemin referans kodu
trxTypeStringİşlem tipi: refund
trxDateStringİşlem tarihi (yyyy-MM-dd formatında)
totalTrxAmountBigDecimalToplam iade tutarı
trxCurrencyStringPara birimi (TRY, USD, EUR)

Satıcı Listesi (sellerList) #

ParametreTipZorunluAçıklama
sellerExternalIdStringSatıcının external ID'si
trxAmountBigDecimalİade edilecek tutar
refundedCommissionAmountBigDecimalİade edilecek komisyon tutarı
withholdingTaxBigDecimalİade edilecek stopaj tutarı
İade Tutarı: 100 TL KDV Hariç: 80 TL İade Stopajı: 80 TL × 0.01 = 0.8 TL d-flex align-items-start mb-4" role="alert">
warning

İndirim Parametreleri ile İade #

İndirim uygulanan işlemlerde iade yaparken dikkat edilmesi gerekenler:

Satıcı İndirimi Olan İade #

{
  "totalTrxAmount": 900.00,
  "sellerList": [
    {
      "sellerExternalId": "SELLER_001",
      "trxAmount": 1000.00,
      "sellerDiscountAmount": 100.00,
      "withholdingTax": 7.20
    }
  ]
}
Ürün Tutarı: 1000 TL
Satıcı İndirimi: 100 TL
Çekilen Tutar (trxAmount - sellerDiscountAmount): 900 TL
totalTrxAmount: 900 TL

Pazaryeri İndirimi Olan İade #

{
  "totalTrxAmount": 900.00,
  "mpDiscountAmount": 100.00,
  "sellerList": [
    {
      "sellerExternalId": "SELLER_001",
      "trxAmount": 1000.00,
      "sellerDiscountAmount": 0.00
    }
  ]
}
Ürün Tutarı: 1000 TL
Pazaryeri İndirimi: 100 TL
totalTrxAmount = trxAmount - mpDiscountAmount = 900 TL

Yanıt #

{
  "data": {
    "trxStatus": "APPROVED",
    "mpReferenceCode": "MPREF987654",
    "trxType": "REFUND",
    "trxReferenceCode": "REFUND123456"
  },
  "success": true,
  "responseCode": "200",
  "responseMessage": "SUCCESS"
}

Kısmi İade Örneği #

// Orijinal ödeme: 500 TL (3 satıcı)
// Sadece 1 satıcıya iade yapılacak / Only 1 seller will be refunded

async function partialRefund() {
  const refund = await paymentRefund({
    apiKey: calculateRefundApiKey(),
    apiSecretKey: process.env.API_SECRET_KEY_CANCEL,
    mpCode: 'MP12345',
    refCode: 'REF_ORIGINAL',
    trxType: 'refund',
    trxDate: '2025-01-20',
    totalTrxAmount: 150.00,  // Sadece 1 satıcının tutarı / Only 1 seller's amount
    trxCurrency: 'TRY',
    sellerList: [
      {
        sellerExternalId: 'SELLER_001',
        trxAmount: 150.00,
        refundedCommissionAmount: 7.50,
        withholdingTax: 1.20
      }
      // Diğer satıcılar gönderilmez / Other sellers are not sent
    ]
  });

  return refund;
}

2. PaymentCancel #

Aynı gün içinde gerçekleşen ödemeleri iptal eder.

Endpoint #

TEST:

POST https://apitest.paynkolay.com.tr/marketplace/v1/payment/cancel

PROD:

POST https://api.paynkolay.com.tr/marketplace/v1/payment/cancel

İstek Parametreleri #

{
  "apiKey": "calculated_api_key_for_cancel",
  "apiSecretKey": "sx_iptal_value",
  "mpCode": "MP12345",
  "refCode": "REF123456789",
  "trxType": "cancel",
  "trxDate": "2025-01-20",
  "totalTrxAmount": 150.00,
  "trxCurrency": "TRY",
  "sellerList": []
}
ParametreTipZorunluAçıklama
apiKeyStringİptal için hesaplanmış API anahtarı
apiSecretKeyStringİptal işlemleri için özel SX değeri
mpCodeStringPazaryeri kodu
refCodeStringİptal edilecek işlemin referans kodu
trxTypeStringİşlem tipi: cancel
trxDateStringİşlem tarihi (yyyy-MM-dd formatında)
totalTrxAmountBigDecimalİptal edilecek toplam tutar
trxCurrencyStringPara birimi
sellerListArrayBoş array gönderilir []

Yanıt #

{
  "data": {
    "trxStatus": "APPROVED",
    "mpReferenceCode": "MPCANCEL987654",
    "trxType": "CANCEL",
    "trxReferenceCode": "CANCEL123456"
  },
  "success": true,
  "responseCode": "200",
  "responseMessage": "SUCCESS"
}

İptal/İade Hash Hesaplama #

İptal ve iade işlemleri için özel bir SX değeri kullanılır ve hash hesaplaması aşağıdaki gibidir:

const crypto = require('crypto');

function calculateRefundCancelApiKey(apiSecretKey_iptal, merchantSecretKey, trxType, trxDate, amount, trxCurrency, referenceCode) {
  // String birleştirme
  const hashString = apiSecretKey_iptal + '|' + merchantSecretKey + '|' + trxType + '|' + trxDate + '|' + amount + '|' + trxCurrency + '|' + referenceCode;

  // SHA512 hash
  const hash = crypto.createHash('sha512').update(hashString, 'utf8').digest();

  // Base64 encode
  return hash.toString('base64');
}

// Kullanım
const apiSecretKey_iptal = process.env.API_SECRET_KEY_CANCEL; // İptal için özel SX
const merchantSecretKey = process.env.MERCHANT_SECRET_KEY;

const apiKey = calculateRefundCancelApiKey(apiSecretKey_iptal, merchantSecretKey, 'refund', '2025-01-20', 100.00, 'TRY', 'REF123');

Tam İade Örneği #

class PaymentRefundManager {
  constructor(apiSecretKey, apiSecretKey_cancel, merchantSecretKey, mpCode) {
    this.apiSecretKey = apiSecretKey;
    this.apiSecretKey_cancel = apiSecretKey_cancel;
    this.merchantSecretKey = merchantSecretKey;
    this.mpCode = mpCode;
  }

  calculateRefundApiKey(trxType, trxDate, amount, trxCurrency, referenceCode) {
    const hashString = this.apiSecretKey_cancel + '|' + this.merchantSecretKey + '|' + trxType + '|' + trxDate + '|' + amount + '|' + trxCurrency + '|' + referenceCode;
    const hash = crypto.createHash('sha512').update(hashString, 'utf8').digest();
    return hash.toString('base64');
  }

  async refundPayment(refCode, sellers) {
    // Toplam tutarı hesapla
    const totalAmount = sellers.reduce((sum, seller) => {
      return sum + (seller.trxAmount - (seller.sellerDiscountAmount || 0));
    }, 0);

    // Stopaj hesapla
    const sellersWithTax = sellers.map(seller => ({
      ...seller,
      withholdingTax: this.calculateWithholdingTax(
        seller.trxAmountWithoutVAT || seller.trxAmount * 0.8
      )
    }));

    const trxType = 'refund';
    const trxDate = new Date().toISOString().split('T')[0];
    const trxCurrency = 'TRY';
    const apiKey = this.calculateRefundApiKey(trxType, trxDate, totalAmount, trxCurrency, refCode);

    const response = await axios.post(
      'https://apitest.paynkolay.com.tr/marketplace/v1/payment/refund',
      {
        apiKey,
        apiSecretKey: this.apiSecretKey_cancel,
        mpCode: this.mpCode,
        refCode,
        trxType,
        trxDate,
        totalTrxAmount: totalAmount,
        trxCurrency,
        sellerList: sellersWithTax
      }
    );

    return response.data;
  }

  calculateWithholdingTax(amountWithoutVAT) {
    return amountWithoutVAT * 0.01; // %1 stopaj
  }

  async cancelPayment(refCode, totalAmount) {
    const trxType = 'cancel';
    const trxDate = new Date().toISOString().split('T')[0];
    const trxCurrency = 'TRY';
    const apiKey = this.calculateRefundApiKey(trxType, trxDate, totalAmount, trxCurrency, refCode);

    const response = await axios.post(
      'https://apitest.paynkolay.com.tr/marketplace/v1/payment/cancel',
      {
        apiKey,
        apiSecretKey: this.apiSecretKey_cancel,
        mpCode: this.mpCode,
        refCode,
        trxType,
        trxDate,
        totalTrxAmount: totalAmount,
        trxCurrency,
        sellerList: []
      }
    );

    return response.data;
  }

  async cancelOrRefund(refCode, paymentDate, totalAmount, sellers = null) {
    const today = new Date().toISOString().split('T')[0];
    const paymentDay = new Date(paymentDate).toISOString().split('T')[0];

    // Aynı gün ise cancel, değilse refund
    if (paymentDay === today) {
      return await this.cancelPayment(refCode, totalAmount);
    } else {
      if (!sellers) {
        throw new Error('Refund için satıcı bilgileri gerekli');
      }
      return await this.refundPayment(refCode, sellers);
    }
  }
}

// Kullanım
const manager = new PaymentRefundManager(
  process.env.API_SECRET_KEY,
  process.env.API_SECRET_KEY_CANCEL,
  process.env.MERCHANT_SECRET_KEY,
  'MP12345'
);

// Otomatik cancel veya refund
const result = await manager.cancelOrRefund(
  'REF123456789',
  '2025-01-20',
  150.00,
  [
    {
      sellerExternalId: 'SELLER_001',
      trxAmount: 100.00,
      refundedCommissionAmount: 5.00
    },
    {
      sellerExternalId: 'SELLER_002',
      trxAmount: 50.00,
      refundedCommissionAmount: 2.50
    }
  ]
);

Kısmi İade Senaryoları #

Senaryo 1: Tek Ürün İadesi (Çok Satıcılı) #

// Orijinal sipariş: 3 satıcı, toplam 500 TL
// Sadece SELLER_002'nin ürünü iade edilecek

await refundPayment('REF123', [
  {
    sellerExternalId: 'SELLER_002',
    trxAmount: 150.00,
    refundedCommissionAmount: 7.50,
    withholdingTax: 1.20
  }
]);
// SELLER_001 ve SELLER_003 iade edilmedi

Senaryo 2: Kısmi Tutar İadesi #

// Satıcı indirim yapmak istiyor
// Orijinal: 200 TL, İade: 50 TL

await refundPayment('REF456', [
  {
    sellerExternalId: 'SELLER_001',
    trxAmount: 50.00,  // Sadece 50 TL iade
    refundedCommissionAmount: 2.50,
    withholdingTax: 0.40
  }
]);

Senaryo 3: Hasarlı Ürün İndirimi #

// Ürün hasarlı geldi, %30 indirim yapılacak
// Orijinal: 300 TL

await refundPayment('REF789', [
  {
    sellerExternalId: 'SELLER_001',
    trxAmount: 90.00,  // 300 * 0.30 = 90 TL iade
    refundedCommissionAmount: 4.50,
    withholdingTax: 0.72
  }
]);

Hata Durumları #

İptal/İade Başarısız Olabilir Çünkü: #

HataSebepÇözüm
ALREADY_REFUNDEDİşlem zaten iade edilmişİade durumunu kontrol edin
INSUFFICIENT_BALANCEYetersiz bakiyeSatıcı hesabında yeterli bakiye olmalı
INVALID_DATEGeçersiz tarihTarih formatını kontrol edin (yyyy-MM-dd)
TRANSACTION_NOT_FOUNDİşlem bulunamadırefCode'u kontrol edin
SAME_DAY_USE_CANCELAynı gün için refund kullanılmışCancel kullanın
INVALID_HASHHash doğrulama hatasıİptal SX değerini kontrol edin

Hata Yönetimi Örneği #

async function safeRefund(refCode, sellers) {
  try {
    const result = await refundPayment(refCode, sellers);

    if (result.success) {
      console.log('İade başarılı:', result.data.trxReferenceCode);
      return result;
    } else {
      throw new Error(result.responseMessage);
    }

  } catch (error) {
    console.error('İade hatası:', error.message);

    // Hata tipine göre işlem
    if (error.message.includes('ALREADY_REFUNDED')) {
      console.log('Bu işlem zaten iade edilmiş');
      // Veritabanında güncelle
    } else if (error.message.includes('INSUFFICIENT_BALANCE')) {
      console.log('Yetersiz bakiye, sonra tekrar dene');
      // Kuyruğa ekle
    } else {
      // Genel hata
      console.log('İade başarısız, destek ekibine bildir');
    }

    throw error;
  }
}

İptal/İade Bildirimi #

async function processRefundWithNotification(refCode, sellers, customerEmail) {
  try {
    // 1. İade işlemini gerçekleştir
    const result = await refundPayment(refCode, sellers);

    // 2. Müşteriye bildirim gönder
    await sendEmail(customerEmail, {
      subject: 'İade İşleminiz Başlatıldı',
      body: `
        Merhaba,

        ${refCode} numaralı siparişiniz için iade işlemi başlatılmıştır.

        İade Tutarı: ${result.data.totalAmount} TL
        İade Referans: ${result.data.trxReferenceCode}

        İade tutarı 2-10 iş günü içinde hesabınıza geçecektir.

        İyi günler dileriz.
      `
    });

    // 3. Satıcılara bildir
    for (const seller of sellers) {
      await notifySeller(seller.sellerExternalId, {
        refCode,
        amount: seller.trxAmount,
        commission: seller.refundedCommissionAmount
      });
    }

    return result;

  } catch (error) {
    // Hata durumunda da müşteriyi bilgilendir
    await sendEmail(customerEmail, {
      subject: 'İade İşlemi Başarısız',
      body: 'İade işleminizde bir sorun oluştu. Lütfen müşteri hizmetleriyle iletişime geçin.'
    });

    throw error;
  }
}

Sonraki Adımlar #

İptal ve iade işlemlerini öğrendikten sonra: