# app/services/notificacao/whatsapp.rb # # Ponto ÚNICO de envio de WhatsApp: escolhe o provedor configurado e devolve # sempre a mesma resposta, venha de onde vier. # # Existe para que trocar Twilio ↔ Baileys seja um campo na tela, e não um `if` # espalhado por cada chamador. O NotificacaoService (aviso ao motorista) e o # Despachante (grupos) passam os dois por aqui. module Notificacao module Whatsapp Resposta = ClienteWhatsapp::Resposta def self.enviar(para:, texto:, config: ConfiguracaoNotificacao.instancia) # Grupo do WhatsApp vem como JID pronto ("120363...@g.us") — não é # telefone, não normaliza. Passa direto para a ponte, que aceita as duas # formas. if Contato::JID_GRUPO_RE.match?(para.to_s.strip) return Resposta.new(ok: false, erro: 'O Twilio não envia para grupo do WhatsApp. ' \ 'Troque o provedor para QR code.') unless config.baileys? return via_baileys(para.to_s.strip, texto) end destino = ConfiguracaoNotificacao.normalizar_telefone(para) return Resposta.new(ok: false, erro: 'Número inválido.') if destino.blank? config.baileys? ? via_baileys(destino, texto) : via_twilio(destino, texto, config) end def self.via_baileys(destino, texto) ClienteWhatsapp.padrao.enviar(para: destino, texto: texto) end def self.via_twilio(destino, texto, config) credenciais = config.credenciais_whatsapp if credenciais.blank? || credenciais[:from].blank? return Resposta.new(ok: false, erro: 'Twilio sem credenciais configuradas.') end ClienteTwilio.montar(credenciais[:sid], credenciais[:token]) .messages.create(from: credenciais[:from], to: ConfiguracaoNotificacao.canal(destino), body: texto) Resposta.new(ok: true) rescue StandardError => e # Falha de envio nunca pode subir: quem chama está no meio de um # fechamento de pagamento. Resposta.new(ok: false, erro: "#{e.class}: #{e.message}") end end end