Ir para conteúdo
  • Cadastre-se

dev botao

Ver Solução Respondido por Sérgio Assunção,
  • Este tópico foi criado há 2278 dias atrás.
  • Talvez seja melhor você criar um NOVO TÓPICO do que postar uma resposta aqui.

Recommended Posts

Pois é, agora to com outro póbrema!!!! 

 

 

Segui as dicas acima, bascicamente, salvei um arquivo .xml, compirmi usando o TCompressionStream (tentei descompactar o .zip gerado mas não dá certo), converti para bit64 e enviei, mas o servidor me retorna um erro dizendo que há um caracter inválido.

 

Não sei isso pode ter sido algumn lixo que o TXMLDocument deixa ao salvar o arquivo...

Link para o comentário
Compartilhar em outros sites

  • Membros Pro

gigainfo, no ambiente de Homologação eu tambem consegui enviar um arquivo esta semana porem no de produção continua dando o seguinte erro:

 

Arquivo XML não aderente ao Schema SNGPC. Consulte http://www.anvisa.gov.br/sngpc/esquemas.asp para auxiliar na resolução dos erros encontrados.

Os itens não validados, que seguem abaixo, foram encaminhados para o e-mail [email protected]. Favor encaminhar os itens não validados para análise do suporte do programa que gera os arquivos XML em seu estabelecimento.

Descrição do erro: The element 'entradaMedicamentos' in namespace 'urn:sngpc-schema' has invalid child element 'classeTerapeutica' in namespace 'urn:sngpc-schema'. List of possible elements expected: 'urn:sngpc-schema:medicamentoEntrada'.. The element 'entradaMedicamentos' in   ...................

Att
Rodrigo Guelf
 

Link para o comentário
Compartilhar em outros sites

  • Membros
  • Solution

gigainfo, no ambiente de Homologação eu tambem consegui enviar um arquivo esta semana porem no de produção continua dando o seguinte erro:

 

Arquivo XML não aderente ao Schema SNGPC. Consulte http://www.anvisa.gov.br/sngpc/esquemas.asp para auxiliar na resolução dos erros encontrados.

Os itens não validados, que seguem abaixo, foram encaminhados para o e-mail [email protected]. Favor encaminhar os itens não validados para análise do suporte do programa que gera os arquivos XML em seu estabelecimento.

Descrição do erro: The element 'entradaMedicamentos' in namespace 'urn:sngpc-schema' has invalid child element 'classeTerapeutica' in namespace 'urn:sngpc-schema'. List of possible elements expected: 'urn:sngpc-schema:medicamentoEntrada'.. The element 'entradaMedicamentos' in   ...................

Veja se você está informando a tag classeTerapeutica dessa forma:

<entradaMedicamentos>
<medicamentoEntrada>
<classeTerapeutica>2</classeTerapeutica>
<registroMSMedicamento>1010000720146</registroMSMedicamento>
<numeroLoteMedicamento>678</numeroLoteMedicamento>
<quantidadeMedicamento>2</quantidadeMedicamento>
<unidadeMedidaMedicamento>1</unidadeMedidaMedicamento>
</medicamentoEntrada>
</entradaMedicamentos>
<entradaMedicamentos>

Ela deve estar juntamente com as outras informações do medicamento.

Sérgio

Editado por gigainfo
Equipe ACBr Sérgio Assunção
Ajude o Projeto ACBr crescer - Assine o SAC

Projeto ACBr

 

[email protected]

Link para o comentário
Compartilhar em outros sites

  • Membros

Eu ainda não consegui achar um modo de compactar o XML no delphi que seja compatível com o webservice, por hora os clientes estão tendo que fazer na unha mesmo a compactação... TCompressionStream não funciona, recebo a mensagem: "Existem caracteres inválidos na mensagem".

Ola Renan ...

Eu uso o componente tsqZip para compactar e a função FileByteToArray para a conversão para o formato aceito.

function FIleToByteArray( const FileName : string ) : TByteDynArray;
const BLOCK_SIZE=1024;
var BytesRead, BytesToWrite, Count : integer;
 F : File of Byte;
 pTemp : Pointer;
begin
 AssignFile( F, FileName );
 Reset(F);
