Skip to content

SDK JavaScript / Node.js

El SDK de JavaScript permite integrar TAYPI en aplicaciones Node.js, Express, Next.js, Nest.js, y cualquier entorno de servidor JavaScript.

SOLO PARA BACKEND

Este SDK es para uso en el servidor (Node.js). Para el frontend del navegador, usa Checkout.js.

Instalacion

bash
npm install taypi.pe

O con Yarn:

bash
yarn add taypi.pe

Requisitos: Node.js 18+.

Configuracion

js
import Taypi from 'taypi.pe';

const taypi = new Taypi(
    'taypi_pk_test_a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4',
    'taypi_sk_test_a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4',
    {
        sandbox: true,    // true = sandbox.taypi.pe (default), false = app.taypi.pe
        timeout: 30,      // Timeout en segundos (default: 30)
        retries: 2,       // Reintentos en errores 5xx (default: 2)
    },
);

O con CommonJS:

js
const Taypi = require('taypi.pe');

const taypi = new Taypi('taypi_pk_test_...', 'taypi_sk_test_...', {
    sandbox: true,
});

NUNCA EXPONGAS TU SECRET KEY

La secret key solo debe existir en tu backend (Node.js). Nunca la incluyas en codigo que se ejecute en el navegador.

Metodos

Todos los metodos son asincronos y retornan Promises.

createCheckoutSession

Crea un pago y devuelve un checkout_token para usar con Checkout.js.

js
const session = await taypi.createCheckoutSession({
    amount: '50.00',
    currency: 'PEN',
    reference: 'ORD-12345',
    description: 'Compra en Mi Tienda',
    metadata: {
        customer_email: 'cliente@example.com',
    },
});

console.log(session.payment_id);      // "a14dfb8e-d5c2-4a69-bae4-4688fef5eac2"
console.log(session.checkout_token);   // "ctk_a1b2c3..."
console.log(session.checkout_url);     // "https://sandbox.taypi.pe/pay/a14dfb8e..."
console.log(session.expires_at);       // "2026-03-15T10:45:00-05:00"

createPayment

Crea un pago y devuelve la informacion completa del QR.

js
const payment = await taypi.createPayment({
    amount: '150.00',
    currency: 'PEN',
    reference: 'ORD-67890',
    description: 'Servicio de consultoria',
});

console.log(payment.payment_id);   // UUID del pago
console.log(payment.status);       // "pending"
console.log(payment.qr_image);     // Data URI base64 de la imagen QR
console.log(payment.checkout_url); // URL para pago por enlace
console.log(payment.expires_at);   // Timestamp de expiracion

getPayment

Consulta el estado actual de un pago.

js
const payment = await taypi.getPayment('a14dfb8e-d5c2-4a69-bae4-4688fef5eac2');

console.log(payment.status);   // "pending", "completed", "expired", "cancelled"
console.log(payment.amount);   // "50.00"
console.log(payment.paid_at);  // "2026-03-15T10:30:00-05:00" o null

listPayments

Lista pagos con filtros opcionales.

js
const payments = await taypi.listPayments({
    status: 'completed',
    from: '2026-03-01',
    to: '2026-03-15',
    page: 1,
    per_page: 20,
});

console.log(payments.data);          // Array de pagos
console.log(payments.total);         // Total de resultados
console.log(payments.current_page);

cancelPayment

Cancela un pago en estado pending.

js
const result = await taypi.cancelPayment('a14dfb8e-d5c2-4a69-bae4-4688fef5eac2');

console.log(result.status);    // "cancelled"
console.log(result.message);   // "Pago cancelado exitosamente"

verifyWebhook

Verifica la firma HMAC-SHA256 de un webhook entrante.

js
const isValid = taypi.verifyWebhook(rawBody, signatureHeader);

if (!isValid) {
    res.status(401).send('Firma invalida');
    return;
}

Ejemplo: Express.js

js
import express from 'express';
import Taypi from 'taypi.pe';

const app = express();
const taypi = new Taypi(
    process.env.TAYPI_PUBLIC_KEY,
    process.env.TAYPI_SECRET_KEY,
    { sandbox: process.env.TAYPI_SANDBOX === 'true' },
);

// Crear sesion de checkout
app.post('/api/crear-pago', async (req, res) => {
    try {
        const session = await taypi.createCheckoutSession({
            amount: '50.00',
            currency: 'PEN',
            reference: `ORD-${Date.now()}`,
            description: 'Compra en Mi Tienda',
        });

        res.json({ checkout_token: session.checkout_token });
    } catch (error) {
        console.error('Error TAYPI:', error.code, error.message);
        res.status(error.httpStatus || 500).json({
            error: error.message,
        });
    }
});

