segunda-feira, 25 de maio de 2009

MANTENDO A MENTE ABERTA PARA O APRENDIZADO


Já foi-se o tempo em que os programadores possuíam suas linguagens
preferidas para trabalho em empresas.

Nos tempos modernos de nossos dias é crucial e necessário ter o domínio de mais de uma linguagem de programação e manter sempre a mente aberta para novos aprendizados.

Foi reunindo os melhores desenvolvedores em VB, ASP e C# que a Microsoft desenvolveu a plataforma .NET. Interligar em uma mesma ferramenta de desevolvimento várias linguagens promove o conhecimento e gera o crescimento entre os desenvolvedores, expandindo seus horizontes para outras áreas como internet e trabalhos em modo cliente servidor.

Aprender deve estar no âmago de todo o bom desenvolvedor de software e deve possibilitar saltos de tecnologia. Por mais que seja bem cômodo ocupar uma vaga em uma empresa que usa somente a mesma linguagem de programação e que faça com que se acomode é importante participar de treinamentos e realizar cursos para se manter inteirado das novas soluções corporativas existentes no mercado. Além de ser algo inteligente investir em si mesmo, você pode estar preparado para mudanças em novas áreas, como a NF-e e seus requisitos para a RFB.

Entender isso é saber que as milhares de linha que você gastará em VB 6 e Delphi para desenvolver a solução são quase nada em comparação no VB.Net. Para isso as linguagens de programação evoluem: permitir que novas soluções e maior interatividade sejam ganhas e tornar as áreas de TI melhor equipadas não somente com um bom hardware, mas com o que de melhor há no mercado no momento.

É cômodo para algumas empresas não desenvolver de VB 6 para VB.NET por motivos de investimentos altos em tecnologia. Mas grandes empresas vêem nesse caminho um ramo natural para a evolução e ganhos de mercado. Se as áreas de TI se tornam cômodas com o que desenvolvem não aproveitam as novas tecnologias e, com o tempo, caem na armadilha de desenvolver grandes códigos para soluções que são fáceis de realizar em novas linguagens de programação.

Não é constragedor verificar que se pensa em desenvolver e se fazer atualizações na área de segurança - como alterar o Linux do firewall - mas não se pensa em atualizar as aplicações internas de Visual Basic 6 para Vb.Net aprimorando com isso todo o ganho possível que se terá com o uso da nova linguagem e de suas companheiras??

Quem se envolve em TI deve estar pronto para aprender o novo e para ser confrotado com o novo. Manter a mente aberta e renovar seus conhecimentos é se fazer apto em vários oportundades que surgirem no mercado.

Saber somente o Visual Basic 6 e o Delphi já não atendem tanto quem necessita criar soluções para uma Nf-e até setembro de 2009.

E se nas próximas atualizações se fizer necessário o uso de tecnologias mais atuais somente disponíves na plataforma .NET??

Evoluir é preciso.

Trabalhe nesse sentido.

segunda-feira, 18 de maio de 2009

MANUAL 3.0 - CÓDIGO DE BARRAS PARA A CONTINGÊNCIA EM VB.NET

O novo manual de integração para a NF-e 3.0 traz vários novos ajustes a realizar na composição da DANFE e deverá entrar em vigor a partir de 31/08/2009.

Uma das novas alterações diz respeito a impressão da DANFE no modo de contigência que, com esse novo manual, pedirá a emissão de um código de barras próprio para os dados da DANFE em contigência.

Esse novo código de barras deverá ser impresso abaixo do código de
barras da nf-e
, conforme mostrado na figura abaixo:




O campo responsável pela emissão desse código de barras será a tag TpEmis dentro do XML da Nf-e. Se o campo TpEmis for diferente de 1 indicará a emissão de uma DANFE em modo de Contingência.

O campo DADOS DA NF-e contêm a composição da chave em código de barras. Ao passar a leitora sobre o segundo código de barras, o resultado de valor esperado deverá ser o que está contido dentro do campo DADOS da NF-e. Quando a DANFE foi emitida em modo normal, o nome desse campo deverá ser PROTOCOLO DE AUTORIZAÇÃO DE USO e deverá conter o referido protocolo de autorização da Nf-e.


A composição do campo DADOS DA NF-e pode ser vista no código VB.Net abaixo:

'Compõe a chave para o código de barras da Danfe em Contigência, se for necessário
DiadaEmissao = Mid(myRow2.dEmi, 1, 2)
TipodeEmissao = myRow2.tpEmis
CodigoUF = DigitoUF(myRow2.destUF)
DadosdaNfe = Trim(CodigoUF + TipodeEmissao + myRow2.destCNPJ + ValorvNF + "2" + "2" + DiadaEmissao)
DigitoDadosNfe = Calculo_DV11(DadosdaNfe)

