payfyio
Providers

PayTR

PayTR integration reference — iframe 3D payment, BIN check, installment info and refunds.

PayTR uses form-urlencoded requests and HMAC-SHA256 token validation. It supports the iframe 3D Secure flow, BIN/installment queries, and partial or full refunds.

Configuration

paytr: {
  enabled: true,
  config: {
    merchantId: process.env.PAYTR_MERCHANT_ID!,
    merchantKey: process.env.PAYTR_MERCHANT_KEY!,
    merchantSalt: process.env.PAYTR_MERCHANT_SALT!,
    baseUrl: 'https://www.paytr.com', // optional
    locale: 'tr',
  },
}

3D Secure (Iframe)

PayTR's primary payment flow is iframe-based 3D Secure.

Get Token:

const result = await payment.paytr.initThreeDSPayment({
  price: '100.00',
  paidPrice: '100.00',
  currency: Currency.TRY,
  callbackUrl: 'https://yoursite.com/payment/callback',
  buyer: { id, name, surname, email, ip, /* ... */ },
  basketItems: [{ id, name, category1, itemType, price }],
});

// Render the iframe HTML returned in result.threeDSHtmlContent
// or embed the token directly:
// <iframe src={`https://www.paytr.com/odeme/guvenli/${result.paymentId}`} />

Handle Callback (webhook):

// PayTR POSTs to your callbackUrl with merchant_oid, status, total_amount, hash
const result = await payment.paytr.completeThreeDSPayment(req.body);

if (result.status === 'success') {
  // update order in DB
}

// Must respond with "OK" to acknowledge
res.send('OK');

BIN Check

Query card network, bank, and card family from the first 6–8 digits.

const info = await payment.paytr.binCheck('552879');

console.log(info.bankName);       // "GARANTİ BANKASI T.A.Ş."
console.log(info.cardAssociation); // "VISA"
console.log(info.cardFamily);      // "Bonus"
console.log(info.cardType);        // "Kredi Kartı"

Via HTTP:

POST /api/pay/paytr/bin-check
{ "binNumber": "552879" }

Installment Info

Query available installment options for a BIN number and amount.

const info = await payment.paytr.installmentInfo({
  binNumber: '552879',
  price: '100.00',
});

if (info.status === 'success' && info.installmentDetails) {
  info.installmentDetails[0].installmentPrices.forEach((opt) => {
    console.log(`${opt.installmentNumber} taksit: ${opt.totalPrice} TL`);
  });
}

Via HTTP:

POST /api/pay/paytr/installment
{ "binNumber": "552879", "price": "100.00" }

Refund

await payment.paytr.refund({
  paymentId: 'merchant-oid',   // your order ID (merchant_oid)
  price: '50.00',
  currency: Currency.TRY,
});

Cancel

PayTR does not support payment voids. cancel() returns a FAILURE status with an explanatory message. To reverse a PayTR payment, call refund() with the original payment amount.

// This will fail — use refund() instead
await payment.paytr.cancel({ paymentId: 'order-id' });
// Returns: { status: 'failure', errorMessage: 'PayTR cancel requires...' }

// Correct approach:
await payment.paytr.refund({ paymentId: 'order-id', price: originalAmount });

On this page