// Webhook — IMPORTANTE: usar express.raw() para obtener el body sin parsear
app.post('/api/webhooks/taypi',
    express.raw({ type: 'application/json' }),
    (req, res) => {
        const signature = req.headers['taypi-signature'] || '';
        const rawBody = req.body.toString();

        const isValid = taypi.verifyWebhook(rawBody, signature);

        if (!isValid) {
            return res.status(401).send('Firma invalida');
        }

        const event = JSON.parse(rawBody);

        if (event.event === 'payment.completed') {
            console.log('Pago completado:', event.payment_id);
            // Actualizar orden en tu base de datos
        }

        res.status(200).send('OK');
    }
);

app.listen(3000, () => console.log('Servidor en puerto 3000'));

IMPORTANTE: Body sin parsear para webhooks

Para verificar la firma del webhook, necesitas el body original sin parsear. Usa express.raw() en la ruta del webhook, no express.json().

Ejemplo: Next.js (App Router)

API Route — Crear pago

ts
// app/api/crear-pago/route.ts
import Taypi from 'taypi.pe';
import { NextResponse } from 'next/server';

const taypi = new Taypi(
    process.env.TAYPI_PUBLIC_KEY!,
    process.env.TAYPI_SECRET_KEY!,
    { sandbox: process.env.TAYPI_SANDBOX === 'true' },
);

export async function POST() {
    try {
        const session = await taypi.createCheckoutSession({
            amount: '50.00',
            currency: 'PEN',
            reference: `ORD-${Date.now()}`,
            description: 'Compra en Mi Tienda',
        });

        return NextResponse.json({
            checkout_token: session.checkout_token,
        });
    } catch (error: any) {
        return NextResponse.json(
            { error: error.message },
            { status: error.httpStatus || 500 },
        );
    }
}

API Route — Webhook

ts
// app/api/webhooks/taypi/route.ts
import Taypi from 'taypi.pe';
import { NextResponse } from 'next/server';

const taypi = new Taypi(
    process.env.TAYPI_PUBLIC_KEY!,
    process.env.TAYPI_SECRET_KEY!,
);

export async function POST(request: Request) {
    const rawBody = await request.text();
    const signature = request.headers.get('taypi-signature') || '';

    const isValid = taypi.verifyWebhook(rawBody, signature);

    if (!isValid) {
        return NextResponse.json({ error: 'Firma invalida' }, { status: 401 });
    }

    const event = JSON.parse(rawBody);

    if (event.event === 'payment.completed') {
        // Actualizar orden en tu base de datos
        console.log('Pago completado:', event.payment_id);
    }

    return NextResponse.json({ received: true });
}

Componente React

tsx
// app/checkout/page.tsx
'use client';

import { useCallback } from 'react';
import Script from 'next/script';

declare global {
    interface Window {
        Taypi: any;
    }
}

export default function CheckoutPage() {
    const handlePay = useCallback(async () => {
        const res = await fetch('/api/crear-pago', { method: 'POST' });
        const { checkout_token } = await res.json();

        window.Taypi.publicKey = process.env.NEXT_PUBLIC_TAYPI_PUBLIC_KEY!;
        window.Taypi.open({
            sessionToken: checkout_token,
            onSuccess: (result: any) => {
                window.location.href = `/gracias?payment=${result.payment_id}`;
            },
            onExpired: () => alert('El QR ha expirado.'),
            onError: (error: any) => alert(error.message),
        });
    }, []);

    return (
        <>
            <Script src="https://app.taypi.pe/v1/checkout.js" />
            <button onClick={handlePay}>Pagar S/ 50.00</button>
        </>
    );
}

Manejo de errores

El SDK lanza TaypiError en caso de errores:

js
import Taypi, { TaypiError } from 'taypi.pe';

try {
    const payment = await taypi.createPayment({
        amount: '50.00',
        currency: 'PEN',
        reference: 'ORD-12345',
    });
} catch (error) {
    if (error instanceof TaypiError) {
        console.error(error.message);    // "El monto debe ser mayor a S/ 1.00"
        console.error(error.code);       // "PAYMENT_INVALID_AMOUNT"
        console.error(error.httpStatus); // 422
    } else {
        // Error de red u otro error inesperado
        console.error('Error inesperado:', error);
    }
}

Tipos de error

CodigoHTTPDescripcion
AUTH_KEY_INVALID401API key invalida o revocada
AUTH_SIGNATURE_INVALID403Firma HMAC incorrecta
RATE_LIMIT_EXCEEDED429Excediste el limite de 60 req/min
PAYMENT_NOT_FOUND404El pago no existe
PAYMENT_INVALID_AMOUNT422Monto fuera de rango
VALIDATION_ERROR422Datos de entrada invalidos
SERVICE_UNAVAILABLE503Servicio temporalmente no disponible

Ver la lista completa en la referencia de errores.

Plataforma de pagos QR interoperables para Perú