Integração com Next.js

Exemplo completo de integração do Hubpay num projeto Next.js 14+ com App Router.

1. Instalar o SDK

bash
pnpm add @hubpay/sdk

2. Variáveis de ambiente

bash
# .env.local
HUBPAY_API_KEY=hpx_test_sua_chave
HUBPAY_WEBHOOK_SECRET=seu_signing_secret

3. Server Action — criar cobrança

typescript
// app/actions/checkout.ts
'use server';

import { Hubpay } from '@hubpay/sdk';

const hubpay = new Hubpay({ apiKey: process.env.HUBPAY_API_KEY! });

export async function createPixCharge(orderId: string, amountCents: number) {
  const charge = await hubpay.charges.create({
    amount: amountCents,
    provider: 'asaas',
    description: `Pedido #${orderId}`,
    metadata: { order_id: orderId },
  }, {
    idempotencyKey: orderId, // garante que cada pedido gera 1 cobrança
  });

  return {
    chargeId: charge.id,
    pixCopyPaste: charge.pix.copy_paste,
    qrCodeBase64: charge.pix.qr_code_base64,
  };
}

4. Webhook handler

typescript
// app/api/webhooks/hubpay/route.ts
import { Hubpay } from '@hubpay/sdk';

const hubpay = new Hubpay({ apiKey: process.env.HUBPAY_API_KEY! });

export async function POST(req: Request) {
  const body = await req.text();
  const signature = req.headers.get('x-hubpay-signature') ?? '';

  const verifier = hubpay.webhooks(process.env.HUBPAY_WEBHOOK_SECRET!);
  if (!verifier.verify(body, signature)) {
    return new Response('Invalid signature', { status: 401 });
  }

  const event = JSON.parse(body);

  if (event.type === 'charge.paid') {
    const orderId = event.data.metadata?.order_id;
    await markOrderAsPaid(orderId);
  }

  return new Response('ok');
}

async function markOrderAsPaid(orderId: string) {
  // sua lógica aqui
}

5. Página de checkout

typescript
// app/checkout/[orderId]/page.tsx
import { createPixCharge } from '@/actions/checkout';

export default async function CheckoutPage({
  params,
}: {
  params: Promise<{ orderId: string }>;
}) {
  const { orderId } = await params;
  const { pixCopyPaste, qrCodeBase64 } = await createPixCharge(orderId, 5000);

  return (
    <div>
      <h1>Pague com Pix</h1>

      {qrCodeBase64 && (
        <img
          src={`data:image/png;base64,${qrCodeBase64}`}
          alt="QR Code Pix"
          width={200}
          height={200}
        />
      )}

      <p>Ou use o Pix copia e cola:</p>
      <code>{pixCopyPaste}</code>
    </div>
  );
}