diff --git a/pytrustnfe/Certificado.py b/pytrustnfe/Certificado.py
new file mode 100644
index 0000000..3d55fa2
--- /dev/null
+++ b/pytrustnfe/Certificado.py
@@ -0,0 +1,24 @@
+#coding=utf-8
+'''
+Created on Jun 16, 2015
+
+@author: danimar
+'''
+import os.path
+from OpenSSL import crypto
+
+
+def converte_pfx_pem(caminho, senha):
+ if not os.path.isfile(caminho):
+ raise Exception('Certificado não existe')
+ stream = open(caminho, 'rb').read()
+ try:
+ certificado = crypto.load_pkcs12(stream, senha)
+
+ privada = crypto.dump_privatekey(crypto.FILETYPE_PEM, certificado.get_privatekey())
+ certificado = crypto.dump_certificate(crypto.FILETYPE_PEM, certificado.get_certificate())
+ except Exception as e:
+ if len(e.message) == 1 and len(e.message[0])==3 and e.message[0][2] == 'mac verify failure':
+ raise Exception('Senha inválida')
+ raise
+ return privada, certificado
\ No newline at end of file
diff --git a/pytrustnfe/HttpClient.py b/pytrustnfe/HttpClient.py
new file mode 100644
index 0000000..52ae183
--- /dev/null
+++ b/pytrustnfe/HttpClient.py
@@ -0,0 +1,38 @@
+#coding=utf-8
+'''
+Created on Jun 16, 2015
+
+@author: danimar
+'''
+from httplib import HTTPSConnection, HTTPResponse
+
+class HttpClient(object):
+
+ def __init__(self, url, chave_pem, certificado_pem):
+ self.url = url
+ self.chave_pem = chave_pem
+ self.certificado_pem = certificado_pem
+
+ def _headers(self):
+ return {
+ u'Content-type': u'application/soap+xml; charset=utf-8',
+ u'Accept': u'application/soap+xml; charset=utf-8'
+ }
+
+ def post_xml(self, post, xml):
+
+ conexao = HTTPSConnection(self.url, '443', key_file=self.chave_pem,
+ cert_file=self.certificado_pem)
+
+ try:
+ conexao.request(u'POST', post, xml, self._headers())
+ response = conexao.getresponse()
+ if response.status == '200':
+ return response.read()
+ except Exception as e:
+ print str(e)
+ finally:
+ conexao.close()
+
+
+
\ No newline at end of file
diff --git a/pytrustnfe/servicos/Comunicacao.py b/pytrustnfe/servicos/Comunicacao.py
new file mode 100644
index 0000000..c46a3b5
--- /dev/null
+++ b/pytrustnfe/servicos/Comunicacao.py
@@ -0,0 +1,54 @@
+#coding=utf-8
+'''
+Created on Jun 14, 2015
+
+@author: danimar
+'''
+
+from lxml import objectify
+from uuid import uuid4
+from pytrustnfe.HttpClient import HttpClient
+from pytrustnfe.Certificado import converte_pfx_pem
+
+import logging
+from logilab.common.registry import objectify_predicate
+logging.basicConfig(level=logging.INFO)
+logging.getLogger('suds.client').setLevel(logging.DEBUG)
+logging.getLogger('suds.transport').setLevel(logging.DEBUG)
+
+
+class Comunicacao(object):
+
+ def __init__(self, certificado, senha):
+ self.certificado = certificado
+ self.senha = senha
+
+
+ def _preparar_temp_pem(self):
+ chave_temp = '/tmp/' + uuid4().hex
+ certificado_temp = '/tmp/' + uuid4().hex
+
+ chave, certificado = converte_pfx_pem(self.certificado, self.senha)
+ arq_temp = open(chave_temp, 'w')
+ arq_temp.write(chave)
+ arq_temp.close()
+
+ arq_temp = open(certificado_temp, 'w')
+ arq_temp.write(certificado)
+ arq_temp.close()
+
+ return chave_temp, certificado_temp
+
+ def envio_nfe(self):
+ chave, certificado = self._preparar_temp_pem()
+
+ c = HttpClient('cad.svrs.rs.gov.br', chave, certificado)
+
+ xml_retorno = c.post_xml('/ws/cadconsultacadastro/cadconsultacadastro2.asmx', '')
+
+ obj = objectify.fromstring(xml_retorno)
+
+ return xml_retorno, obj
+
+
+
\ No newline at end of file
diff --git a/pytrustnfe/servicos/comunicacao.py b/pytrustnfe/servicos/comunicacao.py
deleted file mode 100644
index 2683fd4..0000000
--- a/pytrustnfe/servicos/comunicacao.py
+++ /dev/null
@@ -1,5 +0,0 @@
-'''
-Created on Jun 14, 2015
-
-@author: danimar
-'''
diff --git a/pytrustnfe/test/XMLs/recibo_envio_1.xml b/pytrustnfe/test/XMLs/recibo_envio_1.xml
new file mode 100644
index 0000000..db93561
--- /dev/null
+++ b/pytrustnfe/test/XMLs/recibo_envio_1.xml
@@ -0,0 +1,13 @@
+
+
+ 2
+ SVRS20140728145415
+ 103
+ Lote recebido com sucesso
+ 42
+ 2014-08-18T10:32:32
+
+ 423002149000085
+ 1
+
+
\ No newline at end of file
diff --git a/pytrustnfe/test/XMLs/recibo_envio_2.xml b/pytrustnfe/test/XMLs/recibo_envio_2.xml
new file mode 100644
index 0000000..57c6c9c
--- /dev/null
+++ b/pytrustnfe/test/XMLs/recibo_envio_2.xml
@@ -0,0 +1,13 @@
+
+
+ 2
+ SVRS20140728145415
+ 103
+ Lote recebido com sucesso
+ 42
+ 2014-08-18T17:33:28
+
+ 423002149008908
+ 1
+
+
\ No newline at end of file
diff --git a/pytrustnfe/test/XMLs/recibo_protocolo_sucesso_1.xml b/pytrustnfe/test/XMLs/recibo_protocolo_sucesso_1.xml
new file mode 100644
index 0000000..d528f95
--- /dev/null
+++ b/pytrustnfe/test/XMLs/recibo_protocolo_sucesso_1.xml
@@ -0,0 +1,21 @@
+
+
+ 2
+ SVRS20140729095237
+ 423002149000085
+ 104
+ Lote processado
+ 42
+
+
+ 2
+ SVRS20140729095237
+ 42140803657739000169550020000000011000000018
+ 2014-08-18T10:32:32
+ 342140000660576
+ ladI/iyYJbQx6QW5ihtlBMR1UUY=
+ 100
+ Autorizado o uso da NF-e
+
+
+
\ No newline at end of file
diff --git a/pytrustnfe/test/XMLs/recibo_protocolo_sucesso_2.xml b/pytrustnfe/test/XMLs/recibo_protocolo_sucesso_2.xml
new file mode 100644
index 0000000..29a10d1
--- /dev/null
+++ b/pytrustnfe/test/XMLs/recibo_protocolo_sucesso_2.xml
@@ -0,0 +1,21 @@
+
+
+ 2
+ SVRS20140729095237
+ 423002149008908
+ 104
+ Lote processado
+ 42
+
+
+ 2
+ SVRS20140729095237
+ 42140803657739000169550020000000021000000023
+ 2014-08-18T17:33:28
+ 342140000666829
+ oQsitGdZl1I66NNzpMn8Wf6mI7c=
+ 100
+ Autorizado o uso da NF-e
+
+
+
\ No newline at end of file
diff --git a/pytrustnfe/test/test_certificado.py b/pytrustnfe/test/test_certificado.py
new file mode 100644
index 0000000..229d085
--- /dev/null
+++ b/pytrustnfe/test/test_certificado.py
@@ -0,0 +1,65 @@
+#coding=utf-8
+'''
+Created on Jun 14, 2015
+
+@author: danimar
+'''
+import unittest
+import os, os.path
+from pytrustnfe.Certificado import converte_pfx_pem
+
+CHAVE = '-----BEGIN PRIVATE KEY-----\n' \
+ 'MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAJONRp6l1y2ojgv8\n' \
+ 'tP3AOLW0vjWQqiPseBLM7YAxbzz5R7LYlWHC0ZJ4uIvd4Cvc6AuoNJoeuhzFcwHx\n' \
+ 'PL0TcFuW+5up1ktUohwaJ+/zKrMODCKt0gvif302yqasMnwLh9mGZQIkLkHPOX8p\n' \
+ 'ZQDC4dlqwOyYDi0f+bRd5C7aWx3RAgMBAAECgYADqASP+dwTLZIXifOSNikxl4D/\n' \
+ 'Is6UhU+UZ6+a9Z6kDClSrTtGaOV4k7U/AgiEDb1STKDBEPHbtKjc63Vt2gV2teem\n' \
+ 'ohU0Giv+gD42uuwy2DM31OfYrpR46mzOK9JrpQc78b36ealL3AWJ1gyBbbcOWbAb\n' \
+ 'KmP742V7pcD07EEp4QJBAM/e7M8VdLgOyaQzH9KHekU6fJlI4vy1UwgRUwx3/1W6\n' \
+ 'zlBYo1qXfc7NSVG8ZaSrJwW4rPn393u31CpXv+oc/OMCQQC1txS6nxM9+p/641HX\n' \
+ 'CHXiWJRn0Wv7rT1FyF2dHO+OQOkCCnHCsGDMf3bacTNb7iyaPbXEDac8od5uF/3h\n' \
+ 'aUy7AkBDPGoAeYItXqseL2Mlp6iG5+oRcp/o+YWH4IKqT84JHslI98KutL1+vKvw\n'\
+ 'gi2mW63djeR1Xh1wqP85SvTKduHdAkAIJLlIF8Lr/yRWQQO06EsoJqIX+Pmm4L+j\n'\
+ 'NfSECvztWhlXHxK0D+V2pKu15GbR0t2q1+Micx4wiGyIcIjPJkHrAkAvlbXGFcGT\n'\
+ 'pk9bQ8nl7EYqlvVn1TejzTLfBhBYOse/xT/NI4Kwjkan9R+EJ1cOc9EE8gm1W3jv\n'\
+ 'fMw/Bh2wC5kj\n'\
+ '-----END PRIVATE KEY-----\n'
+
+CERTIFICADO = '-----BEGIN CERTIFICATE-----\n'\
+ 'MIICMTCCAZqgAwIBAgIQfYOsIEVuAJ1FwwcTrY0t1DANBgkqhkiG9w0BAQUFADBX\n'\
+ 'MVUwUwYDVQQDHkwAewA1ADkARgAxAEUANAA2ADEALQBEAEQARQA1AC0ANABEADIA\n'\
+ 'RgAtAEEAMAAxAEEALQA4ADMAMwAyADIAQQA5AEUAQgA4ADMAOAB9MB4XDTE1MDYx\n'\
+ 'NTA1NDc1N1oXDTE2MDYxNDExNDc1N1owVzFVMFMGA1UEAx5MAHsANQA5AEYAMQBF\n'\
+ 'ADQANgAxAC0ARABEAEUANQAtADQARAAyAEYALQBBADAAMQBBAC0AOAAzADMAMgAy\n'\
+ 'AEEAOQBFAEIAOAAzADgAfTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAk41G\n'\
+ 'nqXXLaiOC/y0/cA4tbS+NZCqI+x4EsztgDFvPPlHstiVYcLRkni4i93gK9zoC6g0\n'\
+ 'mh66HMVzAfE8vRNwW5b7m6nWS1SiHBon7/Mqsw4MIq3SC+J/fTbKpqwyfAuH2YZl\n'\
+ 'AiQuQc85fyllAMLh2WrA7JgOLR/5tF3kLtpbHdECAwEAATANBgkqhkiG9w0BAQUF\n'\
+ 'AAOBgQArdh+RyT6VxKGsXk1zhHsgwXfToe6GpTF4W8PHI1+T0WIsNForDhvst6nm\n'\
+ 'QtgAhuZM9rxpOJuNKc+pM29EixpAiZZiRMCSWEItNyEVdUIi+YnKBcAHd88TwO86\n'\
+ 'd126MWQ2O8cu5W1VoDp7hYBYKOnLbYi11/StO+0rzK+oPYAvIw==\n'\
+ '-----END CERTIFICATE-----\n'
+
+class test_assinatura(unittest.TestCase):
+
+ caminho = os.path.dirname(__file__)
+
+ def test_preparar_pfx(self):
+ dir_pfx = os.path.join(self.caminho, 'teste.pfx')
+ chave, certificado = converte_pfx_pem(dir_pfx, '123456')
+ self.assertEqual(chave, CHAVE, 'Chave gerada inválida')
+ self.assertEqual(certificado, CERTIFICADO, 'Certificado gerado inválido')
+
+ def test_pfx_nao_existe(self):
+ self.assertRaises(Exception, converte_pfx_pem, 'file.pfx', '123456')
+
+ def test_pfx_senha_invalida(self):
+ dir_pfx = os.path.join(self.caminho, 'teste.pfx')
+ self.assertRaises(Exception, converte_pfx_pem, dir_pfx, '123')
+
+ def test_pfx_invalido(self):
+ dir_pfx = os.path.join(self.caminho, 'xml_assinado.xml')
+ self.assertRaises(Exception, converte_pfx_pem, dir_pfx, '123456')
+
+
+
\ No newline at end of file
diff --git a/pytrustnfe/test/test_comunicacao.py b/pytrustnfe/test/test_comunicacao.py
new file mode 100644
index 0000000..6c0876f
--- /dev/null
+++ b/pytrustnfe/test/test_comunicacao.py
@@ -0,0 +1,39 @@
+#coding=utf-8
+'''
+Created on Jun 16, 2015
+
+@author: danimar
+'''
+import mock
+import unittest
+import os.path
+from pytrustnfe.servicos.Comunicacao import Comunicacao
+
+XML_RETORNO = '103' \
+ '42'
+
+class test_comunicacao(unittest.TestCase):
+
+ caminho = os.path.dirname(__file__)
+
+ def test_envio_nfe(self):
+ dir_pfx = os.path.join(self.caminho, 'teste.pfx')
+
+ #dir_pfx = '/home/danimar/Desktop/INFOGER.pfx' #Hack
+
+ with mock.patch('pytrustnfe.HttpClient.HTTPSConnection') as HttpsConnection:
+ conn = HttpsConnection.return_value
+ retorno = mock.MagicMock()
+ type(retorno).status = mock.PropertyMock(return_value='200')
+ retorno.read.return_value = XML_RETORNO
+
+ conn.getresponse.return_value = retorno
+
+ com = Comunicacao(dir_pfx, '123456')
+ xml, objeto = com.envio_nfe()
+
+ self.assertEqual(xml, XML_RETORNO, 'Envio de NF-e com problemas - xml de retorno inválido')
+ self.assertEqual(objeto.cUF, 42, 'Envio de NF-e com problemas - objeto de retorno inválido')
+ self.assertEqual(objeto.cStat, 103, 'Envio de NF-e com problemas - objeto de retorno inválido')
+
+