Hoje iremos continuar nossa série de mensagens para o WhatsApp, mostrando como enviar mensagens com quebra linhas, texto negrito, texto itálico e também com pontos de entrada para enviar uma mensagem de boas vindas quando um novo Cliente, Fornecedor ou Vendedor for cadastrado.
Primeiramente pessoal, tenha os fontes NETiZAP.prw e zZapSend.prw disponibilizados na primeira semana da série – clique aqui para saber mais.
Agora, o que precisamos entender, é que o próprio WhatsApp trata situações para deixar o texto personalizado, como por exemplo, itálico ser com underscore/underline, negrito ser com asterisco, tachado ser com um til e monoespaçado com crases.
Para o nosso contexto, iremos usar apenas o itálico e o negrito. Além deles, também iremos usar a quebra de linha, que podemos usar simplesmente o \n para quebra. Mas para deixar nosso fonte de maneira mais fácil o entendimento, iremos adaptar para que ele entenda tags HTML, assim ao receber por exemplo <b>, ele já entenda que irá deixar aquele trecho negrito.
Então abaixo segue o zZapSend com as mudanças realizadas:
//Bibliotecas #Include "TOTVS.ch" /*/{Protheus.doc} User Function zZapSend Função que dispara uma mensagem para um smartphone com o aplicativo do WhatsApp @type Function @author Atilio @since 05/08/2021 @version version @param cTelDestin, Caractere, Telefone de destino com o país 55 e o ddd - por exemplo 5514999998888 @param cMensagem, Caractere, Mensagem que será enviada para esse WhatsApp @return aRet, Array, Posição 1 define se deu certo o envio com .T. ou .F. e a Posição 2 é o JSON obtido como resposta do envio com o protocolo @obs É necessário baixar a classe NETiZAP desenvolvida pelo grande Júlio Wittwer disponível em https://github.com/siga0984/NETiZAP/blob/master/NETiZAP.prw /*/ User Function zZapSend(cTelDestin, cMensagem) Local aArea := GetArea() Local cLinha := SuperGetMV("MV_X_ZAPLI", .F., "5521986855299") Local nPorta := SuperGetMV("MV_X_ZAPPO", .F., 13155) Local cChave := SuperGetMV("MV_X_ZAPCH", .F., "fUzanE5ncxlTAWBjMO30") Local aRet := {.F., ""} Local oZap Default cTelDestin := "" Default cMensagem := "" //Retira caracteres em branco dos lados cTelDestin := Alltrim(cTelDestin) cMensagem := Alltrim(cMensagem) //Transforma o texto em UTF-8 cMensagem := EncodeUTF8(cMensagem) //Retira caracteres especiais do telefone por exemplo +55 (14) 9 9999-8888 cTelDestin := StrTran(cTelDestin, " ", "") cTelDestin := StrTran(cTelDestin, "+", "") cTelDestin := StrTran(cTelDestin, "(", "") cTelDestin := StrTran(cTelDestin, ")", "") cTelDestin := StrTran(cTelDestin, "-", "") //Se houver telefone, mensagem, o número for menor que 12 caracteres (551400000000) e não iniciar com 55 não irá enviar a mensagem If Empty(cTelDestin) .And. Empty(cMensagem) .And. Len(cTelDestin) < 12 .And. SubStr(cTelDestin, 1, 2) != "55" aRet[1] := .F. aRet[2] := '[{"error":"Parametro(s) enviado(s) para zZapSend, invalido(s)"}]' Else //Se na mesma mensagem, tiver o -Enter- normal e tags br, retira os -Enter- If CRLF $ cMensagem .And. "<br>" $ cMensagem cMensagem := StrTran(cMensagem, CRLF, '') EndIf //Agora, irá converter o restante para o formato que o WhatsApp entenda cMensagem := StrTran(cMensagem, CRLF , '\n') cMensagem := StrTran(cMensagem, '<br>' , '\n') cMensagem := StrTran(cMensagem, '<b>' , '*') cMensagem := StrTran(cMensagem, '</b>' , '*') cMensagem := StrTran(cMensagem, '<i>' , '_') cMensagem := StrTran(cMensagem, '</i>' , '_') //Instancia a classe, e passa os parametros da NETiZAP oZap := NETiZAP():New(cLinha, cChave, nPorta) //Define o destino e a mensagem de envio oZap:SetDestiny(cTelDestin) oZap:SetText(cMensagem) //Atualiza o retorno conforme se a mensagem foi enviada ou houve falha If oZap:MessageSend() aRet[1] := .T. aRet[2] := oZap:GetResponse() Else aRet[1] := .F. aRet[2] := oZap:GetLastError() EndIf EndIf RestArea(aArea) Return aRet
Agora, iremos fazer 3 pontos de entrada, para que, ao ser criado um vendedor, um cliente ou um fornecedor, seja enviado uma mensagem de boas-vindas. No caso, os pontos de entrada que usaremos serão:
- Cadastro de Vendedores: MA040TOK
- Cadastro de Fornecedores: CUSTOMERVENDOR – MODELCOMMITNTTS
- Cadastro de Clientes: CRMA980 – MODELCOMMITNTTS
Em cada um desses citados acima, iremos adicionar uma chamada para nosso zZapSend, para que seja enviado uma mensagem personalizada para cada caso. Iremos criar 1 fonte só com as 3 User Function, e iremos chamar de zZapNew.prw. Abaixo o código fonte desenvolvido:
//Bibliotecas #Include "TOTVS.ch" /*/{Protheus.doc} User Function MA040TOK Função na validação do cadastro de vendedores @type Function @author Atilio @since 06/08/2021 @version version @see https://tdn.totvs.com/pages/releaseview.action?pageId=6784256 /*/ User Function MA040TOK() Local aArea := GetArea() Local lRet := .T. Local cNome := "" Local cDDD := "" Local cTelefone := "" Local cApertoMao := "\uD83E\uDD1D" Local cBraco := "\uE14C" Local cMaosJuntas := "\uE41D" Local cMensagem := "" Local aZap := {} //Se for inclusão If INCLUI //Se tiver o nome reduzido, usa ele, do contrário, usa o nome If ! Empty(M->A3_NREDUZ) cNome := Alltrim(M->A3_NREDUZ) Else cNome := Alltrim(M->A3_NOME) EndIf cNome := Capital(cNome) //Pega o DDD, e se o usuário ter digitado 3 caracteres, retira o primeiro, por exemplo, 014 -> 14 cDDD := Alltrim(M->A3_DDDTEL) If Len(cDDD) == 3 cDDD := SubStr(cDDD, 2) EndIf //Pega o Telefone e retira os espaços cTelefone := Alltrim(M->A3_TEL) //Se tiver DDD e Telefone If ! Empty(cDDD) .And. ! Empty(cTelefone) //Monta a mensagem que será enviada ao vendedor cMensagem := 'Olá <b>' + cNome + '</b> ' + cApertoMao + '<br>' + CRLF cMensagem += '<br>' + CRLF cMensagem += 'Seja bem vindo ao nosso time de Vendedores e Representantes ' + cBraco + '<br>' + CRLF cMensagem += '<br>' + CRLF cMensagem += 'Esperamos que a parceria seja próspera e duradoura ' + cMaosJuntas + '<br>' + CRLF cMensagem += '<br>' + CRLF cMensagem += 'Atenciosamente,<br>' + CRLF cMensagem += '<br>' + CRLF cMensagem += '<i>Família Terminal de Informação</i>' + CRLF //Faz o envio da mensagem aZap := u_zZapSend("55" + cDDD + cTelefone, cMensagem) //Se houve falha, mostra a mensagem de erro If ! aZap[1] MsgStop(aZap[2], "Falha no envio") EndIf EndIf EndIf RestArea(aArea) Return lRet /*/{Protheus.doc} User Function CUSTOMERVENDOR Ponto de Entrada no padrão MVC acionado no cadastro de Fornecedores @type Function @author Atilio @since 06/08/2021 @version version @see https://centraldeatendimento.totvs.com/hc/pt-br/articles/360016405952-Cross-Segmento-TOTVS-Backoffice-Linha-Protheus-ADVPL-Ponto-de-entrada-MVC-para-as-rotinas-MATA010-MATA020-e-MATA030 /*/ User Function CUSTOMERVENDOR() Local aArea := GetArea() Local aParam := PARAMIXB Local xRet := .T. Local oObj := Nil Local cIdPonto := "" Local cIdModel := "" Local lIsGrid := .F. Local cMensagem := "" Local nOpc Local cAceno := "\uE41E" Local cSorriso := "\uE056" Local cPiscada := "\uE405" //Se tiver parâmetros If (aParam != Nil) //Pega informações dos parâmetros oObj := aParam[1] cIdPonto := aParam[2] cIdModel := aParam[3] lIsGrid := (Len(aParam) > 3) nOpc := oObj:GetOperation() //Chamada após a gravação total do modelo e fora da transação If (cIdPonto == "MODELCOMMITNTTS") //Se for inclusão If nOpc == 3 //Se tiver o contato, usa ele, do contrário, usa o nome reduzido If ! Empty(SA2->A2_CONTATO) cNome := Alltrim(SA2->A2_CONTATO) Else cNome := Alltrim(SA2->A2_NREDUZ) EndIf cNome := Capital(cNome) //Pega o DDD, e se o usuário ter digitado 3 caracteres, retira o primeiro, por exemplo, 014 -> 14 cDDD := Alltrim(SA2->A2_DDD) If Len(cDDD) == 3 cDDD := SubStr(cDDD, 2) EndIf //Pega o Telefone e retira os espaços cTelefone := Alltrim(SA2->A2_TEL) //Se tiver DDD e Telefone If ! Empty(cDDD) .And. ! Empty(cTelefone) //Monta a mensagem que será enviada ao fornecedor cMensagem := 'Olá <b>' + cNome + '</b> ' + cAceno + '<br>' + CRLF cMensagem += '<br>' + CRLF cMensagem += 'Estamos felizes em fazer negócios com você e sua empresa ' + cSorriso + '<br>' + CRLF cMensagem += '<br>' + CRLF cMensagem += 'Esperamos atender as expectativas e do que precisar conte com nossa equipe ' + cPiscada + '<br>' + CRLF cMensagem += '<br>' + CRLF cMensagem += 'Atenciosamente,<br>' + CRLF cMensagem += '<br>' + CRLF cMensagem += '<i>Família Terminal de Informação</i>' + CRLF //Faz o envio da mensagem aZap := u_zZapSend("55" + cDDD + cTelefone, cMensagem) //Se houve falha, mostra a mensagem de erro If ! aZap[1] MsgStop(aZap[2], "Falha no envio") EndIf EndIf EndIf EndIf EndIf RestArea(aArea) Return xRet /*/{Protheus.doc} User Function CRMA980 Ponto de Entrada no padrão MVC acionado no cadastro de Clientes @type Function @author Atilio @since 06/08/2021 @version version @see https://centraldeatendimento.totvs.com/hc/pt-br/articles/360016405952-Cross-Segmento-TOTVS-Backoffice-Linha-Protheus-ADVPL-Ponto-de-entrada-MVC-para-as-rotinas-MATA010-MATA020-e-MATA030 @obs A função MATA030 será descontinuada em 04/04/2022, então foi usado esse CRMA980 no lugar, veja: https://tdn.totvs.com/pages/releaseview.action?pageId=604230458 /*/ User Function CRMA980() Local aArea := GetArea() Local aParam := PARAMIXB Local xRet := .T. Local oObj := Nil Local cIdPonto := "" Local cIdModel := "" Local lIsGrid := .F. Local cMensagem := "" Local nOpc Local cOculos := "\uD83D\uDE0E" Local cComputador := "\uD83D\uDDA5" Local cSacola := "\uD83D\uDECD" //Se tiver parâmetros If (aParam != Nil) //Pega informações dos parâmetros oObj := aParam[1] cIdPonto := aParam[2] cIdModel := aParam[3] lIsGrid := (Len(aParam) > 3) nOpc := oObj:GetOperation() //Chamada após a gravação total do modelo e fora da transação If (cIdPonto == "MODELCOMMITNTTS") //Se for inclusão If nOpc == 3 //Se tiver o contato, usa ele, do contrário, usa o nome reduzido If ! Empty(SA1->A1_CONTATO) cNome := Alltrim(SA1->A1_CONTATO) Else cNome := Alltrim(SA1->A1_NREDUZ) EndIf cNome := Capital(cNome) //Pega o DDD, e se o usuário ter digitado 3 caracteres, retira o primeiro, por exemplo, 014 -> 14 cDDD := Alltrim(SA1->A1_DDD) If Len(cDDD) == 3 cDDD := SubStr(cDDD, 2) EndIf //Pega o Telefone e retira os espaços cTelefone := Alltrim(SA1->A1_TEL) //Se tiver DDD e Telefone If ! Empty(cDDD) .And. ! Empty(cTelefone) //Monta a mensagem que será enviada ao cliente cMensagem := 'Olá <b>' + cNome + '</b> ' + cOculos + '<br>' + CRLF cMensagem += '<br>' + CRLF cMensagem += 'Lhe desejamos as boas vindas, e saiba que do que precisar, pode nos acionar pelo fone <b>(14) 9 9738-5495</b><br>' + CRLF cMensagem += '<br>' + CRLF cMensagem += 'Caso queira dar uma olhada no nosso portfolio, acesse ' + cComputador + ' https://atiliosistemas.com/projetos/<br>' + CRLF cMensagem += '<br>' + CRLF cMensagem += 'Boas compras ' + cSacola + '<br>' + CRLF cMensagem += '<br>' + CRLF cMensagem += 'Atenciosamente,<br>' + CRLF cMensagem += '<br>' + CRLF cMensagem += '<i>Família Terminal de Informação</i>' + CRLF //Faz o envio da mensagem aZap := u_zZapSend("55" + cDDD + cTelefone, cMensagem) //Se houve falha, mostra a mensagem de erro If ! aZap[1] MsgStop(aZap[2], "Falha no envio") EndIf EndIf EndIf EndIf EndIf RestArea(aArea) Return xRet
Abaixo um print com as mensagens enviadas para vendedores (SA3), fornecedores (SA2) e clientes (SA1):
Obs.: Os códigos desenvolvidos nessa série do WhatsApp, estão dentro do nosso GitHub, o link é https://github.com/dan-atilio/AdvPL.
Lembrando também pessoal, se tiverem interesse em adquirir uma licença da API, entrem em contato com o pessoal da NETiZAP clicando aqui, e digam que conhecem o Atilio do Terminal de Informação.
Bom pessoal, por hoje é só.
Abraços e até a próxima.
Boa tarde Atílio, tudo bem, vê se pode me ajudar?
Baixei o fonte compilei, liberei a porta 13155, e quando efetuo a rotina u_zZapTest(), da o erro http error (10060): Comunication time out.
Bom dia Jeferson, tudo joia?
Que estranho, se você realizar testes com a NETiZAP via Postman também dá o erro?
Outro ponto, o token que eles nos liberaram para testes (em 2021) acho que já expirou. Você esta usando um token gerado por vocês mesmo?
Fico no aguardo.
Tenha uma ótima e abençoada quinta feira.
Um grande abraço.