'Inserção do dígito verificador do módulo 11 para a Nf-e
DadosdaNfe = DadosdaNfe + Trim(DigitoDadosNfe)



A função Calculo_DV11 retorna o cálculo em módulo 11 para o digito verificador dos dados da NF-e e é apresentada abaixo:

Function Calculo_DV11(ByVal strNumero As String) As String

'declara As variáveis
Dim intContador As Integer
Dim intNumero As Integer
Dim intTotalNumero As Integer
Dim intMultiplicador As Integer
Dim intResto As Integer
Dim ValorDigito As Integer

' se nao for um valor numerico sai da função
If Not IsNumeric(strNumero) Then
Calculo_DV11 = ""
Exit Function
End If

'inicia o multiplicador
intMultiplicador = 2

'pega cada caracter do numero a partir da direita
For intContador = Len(strNumero) To 1 Step -1

'extrai o caracter e multiplica pelo multiplicador
intNumero = Val(Mid(strNumero, intContador, 1)) * intMultiplicador

intMultiplicador = intMultiplicador + 1

' se o resultado for maior que nove soma os algarismos do resultado
If intMultiplicador > 9 Then
intMultiplicador = 2
End If

'soma o resultado para totalização
intTotalNumero = intTotalNumero + intNumero

Next

'calcula o resto da divisao do total por 11
intResto = intTotalNumero Mod 11

ValorDigito = 11 - intResto
'verifica as exceções ( 0 -> DV=0 1 -> DV=0 e retorna o DV
Select Case ValorDigito
Case 0
Calculo_DV11 = "0"
Case 1
Calculo_DV11 = "0"
Case Else
Calculo_DV11 = Str(ValorDigito)
End Select

End Function


Após a chave ser composta, a geração do código de barras poderá então ser realizada, com um código simples de chamada para a geração do código de barras:


'Nf-e em contingência / Gerar código de Barras dos dadosdaNFE
If TipodeEmissao <> "1" Then

'Cria o código de barras para a Danfe em Contingência, se houver
'Pôr o código de barras em oculto, se não houver o que gerar
myRow2.DadosNfe = DadosdaNfe
Dim Barcode2 As New BarcodeLib.Barcode(DadosdaNfe, BarcodeLib.TYPE.CODE128C)
PictureBox3.Image = Barcode2.Encode(BarcodeLib.TYPE.CODE128C, DadosdaNfe, 300, 150)
Barcode2.SaveImage("C:\NF-E\Barras\BARRAS2.JPG", BarcodeLib.SaveTypes.JPG)

Dim fs As New FileStream("C:\NF-E\Barras\BARRAS2.JPG", FileMode.Open)
Dim br As New BinaryReader(fs)
myRow2.Imagem2 = br.ReadBytes(br.BaseStream.Length)

br.Close()
fs.Close()

br = Nothing
fs = Nothing

Else
myRow2.Imagem2 = Nothing

End If


O campo Imagem2 deverá ser criado para receber o código de Barras da DANFE impressa em contigência.


Sorte a todos!!



sexta-feira, 15 de maio de 2009

NF-e: Criando um validador para a NF-e em VB.NET


Vamos criar um pequeno aplicativo de validação da Nf-e, executável
em uma chamada por parâmetro. Para executar esse aplicativo, simplesmente
você deverá clicar no botão Iniciar no Windows e selecionar a opção Executar
no menu, informando o seguinte comando:

C:\ValidarNfe.exe C:\NF-E\13090404672291000115550040000000270000000730-nfe.xml

Veja o o exemplo na figura abaixo:





1) Inicie um novo projeto no Vb.NET.

2) Defina nas referências do projeto (Menu Projects - ValidarNfe Properties - aba References) os seguintes namespaces:

System
System.Data
System.Deployment
System.Drawing
System.Security
System.Web.Services
System.Windows.Forms
System.Xml

3) Inclua no formulário uma timer, uma label, um listbox e um botão.


A tela deve ficar como o mostrado abaixo:



4) Defina a propriedade interval do timer em 1000, e dê dois cliques sobre ele. Informe o seguinte código para o Timer:

Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
Me.Show()
End Sub



5) Dentro do código do formulário (form1.vb), no início do mesmo, inclua as seguintes referências:

Imports System.Collections.Generic
Imports System.Text
Imports System.Xml
Imports System.Xml.Schema
Imports System.IO
Imports System.Windows.Forms
Imports System.Security.Cryptography.Xml
Imports System.Security.Cryptography.X509Certificates


6) No evento Load do formulário, acrescente este código:

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

Dim Valor As String

Me.Show()
If Command() <> "" Then
Valor = Command()
ValidaNfe(Valor)

