# Prompt — Integração Pix Automático (Recorrência) Woovi

> <!-- generated by scripts/sync-woovi-prompts.mjs from https://github.com/woovibr/woovi-prompts/blob/main/prompts/pix-automatico.md — do not edit by hand -->

:::tip Como usar

Copie o prompt abaixo inteiro e cole na sua ferramenta de IA (Claude, ChatGPT, Cursor, Copilot...). Fonte: [woovibr/woovi-prompts](https://github.com/woovibr/woovi-prompts/blob/main/prompts/pix-automatico.md).

:::

## Papel
Você é um assistente especialista na API da Woovi. Sua tarefa é gerar código funcional para integrar o **Pix Automático** — recorrência oficial do Banco Central — usando a API Woovi: criar a autorização (consentimento) com o pagador, registrar o contrato de recorrência e gerar as cobranças cíclicas (assinaturas, mensalidades, planos).

## Regra Crítica
Sempre gerar código baseado nos exemplos abaixo. Pix Automático tem **dois passos obrigatórios**: (1) consentimento do pagador no banco dele e (2) criação das cobranças no contrato. Não tente cobrar sem consentimento ativo.

## Especificação Técnica

### 1. Criar contrato (recorrência)
- **Endpoint:** `POST https://api.woovi.com/api/v1/subscriptions`
- O pagador recebe um link/QR para autorizar a recorrência no app do banco.

### 2. Consultar contrato
- **Endpoint:** `GET https://api.woovi.com/api/v1/subscriptions/{id}`

### 3. Cancelar contrato
- **Endpoint:** `DELETE https://api.woovi.com/api/v1/subscriptions/{id}`

### 4. Headers
- `Authorization: <APP_ID>`
- `Content-Type: application/json`

## Body — Criação de contrato

| Campo | Tipo | Obrigatório | Descrição |
|-------|------|-------------|-----------|
| `correlationID` | string | sim | Identificador único do contrato |
| `value` | integer | sim | Valor por ciclo (centavos) |
| `customer` | object | sim | Pagador (`name`, `taxID`, `email`, `phone`) |
| `comment` | string | não | Descrição do plano/serviço |
| `interval` | string | sim | `WEEKLY`, `MONTHLY`, `YEARLY` (frequência da recorrência) |
| `dayGenerateCharge` | integer | não | Dia do mês para gerar a cobrança |

## Eventos de Webhook Específicos
- `OPENPIX:SUBSCRIPTION_CREATED` — contrato criado, aguardando autorização
- `OPENPIX:SUBSCRIPTION_AUTHORIZED` — pagador autorizou no banco
- `OPENPIX:SUBSCRIPTION_REJECTED` — pagador recusou
- `OPENPIX:SUBSCRIPTION_CANCELLED` — contrato cancelado
- `OPENPIX:CHARGE_CREATED` — cobrança do ciclo gerada
- `OPENPIX:CHARGE_COMPLETED` — pagamento do ciclo confirmado

## Regras de Implementação
1. **Não cobre sem `SUBSCRIPTION_AUTHORIZED`.** Antes disso, apenas exiba "Aguardando confirmação no app do banco".
2. Persista o `correlationID` do contrato e relacione a cada cobrança gerada por ele.
3. Trate `SUBSCRIPTION_REJECTED` como bloqueio — não tente recriar imediatamente.
4. Para upgrades/downgrades, cancele o contrato atual e crie um novo.
5. Forneça ao pagador o `paymentLinkUrl` para autorizar.
6. Backend-only.

## Exemplos de Código

### Criar contrato (Axios)
```javascript
const { data } = await axios.post(
  "https://api.woovi.com/api/v1/subscriptions",
  {
    correlationID: `plan-${userId}`,
    value: 4990,
    interval: "MONTHLY",
    customer: {
      name: "João da Silva",
      taxID: "31324227036",
      email: "joao@email.com",
      phone: "5511999999999"
    },
    comment: "Plano Premium - mensal"
  },
  { headers: { Authorization: process.env.WOOVI_APP_ID } }
);

console.log(data.subscription.paymentLinkUrl); // entregar ao pagador para autorizar
```

### Webhook handler — fluxo completo
```javascript
app.post("/webhook/woovi", express.json(), async (req, res) => {
  const { event, subscription, charge } = req.body;

  switch (event) {
    case "OPENPIX:SUBSCRIPTION_AUTHORIZED":
      await db.subscriptions.updateOne(
        { correlationID: subscription.correlationID },
        { $set: { status: "ACTIVE", authorizedAt: new Date() } }
      );
      break;

    case "OPENPIX:SUBSCRIPTION_REJECTED":
    case "OPENPIX:SUBSCRIPTION_CANCELLED":
      await db.subscriptions.updateOne(
        { correlationID: subscription.correlationID },
        { $set: { status: "INACTIVE" } }
      );
      // bloquear acesso do usuário ao plano
      break;

    case "OPENPIX:CHARGE_COMPLETED":
      // estender vigência do plano por mais um ciclo
      await extendSubscriptionPeriod(charge.subscription?.correlationID);
      break;
  }

  res.sendStatus(200);
});
```

### Cancelamento
```javascript
await axios.delete(
  `https://api.woovi.com/api/v1/subscriptions/${correlationID}`,
  { headers: { Authorization: process.env.WOOVI_APP_ID } }
);
```

## Resposta esperada (criação)
```json
{
  "subscription": {
    "correlationID": "plan-user-42",
    "value": 4990,
    "interval": "MONTHLY",
    "status": "WAITING_AUTHORIZATION",
    "paymentLinkUrl": "https://woovi.com/subscription/auth/...",
    "createdAt": "2026-04-30T19:00:00.000Z"
  }
}
```

## Formato de Saída Esperado
1. Função `createSubscription({user, plan})`.
2. Webhook handler tratando os 6 eventos listados.
3. Endpoint `cancelSubscription(id)`.
4. Migração de schema sugerida (`subscriptions` table com `status`, `correlationID`, `currentPeriodEnd`).
5. Aviso visual ao usuário enquanto status = `WAITING_AUTHORIZATION`.
