|
@@ -1,295 +0,0 @@
|
|
|
-# Backend PHP – Orderbook & Pagamentos
|
|
|
|
|
-
|
|
|
|
|
-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.
|
|
|
|
|
-
|
|
|
|
|
-## 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 \
|
|
|
|
|
- -n php-api -v 1.0.0 \
|
|
|
|
|
- -C build/php-api \
|
|
|
|
|
- --prefix / \
|
|
|
|
|
- --description "API PHP php-api (SmartPay)" \
|
|
|
|
|
- --license "Proprietary" \
|
|
|
|
|
- --vendor "SmartPay" \
|
|
|
|
|
- --maintainer "lucas.joaquim@smartpay.com.vc" \
|
|
|
|
|
- --architecture all \
|
|
|
|
|
- --deb-no-default-config-files \
|
|
|
|
|
- --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"}
|
|
|