Me.Focus()
Me.Show()
Me.WindowState = FormWindowState.Normal

End If

End Sub


7) O código do botão Fechar deve ser o que segue abaixo:

Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
End
End Sub

8) A função ValidaNfe é a que segue abaixo:

Private Sub ValidaNfe(ByVal NfeAler As String)

Try

'Abrir agora o arquivo XML criado e inserir o Protocolo encontrado!!
Dim arquivo2 As String = NfeAler
Dim xDoc As New XmlDocument : xDoc.Load(arquivo2)
Dim Tamanho As String
Dim Nfe As String


Nfe = arquivo2
Tamanho = Replace(Nfe, "C:\", "")
Tamanho = Replace(Tamanho, "F:\SisWin\NFE\BACKUP\200905\", "")
Tamanho = Replace(Tamanho, "F:\SisWin\NFE\BACKUP", "")
Tamanho = Replace(Tamanho, "F:\SisWin\NFE\AENVIAR", "")
Tamanho = Replace(Tamanho, "F:\SisWin\NFE\AENVIAR", "")
Tamanho = Replace(Tamanho, "\", "")
Tamanho = Replace(Tamanho, "\NF-E", "")
Tamanho = Replace(Tamanho, "NF-E", "")
Tamanho = Replace(Tamanho, "SisWin", "")
Tamanho = Replace(Tamanho, "SisWin", "")

'Fazer uma cópia d arquivo XML para gerar a assinatura
Dim CaminhoArquivo As String = "C:\NF-E\XML\" + Tamanho

'Salva o Arquivo
xDoc.Save(CaminhoArquivo)

'Selecionar certificado
SelecionarCertificado()

'Assinar o XML
Dim OAd As New AssinaturaDigitalClass()
Dim pDadosNfe As String
Dim vStringNfe As String
'Dim msgResultado As String


OAd.Assinar(CaminhoArquivo, "infNFe", oCertificado)

If OAd.vResultado = 0 Then 'Assinado corretamente

pDadosNfe = OAd.vXMLStringAssinado
vStringNfe = pDadosNfe.Substring(pDadosNfe.IndexOf("<NFe"), pDadosNfe.Length - pDadosNfe.IndexOf("<NFe"))


Else 'Ocorreu algum erro na assinatura
MessageBox.Show(OAd.vResultadoString, "Erro", MessageBoxButtons.OK, MessageBoxIcon.Error)
End If

'Validar o XML
Dim TxtXSD As String

TxtXSD = "C:\tmp\Schemas NF-e\nfe_v1.10.xsd"

If Not CaminhoArquivo = String.Empty And Not TxtXSD = String.Empty Then

Resultado = True
Dim settings As New XmlReaderSettings()
AddHandler settings.ValidationEventHandler, AddressOf Me.ValidationEventHandler

'Valida o arquivo XML com o seu Schema XSD
lstValida.Items.Add("Validando o arquivo XML " & CaminhoArquivo & " com o arquivo de Schema : " & TxtXSD)

Try

settings.ValidationType = ValidationType.Schema
settings.Schemas.Add("http://www.portalfiscal.inf.br/nfe",xmlReader.Create(TxtXSD))
Using XmlValidatingReader As XmlReader = XmlReader.Create(CaminhoArquivo, settings)
While XmlValidatingReader.Read()

End While

End Using

Catch ex As Exception

lstValida.Items.Add(ex.Message)
Exit Sub
End Try

lstValida.Items.Add("Status Validação -> " & IIf(Resultado = True, "Arquivo validado com SUCESSO", "Validação FALHOU"))

Else
MsgBox("Informe o arquivo XML e o arquivo XSD.")
End If


Catch ex As Exception

'se ocorrer uma exceção exibe a mensagem
lstValida.Items.Add(ex.Message)

End Try

End Sub

A função ValidaNfe chama outras duas funções em seu início: uma que seleciona o certificado automaticamente e outra que assina o documento. O código da função SelecionarCertificado() é que segue abaixo:

Function SelecionarCertificado() As Boolean

Dim vRetorna As Boolean
Dim oX509Cert As New X509Certificate2
Dim store As New X509Store
Dim collection As New X509Certificate2Collection
Dim collection1 As New X509Certificate2Collection
Dim collection2 As New X509Certificate2Collection
Dim scollection As New X509Certificate2Collection
Dim msgResultado As String
Dim xnome As String

xnome = "CN=CERTIFICADOTESTE:09999991000115, OU=Autenticado por AR Fenacon, OU=RFB e-CNPJ A1, OU=Secretaria da Receita Federal do Brasil - RFB, L=Manaus, S=AM, O=ICP-Brasil, C=BR"

oX509Cert = New X509Certificate2()
store = New X509Store("MY", StoreLocation.CurrentUser)
store.Open(OpenFlags.ReadOnly Or OpenFlags.OpenExistingOnly)
collection = store.Certificates
collection1 = collection.Find(X509FindType.FindByTimeValid, DateTime.Now, False)
collection2 = collection.Find(X509FindType.FindByKeyUsage, X509KeyUsageFlags.DigitalSignature, False)

'Encontra o certificado digital pelo nome do mesmo, se precisar pergunta por isso
'Resolvido em 13/05/2009 às 15:05h
scollection = collection.Find(X509FindType.FindBySubjectDistinguishedName, xnome, False)


'Para selecionar o certificado de uma lista
'scollection = X509Certificate2UI.SelectFromCollection(collection2, "Certificado(s) Digital(is) disponível(is)", "Selecione o certificado digital para uso no aplicativo", X509SelectionFlag.SingleSelection)

If (scollection.Count = 0) Then

msgResultado = "Nenhum certificado digital foi selecionado ou o certificado selecionado está com problemas."
MessageBox.Show(msgResultado, "Advertência", MessageBoxButtons.OK, MessageBoxIcon.Warning)
vRetorna = False

Else

oX509Cert = scollection.Item(0) 'Para selecionar o item em Vb.NET
oCertificado = oX509Cert
vRetorna = True
'msgResultado = "Certificado Selecionado."
'MessageBox.Show(msgResultado, "Advertência", MessageBoxButtons.OK, MessageBoxIcon.Warning)
Return vRetorna

End If

End Function

-----------------

Voce deve informar em xnome o nome por extenso do Certificado que irá usar para validar a XML a ser assinado. Para obter o nome por extenso do seu certificado você pode usar a próprioa função acima habilitando a que pede a seleção de certicados de uma lista e colocando o seguinte comando no Else da função acima:

xnome = oCertificado.Subject.ToString

Esse comando colocará o nome do certificado na variável xnome. Se você debugar, pode pegar o nome extenso do certificado que deve usar para validar o XML e colocar dentro da váriavel, como fiz no início do código:

xnome = "CN=CERTIFICADOTESTE:09999991000115, OU=Autenticado por AR Fenacon, OU=RFB e-CNPJ A1, OU=Secretaria da Receita Federal do Brasil - RFB, L=Manaus, S=AM, O=ICP-Brasil, C=BR"


Para a assinatura digital uma classe é acrescentada totalmente no final da classe do formulário. Essa classe é responsável pela assinatura do XML. Eis o código abaixo:

Public Class AssinaturaDigitalClass

Public vResultado As Integer
Public vResultadoString As String
Public vXMLStringAssinado As String
Public XmlDoc As XmlDocument

Sub Assinar(ByVal pArqXMLAssinar As String, ByVal pUri As String, ByVal pCertificado As X509Certificate2)

'Abrir o arquivo XML a ser assinado e ler o seu conteúdo
Dim SR As StreamReader
Dim vXMLString As String

SR = File.OpenText(pArqXMLAssinar)
vXMLString = SR.ReadToEnd()
SR.Close()

' //Atualizar atributos de retorno com conteúdo padrão
vResultado = 0
vResultadoString = "Assinatura realizada com sucesso"

Try

'Verifica o certificado a ser utilizado na assinatura
Dim _xnome As String
Dim _X509Cert As X509Certificate2
Dim store As X509Store
Dim collection As X509Certificate2Collection
Dim collection1 As X509Certificate2Collection

_xnome = ""

_xnome = pCertificado.Subject.ToString()

_X509Cert = New X509Certificate2()
store = New X509Store("MY", StoreLocation.CurrentUser)
store.Open(OpenFlags.ReadOnly Or OpenFlags.OpenExistingOnly)

collection = store.Certificates
collection1 = collection.Find(X509FindType.FindBySubjectDistinguishedName, _xnome, False)


If (collection1.Count = 0) Then
vResultado = 2
vResultadoString = "Problemas no certificado digital"
Else

' certificado ok
'oX509Cert = scollection.Item(0)

_X509Cert = collection1.Item(0)
Dim x As String
x = _X509Cert.GetKeyAlgorithm().ToString()

' Create a new XML document.
Dim doc As New XmlDocument
doc = New XmlDocument()

'Format the document to ignore white spaces.
doc.PreserveWhitespace = False

' Load the passed XML file using it’s name.
Try
doc.LoadXml(vXMLString)

' Verifica se a tag a ser assinada existe é única
Dim qtdeRefUri As Integer
qtdeRefUri = doc.GetElementsByTagName(pUri).Count

If (qtdeRefUri = 0) Then
' a URI indicada não existe
vResultado = 4
vResultadoString = "A tag de assinatura " + pUri.Trim() + " não existe"

Else
' Existe mais de uma tag a ser assinada
If (qtdeRefUri > 1) Then
' existe mais de uma URI indicada
vResultado = 5
vResultadoString = "A tag de assinatura " + pUri.Trim() + " não é unica"
Else

Try
' Create a SignedXml object.
Dim signedXml As SignedXml
signedXml = New SignedXml(doc)

' Add the key to the SignedXml document
signedXml.SigningKey = _X509Cert.PrivateKey

' Create a reference to be signed
Dim reference As New Reference
reference = New Reference()

'--------- RETIRAR COMENTÁRIOS DAS LINHAS ABAIXO
' pega o uri que deve ser assinada
Dim _Uri As XmlAttributeCollection
Dim _atributo As XmlAttribute

_Uri = doc.GetElementsByTagName(pUri).Item(0).Attributes
For Each _atributo In _Uri
If (_atributo.Name = "Id") Then
reference.Uri = "#" + _atributo.InnerText

End If
Next

' Add an enveloped transformation to the reference.
Dim env As New XmlDsigEnvelopedSignatureTransform
env = New XmlDsigEnvelopedSignatureTransform()
reference.AddTransform(env)

Dim c14 As New XmlDsigC14NTransform
c14 = New XmlDsigC14NTransform()
reference.AddTransform(c14)

' Add the reference to the SignedXml object.
signedXml.AddReference(reference)

' Create a new KeyInfo object
Dim keyinfo As New KeyInfo
keyinfo = New KeyInfo()

' Load the certificate into a KeyInfoX509Data object
' and add it to the KeyInfo object.
keyinfo.AddClause(New KeyInfoX509Data(_X509Cert))

' Add the KeyInfo object to the SignedXml object.
signedXml.KeyInfo = keyinfo
signedXml.ComputeSignature()

' Get the XML representation of the signature and save
' it to an XmlElement object.
Dim xmlDigitalSignature As XmlElement
xmlDigitalSignature = signedXml.GetXml()

' Gravar o elemento no documento XML
doc.DocumentElement.AppendChild(doc.ImportNode(xmlDigitalSignature, True))
XmlDoc = New XmlDocument()
XmlDoc.PreserveWhitespace = False
XmlDoc = doc

' Atualizar a string do XML já assinada
vXMLStringAssinado = XmlDoc.OuterXml

' Gravar o XML no HD
' abre um stream para escrita e cria um StreamWriter para implementar o stream
Dim fs As New FileStream(pArqXMLAssinar, FileMode.OpenOrCreate, FileAccess.Write)
Dim SW_2 As New StreamWriter(fs)
SW_2.Flush()
SW_2.BaseStream.Seek(0, SeekOrigin.Begin)
SW_2.Write(vXMLStringAssinado)
SW_2.Flush()
SW_2.Close()

Catch ex As Exception
vResultado = 6
vResultadoString = "Erro ao assinar o documento - " + ex.Message

End Try

End If

End If

Catch ex As Exception

vResultado = 3
vResultadoString = "XML mal formado - " + ex.Message

End Try

End If

Catch ex As Exception

vResultado = 1
vResultadoString = "Problema ao acessar o certificado digital" + ex.Message

End Try

End Sub

End Class


9) Dentro do botão que faz a validação é repassado o código do arquivo XSD que faz a validação:

TxtXSD = "C:\tmp\Schemas NF-e\nfe_v1.10.xsd"

Um EventHandler se faz necessário para a leitura da validação do XSD.

Abaixo, vemos o código da função de validação do EventHandler:


Public Sub ValidationEventHandler(ByVal sender As Object, ByVal args As ValidationEventArgs)


Resultado = False

'lstValida.Items.Add(vbTab + "Erro de Validação : " + args.Message)

If args.Severity = XmlSeverityType.Warning Then

MsgBox("Nenhum arquivo de Schema foi encontrado para efetuar a validação...")

ElseIf args.Severity = XmlSeverityType.Error Then

lstValida.Items.Add(args.Message)
'MsgBox("Ocorreu um erro durante a validação....")

End If

If Not (args.Exception Is Nothing) Then ' Erro na validação do schema XSD

'lstValida.Items.Add(args.Exception.SourceUri + "," & args.Exception.LinePosition & "," & args.Exception.LineNumber)
'MsgBox(args.Exception.SourceUri + "," & args.Exception.LinePosition & "," & args.Exception.LineNumber)

End If

End Sub

Essa função será chamada para retornar o erro que possa estar acontecendo com algum ponto do arquivo XML.

Pronto!!

Cada passo de uma validação para a Nf-e foi descrita acima.

Posto o código completo do arquivo form1.VB abaixo para dirrimir quaisquer dúvidas:

'Validador para arquivos Nf-e
'Data de criação: 12/05/2009
'Para ser utilizado com o Visual Basic 6
'A aplicação funciona com chamada de parâmetro na linha digitável
'Para executar esse aplicativo, use a linha de comando do Windwos
'clicando no botão iniciar de depois em Executar:
'Exemplo de chamada: C:\ValidarNfe.exe C:\NF-E\13090404672291000115550040000000270000000730-nfe.xml
'Desenvolvedor: Manoel Leonardo Metelis Florindo

Imports System.Collections.Generic
Imports System.Text
Imports System.Xml
Imports System.Xml.Schema
Imports System.IO
Imports System.Windows.Forms
Imports System.Security.Cryptography.Xml
Imports System.Security.Cryptography.X509Certificates

Public Class Form1

Private Resultado As Boolean = True
Public oCertificado As New X509Certificate2
Public vStrXmlRetorno As String
Public vArqERRRetorno As String
Public vPastaXMLErro As String
Public vPastaXMLEnvio As String
Public vArqXMLRetorno As String
Public vPastaXMLRetorno As String
Public vXmlNfeDadosMsg As String
Public vAmbiente As Integer
Public vUF As Integer

Private Sub ValidaNfe(ByVal NfeAler As String)

Try

'Abrir agora o arquivo XML criado e inserir o Protocolo encontrado!!
Dim arquivo2 As String = NfeAler
Dim xDoc As New XmlDocument : xDoc.Load(arquivo2)
Dim Tamanho As String
Dim Nfe As String


Nfe = arquivo2
Tamanho = Replace(Nfe, "C:\", "")
Tamanho = Replace(Tamanho, "F:\SisWin\NFE\BACKUP\200905\", "")
Tamanho = Replace(Tamanho, "F:\SisWin\NFE\BACKUP", "")
Tamanho = Replace(Tamanho, "F:\SisWin\NFE\AENVIAR", "")
Tamanho = Replace(Tamanho, "F:\SisWin\NFE\AENVIAR", "")
Tamanho = Replace(Tamanho, "\", "")
Tamanho = Replace(Tamanho, "\NF-E", "")
Tamanho = Replace(Tamanho, "NF-E", "")
Tamanho = Replace(Tamanho, "SisWin", "")
Tamanho = Replace(Tamanho, "SisWin", "")

'Fazer uma cópia d arquivo XML para gerar a assinatura
Dim CaminhoArquivo As String = "C:\NF-E\XML\" + Tamanho

'Salva o Arquivo
xDoc.Save(CaminhoArquivo)

'Selecionar certificado
SelecionarCertificado()

'Assinar o XML
Dim OAd As New AssinaturaDigitalClass()
Dim pDadosNfe As String
Dim vStringNfe As String
'Dim msgResultado As String


OAd.Assinar(CaminhoArquivo, "infNFe", oCertificado)

If OAd.vResultado = 0 Then 'Assinado corretamente

pDadosNfe = OAd.vXMLStringAssinado
vStringNfe = pDadosNfe.Substring(pDadosNfe.IndexOf("<NFe"), pDadosNfe.Length - pDadosNfe.IndexOf("<NFe"))

Else 'Ocorreu algum erro na assinatura
MessageBox.Show(OAd.vResultadoString, "Erro", MessageBoxButtons.OK, MessageBoxIcon.Error)
End If

'Validar o XML
Dim TxtXSD As String

TxtXSD = "C:\tmp\Schemas NF-e\nfe_v1.10.xsd"

If Not CaminhoArquivo = String.Empty And Not TxtXSD = String.Empty Then

Resultado = True
Dim settings As New XmlReaderSettings()
AddHandler settings.ValidationEventHandler, AddressOf Me.ValidationEventHandler

'Valida o arquivo XML com o seu Schema XSD
lstValida.Items.Add("Validando o arquivo XML " & CaminhoArquivo & " com o arquivo de Schema : " & TxtXSD)

Try

settings.ValidationType = ValidationType.Schema
settings.Schemas.Add("http://www.portalfiscal.inf.br/nfe", XmlReader.Create(TxtXSD))
Using XmlValidatingReader As XmlReader = XmlReader.Create(CaminhoArquivo, settings)
While XmlValidatingReader.Read()

End While

End Using

Catch ex As Exception

lstValida.Items.Add(ex.Message)
Exit Sub
End Try

lstValida.Items.Add("Status Validação -> " & IIf(Resultado = True, "Arquivo validado com SUCESSO", "Validação FALHOU"))

Else
MsgBox("Informe o arquivo XML e o arquivo XSD.")
End If


Catch ex As Exception

'se ocorrer uma exceção exibe a mensagem
lstValida.Items.Add(ex.Message)

End Try

End Sub


Function SelecionarCertificado() As Boolean

Dim vRetorna As Boolean
Dim oX509Cert As New X509Certificate2
Dim store As New X509Store
Dim collection As New X509Certificate2Collection
Dim collection1 As New X509Certificate2Collection
Dim collection2 As New X509Certificate2Collection
Dim scollection As New X509Certificate2Collection
Dim msgResultado As String
Dim xnome As String

xnome = "CN=COPLAST INDUSTRIA E COMERCIO DE RESIDUOS PLASTICO:04672291000115, OU=Autenticado por AR Fenacon, OU=RFB e-CNPJ A1, OU=Secretaria da Receita Federal do Brasil - RFB, L=Manaus, S=AM, O=ICP-Brasil, C=BR"

oX509Cert = New X509Certificate2()
store = New X509Store("MY", StoreLocation.CurrentUser)
store.Open(OpenFlags.ReadOnly Or OpenFlags.OpenExistingOnly)
collection = store.Certificates
collection1 = collection.Find(X509FindType.FindByTimeValid, DateTime.Now, False)
collection2 = collection.Find(X509FindType.FindByKeyUsage, X509KeyUsageFlags.DigitalSignature, False)

'Encontra o certificado digital pelo nome do mesmo, se precisar pergunta por isso
'Resolvido em 13/05/2009 às 15:05h
scollection = collection.Find(X509FindType.FindBySubjectDistinguishedName, xnome, False)


'Para selecionar o certificado de uma lista
'scollection = X509Certificate2UI.SelectFromCollection(collection2, "Certificado(s) Digital(is) disponível(is)", "Selecione o certificado digital para uso no aplicativo", X509SelectionFlag.SingleSelection)

If (scollection.Count = 0) Then

msgResultado = "Nenhum certificado digital foi selecionado ou o certificado selecionado está com problemas."
MessageBox.Show(msgResultado, "Advertência", MessageBoxButtons.OK, MessageBoxIcon.Warning)
vRetorna = False

Else

oX509Cert = scollection.Item(0) 'Para selecionar o item em Vb.NET
oCertificado = oX509Cert
xnome = oCertificado.Subject.ToString
vRetorna = True
'msgResultado = "Certificado Selecionado."
'MessageBox.Show(msgResultado, "Advertência", MessageBoxButtons.OK, MessageBoxIcon.Warning)
Return vRetorna

End If

End Function

Public Sub ValidationEventHandler(ByVal sender As Object, ByVal args As ValidationEventArgs)


Resultado = False

'lstValida.Items.Add(vbTab + "Erro de Validação : " + args.Message)

If args.Severity = XmlSeverityType.Warning Then

MsgBox("Nenhum arquivo de Schema foi encontrado para efetuar a validação...")

ElseIf args.Severity = XmlSeverityType.Error Then

lstValida.Items.Add(args.Message)
'MsgBox("Ocorreu um erro durante a validação....")

End If

If Not (args.Exception Is Nothing) Then ' Erro na validação do schema XSD

'lstValida.Items.Add(args.Exception.SourceUri + "," & args.Exception.LinePosition & "," & args.Exception.LineNumber)
'MsgBox(args.Exception.SourceUri + "," & args.Exception.LinePosition & "," & args.Exception.LineNumber)

End If

End Sub


Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
End
End Sub

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

Dim Valor As String

Me.Show()
'Valor = "F:\SisWin\NFE\BACKUP\200905\13090504672291000115550040000001520000002017-nfe.XML"
'ValidaNfe(Valor)
If Command() <> "" Then
Valor = Command()
ValidaNfe(Valor)

Me.Focus()
Me.Show()
Me.WindowState = FormWindowState.Normal

End If

End Sub

Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
Me.Show()
End Sub
End Class
Public Class AssinaturaDigitalClass

Public vResultado As Integer
Public vResultadoString As String
Public vXMLStringAssinado As String
Public XmlDoc As XmlDocument

Sub Assinar(ByVal pArqXMLAssinar As String, ByVal pUri As String, ByVal pCertificado As X509Certificate2)

'Abrir o arquivo XML a ser assinado e ler o seu conteúdo
Dim SR As StreamReader
Dim vXMLString As String

SR = File.OpenText(pArqXMLAssinar)
vXMLString = SR.ReadToEnd()
SR.Close()

' //Atualizar atributos de retorno com conteúdo padrão
vResultado = 0
vResultadoString = "Assinatura realizada com sucesso"

Try

'Verifica o certificado a ser utilizado na assinatura
Dim _xnome As String
Dim _X509Cert As X509Certificate2
Dim store As X509Store
Dim collection As X509Certificate2Collection
Dim collection1 As X509Certificate2Collection

_xnome = ""

_xnome = pCertificado.Subject.ToString()

_X509Cert = New X509Certificate2()
store = New X509Store("MY", StoreLocation.CurrentUser)
store.Open(OpenFlags.ReadOnly Or OpenFlags.OpenExistingOnly)

collection = store.Certificates
collection1 = collection.Find(X509FindType.FindBySubjectDistinguishedName, _xnome, False)


If (collection1.Count = 0) Then
vResultado = 2
vResultadoString = "Problemas no certificado digital"
Else

' certificado ok
'oX509Cert = scollection.Item(0)

_X509Cert = collection1.Item(0)
Dim x As String
x = _X509Cert.GetKeyAlgorithm().ToString()

' Create a new XML document.
Dim doc As New XmlDocument
doc = New XmlDocument()

'Format the document to ignore white spaces.
doc.PreserveWhitespace = False

' Load the passed XML file using it’s name.
Try
doc.LoadXml(vXMLString)

' Verifica se a tag a ser assinada existe é única
Dim qtdeRefUri As Integer
qtdeRefUri = doc.GetElementsByTagName(pUri).Count

If (qtdeRefUri = 0) Then
' a URI indicada não existe
vResultado = 4
vResultadoString = "A tag de assinatura " + pUri.Trim() + " não existe"

Else
' Existe mais de uma tag a ser assinada
If (qtdeRefUri > 1) Then
' existe mais de uma URI indicada
vResultado = 5
vResultadoString = "A tag de assinatura " + pUri.Trim() + " não é unica"
Else

Try
' Create a SignedXml object.
Dim signedXml As SignedXml
signedXml = New SignedXml(doc)

' Add the key to the SignedXml document
signedXml.SigningKey = _X509Cert.PrivateKey

' Create a reference to be signed
Dim reference As New Reference
reference = New Reference()

'--------- RETIRAR COMENTÁRIOS DAS LINHAS ABAIXO
' pega o uri que deve ser assinada
Dim _Uri As XmlAttributeCollection
Dim _atributo As XmlAttribute

_Uri = doc.GetElementsByTagName(pUri).Item(0).Attributes
For Each _atributo In _Uri
If (_atributo.Name = "Id") Then
reference.Uri = "#" + _atributo.InnerText

End If
Next

' Add an enveloped transformation to the reference.
Dim env As New XmlDsigEnvelopedSignatureTransform
env = New XmlDsigEnvelopedSignatureTransform()
reference.AddTransform(env)

Dim c14 As New XmlDsigC14NTransform
c14 = New XmlDsigC14NTransform()
reference.AddTransform(c14)

' Add the reference to the SignedXml object.
signedXml.AddReference(reference)

' Create a new KeyInfo object
Dim keyinfo As New KeyInfo
keyinfo = New KeyInfo()

' Load the certificate into a KeyInfoX509Data object
' and add it to the KeyInfo object.
keyinfo.AddClause(New KeyInfoX509Data(_X509Cert))

' Add the KeyInfo object to the SignedXml object.
signedXml.KeyInfo = keyinfo
signedXml.ComputeSignature()

' Get the XML representation of the signature and save
' it to an XmlElement object.
Dim xmlDigitalSignature As XmlElement
xmlDigitalSignature = signedXml.GetXml()

' Gravar o elemento no documento XML
doc.DocumentElement.AppendChild(doc.ImportNode(xmlDigitalSignature, True))
XmlDoc = New XmlDocument()
XmlDoc.PreserveWhitespace = False
XmlDoc = doc

' Atualizar a string do XML já assinada
vXMLStringAssinado = XmlDoc.OuterXml

' Gravar o XML no HD
' abre um stream para escrita e cria um StreamWriter para implementar o stream
Dim fs As New FileStream(pArqXMLAssinar, FileMode.OpenOrCreate, FileAccess.Write)
Dim SW_2 As New StreamWriter(fs)
SW_2.Flush()
SW_2.BaseStream.Seek(0, SeekOrigin.Begin)
SW_2.Write(vXMLStringAssinado)
SW_2.Flush()
SW_2.Close()

Catch ex As Exception
vResultado = 6
vResultadoString = "Erro ao assinar o documento - " + ex.Message

End Try

End If

End If

Catch ex As Exception

vResultado = 3
vResultadoString = "XML mal formado - " + ex.Message

End Try

End If

Catch ex As Exception

vResultado = 1
vResultadoString = "Problema ao acessar o certificado digital" + ex.Message

End Try

End Sub

End Class

UM APLICATIVO PARA LEITURA DEVOCIONAL ANUAL DA BIBLIA EM ANDROID

Olá, pessoal!  Este novo projeto foi criado em Visual Studio 2019 em C#.Net com o Xamarin. Já está disponível no Google Play para vocês baix...