Akbank
Akbank Sanal POS (JSON API) integration reference.
Uses Akbank's Sanal POS JSON API. Every request carries an auth-hash header
(base64(HMAC-SHA512(body, secretKey))).
Configuration
import { betterPayment, akbank } from 'better-payment';
const payment = betterPayment({
providers: {
akbank: akbank({
merchantSafeId: process.env.AKBANK_MERCHANT_SAFE_ID!,
terminalSafeId: process.env.AKBANK_TERMINAL_SAFE_ID!,
secretKey: process.env.AKBANK_SECRET_KEY!,
// subMerchantId?: string
// testMode: defaults to mode === 'sandbox' (test 3D gateway)
// baseUrl: defaults from mode (apipre.akbank.com / api.akbank.com)
}),
},
});paymentId is your order id: the conversationId you pass, or a generated id.
Direct Payment (non-3D)
const result = await payment.akbank.createPayment({ ...paymentRequest, conversationId: 'ORDER123' });
// txnCode 1000; success when responseCode is VPS-00003D Secure (3D_PAY)
const init = await payment.akbank.initThreeDSPayment({
...paymentRequest,
conversationId: 'ORDER123',
callbackUrl: 'https://yoursite.com/api/pay/akbank/payment/complete-3ds',
});
// init.threeDSHtmlContent auto-submits a signed form to the Akbank securepay gatewayAkbank authenticates the card, charges it, and POSTs the signed result to callbackUrl:
const result = await payment.akbank.completeThreeDSPayment(callbackBody);The result is trusted only if:
- the HMAC
hashover the fields inhashParamsis valid, and coversresponseCode,orderId,merchantSafeIdandterminalSafeId; - the terminal ids match your configuration;
- an order history query (txnCode 1010) for the
orderIdagrees with the callback. The signed values are joined without a separator, so the signature alone does not pin the order id; a callback that does not match Akbank's record is rejected asINVALID_HASH.
It is success only when responseCode is VPS-0000 and Akbank reports an
approved payment for the order. A missing result code is never treated as
success. If the query gets no response, the result is pending with
NETWORK_ERROR; check it later with getPayment().
Refund, Cancel & Status
await payment.akbank.refund({ paymentId: 'ORDER123', price: '50.00', currency: 'TRY', ip: '1.2.3.4' }); // 1002
await payment.akbank.cancel({ paymentId: 'ORDER123', ip: '1.2.3.4' }); // 1003
const status = await payment.akbank.getPayment('ORDER123'); // 1010
// status: 'success' (N), 'cancelled' (V/R), 'failure'BIN and installment queries are not supported for Akbank: its Sanal POS API has no installment-rate query. binCheck() and installmentInfo() throw NOT_SUPPORTED. Installment plans come from your Akbank agreement: send installment in the payment request and compute paidPrice from your contracted rates.