Payment Modifications
Payment Modifications Overview
Section titled “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
Section titled “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 |
1. PaymentRefund
Section titled “1. PaymentRefund”Fully or partially refunds a completed payment.
Endpoint
Section titled “Endpoint”TEST:
POST https://apitest.paynkolay.com.tr/marketplace/v1/payment/refundPROD:
POST https://api.paynkolay.com.tr/marketplace/v1/payment/refundRequest Parameters
Section titled “Request 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
Section titled “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)
Section titled “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 with Discount Parameters
Section titled “Refund with Discount Parameters”Things to consider when refunding discounted transactions:
Refund with Seller Discount
Section titled “Refund with Seller Discount”{ "totalTrxAmount": 900.00, "sellerList": [ { "sellerExternalId": "SELLER_001", "trxAmount": 1000.00, "sellerDiscountAmount": 100.00, "withholdingTax": 7.20 } ]}Calculation:
Product Amount: 1000 TLSeller Discount: 100 TLCharged Amount (trxAmount - sellerDiscountAmount): 900 TLtotalTrxAmount: 900 TLRefund with Marketplace Discount
Section titled “Refund with Marketplace Discount”{ "totalTrxAmount": 900.00, "mpDiscountAmount": 100.00, "sellerList": [ { "sellerExternalId": "SELLER_001", "trxAmount": 1000.00, "sellerDiscountAmount": 0.00 } ]}Calculation:
Product Amount: 1000 TLMarketplace Discount: 100 TLtotalTrxAmount = trxAmount - mpDiscountAmount = 900 TLResponse
Section titled “Response”{ "data": { "trxStatus": "APPROVED", "mpReferenceCode": "MPREF987654", "trxType": "REFUND", "trxReferenceCode": "REFUND123456" }, "success": true, "responseCode": "200", "responseMessage": "SUCCESS"}Partial Refund Example
Section titled “Partial Refund Example”// Original payment: 500 TL (3 sellers)// 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, // Only 1 seller's amount trxCurrency: 'TRY', sellerList: [ { sellerExternalId: 'SELLER_001', trxAmount: 150.00, refundedCommissionAmount: 7.50, withholdingTax: 1.20 } // Other sellers are not sent ] });
return refund;}2. PaymentCancel
Section titled “2. PaymentCancel”Cancels payments made on the same day.
Endpoint
Section titled “Endpoint”TEST:
POST https://apitest.paynkolay.com.tr/marketplace/v1/payment/cancelPROD:
POST https://api.paynkolay.com.tr/marketplace/v1/payment/cancelRequest Parameters
Section titled “Request 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 Details
Section titled “Parameter Details”| 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
Section titled “Response”{ "data": { "trxStatus": "APPROVED", "mpReferenceCode": "MPCANCEL987654", "trxType": "CANCEL", "trxReferenceCode": "CANCEL123456" }, "success": true, "responseCode": "200", "responseMessage": "SUCCESS"}Cancel/Refund Hash Calculation
Section titled “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) { // String concatenation const hashString = apiSecretKey_iptal + '|' + merchantSecretKey;
// SHA512 hash const hash = crypto.createHash('sha512').update(hashString, 'utf8').digest();
// Base64 encode return hash.toString('base64');}
// Usageconst apiSecretKey_iptal = process.env.API_SECRET_KEY_CANCEL; // Special SX for cancellationconst merchantSecretKey = process.env.MERCHANT_SECRET_KEY;
const apiKey = calculateRefundCancelApiKey(apiSecretKey_iptal, merchantSecretKey);Full Refund Example
Section titled “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() { const hashString = this.apiSecretKey_cancel + '|' + this.merchantSecretKey; const hash = crypto.createHash('sha512').update(hashString, 'utf8').digest(); return hash.toString('base64'); }
async refundPayment(refCode, sellers) { // Calculate total amount const totalAmount = sellers.reduce((sum, seller) => { return sum + (seller.trxAmount - (seller.sellerDiscountAmount || 0)); }, 0);
// Calculate withholding tax const sellersWithTax = sellers.map(seller => ({ ...seller, withholdingTax: this.calculateWithholdingTax( seller.trxAmountWithoutVAT || seller.trxAmount * 0.8 ) }));
const apiKey = this.calculateRefundApiKey();
const response = await axios.post( 'https://apitest.paynkolay.com.tr/marketplace/v1/payment/refund', { apiKey, apiSecretKey: this.apiSecretKey_cancel, mpCode: this.mpCode, refCode, trxType: 'refund', trxDate: new Date().toISOString().split('T')[0], totalTrxAmount: totalAmount, trxCurrency: 'TRY', sellerList: sellersWithTax } );
return response.data; }
calculateWithholdingTax(amountWithoutVAT) { return amountWithoutVAT * 0.01; // 1% withholding tax }
async cancelPayment(refCode, totalAmount) { const apiKey = this.calculateRefundApiKey();
const response = await axios.post( 'https://apitest.paynkolay.com.tr/marketplace/v1/payment/cancel', { apiKey, apiSecretKey: this.apiSecretKey_cancel, mpCode: this.mpCode, refCode, trxType: 'cancel', trxDate: new Date().toISOString().split('T')[0], totalTrxAmount: totalAmount, trxCurrency: 'TRY', 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];
// If same day, cancel; otherwise refund if (paymentDay === today) { return await this.cancelPayment(refCode, totalAmount); } else { if (!sellers) { throw new Error('Seller information required for refund'); } return await this.refundPayment(refCode, sellers); } }}
// Usageconst manager = new PaymentRefundManager( process.env.API_SECRET_KEY, process.env.API_SECRET_KEY_CANCEL, process.env.MERCHANT_SECRET_KEY, 'MP12345');
// Automatic cancel or refundconst 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
Section titled “Partial Refund Scenarios”Scenario 1: Single Product Refund (Multiple Sellers)
Section titled “Scenario 1: Single Product Refund (Multiple Sellers)”// Original order: 3 sellers, total 500 TL// Only SELLER_002's product will be refunded
await refundPayment('REF123', [ { sellerExternalId: 'SELLER_002', trxAmount: 150.00, refundedCommissionAmount: 7.50, withholdingTax: 1.20 }]);// SELLER_001 and SELLER_003 were not refundedScenario 2: Partial Amount Refund
Section titled “Scenario 2: Partial Amount Refund”// Seller wants to give a discount// Original: 200 TL, Refund: 50 TL
await refundPayment('REF456', [ { sellerExternalId: 'SELLER_001', trxAmount: 50.00, // Only 50 TL refund refundedCommissionAmount: 2.50, withholdingTax: 0.40 }]);Scenario 3: Damaged Product Discount
Section titled “Scenario 3: Damaged Product Discount”// Product arrived damaged, 30% discount will be given// Original: 300 TL
await refundPayment('REF789', [ { sellerExternalId: 'SELLER_001', trxAmount: 90.00, // 300 * 0.30 = 90 TL refund refundedCommissionAmount: 4.50, withholdingTax: 0.72 }]);Error Situations
Section titled “Error Situations”Cancel/Refund May Fail Because:
Section titled “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
Section titled “Error Handling Example”async function safeRefund(refCode, sellers) { try { const result = await refundPayment(refCode, sellers);
if (result.success) { console.log('Refund successful:', result.data.trxReferenceCode); return result; } else { throw new Error(result.responseMessage); }
} catch (error) { console.error('Refund error:', error.message);
// Action based on error type if (error.message.includes('ALREADY_REFUNDED')) { console.log('This transaction has already been refunded'); // Update in database } else if (error.message.includes('INSUFFICIENT_BALANCE')) { console.log('Insufficient balance, try again later'); // Add to queue } else { // General error console.log('Refund failed, notify support team'); }
throw error; }}Cancel/Refund Notification
Section titled “Cancel/Refund Notification”async function processRefundWithNotification(refCode, sellers, customerEmail) { try { // 1. Process refund const result = await refundPayment(refCode, sellers);
// 2. Send notification to customer await sendEmail(customerEmail, { subject: 'Your Refund Has Been Initiated', body: ` Hello,
A refund has been initiated for your order number ${refCode}.
Refund Amount: ${result.data.totalAmount} TL Refund Reference: ${result.data.trxReferenceCode}
The refund amount will be credited to your account within 2-10 business days.
Have a great day. ` });
// 3. Notify sellers for (const seller of sellers) { await notifySeller(seller.sellerExternalId, { refCode, amount: seller.trxAmount, commission: seller.refundedCommissionAmount }); }
return result;
} catch (error) { // Inform customer in case of error await sendEmail(customerEmail, { subject: 'Refund Process Failed', body: 'There was a problem with your refund. Please contact customer service.' });
throw error; }}Next Steps
Section titled “Next Steps”After learning about cancellation and refund operations:
- Masterpass Integration - Alternative payment methods
- Reporting - Refund reports and analyses
- Payment Operations - Payment processing