# Guia de Integração — Sistema PHP Legado → Impressão Térmica Universal

**Para quem vai integrar:** desenvolvedor do sistema legado (PHP).
**Tempo de implementação:** ~30 minutos por botão de impressão.
**Sem dependências novas:** não precisa instalar lib, framework ou alterar versão do PHP.

---

## 1. Como funciona

O seu sistema PHP **continua igual**. A única mudança é no momento de imprimir: em vez de gerar o HTML da passagem e chamar `window.print()`, você vai:

1. Montar um **array PHP** com os dados (que você já tem em mãos).
2. Converter para JSON e codificar em **base64**.
3. Abrir um **popup** apontando para a nossa URL com 2 parâmetros: `cnpj` e `data`.

Isso é tudo. O nosso sistema cuida do resto:

- Renderiza a passagem (ou TUTE) com layout estável.
- Gera barcode e QR Code no frontend (sem `qr_img.php`).
- Imprime na térmica 80mm com fonte legível, sem caracteres corrompidos.

---

## 2. URL de impressão

```
https://rt3773.realetech.net.br/print?cnpj=CNPJ_14_DIGITOS&data=JSON_BASE64
```

| Parâmetro | Obrigatório | Descrição |
|---|---|---|
| `cnpj` | **Sim** | CNPJ da empresa, **só dígitos**, 14 caracteres |
| `data` | **Sim** | JSON da venda codificado em **base64** |
| `modo` | Não | `individual` ou `lote` — sobrescreve a configuração padrão da empresa |

### CNPJs já cadastrados

| Empresa | CNPJ na URL |
|---|---|
| **DATTOLI** Transportes | `06140766000158` |
| **ASTRAN** | `18762919000188` |

⚠️ **Importante:** o CNPJ na URL vai SEM formatação. Nunca `06.140.766/0001-58`.

---

## 3. Código PHP — Botão "Imprimir Passagem"

Cole isso no lugar do código que hoje gera o HTML de impressão:

```php
<?php
// === 1. Monte o array com os dados da venda ===
$dados = [
  "tipo_documento" => "PASSAGEM",

  "empresa" => [
    "nome"    => "DATTOLI",
    "agencia" => "CAIS MORRO DE SÃO PAULO"
  ],

  "venda" => [
    "numero"          => $venda['numero'],        // ex: "345215"
    "data_hora"       => $venda['data_hora'],     // ex: "2026-05-11 11:15"
    "timezone_origem" => "DF",
    "vendedor"        => [
      "id"   => $vendedor['id'],
      "nome" => $vendedor['nome']
    ],
    "forma_pagamento" => "Dinheiro",
    "valor_total"     => 44.00,
    "moeda"           => "BRL"
  ],

  "viagem" => [
    "tipo" => "CONVENCIONAL",
    "trajeto" => [
      "origem"    => "MORRO DE SÃO PAULO",
      "destino"   => "VALENÇA",
      "descricao" => "MORRO DE SÃO PAULO > VALENÇA - CONVENCIONAL"
    ],
    "data_hora_prevista" => "2026-05-11 11:30",
    "timezone_embarque"  => "BA",
    "dia_semana"         => "Segunda",
    "validade"           => "Válida somente para esta data e hora."
  ],

  // === Array de passagens — UMA passagem por passageiro ===
  "passagens" => [
    [
      "pagina"   => 1,
      "codigo"   => "345215.694899",
      "passageiro" => ["nome" => "diego"],
      "produto"  => "PASSAGEM (CONVENCIONAL)",
      "valor"    => 22.00,
      "moeda"    => "BRL",
      "forma_pagamento" => "Dinheiro",

      // Barcode é OPCIONAL — só inclua se quiser
      "barcode" => [
        "tipo"  => "CODE128",
        "valor" => "345215.694899"
      ],

      // QR Code da TUTE embutida — OPCIONAL
      "qrcode_terminal" => [
        "valor"             => "345215.694899",
        "quantidade_copias" => 2
      ],

      // Vouchers — OPCIONAL — coloque na ordem que quer imprimir
      "vouchers" => [
        [
          "tipo"          => "LANCHA",
          "titulo"        => "VOUCHER DA LANCHA",
          "entregar_para" => "LANCHA",
          "trajeto"       => "Composição Terrestre do trajeto MORRO DE SÃO PAULO > VALENÇA - CONVENCIONAL",
          "valor"         => 22.00,
          "assinatura"    => "Ass. do Cobrador"
        ],
        [
          "tipo"          => "ONIBUS",
          "titulo"        => "VOUCHER DO ÔNIBUS",
          "entregar_para" => "ÔNIBUS",
          "trajeto"       => "Composição Terrestre do trajeto MORRO DE SÃO PAULO > VALENÇA - CONVENCIONAL",
          "assinatura"    => "Ass. do Cobrador"
        ]
      ]
    ]
    // ... adicione mais elementos se for uma venda com vários passageiros
  ],

  // Avisos legais — OPCIONAL — se não enviar, usa o padrão configurado da empresa
  "avisos" => [
    "O cliente é responsável por seus pertences tais como malas, bolsas e objetos pessoais.",
    "Não nos responsabilizamos caso esqueça algo na embarcação.",
    "É obrigatória a apresentação da passagem no momento do embarque.",
    "Após recolher esta passagem, o marinheiro deve apresentá-la em até 5 dias corridos no escritório para liberação.",
    "Após 5 dias a passagem não terá validade.",
    "Não amasse sua passagem."
  ],

  "impressao" => [
    "impresso_por" => ["id" => 1, "nome" => "DIEGO"],
    "data_hora"    => date("Y-m-d H:i"),
    "observacao"   => "Todos direitos reservados ©"
  ]
];

// === 2. Codifica em base64 — JSON_UNESCAPED_UNICODE é OBRIGATÓRIO ===
$json_b64 = base64_encode(json_encode($dados, JSON_UNESCAPED_UNICODE));

// === 3. Monta a URL e abre o popup ===
$cnpj = "06140766000158"; // DATTOLI
$url  = "https://rt3773.realetech.net.br/print?cnpj={$cnpj}&data={$json_b64}";

echo "<script>window.open('{$url}', 'thermal_print', 'width=1100,height=900');</script>";
```

