SDKs oficiales
Clientes oficiales para tu backend: crean cobros y checkout sessions, consultan payment intents y verifican webhooks sin rearmar auth ni HMAC a mano.
Los SDKs de KUTI son delgados sobre la API REST. Solo servidor: usan tu secret key (kuti_live_… / kuti_test_…). Nunca los importes en el navegador — para el frontend usa Checkout.js.
@kuti-pe/node — npm. Node 18+.
Ver paquetekuti-pe/kuti-php — Composer. PHP 8.1+.
Ver paquetekuti-pe — PyPI. Python 3.9+.
Ver paqueteQué cubren
Cobro (payment intent) ≠ checkout session. Usa paymentIntents.create para cobro directo (QR / código / link). Usa checkoutSessions.create solo si vas a abrir el modal con Checkout.js.
- paymentIntents: create, list, retrieve, cancel, sendWhatsApp
- checkoutSessions: create (Checkout.js)
- Webhooks: verificar firma (X-Kuti-Signature)
Misma superficie en Node, PHP y Python: mismos recursos, mismos campos y mismos códigos de error.
npm install @kuti-pe/nodeResuelve el monto en tu backend. Usa idempotencyKey (ej. id de orden) al crear.
import { KutiClient } from "@kuti-pe/node";
const kuti = new KutiClient({ secretKey: process.env.KUTI_SECRET_KEY! });
const session = await kuti.checkoutSessions.create(
{
amount: { amount: "249.90", currency: "PEN" },
paymentMethodTypes: ["INTEROPERABLE_QR", "BANK_TRANSFER"],
description: "Zapatillas running talla 42",
customer: { id: "cus_01ABC" },
// customer: { name: §§SLOT_7§§, email: §§SLOT_8§§ },
},
{ idempotencyKey: `order-${orderId}` },
);
// window.Kuti.open({ checkoutUrl: session.checkoutUrl, onSuccess, onFailure })const intent = await kuti.paymentIntents.retrieve(paymentIntentId);
if (intent.status === "SUCCEEDED") {
// fulfill order
}import { verifyWebhookSignature, KutiSignatureVerificationError } from "@kuti-pe/node";
import express from "express";
const app = express();
app.post("/webhooks/kuti", express.text({ type: "*/*" }), (req, res) => {
try {
verifyWebhookSignature(
req.body, // raw body
req.header("X-Kuti-Signature")!,
req.header("X-Kuti-Timestamp")!,
process.env.KUTI_WEBHOOK_SECRET!,
);
} catch (err) {
if (err instanceof KutiSignatureVerificationError) {
return res.status(400).send("Invalid signature");
}
throw err;
}
const event = JSON.parse(req.body);
// payment.succeeded | checkout.session.completed
res.sendStatus(200);
});Siguiente
- Checkout.js — abrir el checkoutUrl en el frontend
- Webhooks — confirmar el pago en tu servidor