Hoje vou mostrar como fazer a integração com WhatsApp usando a API do MktZap no Protheus via AdvPL.
Update – Setembro de 2021:
Pessoal, foi montado também exemplos usando a API da NETiZAP, inclusive criando ChatBot, segue também abaixo a listagem de artigos.
Update 30/07/2021:
Pessoal, o artigo original usa a API do MktZap, recebemos o exemplo também da ConnectZap, abaixo então terão os detalhes de ambas integrações.
NETiZAP
Abaixo a listagem de artigos, usando a API da NETiZAP:
- Enviando mensagens – link
- Enviando eMojis – link
- Personalizando mensagens (quebra de linha) com exemplo de envio automático de boas vindas para clientes, fornecedores e vendedores – link
- Enviando arquivos com exemplo de envio da DANFE via mensagem – link
- Montando um menu interativo com usuário (chatbot) – link
ConnectZap (30/07/2021)
Para visualizar a documentação e os fontes disponibilizados, acesse Criando uma integração com WhatsApp no Protheus usando a API da ConnectZap
MktZap (25/01/2021)
Pessoal, o exemplo apresentado aqui foi disponibilizado com a ajuda do grande Fernando Sauer ( LinkedIn ). Basicamente essa função, utiliza uma integração com a API da MktZap (documentação disponível em https://apidoc.mktzap.com.br/#api-History-PostCompanyIdHistoryActive ), onde através do Company ID e da Key do Cliente é possível disparar mensagens.
Via AdvPL, foram utilizados dois recursos, o HttpGet para buscar o TOKEN do cliente (conforme os parâmetros customizados MV_X_ZAPID e MV_X_ZAPCL, Company ID e Key do Cliente respectivamente), e depois para o disparo da mensagem é usado FWRest com POST.
Então no fonte temos 3 funções, a principal que é a u_zMktZap() que recebe a mensagem, o código do cliente e a loja, e a partir disso ela prepara o envio conforme o campo A1_X_WHATS no cadastro de clientes. As outras duas funções são estáticas, a fGetToken() que busca o TOKEN do cliente conforme os parâmetros e a fEnviaMsg() que monta a mensagem e realiza o disparo dela usando a API do MktZap.
Pessoal, ressalto que a integração abaixo é para envio de mensagens, se você quiser uma ferramenta completa no Protheus com integração com BOTS, recomendo:
- BOTs da UserFunction, o George Allan dá um suporte excelente
- NETiZap, o Thiago tem uma documentação riquíssima de API, inclusive tem um exemplo de uso nesse link do Tudo em AdvPL
Sem mais delongas, abaixo o código desenvolvido:
//Bibliotecas #Include 'TOTVS.ch' #Include 'ParmType.ch' #Include 'TopConn.ch' #Include "RestFul.ch" #Include "RPTDef.ch" /*/{Protheus.doc} User Function zMktZap Envia mensagem para WhatsApp usando a API do MktZap para algum cliente cadastrado na SA1 @author Fernando Sauer @since 16/10/2020 @version 1.0 @type function @return lRet, Lógico, Retorna se deu certo (.T.) ou não (.F.) o disparo no WhatsApp @obs Documentação da API: https://apidoc.mktzap.com.br/#api-History-PostCompanyIdHistoryActive Exemplo documentado e adaptado por Daniel Atilio @example u_zMktZap("Esse é um teste da Atilio Sistemas", "000001", "01") /*/ User Function zMktZap(cMensagem, cCliente, cLoja) Local aArea := GetArea() Local cToken := "" Local cNumero := "" Local cPais := "" Local lRet := .F. Default cMensagem := "" Default cCliente := "" Default cLoja := "" DbSelectArea("SA1") SA1->(DbSetOrder(1)) // Filial + Código + Loja //Se conseguir posicionar no cadastro de clientes If SA1->(DbSeek(FWxFilial("SA1") + cCliente + cLoja)) .And. ! Empty(cMensagem) //Obtem o TOKEN para disparar a mensagem cToken := fGetToken() //Se deu certo o TOKEN (texto for diferente de ERRO If Upper(cToken) != "ERRO" //Montando o número de telefone para ficar no padrão País + DDD + Número (5514999999999) - buscando de campo customizado chamado A1_X_WHATS cNumero := Alltrim(SA1->A1_X_WHATS) cPais := Alltrim(SA1->A1_PAIS) //Remove caracteres especiais do número, como hífen e parenteses cNumero := StrTran(cNumero, "-", "") cNumero := StrTran(cNumero, " ", "") cNumero := StrTran(cNumero, "(", "") cNumero := StrTran(cNumero, ")", "") //Se o começo do número for diferente de 55, e o país for Brasil, adiciona 55 na esquerda If SubStr(cNumero, 1, 2) != "55" .And. cPais == "105" cNumero := "55" + cNumero EndIf //Chama a função de envio de mensagem, e se não deu certo, mostra mensagem lRet := fEnviaMsg(cToken, cMensagem, cNumero, Alltrim(SA1->A1_NOME)) If ! lRet MsgStop("Falha ao enviar a mensagem!", "Atenção") EndIf Else MsgStop("Falha ao buscar o TOKEN!", "Atenção") EndIf Else MsgStop("Cliente não encontrado e/ou Mensagem vazia!", "Atenção") EndIf RestArea(aArea) Return lRet /*/{Protheus.doc} fGetToken Função para buscar o TOKEN do MktZap via HttpGet @author Fernando Sauer @since 16/10/2020 @version 1.0 @type function @return cToken, Caractere, Código do TOKEN disponibilizadopelo MktZap /*/ Static function fGetToken() Local cUrl := "" Local cCompId := Alltrim(GetMV("MV_X_ZAPID")) //ID da Compania - deve ser cadastrado e informado conforme MktZap disponibiliza Local cCliKey := Alltrim(GetMV("MV_X_ZAPCL")) //Chave - deve ser cadastrado e informado conforme MktZap disponibiliza Local aGetTok := {} Local cToken := "" Local cTpRet := "" Local cHtmlPage //Montando a string que será enviada para o MktZap cUrl := "https://api.mktzap.com.br/company/" cUrl += cCompId cUrl += "/token?clientKey=" cUrl += cCliKey //Executa uma requisição através do HttpGet cHtmlPage := HttpGet(cUrl) //Trata a string que foi retornada cHtmlPage := StrTran(cHtmlPage, ':', ";") cHtmlPage := StrTran(cHtmlPage, '{', "") cHtmlPage := StrTran(cHtmlPage, '}', "") cHtmlPage := StrTran(cHtmlPage, '"', "") //Quebrando a string em um array e pegando a primeira posição aGetTok := StrTokArr( cHtmlPage, ";" ) cTpRet := aGetTok[1] //Se veio a informação, pega a segunda posição sendo o TOKEN, senão retornará erro If Upper(cTpRet) == "ACCESSTOKEN" cToken := aGetTok[2] Else cToken := "Erro" EndIf Return cToken /*/{Protheus.doc} fEnviaMsg Função que faz o envio da mensagem @author Fernando Sauer @since 16/10/2020 @version 1.0 @type function @return lRet, Lógico, Retorna se deu certo (.T.) ou não (.F.) o disparo no WhatsApp /*/ Static Function fEnviaMsg(cToken, cMensagem, cNumero, cNome) Local cUrlRegisto := 'https://api.mktzap.com.br' Local cCompId := Alltrim(GetMV("MV_X_ZAPID")) //ID da Compania - deve ser cadastrado e informado conforme MktZap disponibiliza Local oRestClient := FWRest():New(cUrlRegisto) Local cClasse := "/company/" + cCompId +"/history/active" Local aHeadSend := {} Local cJson := '' Local cBodyEnv := '' Local oObjResul := Nil Local cMsgExib := '' Local cAmbiente := "whatsapp" Local lRet := .F. Default cMensagem := "" Default cNumero := "" /* Modelo de Mensagem para envio cMensagem := "Olá, *"+ AllTrim(cNome) + "* " + SPACE(80)//+ CRLF cMensagem += "Lembramos que você possui um boleto que vencerá nos próximos dias. " + SPACE(80)//+ CRLF cMensagem += "Beneficiário: " + FWFilialName(SUBSTR(SE1->E1_FILIAL,1,2)) + " " + SPACE(80)//+ CRLF cMensagem += "Vencimento: *"+ DtoC(SE1->E1_VENCREA) + "* " + SPACE(80)//+ CRLF cMensagem += "Valor R$: *" + AllTrim(TRANSFORM(SE1->E1_VALOR, "@E 999,999.99")) + "* " + SPACE(100) //+ CRLF cMensagem += "Cógido de Barras para Pagamento: " + cCodBar + " " //+ CRLF*/ //Monta o Cabeçalho aAdd(aHeadSend, "Content-Type: application/json; charset=UTF-8") aAdd(aHeadSend, "Accept: application/json") aAdd(aHeadSend, "User-Agent: Chrome/65.0 (compatible; Protheus " + GetBuild() + ")") aAdd(aHeadSend, "Authorization: Basic " + cToken) //Monta a mensagem que será enviada cBodyEnv := '{' + CRLF cBodyEnv += ' "type": "' + cAmbiente + '",' + CRLF // Texto: whatsapp cBodyEnv += ' "phone_number": "' + cNumero + '",' + CRLF // Número para envio da mensagem cBodyEnv += ' "name": "' + cNome + '",' + CRLF // Nome da Pessoa que a mensagem será enviada cBodyEnv += ' "messages": [' + CRLF cBodyEnv += ' {' + CRLF cBodyEnv += ' "type": "text" ,' + CRLF cBodyEnv += ' "content": "' + cMensagem + '" ' + CRLF cBodyEnv += ' }' + CRLF cBodyEnv += ' ]' + CRLF cBodyEnv += '}' + CRLF //Tira caracteres especiais e transforma a codificação cBodyEnv := A140IRemASC(cBodyEnv) cBodyEnv := EncodeUtf8(cBodyEnv) //Define o path onde será feito a requisição Informa o path aonde será feito a requisição oRestClient:setPath(cClasse) //Define o conteúdo do body oRestClient:SetPostParams(cBodyEnv) //Efetua o Post para enviar a mensagem If oRestClient:Post(aHeadSend) //Busca o resultado cMsgExib := oRestClient:GetResult() cJson := cMsgExib // Converte string no Formato JSon para Objeto If FWJsonDeserialize(cJson, @oObjResul) //Se houve erro, ficará na variável If Type('oObjResul:Error') == 'C' cMsgExib := oObjResul:Error lRet := .F. Else lRet := .T. EndIf //Se houve algum erro dentro do JSON será exibido Else cMsgExib := "Erro JSON: " + cJson lRet := .F. EndIf Else cMsgExib := "Erro no Post: " + oRestClient:GetLastError() + CRLF cMsgExib += oRestClient:GetResult() lRet := .F. EndIf //Mostra mensagem ao encerrar a função If lRet MsgInfo("Mensagem enviada com sucesso!", "Atenção") Else MsgStop(cMsgExib, "Erro") EndIf Return lRet
Bom pessoal, por hoje é só.
Abraços e até a próxima.
Fiquei na dúvida com estes campos: Como saber sobre o ID e Key do Cliente, onde encontras estes.
MV_X_ZAPID e MV_X_ZAPCL
Boa tarde Edmilson.
Para conseguir um ID e o Key do Cliente, é necessário assinar o serviço do MktZap – https://www.gruponewway.com.br/
Boa tarde! Em contato com MktZap, só oferecem a plataforma inteira deles de troca de mensagens Não oferencem ID e o Key. Será que voce consegue com eles alguns pra gente testar?
Bom dia.
Posso tentar jovem, mas acho que só disponibilizam a plataforma mediante a assinatura mesmo.
Grande abraço.
Boa tarde amigos.
Uma outra solução é o Connectzap.
Ele possibilita:
Envio de boleto bancário para clientes com notificações sobre vencimento.
Envio de solicitação de aprovação para determinado processo como: Solicitação de Compras, Pedido de Compras, Cotação, Contratos, etc.
Envio de Nota Fiscal de Saída para clientes.
Envio de contra-cheque para funcionários.
Comunicação do RH com Funcionários.
Notificações diversas, como saldo em estoque, não conformidades, procedimentos de segurança, servidor com baixa memória, etc.
http://www.connectzap.com.br
Bom dia Jader.
Opa, obrigado por divulgar sua ferramenta aqui também jovem.
Grande abraço.
Boa tarde amigos, estou com uma situação na minha empresa em que preciso enviar um relatório diariamente para os vendedores, irei colocar esse relatório no schedule, gostaria de saber se alguém já fez a integração pra mandar algum relatório de forma automatica pelo WhatsApp dessa forma?
Boa tarde Tiago.
Sim já disponibilizamos um exemplo, segue o link: https://terminaldeinformacao.com/2021/09/20/enviando-arquivos-pelo-whatsapp-usando-advpl-tl/
Nesse caso, usamos a DANFE para envio, você pode adaptar sua necessidade gerando um FWMSPrinter em pdf.