---

## 4. Código PHP — Botão "Imprimir TUTE avulsa"

Para vender só o acesso ao terminal (sem passagem):

```php
<?php
$dados_tute = [
  "tipo_documento" => "TUTE",

  "empresa" => [
    "nome"    => "DATTOLI",
    "agencia" => "CAIS MORRO DE SÃO PAULO"
  ],

  "terminal" => [
    "nome" => "TERMINAL MORRO DE SÃO PAULO"
  ],

  "data_hora" => [
    "data"     => date("Y-m-d"),
    "hora"     => date("H:i"),
    "timezone" => "BA"
  ],

  "valor_unitario" => 2.10,
  "moeda"          => "BRL",

  // Array de TUTEs — uma entrada por TUTE vendida
  "itens" => [
    [
      "pagina" => 1,
      "codigo" => "580636.1166936",
      "valor"  => 2.10,
      "moeda"  => "BRL",
      "qrcode" => [
        "valor"             => "580636.1166936",
        "quantidade_copias" => 2
      ]
    ],
    [
      "pagina" => 2,
      "codigo" => "580636.1166937",
      "valor"  => 2.10,
      "moeda"  => "BRL",
      "qrcode" => [
        "valor"             => "580636.1166937",
        "quantidade_copias" => 2
      ]
    ]
  ],

  "impressao" => [
    "impresso_por" => ["id" => 1, "nome" => "DIEGO"],
    "data_hora"    => date("Y-m-d H:i")
  ],

  "rodape" => ["texto" => "Todos direitos reservados ©"],
  "corte"  => ["texto" => "Destaque aqui"]
];

$json_b64 = base64_encode(json_encode($dados_tute, JSON_UNESCAPED_UNICODE));
$cnpj     = "06140766000158";
$url      = "https://rt3773.realetech.net.br/print?cnpj={$cnpj}&data={$json_b64}";

echo "<script>window.open('{$url}', 'thermal_print', 'width=1100,height=900');</script>";
```

---

## 5. Código PHP — Múltiplas passagens em uma venda (lote)

Cliente comprou 3 passagens? É só colocar 3 elementos no array `passagens`:

```php
<?php
$dados['passagens'] = [
  [ "pagina" => 1, "codigo" => "345215.694899", "passageiro" => ["nome" => "Diego"],   /* ... */ ],
  [ "pagina" => 2, "codigo" => "345215.694900", "passageiro" => ["nome" => "Maria"],   /* ... */ ],
  [ "pagina" => 3, "codigo" => "345215.694901", "passageiro" => ["nome" => "Joao"],    /* ... */ ],
];

// Opcionalmente, força o modo lote (todas impressas em sequência, com corte no fim):
$url = "https://rt3773.realetech.net.br/print?cnpj={$cnpj}&data={$json_b64}&modo=lote";
```

---

## 6. Campos opcionais — o que acontece se você omitir

