WooCommerce integrado a serviços de hidrojateamento em colunas: arquitetura técnica
Como integrar WooCommerce a serviços de hidrojateamento em colunas usando APIs, webhooks e automações para gestão técnica de ordens de serviço.
Um condomínio na zona oeste de São Paulo aciona o site da administradora às 22h de uma sexta-feira: a coluna principal de esgoto entupiu e o refluxo atinge três andares. O síndico acessa o portal, seleciona “Hidrojateamento de coluna predial — urgência noturna”, preenche o andar de acesso e a metragem estimada, paga via PIX e recebe confirmação imediata. Nos bastidores, o pedido disparou webhook para o sistema de gestão de campo, alocou o técnico de plantão mais próximo e enviou a ordem de serviço com geolocalização e dados de acesso ao WhatsApp dele. Às 23h15 a equipe estava no local. Esse cenário só existe porque a camada de e-commerce deixou de ser apenas carrinho de compras e virou orquestradora de operações técnicas.
A integração entre WooCommerce e serviços de hidrojateamento em colunas exige mais que instalar plugins: requer arquitetura de eventos, contratos de dados bem definidos e tratamento de falhas que garantam idempotência. O desenvolvedor WordPress atua como engenheiro de integração, conectando a camada de apresentação (produtos, checkout, conta do cliente) à camada de execução (agendamento, despacho, relatório técnico, faturamento). Cada ponto de contato — do atributo do produto ao webhook de reembolso — carrega implicações operacionais que, se mal modeladas, geram ordens duplicadas, técnicos ociosos ou clientes sem resposta.
Este artigo detalha a implementação técnica dessa integração: modelagem de produtos como serviços técnicos, captura de metadados no checkout, design de webhooks resilientes, sincronia de status bidirecional e automações que eliminam retrabalho manual. O foco está no código, na arquitetura e nas decisões que separam um protótipo frágil de um sistema que roda em produção sob demanda real.
Modelagem de produtos como serviços técnicos
No WooCommerce padrão, produtos são físicos ou virtuais. Para hidrojateamento, o tipo “Serviço” (introduzido no WooCommerce 7.8+) remove abas de envio e estoque, mas não resolve a complexidade de precificação variável. A solução está em atributos globais padronizados: “Diâmetro da coluna” (100mm, 150mm, 200mm), “Material” (PVC, ferro fundido, amianto), “Metragem linear” (faixas de 5m), “Tipo de acesso” (caixa de inspeção, ralo de piso, quebra-piso) e “Urgência” (comercial, 24h, noturna). Cada combinação define um multiplicador de preço base.
Campos personalizados no checkout capturam dados operacionais: “Ponto de referência interno”, “Restrição de horário no condomínio”, “Número de andares afetados”, “Histórico de entupimentos recentes”. Esses campos são salvos como meta do pedido (_ponto_referencia, _restricao_horario, etc.) e incluídos no payload do webhook. Use o hook woocommerce_checkout_fields para adicionar e woocommerce_checkout_update_order_meta para persistir. Valide no frontend com JavaScript (máscara de telefone, CEP com ViaCEP) para reduzir erro humano.
Exemplo de registro de atributo técnico via código:
function registrar_atributos_hidrojateamento() {
$atributos = [
'pa_diametro' => [
'name' => 'Diâmetro da coluna',
'type' => 'select',
'values' => ['100mm', '150mm', '200mm', '250mm'],
'attribute_label' => 'Diâmetro',
'attribute_type' => 'select',
'attribute_orderby' => 'menu_order',
'attribute_public' => 1,
],
'pa_material' => [
'name' => 'Material da tubulação',
'type' => 'select',
'values' => ['PVC', 'Ferro fundido', 'Amianto', 'Concreto'],
],
'pa_urgencia' => [
'name' => 'Nível de urgência',
'type' => 'select',
'values' => ['Comercial (8h-18h)', '24 horas', 'Noturna (22h-6h)'],
],
];
foreach ($atributos as $slug => $args) {
wc_create_attribute($args);
}
}
add_action('init', 'registrar_atributos_hidrojateamento');
Precificação dinâmica baseada em atributos técnicos
O preço final não é fixo: varia com diâmetro, metragem, urgência e acesso. Evite criar uma variação para cada combinação (explosão combinatória). Em vez disso, use o hook woocommerce_before_calculate_totals para aplicar multiplicadores no carrinho. Cada item do carrinho carrega os atributos selecionados; a lógica lê esses valores, consulta tabela de multiplicadores (armazenada em opção do site ou custom table) e define o preço unitário antes do cálculo de totais.
function aplicar_multiplicadores_hidrojateamento($cart) {
if (is_admin() && !defined('DOING_AJAX')) return;
$multiplicadores = get_option('hidrojateamento_multiplicadores', [
'diametro' => ['100mm' => 1.0, '150mm' => 1.35, '200mm' => 1.75, '250mm' => 2.2],
'urgencia' => ['Comercial (8h-18h)' => 1.0, '24 horas' => 1.5, 'Noturna (22h-6h)' => 2.0],
'acesso' => ['caixa_inspecao' => 1.0, 'ralo_piso' => 1.2, 'quebra_piso' => 1.8],
]);
foreach ($cart->get_cart() as $cart_item) {
$product = $cart_item['data'];
if (!$product->is_type('service')) continue;
$base_price = (float) $product->get_price();
$diametro = $cart_item['variation']['attribute_pa_diametro'] ?? '';
$urgencia = $cart_item['variation']['attribute_pa_urgencia'] ?? '';
$acesso = $cart_item['meta_data']['_tipo_acesso'] ?? 'caixa_inspecao';
$multiplicador = 1.0;
$multiplicador *= $multiplicadores['diametro'][$diametro] ?? 1.0;
$multiplicador *= $multiplicadores['urgencia'][$urgencia] ?? 1.0;
$multiplicador *= $multiplicadores['acesso'][$acesso] ?? 1.0;
$cart_item['data']->set_price($base_price * $multiplicador);
}
}
add_action('woocommerce_before_calculate_totals', 'aplicar_multiplicadores_hidrojateamento', 20, 1);
Essa abordagem mantém o catálogo enxuto (um produto por tipo de serviço) e delega a complexidade à camada de cálculo. A tabela de multiplicadores pode ser gerenciada via painel admin personalizado (Settings API) para que o gestor altere preços sem deploy de código.
Arquitetura de webhooks resilientes
Webhooks do WooCommerce são HTTP POST com payload JSON assinado via HMAC-SHA256 (segredo configurado no painel). O endpoint receptor deve: (1) verificar assinatura comparando hash_hmac('sha256', $body, $secret) com header X-WC-Webhook-Signature; (2) checar idempotência via header X-WC-Webhook-ID (UUID único por evento) armazenado em tabela wp_hidrojateamento_webhook_log com colunas webhook_id, evento, payload, processado_em; (3) processar em background (fila) para responder 2xx em < 2s e evitar reenvio por timeout.
Estrutura mínima do endpoint:
// wp-json/hidrojateamento/v1/webhook/pedido
add_action('rest_api_init', function() {
register_rest_route('hidrojateamento/v1', '/webhook/pedido', [
'methods' => 'POST',
'callback' => 'processar_webhook_pedido',
'permission_callback' => '__return_true',
]);
});
function processar_webhook_pedido(WP_REST_Request $request) {
$secret = get_option('wc_webhook_secret_hidrojateamento');
$signature = $request->get_header('X-WC-Webhook-Signature');
$body = $request->get_body();
$expected = base64_encode(hash_hmac('sha256', $body, $secret, true));
if (!hash_equals($expected, $signature)) {
return new WP_REST_Response(['erro' => 'Assinatura inválida'], 401);
}
$webhook_id = $request->get_header('X-WC-Webhook-ID');
global $wpdb;
$ja_processado = $wpdb->get_var($wpdb->prepare(
"SELECT 1 FROM {$wpdb->prefix}hidrojateamento_webhook_log WHERE webhook_id = %s",
$webhook_id
));
if ($ja_processado) {
return new WP_REST_Response(['status' => 'duplicado'], 200);
}
$payload = json_decode($body, true);
// Enfileirar processamento assíncrono (Action Scheduler / WP-Cron / RabbitMQ)
as_enqueue_async_action('processar_pedido_hidrojateamento', ['payload' => $payload, 'webhook_id' => $webhook_id]);
// Log imediato para idempotência
$wpdb->insert($wpdb->prefix . 'hidrojateamento_webhook_log', [
'webhook_id' => $webhook_id,
'evento' => $request->get_header('X-WC-Webhook-Topic'),
'payload' => $body,
'processado_em' => current_time('mysql', 1),
]);
return new WP_REST_Response(['status' => 'enfileirado'], 202);
});
Configure no WooCommerce: Settings → Advanced → Webhooks → Add webhook. Tópicos essenciais: order.created, order.updated, order.paid, order.cancelled, order.refunded. URL aponta para seu endpoint REST. Secret gerado aleatoriamente (32 chars) e salvo em opção. Teste com RequestBin ou ngrok antes de produção.
Sincronia bidirecional de status
O fluxo não é unidirecional. O sistema de campo (app do técnico, ERP, planilha) deve atualizar o pedido no WooCommerce para que o cliente veja progresso em “Minha conta” e e-mails automáticos disparem. Use a REST API do WooCommerce (Consumer Key/Secret com permissão read/write) para PUT /wp-json/wc/v3/orders/{id} com status mapeado: novo → processing, agendado → on-hold (com meta _data_agendamento), em_execucao → processing (meta _tecnico_id, _inicio_execucao), concluido → completed (meta _relatorio_tecnico_url, _fotos_antes_depois), cancelado → cancelled (meta _motivo_cancelamento).
Mapeamento sugerido:
| Status campo | Status WooCommerce | Metas adicionadas |
|---|---|---|
| Novo | processing | — |
| Agendado | on-hold | _data_agendamento, _tecnico_id |
| Em execução | processing | _inicio_execucao, _tecnico_id |
| Concluído | completed | _relatorio_tecnico_url, _fotos_antes_depois, _assinatura_cliente |
| Cancelado | cancelled | _motivo_cancelamento, _cancelado_por |
Implemente no sistema de campo uma fila de sincronização com retry exponencial (1min, 5min, 15min, 1h) e dead-letter queue para falhas persistentes. Logue cada tentativa. O cliente recebe e-mail nativo do WooCommerce a cada mudança de status; personalize templates via woocommerce/emails/ no tema filho.
Automações que eliminam retrabalho manual
Além da integração núcleo, três automações de alto impacto: (1) Notificação de técnico via WhatsApp Business API ao criar ordem — use template aprovado (HSM) com variáveis: nome cliente, endereço, serviço, urgência, link Google Maps. Disparada pela action assíncrona que processa order.paid. (2) Geração automática de relatório técnico em PDF ao concluir — hook woocommerce_order_status_completed dispara geração via DomPDF/mPDF com dados do pedido, fotos anexadas (ACF repeater no pedido), assinatura digital (canvas no app do técnico). PDF salvo no S3/Wasabi e URL gravada em _relatorio_tecnico_url. (3) Follow-up de satisfação 48h após conclusão — Action Scheduler agenda enviar_pesquisa_satisfacao com link para formulário (Gravity Forms/Typeform) que grava NPS no meta do pedido.
Exemplo de agendamento de follow-up:
function agendar_follow_up_satisfacao($order_id) {
$order = wc_get_order($order_id);
if (!$order || $order->get_status() !== 'completed') return;
as_schedule_single_action(
strtotime('+48 hours'),
'enviar_pesquisa_satisfacao',
['order_id' => $order_id]
);
}
add_action('woocommerce_order_status_completed', 'agendar_follow_up_satisfacao');
function enviar_pesquisa_satisfacao($args) {
$order = wc_get_order($args['order_id']);
$email = $order->get_billing_email();
$link = 'https://seusite.com/pesquisa-satisfacao/?order=' . $order->get_order_number();
wp_mail($email, 'Como foi seu atendimento?', "Avalie nosso serviço: $link");
}
add_action('enviar_pesquisa_satisfacao', 'enviar_pesquisa_satisfacao');
Monitoramento, observabilidade e recuperação de falhas
Em produção, falhas acontecem: webhook não entrega, API do WhatsApp cai, PDF não gera. Implemente painel de saúde (admin page) que mostra: últimos 50 webhooks recebidos (status, latência, erro), fila de ações agendadas (pendentes, falhas, executadas), taxa de sucesso de sincronização de status (últimas 24h). Use Action Scheduler nativo (incluído no WooCommerce) ou biblioteca externa (Laravel Horizon style) com dashboard. Configure alertas: se > 5% webhooks falham em 1h → Slack/email para equipe dev; se fila > 100 jobs pendentes → escalação.
Para recuperação: script CLI (wp cli command) que re-processa webhooks falhos por ID ou re-dispara sincronização de status para pedidos em intervalo de datas. Teste mensalmente em staging simulando falhas (derrubar endpoint, invalidar secret, corromper payload). Documente runbooks: “Como reenviar webhooks dos últimos 7 dias”, “Como forçar status ‘completed’ em lote”.
A integração madura não é a que nunca falha, mas a que expõe falhas rápido, permite reprocessamento seguro e mantém rastreabilidade ponta a ponta — do clique no botão “Pagar” ao técnico assinando o relatório no local. Para equipes que precisam de suporte operacional imediato, uma desentupidora em São Paulo e região com infraestrutura técnica integrada ao fluxo digital reduz o tempo entre chamado e resolução.
Boas práticas de segurança e LGPD
Dados de endereço, telefone e geolocalização são dados pessoais sensíveis. Criptografe em trânsito (TLS 1.2+) e em repouso (colunas criptografadas ou filesystem encrypted). No payload do webhook, envie apenas o necessário; evite enviar CPF/CNPJ se não for usado no campo. Implemente política de retenção: logs de webhook 90 dias, PDFs de relatório 5 anos (exigência fiscal), metadados do pedido enquanto a conta existir. Permita exclusão via “Minha conta” (hook woocommerce_privacy_delete_personal_data) que anonimiza meta do pedido e remove do sistema de campo via API.
Valide nonce em endpoints AJAX do painel admin. Use current_user_can('manage_woocommerce') em rotas REST sensíveis. Rotacione segredos de webhook a cada 90 dias (script automatizado que atualiza no WooCommerce e no .env do receptor). Audite acessos: logue IP, user-agent, user_id em toda escrita no banco relacionada a ordens de serviço.
Testes de contrato e pipeline de deploy
Trate a integração como microsserviço: testes de contrato (Pact ou JSON Schema) entre payload do webhook e consumidor. No CI/CD: (1) unit tests para lógica de multiplicadores, (2) integration tests com WooCommerce headless (WP-CLI + PHPUnit) simulando pedidos, (3) contract tests validando schema do payload order.paid contra consumidor, (4) smoke test em staging disparando webhook real via ngrok. Deploy com feature flag (HIDROJATEAMENTO_INTEGRACAO_ATIVA) para rollback instantâneo. Versionamento de payload: v1 no header Accept: application/vnd.hidrojateamento.v1+json; quebre compatibilidade apenas em v2 com período de transição.
A complexidade real não está no código do hook, mas na disciplina de engenharia: versionamento, observabilidade, idempotência, recuperação. Equipes que investem nisso transformam o WooCommerce em backbone operacional confiável — não apenas loja virtual.
A integração entre WooCommerce e hidrojateamento em colunas bem-sucedida depende de modelagem de dados rigorosa, webhooks idempotentes, sincronia bidirecional de status e automações que removem o humano do loop operacional. Comece com um serviço-piloto, meça latência ponta a ponta (clique → técnico notificado), itere. O código mostrado aqui é base; cada operação adiciona nuances (múltiplas equipes, SLA contratual, faturamento recorrente). Trate a integração como produto, não como script — e ela escalará junto com a demanda.
Checklist prático
Perguntas frequentes
Como o WooCommerce identifica qual serviço de hidrojateamento o cliente precisa?
Através de produtos do tipo 'Serviço' configurados com atributos técnicos (diâmetro da coluna, tipo de obstrução, urgência) e campos personalizados no checkout que capturam metadados essenciais para o despacho da equipe técnica.
Qual a melhor forma de sincronizar status do pedido com a equipe de campo?
Webhooks do WooCommerce disparam eventos (pedido pago, processando, concluído) para um endpoint que atualiza o sistema de gestão de campo ou envia notificação via WhatsApp/API de mensageria com os dados técnicos do serviço.
É possível calcular preço dinâmico baseado na complexidade do hidrojateamento?
Sim, usando plugins de precificação dinâmica ou código customizado no hook 'woocommerce_before_calculate_totals' que aplica multiplicadores baseados em atributos do produto (metragem, acesso difícil, horário noturno) antes de finalizar o pedido.
Como garantir idempotência nas notificações de webhook para evitar ordens duplicadas?
Implemente verificação de assinatura HMAC (header X-WC-Webhook-Signature) e armazene o ID do evento processado (X-WC-Webhook-ID) em tabela de log para ignorar reenvios do WooCommerce em casos de timeout ou falha de rede.
Quais dados do cliente devem trafegar entre WooCommerce e o sistema de campo?
Nome, telefone, endereço completo com ponto de referência, dados do imóvel (tipo, número de andares), descrição do problema relatada no checkout, histórico de serviços anteriores e observações de acesso (portaria, restrições de horário).
Como tratar cancelamentos e reembolsos na integração?
Configure webhook para evento 'order_refunded' ou 'order_cancelled' que aciona rotina de cancelamento no sistema de campo, libera o técnico alocado e registra o motivo no CRM para auditoria e métricas de taxa de cancelamento por serviço.