Envio de arquivo em API

Projeto [x]Harbour - Compilador de código aberto compatível com o Clipper.

Moderador: Moderadores

FFreire2
Usuário Nível 1
Usuário Nível 1
Mensagens: 1
Registrado em: 21 Jun 2022 16:41
Localização: Itaporanga-SP

Envio de arquivo em API

Mensagem por FFreire2 »

Prezados...

Estou com um "pequeno" problema, estou começando a utilizar a api de pagamentos da tecnospeed e me deparei com o seguinte problema.

No código abaixo, preciso enviar o arquivo de formato "ofx" que é um extrato salvo no internet banking, mas só me retorna status = 500 ou seja, erro interno. Sei que o problema é na composição do body, pois
ja enviei via postman e retorna o que preciso, o que fazer?

Ja consegui me comunicar normalmente com a api em outras requisições, mas enviando o arquivo não.

Código: Selecionar todos


zBody := '{ "file:", "c:\teste\extrato.ofx"}'

// Define rota principal
cUrl := 'https://staging.pagamentobancario.com.br/api/v1/statement/parser'

// Cria servico
TRY
   oServer := WIN_OLECREATEOBJECT( "MSXML2.ServerXMLHTTP")
CATCH
   MsgMenu('Erro na criação do serviço...',{'&OK'},,"IM__ERRO",'Atenção',,,'32 ERR CAN',,,_branco_)
   xOk := .F.
END

IF xOk
   TRY
      oServer:Open( 'POST', cUrl, .F. )
      oServer:SetRequestHeader( 'cnpjSh', CnpjSH ) // CNPJ DA SOFTWARE HOUSE
      oServer:SetRequestHeader( 'tokenSh', TokenSH ) // TOKEN DA SOFTWARE HOUSE
      oServer:SetRequestHeader( 'payercpfcnpj', zPayerCpfCnpj ) // CNPJ DO PAGADOR
      oServer:SetRequestHeader( 'Content-Type', 'multipart/form-data' )
      oServer:Send(zBody)
      oServer:WaitForResponse( 5000 )
   CATCH
      MsgMenu('Erro na conexão da API...',{'&OK'},,"IM__ERRO",'Atenção',,,'32 ERR CAN',,,_branco_)
      xOk := .F.
   END
END

Avatar do usuário
FFreire
Usuário Nível 3
Usuário Nível 3
Mensagens: 113
Registrado em: 19 Mai 2013 16:16
Localização: Andirá-PR / Itaporanga-SP

Envio de arquivo em API

Mensagem por FFreire »

Resolvido com o seguinte código!!!

Código: Selecionar todos

//-------------------------
FUNCTION LerExtrato(zconta)
//-------------------------

LOCAL xarq := LerArquivo("*.ofx","Selecione arquivo de extrato OFX...","",.F.,.T.)
LOCAL aDadosLocal, aRetorno, xBody := '', xBound := ''

IF !EMPTY(xarq)
   aDadosLocal := RetPesqSQL(zconta,'cadcxccdet AS a, cadlocalmovimento AS b',{'b.cnpj','b.cpf'},,,.T.,'a.fkcxcc = '+C2Sql(zconta)+' AND a.fklocalmovimento = b.id')

   // Monta body para ser enviado o arquivo selecionado
   ArqToApi_Body(xarq,@xBody,@xBound)

   aRetorno := ApiPagamentos('statement/parser',,'POST',IIF(EMPTY(aDadosLocal[1,1]),aDadosLocal[1,2],aDadosLocal[1,1]),xBody,.T.,xBound)
   IF !EMPTY(aRetorno)
      aRetorno := ApiPagamentos('statement/parser/'+aRetorno["uniqueId"],,'GET',IIF(EMPTY(aDadosLocal[1,1]),aDadosLocal[1,2],aDadosLocal[1,1]))
   END

END

RETURN(NIL)

//-----------------------------------------------
STATIC FUNCTION ArqToApi_Body(zFile,zBody,zBound)
//-----------------------------------------------

LOCAL xFileUpload  := HB_FNAMENAMEEXT(zFile)
LOCAL xHexDTStamp  := HB_NUMTOHEX( VAL( HB_TTOS( HB_DATETIME() ) + STRZERO( HB_RANDOMINT( 0, 99 ), 2 ) ) ) 
LOCAL xBoundarySep

zBound       := PADLEFT( xHexDTStamp, 40, '-' )
xBoundarySep := '--' + zBound + CRLF

zBody += xBoundarySep
zBody += 'Content-Disposition: form-data; name="file"; filename="' + xFileUpload + '"' + CRLF
zBody += 'Content-Type: text/xml' + CRLF + CRLF
zBody += FILESTR( zFile )
zBody += CRLF
zBody += '--' + zBound + '--' + CRLF

RETURN(NIL)

//-----------------------------------------------------------------------------------------------
STATIC FUNCTION ApiPagamentos(zRota,zQueryParam,zMetodo,zPayerCpfCnpj,zBody,zTipoConteudo,zBound)
//-----------------------------------------------------------------------------------------------

LOCAL xOk := .T.
LOCAL cUrl := ''
LOCAL xMsg, aErrors, nCnt
LOCAL cHtml, aHtml := ''

// zRota         -> Final da rota para ser acrescentado ao URL principal, quando houver "path parameters" passar junto
// zQueryParam   -> Quando houver "query parameters" passar em matriz para ser adicionado a URL principal
// zMetodo       -> Metodo a ser utilizado (POST,GET,PUT,DELETE)
// zPayerCpfCnpj -> Quando zRota a ser utilizada, necessitar do CNPJ/CPF do pagador
// zBody         -> Quando for necessário enviar o body (montar na chamada)
// zTipoConteudo -> Se o body contem arquivo a ser enviado
// zBound        -> Composição do limite

