A SDK inclui uma integração de referência completa — a Wow Media Store — em examples/fake-store/. É uma loja funcional com produtos, carrinho, checkout, webhook e páginas de retorno. Usa-a como mapa para a tua própria integração.
A integração de referência é didática. O webhook de exemplo não valida HMAC (está marcado como TODO). Em produção, segue sempre o guia de Segurança e valida a assinatura.

Stack

  • Backend: Node.js + Express + TypeScript
  • Base de dados: SQLite (prepared statements)
  • Frontend: HTML + a FaciPay JS SDK

Correr localmente

cd examples/fake-store
npm install
cp .env.example .env   # preenche com as tuas credenciais de sandbox
npm run dev            # http://localhost:3000

Anatomia

fake-store/
├── src/
│   ├── server.ts                     # Express + rotas estáticas
│   ├── routes/
│   │   ├── orders.ts                 # criar ordem a partir do carrinho
│   │   ├── cart.ts                   # carrinho
│   │   └── webhook.ts                # recebe notificações da FaciPay
│   ├── services/
│   │   ├── FaciPayService.ts         # token + createPaymentOrder + getOrder
│   │   └── OrderStatusService.ts     # transições de estado
│   ├── database/database.ts          # SQLite + statements
│   └── public/
│       ├── checkout.html             # SDK: generateButton + callbacks
│       ├── success.html  pending.html  pending-ref.html  cancel.html
└── .env.example

O fluxo, passo a passo

1

Carrega produtos e carrinho

A loja lê produtos da BD e mantém um carrinho por sessão.
2

Renderiza o botão FaciPay

checkout.html chama FaciPay(token).generateButton({...}).render('#facipay-checkout-button').
3

createOrder() → backend

O callback faz POST /api/orders/create-from-cart. O servidor recalcula o total, cria a ordem na BD e chama FaciPayService.createOrder() → devolve referenceNumber.
4

Popup e callbacks

A SDK abre o popup. Conforme o resultado, dispara onApprove, onPending ou onCancel, e a loja redireciona para success / pending-ref / cancel.
5

Webhook

A FaciPay chama POST /api/webhook/payment. O OrderStatusService atualiza o estado (CON/CAN/PEN) e executa ações pós-pagamento (limpar carrinho, etc.).

Backend: criar a ordem

O FaciPayService.createOrder() mostra o fluxo real de token + criação de ordem (ver Autenticação):
const accessToken = await this.getAccessToken();

const response = await fetch(`${this.apiUrl}/facipaypartner/createPaymentOrder`, {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json; charset=utf-8',
    Authorization: `Bearer ${accessToken}`,
    'Accept-Language': 'pt',
  },
  body: JSON.stringify({
    externalTransactionId: data.orderId,
    clientId: newClientId,
    applicationUUID: this.publishableKey, // sem prefixo
    name: data.description,
    image: data.image,
    amount: data.amount,
    quantity: 1,
    additionalInfo: JSON.stringify({
      returnUrl: data.additionalInfo.returnUrl,
      cancelUrl: data.additionalInfo.cancelUrl,
      webhookUrl: data.additionalInfo.webhookUrl,
    }),
  }),
});

const res = await response.json();
return { referenceNumber: res.data.referenceNumber };

Frontend: SDK real

O checkout.html usa funcionalidades além do básico — referências múltiplas, info do cliente e atualização de quantidade:
await facipay.generateButton({
  async createOrder() { /* POST /api/orders/create-from-cart → referenceNumber */ },
  async onApprove(data, actions) { /* sincroniza estado, redireciona */ },
  async onPending(data, actions) { /* mostra referência EMIS */ },
  async onClick(data) {
    facipay.button.addCustomerInfo({ name, phone });
  },
  options: faciPayConfig.options,
}).render('#facipay-checkout-button');

// Referências múltiplas (um item por linha do carrinho)
facipay.button.addAllPaymentReferences(cart.items.map(item => ({
  referenceNumber: String(item.id),
  referenceDescription: item.name,
  referenceAmount: item.price,
  referenceQuantity: item.quantity,
  referenceTotalQuantity: item.stock_quantity,
})));
Os scripts facipay-profiles.js e facipay-settings.js do exemplo são andaimes do demo (troca de credenciais entre perfis) — não fazem parte da SDK pública.

Próximo passo: Segurança

Como validar o webhook corretamente (o que o exemplo ainda não faz).