try
 Count := FileSize( F );
 SetLength(Result, Count );
 pTemp := @Result[0];
 BytesRead := BLOCK_SIZE;
 while (BytesRead = BLOCK_SIZE ) do
 begin
  BytesToWrite := Min(Count, BLOCK_SIZE);
  BlockRead(F, pTemp^, BytesToWrite , BytesRead );
   pTemp := Pointer(LongInt(pTemp) + BLOCK_SIZE);
  Count := Count-BytesRead;
 end;
finally
  CloseFile( F );
 end;
end;

Sérgio 

Equipe ACBr Sérgio Assunção
Ajude o Projeto ACBr crescer - Assine o SAC

Projeto ACBr

 

[email protected]

Link para o comentário
Compartilhar em outros sites

Ainda não está funcionando, eu precisei salvar o arquivo .xml em disco e pedir para os usuários compactarem e enviarem pelo site, adivinha se já não estão reclamando... ehueheuheuhe

 

Estou usando o seguinte método para compactar:

 

function TSngpc2Gerenciador.GetXmlCompressedInZipFileFromString(pString: string): string;
var
  vXmlDocument: TStrings;
  vFileName: string;
  vInFile,
    vTmpFile: TFileStream;
  vCompr: TCompressionStream;
  vL: Integer;
