Uma integração deixa de ser um detalhe técnico quando seus campos, códigos de erro e regras de acesso aparecem em controladores, serviços de aplicação, modelos e processos de negócio. Nesse ponto, mudar de fornecedor, atualizar uma API ou tratar um incidente externo exige modificar partes da aplicação que não deveriam conhecer esse sistema.
Isolar integrações externas em PHP consiste em estabelecer uma fronteira clara: o domínio expressa o que precisa em sua própria linguagem, e uma camada de infraestrutura traduz essa necessidade para o protocolo, formato e comportamento concretos do fornecedor. Não se trata de ocultar uma API atrás de uma classe com outro nome, mas de impedir que suas decisões condicionem toda a aplicação.
Quando uma integração já está contaminando a aplicação

O acoplamento costuma crescer de forma incremental. Uma equipe consome uma API a partir de um controlador para resolver uma entrega urgente; depois, outro fluxo reutiliza o mesmo cliente; por fim, os arrays de resposta e as exceções do SDK tornam-se dependências implícitas do negócio.
- Os casos de uso recebem ou retornam arrays com nomes de campos do fornecedor.
- A lógica de negócio compara códigos externos, como
ERR_42ouPENDING_REVIEW. - Controladores, comandos e jobs em fila constroem requisições HTTP diretamente.
- As exceções do SDK externo são capturadas fora da infraestrutura.
- Uma alteração de credenciais, endpoints ou versões obriga a editar vários módulos.
- Os testes do domínio precisam de conexões reais, tokens ou respostas simuladas do fornecedor.
Esses sinais não significam que seja necessário iniciar uma reescrita completa. Indicam, sim, que convém priorizar a integração pelo seu risco: criticidade para o negócio, frequência de mudanças do fornecedor, volume de consumidores internos, sensibilidade dos dados e dificuldade para se recuperar de uma falha.
Definir contratos a partir da linguagem do negócio
O contrato interno, também chamado de porta, deve descrever uma capacidade de que a aplicação precisa, não uma reprodução do catálogo de operações de uma API externa. Por exemplo, uma aplicação de reservas pode precisar de “solicitar uma reserva”, “consultar seu status” e “cancelá-la”. O domínio não precisa saber que um fornecedor usa XML, OAuth, um identificador numérico ou uma convenção específica de tentativas.
Uma porta pode ser expressa como uma interface PHP:
interface ReservationGateway
{
public function request(ReservationRequest $request): ReservationResult;
public function status(ReservationReference $reference): ReservationStatus;
public function cancel(ReservationReference $reference): void;
}Os tipos do contrato devem pertencer à linguagem interna. ReservationRequest contém os dados necessários para a decisão de negócio; não deveria incluir campos de autenticação, cabeçalhos HTTP nem nomes legados do fornecedor. Da mesma forma, uma referência interna pode encapsular a identidade externa sem torná-la dominante em todos os casos de uso.
Os componentes de uma fronteira de integração
Porta, adaptador e DTO interno
A porta é a interface consumida pela aplicação. O adaptador é a implementação que se comunica com o sistema externo. Entre ambos, os DTOs internos transferem dados com uma estrutura estável para a aplicação.
O adaptador traduz nos dois sentidos: converte o DTO interno em uma requisição específica e normaliza a resposta para um resultado que o domínio possa interpretar. Se o fornecedor mudar guest_count para travellers, a mudança deve ficar contida nesse adaptador.
Configuração, credenciais e transporte
Endpoints, tokens, timeouts, certificados e políticas de tentativa são preocupações de infraestrutura. Devem ser injetados por meio de configuração e mantidos fora de entidades e serviços de domínio. Também convém separar o cliente HTTP ou SDK do adaptador: isso facilita substituir bibliotecas, registrar telemetria e testar o mapeamento sem depender do transporte real.
Tradução de erros e estados incertos
Nem todas as falhas têm o mesmo tratamento. Um erro de validação rejeitado pelo fornecedor pode ser recuperável para o usuário; uma falha de autenticação exige intervenção operacional; um timeout pode deixar um estado incerto porque o fornecedor talvez tenha processado a solicitação.
O contrato interno deve representar essas diferenças sem filtrar exceções alheias. Por exemplo, o adaptador pode transformar uma resposta de validação em ReservationRejected, um problema temporário em TemporaryUnavailable e um timeout após enviar a solicitação em UnknownSubmissionState. Este último não deve ser tratado como um simples erro: pode exigir consulta posterior por uma chave de idempotência ou reconciliação operacional.
Traduzir erros não significa apagar detalhes. Registre de forma segura o identificador de correlação, a causa técnica e a resposta relevante, evitando expor segredos ou dados sensíveis ao usuário.
Exemplo de encapsulamento de um serviço de reservas
Suponhamos que um fornecedor exija uma requisição JSON com datas em um formato específico, um código próprio de hotel e um cabeçalho de autorização. O caso de uso interno não deveria construir essa requisição. Ele recebe uma solicitação de reserva, aplica suas regras e chama ReservationGateway.
O adaptador ExternalReservationAdapter realiza as tarefas específicas:
- Converte o identificador interno da acomodação para o código reconhecido pelo fornecedor.
- Formata datas, hóspedes e preferências conforme o contrato externo.
- Adiciona credenciais e uma chave de idempotência.
- Interpreta códigos HTTP, corpos de erro e status próprios.
- Retorna uma referência e um status internos.
A aplicação mantém a regra de quando uma reserva é aceitável; o adaptador mantém a regra de como solicitá-la a esse fornecedor. Se um segundo fornecedor for incorporado, a mesma porta poderá ser implementada, desde que a capacidade de negócio seja equivalente. Caso contrário, forçar uma interface comum pode ocultar diferenças importantes e criar decisões ambíguas.
Como extrair uma integração já acoplada
A migração segura não exige interromper a evolução do produto. Comece com um inventário: localize chamadas diretas, classes do SDK, formatos externos, exceções filtradas e consumidores. Identifique primeiro os caminhos críticos ou os que mudam com maior frequência.
- Introduza uma fachada: crie a porta e um adaptador inicial que possa reutilizar temporariamente parte do cliente existente.
- Migre consumidores por fluxo: substitua as chamadas diretas de um caso de uso por vez. Evite manter duas interpretações diferentes do mesmo erro.
- Centralize o mapeamento: remova conversões de campos e códigos externos de controladores, serviços e templates.
- Adicione observabilidade: registre latência, resultados, erros normalizados e correlação entre a requisição interna e a chamada externa.
- Remova o acesso direto: quando não restarem consumidores, restrinja ou elimine o cliente exposto para evitar regressões.
Durante a transição, a fachada não deve se transformar em um contêiner genérico de métodos do SDK. Sua finalidade é definir uma fronteira útil e estável, não transferir o acoplamento para outra pasta.
Testes e critérios para validar o isolamento
Os testes do domínio devem usar dublês da porta. Assim, verificam decisões de negócio sem rede, credenciais ou comportamentos acidentais do fornecedor. Os testes do adaptador, por outro lado, devem verificar o mapeamento de requisições, respostas e erros em um ambiente controlado, um servidor simulado ou contratos documentados pelo sistema externo.
O resultado é verificável se estes critérios forem atendidos:
- Uma mudança de formato, endpoint ou SDK se concentra no adaptador e em sua configuração.
- Os casos de uso dependem de contratos internos, não de clientes HTTP nem de tipos externos.
- As exceções e os códigos do fornecedor não atravessam a fronteira.
- Os estados incertos têm tratamento explícito, incluindo idempotência ou consulta posterior quando necessária.
- Os testes de negócio são executados com dublês, e os de integração validam a tradução real.
Erros comuns antes de incorporar outro fornecedor

A abstração prematura é um risco: não crie uma hierarquia complexa para uma única integração estável sem necessidades reais de substituição. O extremo oposto também falha: replicar toda a API externa em uma interface interna faz com que o domínio herde sua complexidade.
Antes de integrar, confirme qual capacidade o negócio precisa, quem é responsável por cada dado, quais erros são acionáveis, como se evita a duplicidade de operações e o que ocorrerá se não houver resposta. Defina a porta com base nessas decisões, implemente o adaptador como tradutor e mantenha as particularidades externas na borda. Essa disciplina permite isolar integrações externas em PHP sem transformar cada mudança de fornecedor em uma alteração transversal da aplicação.



