Payment Modifications
Payment Modifications Overview #
You can cancel or refund payments made in the marketplace system. On this page, you will learn about the following operations:
- PaymentRefund - Partial or full refund operations
- PaymentCancel - Payment cancellation (same day only)
Cancel vs Refund #
| Operation | When? | Description |
|---|---|---|
| Cancel | Same day | Payment is cancelled on the same day, customer is not charged |
| Refund | Next day and after | The charged amount is refunded to the customer, takes 2-10 business days |
Use PaymentCancel for same-day cancellation, PaymentRefund for subsequent days.
1. PaymentRefund #
Fully or partially refunds a completed payment.
Endpoint #
TEST:
POST https://apitest.paynkolay.com.tr/marketplace/v1/payment/refundPROD:
POST https://api.paynkolay.com.tr/marketplace/v1/payment/refundRequest Parameters #
{
"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
}
]
}Parameter Details #
| Parameter | Type | Required | Description |
|---|---|---|---|
| apiKey | String | ✅ | Calculated API key for cancellation/refund |
| apiSecretKey | String | ✅ | Special SX value for cancellation operations |
| mpCode | String | ✅ | Marketplace code |
| refCode | String | ✅ | Reference code of the original transaction |
| trxType | String | ✅ | Transaction type: refund |
| trxDate | String | ✅ | Transaction date (in yyyy-MM-dd format) |
| totalTrxAmount | BigDecimal | ✅ | Total refund amount |
| trxCurrency | String | ✅ | Currency (TRY, USD, EUR) |
Seller List (sellerList) #
| Parameter | Type | Required | Description |
|---|---|---|---|
| sellerExternalId | String | ✅ | Seller's external ID |
| trxAmount | BigDecimal | ✅ | Amount to be refunded |
| refundedCommissionAmount | BigDecimal | ❌ | Commission amount to be refunded |
| withholdingTax | BigDecimal | ❌ | Withholding tax amount to be refunded |
Refund Amount: 100 TL
Excluding VAT: 80 TL
Refund Withholding Tax: 80 TL × 0.01 = 0.8 TL
d-flex align-items-start mb-4" role="alert">
warning
Refund with Discount Parameters #
Things to consider when refunding discounted transactions:
Refund with Seller Discount #
{
"totalTrxAmount": 900.00,
"sellerList": [
{
"sellerExternalId": "SELLER_001",
"trxAmount": 1000.00,
"sellerDiscountAmount": 100.00,
"withholdingTax": 7.20
}
]
}Product Amount: 1000 TL
Seller Discount: 100 TL
Charged Amount (trxAmount - sellerDiscountAmount): 900 TL
totalTrxAmount: 900 TLRefund with Marketplace Discount #
{
"totalTrxAmount": 900.00,
"mpDiscountAmount": 100.00,
"sellerList": [
{
"sellerExternalId": "SELLER_001",
"trxAmount": 1000.00,
"sellerDiscountAmount": 0.00
}
]
}Product Amount: 1000 TL
Marketplace Discount: 100 TL
totalTrxAmount = trxAmount - mpDiscountAmount = 900 TLResponse #
{
"data": {
"trxStatus": "APPROVED",
"mpReferenceCode": "MPREF987654",
"trxType": "REFUND",
"trxReferenceCode": "REFUND123456"
},
"success": true,
"responseCode": "200",
"responseMessage": "SUCCESS"
}Partial Refund Example #
// 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 #
Cancels payments made on the same day.
Endpoint #
TEST:
POST https://apitest.paynkolay.com.tr/marketplace/v1/payment/cancelPROD:
POST https://api.paynkolay.com.tr/marketplace/v1/payment/cancelRequest Parameters #
{
"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": []
}| Parameter | Type | Required | Description |
|---|---|---|---|
| apiKey | String | ✅ | Calculated API key for cancellation |
| apiSecretKey | String | ✅ | Special SX value for cancellation operations |
| mpCode | String | ✅ | Marketplace code |
| refCode | String | ✅ | Reference code of the transaction to be cancelled |
| trxType | String | ✅ | Transaction type: cancel |
| trxDate | String | ✅ | Transaction date (in yyyy-MM-dd format) |
| totalTrxAmount | BigDecimal | ✅ | Total amount to be cancelled |
| trxCurrency | String | ✅ | Currency |
| sellerList | Array | ✅ | Sent as empty array [] |
Response #
{
"data": {
"trxStatus": "APPROVED",
"mpReferenceCode": "MPCANCEL987654",
"trxType": "CANCEL",
"trxReferenceCode": "CANCEL123456"
},
"success": true,
"responseCode": "200",
"responseMessage": "SUCCESS"
}Cancel/Refund Hash Calculation #
A special SX value is used for cancellation and refund operations, and the hash calculation is as follows:
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');The
apiSecretKey value used for cancellation/refund operations is different from payment operations. This value will be provided to you separately as cancellation sx.Full Refund Example #
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
}
]
);Partial Refund Scenarios #
Scenario 1: Single Product Refund (Multiple Sellers) #
// 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 edilmediScenario 2: Partial Amount Refund #
// 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
}
]);Scenario 3: Damaged Product Discount #
// Ü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
}
]);Error Situations #
Cancel/Refund May Fail Because: #
| Error | Reason | Solution |
|---|---|---|
| ALREADY_REFUNDED | Transaction already refunded | Check refund status |
| INSUFFICIENT_BALANCE | Insufficient balance | Seller account must have sufficient balance |
| INVALID_DATE | Invalid date | Check date format (yyyy-MM-dd) |
| TRANSACTION_NOT_FOUND | Transaction not found | Check refCode |
| SAME_DAY_USE_CANCEL | Refund used for same day | Use Cancel |
| INVALID_HASH | Hash validation error | Check cancellation SX value |
Error Handling Example #
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;
}
}Cancel/Refund Notification #
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;
}
}Next Steps #
After learning about cancellation and refund operations:
- 1. Masterpass Integration - Alternative payment methods
- 2. Reporting - Refund reports and analyses
- 3. Payment Operations - Payment processing