|
|
@@ -1,9 +1,282 @@
|
|
|
-1. run ```./bin/setup```
|
|
|
+# Backend PHP – Orderbook & Pagamentos
|
|
|
|
|
|
-(deleta o banco existente, cria o banco de dados com as credenciais do ENV e aplica migrations)
|
|
|
-2. run ```composer install (instala dependencias)```
|
|
|
+Este documento reúne as instruções de execução e, principalmente, o contrato HTTP dos
|
|
|
+endpoints relacionados ao fluxo de orderbook/pagamentos. Use-o como referência ao
|
|
|
+implementar as chamadas no frontend.
|
|
|
|
|
|
-3. run ```X_LISTEN=127.0.0.1:8000 php public/index.php```
|
|
|
+## Como rodar localmente
|
|
|
+
|
|
|
+1. `./bin/setup` – recria o banco usando as credenciais do `.env` e aplica todas as migrations.
|
|
|
+2. `composer install` – instala dependências PHP.
|
|
|
+3. `X_LISTEN=127.0.0.1:8000 php public/index.php` – sobe a API localmente.
|
|
|
+
|
|
|
+> A aplicação também traz um `build` Deb (ver trecho fpm no final deste arquivo) caso seja
|
|
|
+> necessário gerar um pacote.
|
|
|
+
|
|
|
+## Convenções gerais
|
|
|
+
|
|
|
+- **Base URL**: `http://localhost:8000` (ajuste conforme ambiente).
|
|
|
+- **Autenticação**: todos os endpoints abaixo exigem JWT (`Authorization: Bearer <token>`),
|
|
|
+ exceto quando indicado.
|
|
|
+- **Formato de resposta**: todos usam `ResponseLib` e retornam o seguinte envelope:
|
|
|
+
|
|
|
+ ```json
|
|
|
+ {
|
|
|
+ "status": "ok" | "failed",
|
|
|
+ "msg": "[100] Request ok." | "<detalhe de erro>",
|
|
|
+ "code": "S_*" | "E_*",
|
|
|
+ "data": { ... } | []
|
|
|
+ }
|
|
|
+ ```
|
|
|
+
|
|
|
+## Fluxo resumido
|
|
|
+
|
|
|
+1. **/token/orderbook** – atualiza um token e cria uma ordem aberta.
|
|
|
+2. **/orderbook/filter** – frontend lista ordens por estado/commodity.
|
|
|
+3. **/orderbook/payment** – inicia o pagamento (gera PIX e IDs externos).
|
|
|
+4. **/orderbook/transfer** – após o pagamento concluir (Woovi → webhook atualiza status),
|
|
|
+ transfere o token para a carteira da empresa.
|
|
|
+5. **/b3/payment/confirm** – confirma status do pagamento associado à CPR e dispara registro
|
|
|
+ na B3/criação de token.
|
|
|
+
|
|
|
+As seções a seguir detalham os contratos JSON de cada etapa.
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+### 1. `POST /token/orderbook`
|
|
|
+Cria uma ordem no orderbook para um token existente (atualiza o valor do token e registra a
|
|
|
+ordem como `STATUS_OPEN`).
|
|
|
+
|
|
|
+| Campo | Tipo / Regra |
|
|
|
+|--------------------|------------------------------------------------|
|
|
|
+| `cpr_id` | inteiro positivo |
|
|
|
+| `value` | numérico (será arredondado para inteiro) |
|
|
|
+| `state` | string não vazia (UF, ex.: `"SP"`) |
|
|
|
+| `commodity_type` | string não vazia (ex.: `"SOJA"`) |
|
|
|
+| `token_external_id`| string não vazia – precisa bater com o token |
|
|
|
+
|
|
|
+**Exemplo de request**
|
|
|
+```json
|
|
|
+{
|
|
|
+ "cpr_id": 42,
|
|
|
+ "value": 150000.75,
|
|
|
+ "state": "sp",
|
|
|
+ "commodity_type": "SOJA",
|
|
|
+ "token_external_id": "TOKEN_ABC123"
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+**Sucesso (`200 – S_ORDERBOOK_CREATED`)**
|
|
|
+```json
|
|
|
+{
|
|
|
+ "status": "ok",
|
|
|
+ "msg": "[100] Request ok.",
|
|
|
+ "code": "S_ORDERBOOK_CREATED",
|
|
|
+ "data": {
|
|
|
+ "message": "Token atualizado e ordem registrada com sucesso",
|
|
|
+ "token_id": 99,
|
|
|
+ "orderbook_id": 321
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+**Principais erros**
|
|
|
+- `400 – E_VALIDATE`: falha de validação (`cpr_id`, campos vazios etc.).
|
|
|
+- `404 – E_TOKEN_NOT_FOUND`: nenhum token encontrado para a CPR informada.
|
|
|
+- `409 – E_TOKEN_MISMATCH`: o `token_external_id` informado não corresponde ao da CPR.
|
|
|
+- `500 – E_ORDERBOOK`: falha ao atualizar token/criar ordem.
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+### 2. `POST /orderbook/filter`
|
|
|
+Lista ordens abertas por estado e tipo de commodity.
|
|
|
+
|
|
|
+| Campo | Tipo / Regra |
|
|
|
+|------------------|-------------------------------|
|
|
|
+| `state` | string não vazia |
|
|
|
+| `commodity_type` | string não vazia |
|
|
|
+
|
|
|
+**Request**
|
|
|
+```json
|
|
|
+{
|
|
|
+ "state": "SP",
|
|
|
+ "commodity_type": "SOJA"
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+**Sucesso (`200`)**
|
|
|
+- `S_ORDERBOOK_FILTER`: quando há ordens.
|
|
|
+- `S_ORDERBOOK_EMPTY`: lista vazia.
|
|
|
+
|
|
|
+```json
|
|
|
+{
|
|
|
+ "status": "ok",
|
|
|
+ "msg": "[100] Request ok.",
|
|
|
+ "code": "S_ORDERBOOK_FILTER",
|
|
|
+ "data": {
|
|
|
+ "state": "SP",
|
|
|
+ "commodity_type": "SOJA",
|
|
|
+ "orders": [
|
|
|
+ {
|
|
|
+ "orderbook_id": 321,
|
|
|
+ "orderbook_amount": "1000",
|
|
|
+ "token_external_id": "TOKEN_ABC123",
|
|
|
+ "status_id": 0,
|
|
|
+ "token_commodities_value": 150000,
|
|
|
+ "token_commodities_amount": 1000,
|
|
|
+ "chain_id": 1,
|
|
|
+ "wallet_id": 10
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+**Erros comuns**
|
|
|
+- `400 – E_VALIDATE`: campos ausentes/invalidos.
|
|
|
+- `500 – E_DATABASE`: erro ao consultar o orderbook.
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+### 3. `POST /orderbook/payment`
|
|
|
+Inicia o processo de pagamento para uma ordem aberta. Retorna o código PIX/ID externo para o
|
|
|
+frontend exibir ao usuário.
|
|
|
+
|
|
|
+| Campo | Tipo / Regra |
|
|
|
+|----------------|-------------------|
|
|
|
+| `orderbook_id` | inteiro positivo |
|
|
|
+
|
|
|
+**Request**
|
|
|
+```json
|
|
|
+{
|
|
|
+ "orderbook_id": 321
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+**Sucesso (`200 – S_ORDERBOOK_PAYMENT`)**
|
|
|
+```json
|
|
|
+{
|
|
|
+ "status": "ok",
|
|
|
+ "msg": "[100] Request ok.",
|
|
|
+ "code": "S_ORDERBOOK_PAYMENT",
|
|
|
+ "data": {
|
|
|
+ "orderbook_id": 321,
|
|
|
+ "payment_id": 555,
|
|
|
+ "payment_code": "000201...",
|
|
|
+ "payment_external_id": "PAY_a1b2c3d4",
|
|
|
+ "token_external_id": "TOKEN_ABC123"
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+**Erros possíveis**
|
|
|
+- `400 – E_VALIDATE`: `orderbook_id` inválido.
|
|
|
+- `404 – E_NOT_FOUND`: orderbook inexistente.
|
|
|
+- `409 – E_ORDERBOOK_STATUS`: ordem não está `STATUS_OPEN`.
|
|
|
+- `422 – E_TOKEN_VALUE`: valor calculado do token ≤ 0.
|
|
|
+- `500 – E_DATABASE` ou `E_PAYMENT`: problemas ao ler base ou iniciar o pagamento.
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+### 4. `POST /orderbook/transfer`
|
|
|
+Verifica se o pagamento (Woovi) foi concluído e transfere o token para a carteira da empresa
|
|
|
+autenticada. Deve ser chamado após o webhook da Woovi marcar o pagamento como concluído.
|
|
|
+
|
|
|
+| Campo | Tipo / Regra |
|
|
|
+|--------------------|-----------------------------|
|
|
|
+| `external_id` | string não vazia (ID Woovi) |
|
|
|
+| `token_external_id`| string não vazia |
|
|
|
+
|
|
|
+**Request**
|
|
|
+```json
|
|
|
+{
|
|
|
+ "external_id": "PAY_a1b2c3d4",
|
|
|
+ "token_external_id": "TOKEN_ABC123"
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+**Sucesso**
|
|
|
+- `200 – S_TOKEN_TRANSFERRED`: transferência executada e orderbook marcado como concluído.
|
|
|
+- `200 – S_TOKEN_ALREADY_TRANSFERRED`: ordem já estava concluída anteriormente.
|
|
|
+
|
|
|
+```json
|
|
|
+{
|
|
|
+ "status": "ok",
|
|
|
+ "msg": "[100] Request ok.",
|
|
|
+ "code": "S_TOKEN_TRANSFERRED",
|
|
|
+ "data": {
|
|
|
+ "orderbook_id": 321,
|
|
|
+ "token_external_id": "TOKEN_ABC123",
|
|
|
+ "destination_address": "0x8AC9...",
|
|
|
+ "transfer_output": "Transfer success",
|
|
|
+ "transfer_error": ""
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+**Erros principais**
|
|
|
+- `400 – E_VALIDATE`: body inválido.
|
|
|
+- `401 – E_VALIDATE`: empresa não encontrada no contexto JWT.
|
|
|
+- `403 – E_FORBIDDEN`: orderbook pertence a outra empresa.
|
|
|
+- `404 – E_NOT_FOUND`: pagamento ou orderbook inexistente / `E_WALLET_NOT_FOUND` para carteira.
|
|
|
+- `409 – E_PAYMENT_PENDING`: pagamento ainda não tem `status_id = 1`.
|
|
|
+- `500 – E_DATABASE` ou `E_TRANSFER`: falhas ao consultar dados ou executar o comando de transferência.
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+### 5. `POST /b3/payment/confirm`
|
|
|
+Confirma o status do pagamento ligado a uma CPR (usa `payment_id`) e, se concluído, envia a
|
|
|
+CPR para a B3 e cria o token correspondente. Necessita header `Authorization` (JWT) e pode
|
|
|
+receber o token B3 via body ou headers customizados (`X-B3-Authorization`).
|
|
|
+
|
|
|
+| Campo | Tipo / Regra |
|
|
|
+|-------------------|-----------------------------------------------|
|
|
|
+| `payment_id` | inteiro positivo |
|
|
|
+| `b3_access_token` | opcional (string). Pode vir também via header |
|
|
|
+
|
|
|
+**Request**
|
|
|
+```json
|
|
|
+{
|
|
|
+ "payment_id": 555,
|
|
|
+ "b3_access_token": "Bearer ..."
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+**Sucesso (`200 – S_CPR_SENT`)**
|
|
|
+```json
|
|
|
+{
|
|
|
+ "status": "ok",
|
|
|
+ "msg": "[100] Request ok.",
|
|
|
+ "code": "S_CPR_SENT",
|
|
|
+ "data": {
|
|
|
+ "message": "CPR enviada e token criado com sucesso",
|
|
|
+ "payment_id": 555,
|
|
|
+ "b3_response": {"status": "OK"},
|
|
|
+ "token_id": 99,
|
|
|
+ "token_external_id": "TOKEN_ABC123",
|
|
|
+ "tx_hash": "0x..."
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+**Erros principais**
|
|
|
+- `400 – E_VALIDATE`: `payment_id` ausente/≤0.
|
|
|
+- `404 – E_NOT_FOUND`: pagamento inexistente / `E_CPR_NOT_FOUND` (sem CPR ligada).
|
|
|
+- `409 – E_PAYMENT_PENDING`: pagamento ainda pendente (`status_id = 0`).
|
|
|
+- `409 – E_PAYMENT_STATUS`: status diferente de concluído.
|
|
|
+- `502 – E_EXTERNAL`: falha ao comunicar com a B3.
|
|
|
+- `500 – E_TOKEN_CREATE` / `E_CPR_UPDATE`: problemas internos ao gerar token ou ligar CPR → token.
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## Observações adicionais
|
|
|
+
|
|
|
+- O webhook da Woovi (`POST /woovi/webhook`) marca o pagamento como concluído (`status_id = 1`).
|
|
|
+ Esse passo é obrigatório para que `/orderbook/transfer` aceite a transferência.
|
|
|
+- Todos os valores monetários são tratados em inteiros (centavos) após arredondamento.
|
|
|
+- Utilize os `code` (`S_*`/`E_*`) para tratar estados no frontend sem depender apenas de mensagens.
|
|
|
+
|
|
|
+## Geração de pacote Deb (opcional)
|
|
|
|
|
|
```
|
|
|
fpm -s dir -t deb \
|
|
|
@@ -19,5 +292,4 @@ fpm -s dir -t deb \
|
|
|
--config-files /etc/php-api \
|
|
|
--depends "php8.2-cli | php-cli (>= 8.2)" \
|
|
|
opt/php-api etc/php-api var/log/php-api
|
|
|
-Created package {:path=>"php-api_1.0.0_all.deb"}
|
|
|
-```
|
|
|
+Created package {:path=>"php-api_1.0.0_all.deb"}
|