| Campo | Se você OMITIR ele | Quando OMITIR |
|---|---|---|
| `passagens[].barcode` | Não imprime barcode | Vendas que não precisam de leitura na catraca |
| `passagens[].qrcode_terminal` | Não imprime a TUTE embutida ao fim | Vendas sem direito a acesso ao terminal |
| `passagens[].vouchers` | Não imprime os vouchers | Vendas que vão direto, sem transbordo terrestre |
| `vouchers[].valor` | Só não exibe o valor no voucher | Voucher do Ônibus geralmente não tem valor |
| `avisos` | Usa os avisos padrão configurados para a empresa | Sempre que possível, omita — fica mais fácil de manter |
| `impressao.observacao` | Não imprime a observação final | — |

---

## 7. Combinações comuns

| Situação | `barcode` | `qrcode_terminal` | `vouchers` |
|---|:---:|:---:|:---:|
| Passagem convencional completa (Lancha + Ônibus + TUTE) | ✅ | ✅ | LANCHA, ONIBUS |
| Passagem simples (sem terminal, sem vouchers) | ✅ | ❌ | ❌ |
| Passagem só com voucher LANCHA | ✅ | ❌ | LANCHA |
| Passagem só com voucher ONIBUS | ✅ | ❌ | ONIBUS |
| TUTE avulsa (só acesso ao terminal) | — | — | — *(usa `tipo_documento: "TUTE"`)* |

A ordem dos vouchers no array **define a ordem de impressão**. Se você quer Ônibus antes da Lancha, é só inverter os elementos do array.

---

## 8. Como testar SEM mexer no seu sistema

Você pode validar a integração antes de plugar no botão real:

1. Abra: **https://rt3773.realetech.net.br/teste**
2. Escolha a empresa e um dos casos prontos (Passagem completa, TUTE, etc.).
3. Você verá o JSON na tela.
4. Copie esse JSON, **adapte os dados** para uma venda real do seu sistema.
5. No PHP local, faça `base64_encode(json_encode($seu_array, JSON_UNESCAPED_UNICODE))`.
6. Compare com a URL gerada pela tela de teste — se o resultado for parecido, está certo.

Você também pode colar a URL completa direto no navegador para ver como vai imprimir.

---

## 9. Erros mais comuns

| Sintoma | Causa provável | Correção |
|---|---|---|
| Caracteres como `ã` na impressão | Esqueceu `JSON_UNESCAPED_UNICODE` | Adicione `JSON_UNESCAPED_UNICODE` em `json_encode($dados, JSON_UNESCAPED_UNICODE)` |
| "Empresa X não encontrada — usando configuração padrão" | CNPJ errado na URL ou formatado | Use somente 14 dígitos. Verifique se o CNPJ está cadastrado em `/admin.html` |
| Tela de erro "tipo_documento inválido" | Campo `tipo_documento` ausente ou diferente de `PASSAGEM`/`TUTE` | Confira o nome do campo (case-sensitive, maiúsculas) |
| QR code aparece em branco | Campo `valor` do `qrcode_terminal`/`qrcode` está vazio | Garanta que o `valor` é uma string não-vazia |
| Sai em várias páginas A4 com folhas em branco | Destino selecionado no Chrome é "Salvar em PDF" (A4 padrão) | No diálogo: selecione a impressora térmica real, OU mude o tamanho do papel para "Personalizado — 80mm × 3276mm" |
| Popup não abre | Bloqueador de popups | Permita popups para o site da Dattoli |

---

## 10. Checklist de implementação

Para cada botão de impressão que você for adaptar:

- [ ] Identifiquei qual é o `tipo_documento` (PASSAGEM ou TUTE)
- [ ] Montei o array PHP com os dados da venda
- [ ] Estou usando `JSON_UNESCAPED_UNICODE` no `json_encode`
- [ ] Estou usando o CNPJ correto (14 dígitos, sem formatação)
- [ ] Removi o código antigo que renderizava o HTML e chamava `window.print()`
- [ ] Testei abrindo a URL final num navegador antes de plugar no botão
- [ ] Testei na impressora térmica real

---

## 11. Suporte

- **Documentação técnica completa:** `/docs/thermal-print-app-spec.md` (esquema completo de campos)
- **Planejamento do sistema:** `/docs/PLANEJAMENTO.md`
- **Página de admin (para ver/editar empresas):** https://rt3773.realetech.net.br/admin
- **Tela de testes:** https://rt3773.realetech.net.br/teste

Em caso de dúvida, abra a tela de testes, escolha um dos presets parecido com o que você quer, copie o JSON e adapte.

---

*Documento gerado pela equipe Reale Tech — versão 1.0 — 2026-05-11.*