zRota         := IIF( zRota == NIL, '', zRota )
zQueryParam   := IIF( zQueryParam == NIL, '', zQueryParam )
zMetodo       := IIF( zMetodo == NIL, '', zMetodo )
zPayerCpfCnpj := IIF( zPayerCpfCnpj == NIL, '', zPayerCpfCnpj )
zBody         := IIF( zBody == NIL, '', zBody )
zTipoConteudo := IIF( zTipoConteudo == NIL, .F., zTipoConteudo )

IF EMPTY(zRota)
   MsgMenu('zRota tem que conter final da rota e path parameters se houver',{'&OK'},,"IM__ERRO",'Atenção',,,'32 ERR CAN',,,_branco_)
   xOk := .F.
ELSEIF !EMPTY(zQueryParam) .AND. VALTYPE(zQueryParam) <> 'A'
   MsgMenu('zQueryParam tem que conter MATRIZ com query parameters se houver',{'&OK'},,"IM__ERRO",'Atenção',,,'32 ERR CAN',,,_branco_)
   xOk := .F.
ELSEIF !zMetodo $ 'POST_GET_PUT_DELETE'
   MsgMenu('zMetodo só pode conter POST/GET/PUT/DELETE',{'&OK'},,"IM__ERRO",'Atenção',,,'32 ERR CAN',,,_branco_)
   xOk := .F.
ELSEIF VALTYPE(zTipoConteudo) <> 'L'
   MsgMenu('zTipoConteudo tem que ser LÓGICO',{'&OK'},,"IM__ERRO",'Atenção',,,'32 ERR CAN',,,_branco_)
   xOk := .F.
ELSEIF zTipoConteudo .AND. EMPTY(zBound)
   MsgMenu('Quando zTipoConteudo, zBound tem que ter conteúdo',{'&OK'},,"IM__ERRO",'Atenção',,,'32 ERR CAN',,,_branco_)
   xOk := .F.
END

IF xOk
   // Define rota principal
   IF ArqAdm[APIPGTOS_AMB] == 'P' // Producao
      cUrl := 'https://api.pagamentobancario.com.br/api/v1/'
   ELSE // Homologação
      cUrl := 'https://staging.pagamentobancario.com.br/api/v1/'
   END
   // Atribui a rota, complemento de rota passada em parametro
   cUrl += zRota

   // Atribui a rota, parametro query
   IF !EMPTY(zQueryParam)
      cUrl += '?'
      FOR nCnt = 1 TO LEN(zQueryParam)
         cUrl += zQueryParam[nCnt]
         IF LEN(zQueryParam) > nCnt
            cUrl += '&'
         END
      NEXT
   END

   // Cria servico
   TRY
      oServer := WIN_OLECREATEOBJECT( "MSXML2.ServerXMLHTTP")
   CATCH
      MsgMenu('Erro na criação do serviço...',{'&OK'},,"IM__ERRO",'Atenção',,,'32 ERR CAN',,,_branco_)
      xOk := .F.
   END

   IF xOk
      TRY
         oServer:Open( zMetodo, cUrl, .F. )
         oServer:SetRequestHeader( 'cnpjSh', CnpjSH )
         oServer:SetRequestHeader( 'tokenSh', TokenSH )
         IF !EMPTY(zPayerCpfCnpj)
            oServer:SetRequestHeader( 'payercpfcnpj', zPayerCpfCnpj )
         END
         IF zTipoConteudo
            oServer:setRequestHeader( "accept", "text/plain")
            oServer:setRequestHeader( "Content-Length", ALLTRIM(STR(LEN(zBody))))
            oServer:setRequestHeader( "Content-Type", "multipart/form-data; boundary=" + zBound )
         ELSE
            oServer:SetRequestHeader( 'Content-Type', 'application/json' )
         END
         IF !EMPTY(zBody)
            oServer:Send(zBody)
         ELSE
            oServer:Send()
         END
         oServer:WaitForResponse( 5000 )
      CATCH
         MsgMenu('Erro na conexão da API...',{'&OK'},,"IM__ERRO",'Atenção',,,'32 ERR CAN',,,_branco_)
         xOk := .F.
      END

      IF xOk
         IF oServer:status == 200 .OR. oServer:status == 201
            cHtml := oServer:ResponseBody
            IF !EMPTY(cHtml)
               hb_jsondecode( cHtml, @aHtml )
            END
         ELSE
            IF oServer:status == 202 // Em processamento
               MsgMenu('Em processamento... Aguarde e repita a solicitação !!!',{'&OK'},,"IM__EXCLAMA",'Atenção',,,'32 ESC CAN',,,_branco_)
            ELSE
               xMsg := ''
               hb_jsondecode( oServer:responseText, @xMsg )
               IF oServer:status >= 500 .OR. xMsg["code"] == 401 .OR. xMsg["code"] == 404
                  xMsg := HB_OEMTOANSI(xMsg["message"])
               ELSE
                  aErrors := xMsg["errors"]
                  xMsg    := ''
                  FOR nCnt = 1 TO LEN(aErrors)
                     xMsg += ALLTRIM(STR(aErrors[nCnt,"internalCode"]))+'-'+HB_OEMTOANSI(aErrors[nCnt,"message"])+SALTO_LINHA
                  NEXT
               END
               MsgMenu(xMsg,{'&OK'},,"IM__ERRO",'Atenção',,,'32 ERR CAN',,,_branco_)
            END
         END
      END
   END
END

RETURN(aHtml)

Harbour 3.2.0+MiniGui Extended 16.02+BCC5 / HWGdebug / SIXCDX / PostgreSQL 9.5 / LetoDB 2.15 / Java8
fabiano@ffsoft.com.br
Responder