One API forTurkish payments.

Better Payment gives iyzico, PayTR, Parampos and Akbank one type-safe interface, with signature-verified callbacks and a secure-by-default HTTP handler.

$npm install better-payment
betterPayment()
One API · 4 providers

Every gateway has a
completely different API.

Different request shapes, signatures, error formats and callback rules. Better Payment implements each one against the provider's specification and gives you one set of types to work with.

iyzico

Payment gateway

IYZWSv2-signed JSON API with non-3D and 3D Secure payments, a hosted checkout form, pay with IBAN (PWI), subscriptions, and BIN and installment queries.

Capabilities

  • Non-3D & 3D Secure
  • Hosted checkout form
  • Pay with IBAN (PWI)
  • Subscriptions
  • BIN & installment queries
  • Refund, cancel, status
Without · iyzico APIWith Better Payment
// JSON body + IYZWSv2 signature on every request
const rnd = Date.now() + "123456789";
const uri = "/payment/iyzipos/checkoutform/initialize/auth/ecom";
const signature = createHmac("sha256", secretKey)
  .update(rnd + uri + JSON.stringify(body))
  .digest("hex");
const auth = btoa(
  `apiKey:${apiKey}&randomKey:${rnd}&signature:${signature}`,
);

const res = await fetch(baseUrl + uri, {
  method: "POST",
  headers: {
    Authorization: "IYZWSv2 " + auth,
    "x-iyzi-rnd": rnd,
    "Content-Type": "application/json",
  },
  body: JSON.stringify(body),
});
// Map iyzico's status and error codes yourself
// Hosted checkout form
const result = await payment.iyzico.initCheckoutForm({
  price: "100.00",
  paidPrice: "100.00",
  currency: "TRY",
  basketId: "B1",
  callbackUrl: "https://yoursite.com/checkout/callback",
  buyer: { ... },
  basketItems: [ ... ],
});

// Render result.checkoutFormContent on your page
result.status; // "success" | "failure" | "pending"

Everything you need,
nothing you don't.

Unified API surface

createPayment, initThreeDSPayment, refund, cancel and getPayment take the same request types on every provider and return the same result shape.

Zero dependencies

No runtime dependencies, ESM and CJS builds, and a browser-safe client. Runs on Node.js, Vercel Edge, Cloudflare Workers, Deno and Bun.

Verified callbacks

3D Secure callbacks and PayTR notifications are checked against your own credentials, in constant time, before anything counts as paid.

Secure-by-default handler

The HTTP handler exposes only callbacks and card queries by default. Refunds, cancels and lookups require an authorize hook.

No double charges

A timeout returns pending with NETWORK_ERROR instead of guessing. Payment, refund and cancel requests are never retried automatically.

Bank virtual POS,
same interface.

Talk to a bank's virtual POS directly, without a payment institution in between, using the same request and result types.

AkbankLive

Sanal POS · direct integration

Akbank's Sanal POS JSON API with HMAC-SHA512 signed requests, signature-verified 3D Secure (3D_PAY) callbacks, refunds, voids and order status queries.

View Akbank docs
  • HMAC-SHA512Signed requests & callbacks
  • 2D & 3D SecureBoth flows supported
  • Verified Callbacks3D results checked with your key
  • Direct APINo third-party middleware

On the roadmap

Scroll to explore what's next

  1. Bank virtual POS

  2. Live
  3. Live
  4. Live
  5. Live
  6. Live
  7. Live
  8. Live
  9. Planned · #37
  10. Planned · #38
  11. Planned · #39
  12. Planned · #39
  13. Planned · #133
  14. Payment institutions

  15. Live
  16. Planned · #40
  17. Planned · #40
  18. Planned · #40

Want to contribute?
Let's build the next part together.

A new provider, a clearer guide, a test that catches a bug. Every contribution makes Better Payment better for everyone.

Built by our contributors

Built in the open. Improved together.

All contributors on GitHub

Up and running
in minutes.

  1. 01

    Install the package

    terminal
    $ npm install better-payment
  2. 02

    Configure your providers

    lib/payment.ts
    import { betterPayment, iyzico } from "better-payment";
    
    export const payment = betterPayment({
      mode: "sandbox", // test URLs and provider test modes
      providers: {
        iyzico: iyzico({
          apiKey: process.env.IYZICO_API_KEY!,
          secretKey: process.env.IYZICO_SECRET_KEY!,
        }),
      },
    });
  3. 03

    Start a 3D Secure payment

    app/checkout.ts
    import { payment } from "@/lib/payment";
    
    const result = await payment.iyzico.initThreeDSPayment({
      price: "100.00",
      paidPrice: "100.00",
      currency: "TRY",
      basketId: "B1",
      callbackUrl: "https://yoursite.com/api/pay/iyzico/payment/complete-3ds",
      paymentCard: { ... },
      buyer: { ... },
      shippingAddress: { ... },
      billingAddress: { ... },
      basketItems: [ ... ],
    });
    
    // Render result.threeDSHtmlContent. The bank posts back to callbackUrl,
    // where the handler verifies the result before you mark the order paid.

Stop rewriting
payment logic.

One package for iyzico, PayTR, Parampos and Akbank, with full TypeScript support. Upgrading from 3.x? Read what's new since the reset.

$npm install better-payment