begin
  //Salva o arquivo
  vFileName := FormatDateTime('yyyymmddhhnnsszzz', Now);
  vXmlDocument := TStringList.Create;
  vXmlDocument.Text := StringReplace(StringReplace(pString, #10, '', [rfReplaceAll]), #10, '', [rfReplaceAll]);
  vXmlDocument.SaveToFile(ExtractFilePath(ParamStr(0)) + '\' + vFileName + '.xml');


  //Compacta o arquivo
  vInFile := TFileStream.Create(ExtractFilePath(ParamStr(0)) + '\' + vFileName + '.xml', fmOpenRead);
  vTmpFile := TFileStream.Create(ExtractFilePath(ParamStr(0)) + '\' + vFileName + '.zip', fmCreate);
  vCompr := TCompressionStream.Create(clDefault, vTmpFile);
  vL := vInFile.Size;
  try
    vCompr.CopyFrom(vInFile, vL); // Efetua a compressão do arquivo
  finally
    vInFile.Free;
    vCompr.Free;
    vTmpFile.Free;
    vXmlDocument.Free;
  end;


  //Remove o XML antigo
  DeleteFile(ExtractFilePath(ParamStr(0)) + '\' + vFileName + '.xml');


  //Atribui o valor de retorno
  Result := ExtractFilePath(ParamStr(0)) + '\' + vFileName + '.zip';
end;
 
 
Este método retorna o nome do arquivo que irei converter para TByteDynArray com o método abaixo:
function TSngpc2Gerenciador.FileToByteArray(const pFileName: string): TByteDynArray;
const
  BLOCK_SIZE = 1024;
var
  vBytesRead, vBytesToWrite, vCount: integer;
  vF: file of Byte;
  vTemp: Pointer;
begin
  AssignFile(vF, pFileName);
  Reset(vF);
  try
    vCount := FileSize(vF);
    SetLength(Result, vCount);
    vTemp := @Result[0];
    vBytesRead := BLOCK_SIZE;
    while (vBytesRead = BLOCK_SIZE) do
    begin
      vBytesToWrite := Min(vCount, BLOCK_SIZE);
      BlockRead(vF, vTemp^, vBytesToWrite, vBytesRead);
      vTemp := Pointer(LongInt(vTemp) + BLOCK_SIZE);
      vCount := vCount - vBytesRead;
    end;
  finally
    CloseFile(vF);


    //Exclui o arquivo antigo
    DeleteFile(pFileName);
  end;
end;

 

E na hora da chamada ao web service:

Result := WsTeste.EnviaArquivoSNGPC(pEmail, pSenha, FileToByteArray(GetXmlCompressedInZipFileFromString(pArquivo)), pHash);

dá aquele erro de caracteres inválidos na mensagem.

Link para o comentário
Compartilhar em outros sites

  • Membros

Aqui esta o problema:
 

Result := WsTeste.EnviaArquivoSNGPC(pEmail, pSenha, FileToByteArray(GetXmlCompressedInZipFileFromString(pArquivo)), pHash);

Tente assim:
 

var     FileData : TByteDynArray;
WebService : sngpcSoap;
...
   FileData := FileToByteArray('C:\SeuArquivo.zip');
...
Retorno := WebService.EnviaArquivoSNGPC(email,senha,FileData, HashId);

Sérgio

Equipe ACBr Sérgio Assunção
Ajude o Projeto ACBr crescer - Assine o SAC

Projeto ACBr

 

[email protected]

Link para o comentário
Compartilhar em outros sites

Ainda continua o erro, ali basicamente você trocou 6 por meia dúzia, porque o método GetXmlCompressedInZipFileFromString recebe o conteúdo do XML e retorna o nome (endereço) do arquivo .zip, o método FileToByteArray recebe o nome do arquivo e devolve um TByteDynArray. Então eu chamar um dentro do outro ou um depois do outro dá no mesmo.

Link para o comentário
Compartilhar em outros sites

  • Membros

Ainda continua o erro, ali basicamente você trocou 6 por meia dúzia, porque o método GetXmlCompressedInZipFileFromString recebe o conteúdo do XML e retorna o nome (endereço) do arquivo .zip, o método FileToByteArray recebe o nome do arquivo e devolve um TByteDynArray. Então eu chamar um dentro do outro ou um depois do outro dá no mesmo.

Bom aqui eu uso da forma que eu lhe expliquei e já esta sendo usado a uma semana sem problemas.

 

Sérgio

Equipe ACBr Sérgio Assunção
Ajude o Projeto ACBr crescer - Assine o SAC

Projeto ACBr

 

[email protected]

Link para o comentário
Compartilhar em outros sites

gigainfo, talvez o problema esteja no compactação, eu utilizo a seguinte rotina:

unit System.zip;

      ZipFile := TZipFile.Create;
      try
        ZipFile.Open('SNGPC.zip', zmWrite);
        ZipFile.add('SNGPC.xml');
        ZipFile.Close;
      finally
        ZipFile.Free;
      end;
Link para o comentário
Compartilhar em outros sites

  • Membros

 

gigainfo, talvez o problema esteja no compactação, eu utilizo a seguinte rotina:

unit System.zip;

      ZipFile := TZipFile.Create;
      try
        ZipFile.Open('SNGPC.zip', zmWrite);
        ZipFile.add('SNGPC.xml');
        ZipFile.Close;
      finally
        ZipFile.Free;
      end;

Pode ser mesmo... eu uso aqui o tsqZip e não tenho problemas.

 

Sérgio

Equipe ACBr Sérgio Assunção
Ajude o Projeto ACBr crescer - Assine o SAC

Projeto ACBr

 

[email protected]

Link para o comentário
Compartilhar em outros sites

"Caracteres inválidos encontrados no texto" 

 

Não aguento mais essa frase heheheheh

 

mexi no código e agora ele está assim:

 

 

vFileName := GetXmlCompressedInZipFileFromString(pArquivo);
vHash := MD5File(vFileName);
vFile := FileToByteArray(vFileName);


WsTeste := GetSngpcSoapTeste();
Result := WsTeste.EnviaArquivoSNGPC(pEmail, pSenha, vFile, vHash);

Seguem abaixo as funções utilizadas:

 

 

function TSngpc2Gerenciador.GetXmlCompressedInZipFileFromString(pString: string): string;
var
  vFileName: string;
  vXmlDocument: TStrings;
  vZipFile: TZipFile;
begin
  //Salva o arquivo
  vFileName := FormatDateTime('yyyymmddhhnnsszzz', Now);


  if not DirectoryExists(ExtractFilePath(ParamStr(0)) + 'i_o\Sngpc') then
    ForceDirectories(ExtractFilePath(ParamStr(0)) + 'i_o\Sngpc');


  vXmlDocument := TStringList.Create;
  vXmlDocument.Text := StringReplace(StringReplace(pString, #10, '', [rfReplaceAll]), #13, '', [rfReplaceAll]);
  vXmlDocument.SaveToFile(ExtractFilePath(ParamStr(0)) + 'i_o\Sngpc\' + vFileName + '.xml');


  //Compacta o arquivo
  vZipFile := TZipFile.Create;
  try
    vZipFile.Open(ExtractFilePath(ParamStr(0)) + 'i_o\Sngpc\' + vFileName + '.zip', zmWrite);
    vZipFile.Add(ExtractFilePath(ParamStr(0)) + 'i_o\Sngpc\' + vFileName + '.xml');
    vZipFile.Close;
  finally
    vZipFile.Free;
  end;


  //Remove o XML antigo
  DeleteFile(ExtractFilePath(ParamStr(0)) + 'i_o\Sngpc\' + vFileName + '.xml');


  //Atribui o valor de retorno
  Result := ExtractFilePath(ParamStr(0)) + 'i_o\Sngpc\' + vFileName + '.zip';
end;

 

function TSngpc2Gerenciador.MD5File(const pFileName: string): string;
 var
   vMD5 : TIdHashMessageDigest5;
   vFs : TFileStream;
 begin
   vMD5 := TIdHashMessageDigest5.Create;
   vFs := TFileStream.Create(pFileName, fmOpenRead OR fmShareDenyWrite) ;
   try
     Result := vMD5.HashStreamAsHex(vFs);
   finally
     vMD5.Free;
     vFs.Free;
   end;
end;

 

 

function TSngpc2Gerenciador.FileToByteArray(const pFileName: string): TByteDynArray;
const
  BLOCK_SIZE = 1024;
var
  vBytesRead, vBytesToWrite, vCount: integer;
  vF: file of Byte;
  vTemp: Pointer;
begin
  AssignFile(vF, pFileName);
  Reset(vF);
  try
    vCount := FileSize(vF);
    SetLength(Result, vCount);
    vTemp := @Result[0];
    vBytesRead := BLOCK_SIZE;
    while (vBytesRead = BLOCK_SIZE) do
    begin
      vBytesToWrite := Min(vCount, BLOCK_SIZE);
      BlockRead(vF, vTemp^, vBytesToWrite, vBytesRead);
      vTemp := Pointer(LongInt(vTemp) + BLOCK_SIZE);
      vCount := vCount - vBytesRead;
    end;
  finally
    CloseFile(vF);
  end;
end;

Código novo, mesmo erro :x

 

Link para o comentário
Compartilhar em outros sites

  • 2 semanas depois ...

código rodando legal

Gerar o arquivo

1º é criado o arquivo xml seguindo o leiaute 2.0

2º é gravado no banco de dados em uma tabela  o nome do arquivo xml ex: c:\sistema\sngpc\mov_0105_a_0305.xml, o hash, e status de controle, e um campo de mensagem (blob)

Estrutura do arquivo de controle
id_arquivo auto
Data          date
Arquivo      varchar(60) // Ex 'C:\Sistema\sngpc\mov_0105_a_0605.xml'
Mensagem blob
Hash          varchar(32)
status        varchar(1)   valores 1,2      2=Arquivo transmitido

procedure TFArquivos.btTransmitirClick(Sender: TObject);
var strArquivo:String;
    bdaArquivo:TByteDynArray;
    xmlArquivo:TXMLDocument;
    strHash:String;
    strMens:String;
    wsEmail,wsSenha:WideString;
begin

  // dmFar.IBDSsngpc é uma tabela onde contém os dados nome do arquivo,hash,mensagem de retorno e status de trasmissão  para controle do usuário


   if dmFar.IBDSsngpc['status']='2' then showMessage('Arquivo já foi transmitido.');
   bdaArquivo:=Nil;
   if dmFar.IBDSsngpc['status']='1' then
   begin
      screen.Cursor:=crHourGlass;
      strArquivo:=dmFar.IBDSsngpc['NomeArquivo'];
      if not fileexists(strArquivo) then
      begin
         screen.Cursor:=crDefault;
         showMessage('Não encontrei o arquivo '+strArquivo);
         exit;
      end;
      wsEmail:=FPrincipal.stremail;
      wsSenha:=FPrincipal.strsenha;
      xmlArquivo:=TXMLDocument.Create(Self);
      xmlArquivo.LoadFromFile(strArquivo);
      strHash   :=dmFar.IBDSsngpc['hash'];  // gravado na tabela
      strArquivo:=ExtractFileName(strArquivo);
      bdaArquivo:=FileToByteArray(zipar(strArquivo));
      FMensagemSNGPC:=TFMensagemSNGPC.Create(Self);
      strmens:=GetsngpcSoap(blnHom,False,'',nil).ValidarUsuario(wsEmail,wsSenha);
      FMensagemSNGPC.memo1.Lines.Add('Arquivo: '+strArquivo);
      FMensagemSNGPC.memo1.Lines.Add('Mensagem de usuário e senha:     '+strMens);
      FMensagemSNGPC.memo1.Lines.Add(strArquivo);
      strmens:=GetsngpcSoap(blnHom,False,'',nil).EnviaArquivoSNGPC(wsEmail,wsSenha,bdaArquivo,strHash);
      FMensagemSNGPC.memo1.Lines.Add('');
      FMensagemSNGPC.memo1.Lines.Add('');
      FMensagemSNGPC.memo1.Lines.Add('=============================================================');
      FMensagemSNGPC.memo1.Lines.Add('Mensagem de envio: '+strMens);
      FMensagemSNGPC.memo1.Lines.Add('=============================================================');
      FMensagemSNGPC.ShowModal;
     
      dmFar.IBDSsngpc.Edit;
      dmFar.IBDSsngpc['status']:='2';
      dmFar.IBDSsngpc['mensagem']:=FMensagemSNGPC.memo1.Text;
      dmFar.IBDSsngpc.Post;
      FMensagemSNGPC.Free;
      xmlArquivo.Free;
      screen.Cursor:=crDefault;
   end;
end;


// funçoes auxiliares

function TFArquivos.Zipar(strArquivo:string):String; // função para compactar e retornar o nome do arquivo
var tsqZip1:TtsqZip;
begin
   tsqZip1:=TtsqZip.Create(Self);
   tsqZip1.FilesToZip.Add(strArquivo);
   tsqZip1.ZipFileName:=copy(strArquivo,1,length(strArquivo)-3)+'zip';
   tsqZip1.Execute;
   result:=tsqZip1.ZipFileName;
end;
function TFArquivos.FileToByteArray(const FileName: String): TByteDynArray;
const BLOCK_SIZE=1024;
var BytesRead, BytesToWrite, Count : Integer;
    F : File of Byte;
    pTemp : Pointer;
begin
   AssignFile( F, FileName );
   Reset(F);
   try
      Count := FileSize(F);
      SetLength(Result, Count);
      pTemp := @Result[0];
      BytesRead := BLOCK_SIZE;
      while (BytesRead = BLOCK_SIZE) do
      begin
         BytesToWrite := Min(Count, BLOCK_SIZE);
         BlockRead(F, pTemp^, BytesToWrite , BytesRead );
         pTemp := Pointer(LongInt(pTemp) + BLOCK_SIZE);
         Count := Count-BytesRead;
      end;
   finally
      CloseFile( F );
   end;
end;
Link para o comentário
Compartilhar em outros sites

Ola fabricio parbens pela iniciativa ficou otimo me poupou muito tempo porem qunado tentei enviar o inventario inicial deu ero de eschema no caso faltou no final do corpo a tag insumos conforme abaixo no iventario.  tive de por ela na mao existira alguma forma de colocar automaticamente pelo componente ?

 

</medicamentos>

<insumos>

</insumos>

</corpo>

</mensagemSNGPCInventario>

Link para o comentário
Compartilhar em outros sites

  • Membros

Ola fabricio parbens pela iniciativa ficou otimo me poupou muito tempo porem qunado tentei enviar o inventario inicial deu ero de eschema no caso faltou no final do corpo a tag insumos conforme abaixo no iventario.  tive de por ela na mao existira alguma forma de colocar automaticamente pelo componente ?

 

</medicamentos>

<insumos>

</insumos>

</corpo>

</mensagemSNGPCInventario>

Caso não informe nenhum insumo no inventário a tag deve ficar da seguinte forma: <insumos />

 

Sérgio

Equipe ACBr Sérgio Assunção
Ajude o Projeto ACBr crescer - Assine o SAC

Projeto ACBr

 

[email protected]

Link para o comentário
Compartilhar em outros sites

  • Membros

Segue em anexo o arquivo .zip que gero pelo sistema, e na hora do envio dá a mensagem de caractere inválido. Eu já tentei enviar ele manualmente pela página de upload do sngpc e por lá funciona normalmente.

A sua variavel pHash ta declarada como String ou WideString ? Qual a versão do seu Delphi ? Tem como vc anexar a unit importada pelo WSDL Importer ?

 

Sérgio

Equipe ACBr Sérgio Assunção
Ajude o Projeto ACBr crescer - Assine o SAC

Projeto ACBr

 

[email protected]

Link para o comentário
Compartilhar em outros sites

  • Membros

Olá Renan... o meu aplicativo foi desenvolvido no Delphi 7 e veja a diferença entre a minha unit importada com a sua:

    function  ValidarUsuario(const Email: WideString; const Senha: WideString): WideString; stdcall;
    function  EnviaArquivoSNGPC(const Email: WideString; const Senha: WideString; const Arq: TByteDynArray; const HashIdentificacao: WideString): WideString; stdcall;
    function  ConsultaDadosArquivoSNGPC(const Email: WideString; const Senha: WideString; const CNPJ: WideString; const Hash: WideString): WideString; stdcall;


    function  ValidarUsuario(const Email: string; const Senha: string): string; stdcall;
    function  EnviaArquivoSNGPC(const Email: string; const Senha: string; const Arq: TByteDynArray; const HashIdentificacao: string): string; stdcall;
    function  ConsultaDadosArquivoSNGPC(const Email: string; const Senha: string; const CNPJ: string; const Hash: string): string; stdcall;

 Sérgio

Equipe ACBr Sérgio Assunção
Ajude o Projeto ACBr crescer - Assine o SAC

Projeto ACBr

 

[email protected]

Link para o comentário
Compartilhar em outros sites

Olá Renan... o meu aplicativo foi desenvolvido no Delphi 7 e veja a diferença entre a minha unit importada com a sua:

    function  ValidarUsuario(const Email: WideString; const Senha: WideString): WideString; stdcall;
    function  EnviaArquivoSNGPC(const Email: WideString; const Senha: WideString; const Arq: TByteDynArray; const HashIdentificacao: WideString): WideString; stdcall;
    function  ConsultaDadosArquivoSNGPC(const Email: WideString; const Senha: WideString; const CNPJ: WideString; const Hash: WideString): WideString; stdcall;


    function  ValidarUsuario(const Email: string; const Senha: string): string; stdcall;
    function  EnviaArquivoSNGPC(const Email: string; const Senha: string; const Arq: TByteDynArray; const HashIdentificacao: string): string; stdcall;
    function  ConsultaDadosArquivoSNGPC(const Email: string; const Senha: string; const CNPJ: string; const Hash: string): string; stdcall;

 Sérgio

 

Isso é porque o WideString do Delphi 7 é o tipo string do Delphi XE+

Link para o comentário
Compartilhar em outros sites

Caso não informe nenhum insumo no inventário a tag deve ficar da seguinte forma: <insumos />

 

Sérgio

Entao amigos estou informando que o componente esta maravilhoso porem ele nao esta criando a tag ao final  quando nao ha insumos sendo assim nescessario criar manualmente no meu caso e uso exclusivo de farmacia e nao uso insumos e no caso do envio da movimentacao diaria tornase inviavel pois nao da pra abrir todos os arquivos e inserir a tag manualmente.  estou pedingo a gentileza do nosso amigo que desenvolveu pra dar uma dica pra gente  ou se alguem souber como fazelo

Link para o comentário
Compartilhar em outros sites

  • Este tópico foi criado há 2278 dias atrás.
  • Talvez seja melhor você criar um NOVO TÓPICO do que postar uma resposta aqui.
Visitante
Este tópico está agora fechado para novas respostas
×
×
  • Criar Novo...

Informação Importante

Colocamos cookies em seu dispositivo para ajudar a tornar este site melhor. Você pode ajustar suas configurações de cookies, caso contrário, assumiremos que você está bem para continuar.

The popup will be closed in 10 segundos...