# 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 `), exceto quando indicado. - **Formato de resposta**: todos usam `ResponseLib` e retornam o seguinte envelope: ```json { "status": "ok" | "failed", "msg": "[100] Request ok." | "", "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"}