Em Python como em outras linguagens, todo meio de comunicação via rede utiliza basicamente socket em seu nível mais baixo para prover essa comunicação, seja o meio de comunicação SOAP, rpc, http, etc.
Algumas vezes estes serviços externos fornecem a possibilidade de utilização de canais seguros para comunicação (ssl). Em alguns casos o serviço a ser utilizado pode até mesmo obrigar o uso de comunicação segura, para isso precisamos utilizar socket + ssl. Dependendo da necessidade do projeto pode ser necessário utilizar também um certificado digital juntamente com a conexão ssl como forma de autenticação.
Para utilizar comunicação segura o módulo 'socket' prove a função 'ssl', que de maneira simples executa a comunicação com o serviço desejado via ssl. Essa função também pode receber dois parâmetros , 'key_file' e 'cert_file' respectivamente o 'path' do arquivo PEM para a chave privada e o 'path' para o arquivo PEM do certificado.
Uma assinatura digital geralmente é um arquivo binário no formato 'pkcs12' com a extensão '.pfx', sendo assim precisamos abrir esse arquivo e retirar as duas informações que o 'ssl' precisa (key_file, cer_file) e salvar nos arquivos com o formato PEM. Para isso utilizamos openssl e pyopenssl, 'bindings' para python da 'lib' 'openssl'.
Com os módulos instalados, vamos abrir o certificado no formato binário, transformar no objeto 'pkcs12' e então retirar as informações do certificado e da chave privada para em seguida salvar cada um em arquivo separado.
Alguns certificados podem estar codificados sendo necessário informar a frase para decodificação, para tal temos o parâmetro 'passphrase', se não for preciso é só não informar o parâmetro como no exemplo abaixo.
from OpenSSL import crypto
# Lendo o arquivo pfx no formato pkcs12 como binario
pkcs12 = crypto.load_pkcs12(open('certificado.pfx', 'rb').read(), 'passphrase')
# Retorna a string decodificado do certificado
cert_str = crypto.dump_certificate(crypto.FILETYPE_PEM, pkcs12.get_certificate())
# Retorna a string decodificado da chave privada
key_str = crypto.dump_privatekey(crypto.FILETYPE_PEM, pkcs12.get_privatekey())
# Gravando a string no dicso
open('cert.pem', 'wb').write(cert_str)
# Gravando a string no dicso
open('key.ptm', 'wb').write(key_str)
Agora para finalizar basta efetuar a comunicação com o serviço desejado utilizando o modulo 'socket' e a função 'ssl' passando os parâmetros de chave e certificado:
proxy = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
proxy.connect(('www.lzt.com.br', 80))
proxy_ssl = socket.ssl(proxy, 'key.pem', 'cert.pem')
Pronto! Com o objeto 'proxy' podemos fazer requisições a serviços que utilizem conexão 'ssl' com certificados digitais.
6 comentários:
Boa tarde!
Estou tentando fazer a comunicação com o webservice do sefaz, na implemetação da NFE, e não estou tento sucesso.
Os procedimentos citados nesse tutorial deveriam funcionar no caso da nota fiscal, certo?
proxy.connect(('https://homolog.sefaz.go.gov.br/nfe/services/NfeRecepcao',443))
Erro: Name or service not know
Alguma sugestão?
Re: Bruno
Boa tarde!
Bruno, no post estou conectando em endereço qualquer utilizando apenas socket. NFE é um serviço que utiliza SOAP para comunicação. Você precisa de um modulo para soap como SOAPy ou suds.
Antes de utilizar o webservice você precisa autenticar no serviço.
Eu não tenho acompanhado o serviço NFE mas posso tentar ajudar.
Fique a vontade para me contatar por email.
Obrigado pela ajuda, vou dar uma estudada em SOAPy.
Também estou com esta demanda para Nota Fiscal eletrônica!
Eu dei uma olhada já no SOAPpy, mas parece que ele foi descontinuado...
O suds também olhei, mas não sei se é oreiada, mas não consegui conectar utilizando https com ele ...
Vocês tiveram algum sucesso na implementação desta solução ?!
Boa tarde Victor!
Achei muito interessante sua explicação, parabéns. Você teria um código python exemplo da implantação da NFe.
Bom, eu achei algo em python que implementa NFe, http://github.com/marinho/PyNFe ... Muito interessante.
Postar um comentário