Re: [harbourminigui] LIB WhatsApp for Harbour via API/REST

61 views
Skip to first unread message

Marcelo de Paula

unread,
Oct 14, 2025, 3:05:29 PM (13 days ago) Oct 14
to Mrc, Harbour Minigui
Boa tarde meu amigo.
Te ajudo com todo prazer caso tenha interesse sem custo algum. 

Eu uso Windows 10 DeskTop + NODE + biblioteca WhatsApp.Web 
Minigui Extended + Borland BCC5.8 +Harbour Caso interesse te passo os caminhos. 

Uma classe para você analisar:


#include <hmg.ch>
#include 'Minigui.ch'
#include "hbextcdp.ch"          //all CodePages
#include "hbthread.ch"
#include "directry.ch"
#include "hbclass.ch"

#require "hbtip"
#require "hbssl"

CLASS TEnvioWhats
    DATA cURL
    DATA cOPT
    DATA cCelular
    DATA cCliente  
    DATA oFile
    DATA headers
    DATA body
    DATA response
    DATA lDebug     INIT .F.
    DATA oHttp

    METHOD New(cParametro, cName) CONSTRUCTOR
    METHOD BuildBody()
    METHOD AddHeader(cHeader)
    METHOD SetDebug(lEnable)
    METHOD Execute()
    METHOD CheckErrors()

    DESTRUCTOR Destroy()
ENDCLASS

METHOD New(cParametro , cName ) CLASS TEnvioWhats
    LOCAL aLines := hb_ATokens(cParametro, '_')

    hb_defaultValue(cName, '')

    // Configura headers padrão
    ::cURL    := "http://localhost:8000/zdg-media"
    ::headers := { "Content-Type: application/x-www-form-urlencoded" }

    ::cCelular := aLines[1]
    ::oFile    := cParametro
    ::cCliente := cName
   
RETURN Self

METHOD BuildBody() CLASS TEnvioWhats
    LOCAL aMessages := {;
        "Olá %s, segue em anexo o recibo. Obrigado pela confiança!",;
        "Prezado %s, anexo o recibo solicitado. Agradecemos!",;
        "%s, segue o recibo conforme solicitado. Atenciosamente!",;
        "Olá %s, conforme combinado, segue o recibo. Obrigado!";
    }
    LOCAL nRandom := hb_RandomInt(1, LEN(aMessages))
    LOCAL cMessage := aMessages[nRandom]
    LOCAL cFileURL

    cMessage := hb_StrReplace(cMessage, {"%s" => AllTrim(::cCliente)})
    cFileURL := "https://seu_endereço.com.br/recibo/" + ::oFile

    ::body := "number=55" + ::cCelular + ;
                  "&nome=" + AllTrim(::cCliente) + ;
                  "&file=" + cFileURL + ;
                  "&mensagem=" + hb_UrlEncode(cMessage)
RETURN NIL

METHOD AddHeader(cHeader) CLASS TEnvioWhats
    AAdd(::headers, cHeader)
RETURN Self

METHOD SetDebug(lEnable) CLASS TEnvioWhats
    ::lDebug := hb_defaultValue(lEnable, .F.)
RETURN Self

METHOD CheckErrors() CLASS TEnvioWhats
    LOCAL lError := .F.
   
    IF Empty(::cCelular)
        ::response := "Erro: Número de celular não definido!"
        lError := .T.
    ENDIF
   
    IF Empty(::oFile)
        ::response := "Erro: Arquivo não especificado!"
        lError := .T.
    ENDIF
   
RETURN !lError

METHOD Execute() CLASS TEnvioWhats
    LOCAL cDebug
    LOCAL nErr, cErr
    LOCAL aPartion
    LOCAL aRePartion
    LOCAL cResponse := ""

    ::response := ''
    // Verifica pré-requisitos
    IF !::CheckErrors()
        ::response := "Erro na configuração"
        RETURN .F.
    ENDIF

    // Constrói o corpo da requisição
    ::BuildBody()

    // Cria objeto TIP
    // Cria objeto MSXML2 (SEU MÉTODO CONFIÁVEL)
    TRY
        ::oHttp := win_OleCreateObject("MSXML2.ServerXMLHTTP.6.0")
    CATCH
        ::response := "Erro: MSXML2.ServerXMLHTTP não disponível"
        RETURN .F.
    END TRY
    // Configura opções
    ::oHttp:setOption('2', '13056')  // Ignorar erros SSL

    // Executa a requisição
    TRY
        ::oHttp:Open("POST", ::cURL, .F.)
        ::oHttp:SetRequestHeader("Content-Type", "application/x-www-form-urlencoded")
        ::oHttp:SetRequestHeader("Connection", "keep-alive")
       
        ::oHttp:Send(::body)
        ::oHttp:WaitForResponse(30000)  // 30 segundos timeout
       
        // Obtém resposta
        cResponse := ::oHttp:ResponseText
        nErr := 0  // Sucesso
    CATCH
        cResponse := "Erro na conexão/comunicação"
        nErr := -1
        RETURN .F.
    END TRY

    // Modo debug exibe detalhes
    aPartion   := hb_ATokens( ::body , '=' )
    aRePartion := hb_ATokens( aPartion[3] , '&' )
    ::response := cResponse
    // Monta linha colorida
    oDebug  += ;
            SUBSTR( aPartion[2] , 3,11) + ;
            "  Cliente: " + aRePartion[1] + ;
            "  Status: " + Time() + ' -> ' + ;
            IIF(nErr == 0, "SUCESSO", "ERRO: " + ::response) + hb_eol()
    RETURN (nErr == 0)

// Libera o objeto OLE
METHOD Destroy() CLASS TEnvioWhats
    IF HB_ISOBJECT(::oHttp)
        ::oHttp := NIL  // Libera o objeto OLE
    ENDIF
    RETURN

// Adicione esta função no início do seu programa
FUNCTION hb_UrlEncode(cString)
    LOCAL cResult := ""
    LOCAL cChar
    LOCAL nAsc
   
    FOR i := 1 TO LEN(cString)
        cChar := SUBSTR(cString, i, 1)
        nAsc := ASC(cChar)
       
        DO CASE
        CASE (nAsc >= 48 .AND. nAsc <= 57) .OR. ;  // 0-9
             (nAsc >= 65 .AND. nAsc <= 90) .OR. ;  // A-Z
             (nAsc >= 97 .AND. nAsc <= 122) .OR. ; // a-z
             cChar $ ".-_~"
            cResult += cChar
        OTHERWISE
            cResult += "%" + STRZERO(nAsc, 2, 16)
        ENDCASE
    NEXT
    RETURN cResult

Em ter., 14 de out. de 2025 às 12:29, Mrc <mrcl...@gmail.com> escreveu:
Buenas tardes.

Qué usas para enviar los mensajes?
Cuánto cuesta y cuáles son los pasos para configurarlo?

Un saludo

Em qui., 25 de set. de 2025 às 03:56, Marcelo de Paula <depau...@gmail.com> escreveu:
Isso é muito complicado. De qualquer forma você fica amarrado aí servidor do fornecedor desse serviço.

Se alguém se interessar eu explico como montar o seu próprio.

Depaula.jau

rry...@poczta.onet.pl

unread,
Oct 15, 2025, 1:49:12 AM (13 days ago) Oct 15
to Harbour Minigui
Is it a mistake ?
STRZERO(nAsc, 2, 16)

strzero(160,2,16) returns ** ?

Reply all
Reply to author
Forward
0 new messages