# 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.