# Callbacks Assinaturas e shapes de dados de cada callback do botão. Os callbacks recebem o resultado do pagamento. Cada um é `async`. Alguns recebem um objeto `actions` para controlar o botão ou reagir ao fecho do popup. Esta referência segue a implementação **JavaScript** atual da SDK (`Button.js`), que é a fonte autoritativa. As definições TypeScript no repositório estão desatualizadas. ## createOrder ```ts createOrder: () => Promise ``` Chamado **antes** de abrir o popup. Cria a ordem no seu backend e devolve um identificador de transação (o `merchantTransactionId`) — a SDK guarda-o como `paymentOrderId` e usa-o no fluxo. **Tem** de devolver uma **string não-vazia**. Se devolver `null`, `undefined` ou `''`, o popup não avança. ```js async createOrder() { const r = await fetch('/api/facipay/create-order', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ items: cart }), }); if (!r.ok) throw new Error('Falha ao criar ordem'); const { referenceNumber } = await r.json(); return referenceNumber; // usado como paymentOrderId } ``` ## onApprove ```ts onApprove: (data, actions) => Promise ``` Pagamento aprovado. `data` tem a forma `{ payment: { orderId, status, type, data } }`. `actions` expõe **apenas** `onPopupWindowClosed`. O `paymentOrderId` (o valor devolvido por `createOrder`). Estado do pagamento (`paymentStatus`). Tipo de pagamento (`tpPayment`) — `dir` | `mcx` | `ref`. Dados do pagamento (`paymentData`): referência, entidade, valor, etc. Regista uma função a correr quando o popup fecha — o sítio certo para redirecionar. ```js async onApprove(data, actions) { actions.onPopupWindowClosed(() => { window.location.href = `/sucesso?orderId=${data.payment.orderId}`; }); } ``` ## onPending ```ts onPending: (data, actions) => Promise ``` Pagamento pendente (Referência EMIS). Mesma forma de `onApprove`: `{ payment: { orderId, status, type, data } }`. Os dados da referência estão em `data.payment.data`. A referência a mostrar ao cliente. Número da entidade. Nome da entidade. Valor a pagar. ```js async onPending(data, actions) { actions.onPopupWindowClosed(() => { const ref = data.payment.data.paymentReference; const entity = data.payment.data.entity.number; window.location.href = `/pendente?ref=${ref}&entity=${entity}`; }); } ``` ## onCancel ```ts onCancel: (data) => Promise ``` O utilizador cancelou (evento `PAYMENT_CANCELED`) ou fechou o popup sem concluir. Reabra o carrinho ou mostre um CTA para tentar de novo. ```js async onCancel(data) { window.location.href = '/cancelado'; } ``` ## onError ```ts onError: (data) => Promise ``` Erro na transação (evento `PAYMENT_ERROR` ou falha ao abrir o popup). ```js async onError(error) { console.error('FaciPay error:', error); showToast('Ocorreu um erro. Tente novamente.', 'error'); } ``` ## onInit ```ts onInit: (actions) => Promise ``` Botão inicializado. `actions` expõe `enable()` e `disable()`. ```js async onInit(actions) { if (!cartIsValid) actions.disable(); } ``` ## onClick ```ts onClick: (data, actions) => Promise ``` Disparado no clique, **antes** do `createOrder()`. `actions` expõe `enable()`, `disable()` e `reject()`. Chamar `actions.reject()` **interrompe** o fluxo (o popup não abre) — ideal para validar formulários. Interrompe a sequência do botão (cancela este clique). ```js async onClick(data, actions) { const customer = validateCustomerForm(); if (!customer) { actions.reject(); // cancela o fluxo deste clique return; } facipay.button.addCustomerInfo({ name: customer.name, phone: customer.phone }); } ``` render, destroy, referências, cliente e actions.