Padrões de integração Magento 2 com ERP que se sustentam
Quase toda loja Magento acima de certo tamanho conversa com um ERP. Produtos e preços vêm dele, o estoque vem dele, os pedidos vão para ele, e notas e envios voltam. A marca do ERP muda de projeto para projeto, mas os problemas de integração são os mesmos: quem é dono de qual dado, com que frequência ele se move, o que acontece quando um dos lados cai e como evitar registros duplicados ou perdidos.
Este artigo passa pelos padrões de integração que vejo funcionar no Magento 2.4, onde cada um se encaixa e as partes do Magento que você usa para construí-los.
Decida primeiro quem é dono dos dados
Antes de escolher o transporte, anote qual sistema é a fonte da verdade para cada entidade. Uma divisão típica fica assim:
| Entidade | Dono usual | Direção |
|---|---|---|
| Dados mestres de produto, SKUs, custo | ERP | ERP para Magento |
| Conteúdo de marketing, imagens, campos de SEO | Magento ou um PIM | Fica no Magento |
| Preços e tier prices | ERP | ERP para Magento |
| Estoque por armazém | ERP ou WMS | ERP para Magento |
| Pedidos | Magento | Magento para ERP |
| Status do pedido, envios, rastreio | ERP | ERP para Magento |
| Clientes | Depende de B2B ou B2C | Muitas vezes nos dois sentidos |
O objetivo da tabela é proibir edições no lado que não é dono. Se os preços vêm do ERP, um admin que muda um preço no Magento vai vê-lo sobrescrito na próxima sincronização. Esse é o comportamento correto, mas só se todo mundo souber. Alguns times travam esses campos no formulário do admin com um pequeno modifier de UI component para tornar a regra visível.
Padrão 1: arquivos em lote agendados
O padrão mais antigo e ainda comum. O ERP deixa arquivos CSV ou XML no SFTP, um cron do Magento os pega e importa, e o Magento grava arquivos de pedido no sentido contrário.
Funciona bem para catálogos grandes que mudam uma ou poucas vezes por dia, e para ERPs sem API utilizável. Os pontos fracos são latência e tratamento de erro. Um arquivo que falha no meio deixa você sem saber o que foi aplicado. Se for por esse caminho:
- Processe os arquivos de forma idempotente. Importar o mesmo arquivo duas vezes precisa dar o mesmo resultado.
- Mova os arquivos processados para uma pasta de arquivo morto e os que falharam para uma pasta de erro, nunca apague.
- Para produtos, use o framework de import ou uma abordagem em bulk em vez de salvar produto por produto pelo repository.
Padrão 2: o ERP chama as APIs do Magento
Aqui o ERP ou o conector dele é o lado ativo. Ele chama a REST API do Magento para atualizar produtos, preços e estoque, e faz polling dos pedidos novos. O Magento não precisa de nada customizado para os fluxos básicos, que é o principal atrativo.
Para estoque, use o endpoint de source items do MSI em vez do endpoint legado de stock item, para que as quantidades caiam na source certa:
curl -X POST "https://example.com/rest/V1/inventory/source-items" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"sourceItems":[{"sku":"ABC-123","source_code":"warehouse_sp","quantity":42,"status":1}]}'
Para volumes grandes, vale conhecer os endpoints assíncronos de bulk. Uma requisição para /rest/async/bulk/V1/products com um array de payloads devolve um bulk UUID na hora, e as operações são processadas pelo consumer async.operations.all. Depois você consulta o status do bulk em /rest/V1/bulk/{bulkUuid}/status. Isso evita que o ERP fique esperando centenas de saves síncronos de produto.
O ponto fraco desse padrão é o polling de pedidos. Fazer polling em /V1/orders com filtro em updated_at funciona, mas você precisa lidar com diferenças de relógio e com pedidos atualizados durante a janela do polling. Sobreponha a janela um pouco e deduplique no lado do ERP pelo increment ID. Use um integration token só com os recursos de API de que o ERP precisa.
Padrão 3: o Magento envia eventos por uma queue
Quando os pedidos precisam chegar ao ERP em segundos, o Magento deve enviar em vez de esperar ser consultado. Fazer a chamada HTTP ao ERP dentro da requisição de checkout é um erro. Se o ERP está lento, o checkout fica lento. Se ele está fora do ar, você perde a exportação do pedido ou faz o pedido falhar. A solução é publicar uma mensagem e deixar um consumer fazer a chamada.
Declare um topic em etc/communication.xml:
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:framework:Communication/etc/communication.xsd">
<topic name="vendor.erp.order.export" request="string"/>
</config>
Publique o ID do pedido a partir de um observer que roda depois que o pedido é salvo:
<?php
declare(strict_types=1);
namespace Vendor\Erp\Observer;
use Magento\Framework\Event\Observer;
use Magento\Framework\Event\ObserverInterface;
use Magento\Framework\MessageQueue\PublisherInterface;
use Magento\Framework\Serialize\Serializer\Json;
class PublishOrderExport implements ObserverInterface
{
public function __construct(
private readonly PublisherInterface $publisher,
private readonly Json $json
) {
}
public function execute(Observer $observer): void
{
$order = $observer->getEvent()->getOrder();
if (!$order || !$order->getEntityId()) {
return;
}
$this->publisher->publish(
'vendor.erp.order.export',
$this->json->serialize(['order_id' => (int) $order->getEntityId()])
);
}
}
Depois ligue o queue_publisher.xml, o queue_topology.xml e o queue_consumer.xml, e escreva um consumer que carrega o pedido, faz o mapeamento e envia. A ligação completa, incluindo retries e rodar consumers sob o supervisor, está em consumers de RabbitMQ no Magento 2.
Envie só o ID na mensagem, não o pedido inteiro. O consumer deve carregar dados atualizados, porque o pedido pode ter mudado entre a publicação e o consumo. Isso também mantém as mensagens pequenas e evita vazar dados de clientes para os logs da queue.
Escolha o evento com cuidado. Pedidos podem ser criados pela loja, pelo admin, pelas APIs REST e GraphQL e por imports, e nem todos os caminhos disparam os mesmos eventos. Uma rede de segurança ajuda: adicione uma coluna erp_exported_at no pedido e um cron que pega os pedidos com mais de alguns minutos sem essa flag. Assim um evento perdido vira atraso, não pedido perdido.
Padrão 4: middleware ou iPaaS
Com vários sistemas em volta da loja (ERP, WMS, marketplaces, CRM), as integrações ponto a ponto se multiplicam. Uma camada de middleware, seja um iPaaS comercial ou um serviço pequeno que você mesmo roda, fica no meio, conversa com o Magento pelas APIs e cuida de mapeamento, retries e monitoramento fora da loja.
Isso deixa o Magento mais leve e os upgrades mais fáceis, já que menos código customizado vive no codebase. O custo é mais um sistema para hospedar e monitorar, e a lógica de mapeamento fica fora das ferramentas habituais do time de Magento. É uma boa escolha quando a lógica de integração é complexa ou compartilhada entre canais. Para uma loja só com ERP, muitas vezes é mais do que o necessário.
O que quebra toda integração com ERP
Falta de idempotência
Redes falham depois que a requisição foi processada mas antes da resposta chegar. O remetente tenta de novo e agora existem dois envios ou duas credit memos. Toda escrita que cruza a fronteira deve levar um ID externo que o lado receptor confere antes de criar qualquer coisa. No Magento, guarde o número do documento do ERP no envio ou na nota em uma coluna customizada ou extension attribute e consulte antes de criar um novo. Veja extension attributes para saber como adicionar esses campos do jeito certo.
Atualizações parciais que apagam dados
Um payload de produto sem um campo pode significar "deixe como está" ou "limpe", dependendo do endpoint e de como o conector monta a requisição. Teste isso em uma cópia de staging para todo campo que o ERP envia, principalmente para atributos com escopo de store view, onde um save no scope errado pode sobrescrever traduções.
Disputas de estoque
O ERP envia um snapshot completo de estoque enquanto o Magento continua recebendo pedidos. Se o snapshot foi tirado antes de pedidos recentes serem exportados, ele pode aumentar um estoque que já foi vendido. As reservations do MSI ajudam porque a salable quantity é calculada como quantidade menos reservations abertas, mas o ERP ainda precisa enviar quantidades que levem em conta os pedidos que ele já recebeu. A mecânica está em salable quantity e reservations.
Falta de visibilidade
Quando um cliente pergunta onde está o pedido, alguém precisa ver se ele chegou ao ERP. Registre cada exportação com o ID do pedido, o hash do payload, a resposta e a hora. Use um arquivo de log dedicado ou uma tabela no banco que o suporte consiga ler no admin. Uma exportação que falhou e que ninguém vê por três dias é o problema real mais comum nessa área.
Escolhendo um padrão
Para a maioria das lojas de porte médio, uma mistura funciona melhor: lote ou bulk API para catálogo e preços, API de source items do MSI para estoque e push baseado em queue para pedidos, com um cron de segurança. Tempo real para tudo raramente é necessário e custa muito em complexidade. O lado da exportação de pedidos, incluindo mapeamento e tratamento de status, é coberto com mais detalhe em exportando pedidos do Magento 2 para um ERP.
FAQ
O ERP deve chamar o Magento ou o Magento deve chamar o ERP?
Normalmente o ERP envia catálogo, preço e estoque para o Magento, e o Magento envia os pedidos por uma queue. O lado que é dono do dado e sabe quando ele mudou deve iniciar a transferência.
É seguro chamar a API do ERP durante o checkout?
Evite. Um ERP lento ou indisponível então deixa o checkout lento ou o quebra. Publique uma mensagem em uma queue e deixe um consumer enviar o pedido em segundo plano.
Como evito pedidos duplicados no ERP?
Use o increment ID do Magento como referência externa e faça o ERP rejeitar ou atualizar registros existentes com essa referência. No lado do Magento, guarde uma flag ou o número do documento do ERP quando a exportação der certo.
O que é a async bulk API do Magento?
É um conjunto de endpoints REST em /rest/async/bulk/ que aceitam muitas operações em uma requisição, devolvem um bulk UUID e as processam em segundo plano por um consumer de message queue.
Atendo como freelancer em Magento e Adobe Commerce, incluindo integrações com ERP. Se precisar de ajuda com isso, fale comigo.
Artigos relacionados
Exportar pedidos do Magento 2 para o ERP sem perder nenhum
Um jeito confiável de exportar pedidos do Magento 2 para um ERP: colunas de status, o evento certo, message queue, retries, idempotência e um cron de segurança.
Como criar um endpoint REST API customizado no Magento 2
Crie um endpoint REST API customizado no Magento 2.4.8 com webapi.xml, uma service interface e ACL. Cobre acesso de admin, cliente e anônimo, com exemplos.
Extension attributes no Magento 2: dados em pedidos e APIs
Adicione dados customizados a entidades do Magento 2 com extension attributes: extension_attributes.xml, plugins de repository, storage, saída REST e armadilhas comuns.
Autenticação na REST API do Magento 2: admin, customer e integration
Como funciona a autenticação na REST API do Magento 2: tokens de admin e customer, integrations, OAuth, bearer, 2FA, validade dos tokens e padrões seguros.