From 65dfbb08d78252601e673fb5bb45c0bce64c4094 Mon Sep 17 00:00:00 2001 From: Victor Hugo Date: Sat, 22 Sep 2012 14:16:16 -0300 Subject: [PATCH 1/7] checkout transparente + dados do pagador --- .gitignore | 1 + README.md | 8 ++++++-- moipy/moip.py | 22 +++++++++++++++++++--- setup.py | 4 ++-- test/__init__.py | 0 test/test.py | 34 ++++++++++++++++++++++++++++++++++ 6 files changed, 62 insertions(+), 7 deletions(-) create mode 100644 test/__init__.py diff --git a/.gitignore b/.gitignore index 900205c..072a880 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ dist/** .pydevproject .settings nbproject/ +.idea \ No newline at end of file diff --git a/README.md b/README.md index 5f073de..dd992a0 100644 --- a/README.md +++ b/README.md @@ -6,8 +6,9 @@ Camada de abstração para integração via API com o MoIP em Python. - Author: Hebert Amaral - Contributor: Ale Borba - Contributor: Igor Hercowitz + - Contributor: Victor Hugo - - Version: v0.2 + - Version: v0.3 Dependências ------------ @@ -52,6 +53,10 @@ Basta importar a classe do MoIP e sair brincando :-) ChangeLog ---------- + v0.3 + - Suporte a checkout transparente + - Adição dos dados do Pagador + - Teste do envio de intrução para checkout transparente v0.2 - Refatorações de código @@ -64,7 +69,6 @@ ToDo ------ - Aplicar testes automatizados usando unittest - - Incluir dados do pagador - Validar campos diff --git a/moipy/moip.py b/moipy/moip.py index 4692846..c2b781d 100644 --- a/moipy/moip.py +++ b/moipy/moip.py @@ -83,7 +83,23 @@ def set_recebedor(self,login_moip,email,apelido): self._monta_xml(self.xml_node, unique=True, InstrucaoUnica=dict(Recebedor=dict(LoginMoip=login_moip, Email=email, Apelido=apelido))) return self - + + def set_pagador(self, **pagador): + + if not 'EnderecoCobranca' in pagador: + return False + + if not 'Pais' in pagador['EnderecoCobranca']: + pagador['EnderecoCobranca']['Pais'] = 'BRA' + + self._monta_xml(self.xml_node, unique=True, InstrucaoUnica=dict(Pagador=pagador)) + + return self + + def set_checkout_transparente(self): + + instrucao = self._monta_xml(self.xml_node, unique=True, InstrucaoUnica=dict()) + instrucao.find('InstrucaoUnica').set('TipoValidacao','Transparente') def envia(self): resposta = RespostaMoIP() @@ -91,7 +107,7 @@ def envia(self): passwd = self.token + ":" + self.key passwd64 = base64.b64encode(passwd) - + curl = pycurl.Curl() curl.setopt(pycurl.URL,self.url) curl.setopt(pycurl.HTTPHEADER,["Authorization: Basic " + passwd64]) @@ -102,7 +118,7 @@ def envia(self): curl.setopt(pycurl.WRITEFUNCTION,resposta.callback) curl.perform() curl.close() - + self.retorno = resposta.conteudo return self diff --git a/setup.py b/setup.py index c9cf5b7..36ba025 100644 --- a/setup.py +++ b/setup.py @@ -5,8 +5,8 @@ setup(name='Moipy', version='0.2', description='Python integration with MoIP payment gateway via API', - author=['Herberth Amaral','Ale Borba'], - author_email=['herberthamaral@gmail.com','ale.alvesborba@gmail.com'], + author=['Herberth Amaral','Ale Borba','Victor'], + author_email=['herberthamaral@gmail.com','ale.alvesborba@gmail.com','vitalbh@gmail.com'], url='http://labs.moip.com.br/', packages=['moipy'], classifiers=[ diff --git a/test/__init__.py b/test/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/test/test.py b/test/test.py index e69de29..6c5db8a 100644 --- a/test/test.py +++ b/test/test.py @@ -0,0 +1,34 @@ +import unittest +from moipy.moip import Moip +import random + +class MoipTestCase(unittest.TestCase): + + def setUp(self): + self.moip = Moip('Razao do Pagamento') + self.moip.set_credenciais(token='PUMLYQSCI0JNCFGQQWGGKJNMG4QRX5DH',key='PHMLUTXWEJ0D5VJZDBFUFZYPZ4IWIC2AGUWMVRWE') + self.moip.set_ambiente('sandbox') + + + def test_set_pagador(self): + + self.moip.set_checkout_transparente() + self.moip.set_valor('12345') + self.moip.set_data_vencimento('yyyy-mm-dd') + self.moip.set_id_proprio(str(random.randrange(500000))) + + endereco = dict(Logradouro='Rua santa ceia',Numero='222',Bairro='Buritis',Cidade='Belo Horizonte',Estado='MG',CEP='30850170',TelefoneFixo='3125124444') + + self.moip.set_pagador(Nome='Victor',Email='vitalbh@gmail.com',Apelido='vitalbh',IdPagador='1',EnderecoCobranca=endereco) + + self.moip.envia() + + resposta = self.moip.get_resposta() + + self.assertEqual(resposta['sucesso'],'Sucesso') + self.assertIsInstance(resposta['token'],str) + + + + if __name__ == '__main__': + unittest.main() \ No newline at end of file From 3eaa146b1bac26bb378ab133f12e7a7c4b8fe856 Mon Sep 17 00:00:00 2001 From: Victor Hugo Date: Sat, 22 Sep 2012 14:21:41 -0300 Subject: [PATCH 2/7] Update README.md --- README.md | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index dd992a0..e72b5c7 100644 --- a/README.md +++ b/README.md @@ -53,17 +53,18 @@ Basta importar a classe do MoIP e sair brincando :-) ChangeLog ---------- - v0.3 - - Suporte a checkout transparente - - Adição dos dados do Pagador - - Teste do envio de intrução para checkout transparente + +v0.3 + - Suporte a checkout transparente + - Adição dos dados do Pagador + - Teste do envio de intrução para checkout transparente - v0.2 - - Refatorações de código - - Retirada dos DocTests +v0.2 + - Refatorações de código + - Retirada dos DocTests - v0.1 - - First version +v0.1 + - First version ToDo ------ From 3df37fc0651b4ce6d0cace7f6c463897bb38ec3f Mon Sep 17 00:00:00 2001 From: Victor Hugo Date: Sat, 22 Sep 2012 14:29:09 -0300 Subject: [PATCH 3/7] Update README.md --- README.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/README.md b/README.md index e72b5c7..18c2f50 100644 --- a/README.md +++ b/README.md @@ -51,6 +51,17 @@ Basta importar a classe do MoIP e sair brincando :-) print moip.get_resposta() # {sucesso:'Sucesso','token':'KJHSDASKD392847293AHFJKDSAH'} + +Para checkout transparente basta chamar: + + self.moip.set_checkout_transparente() + +neste caso é obrigatorio passar os dados do pagador: + + endereco = dict(Logradouro='Rua xxxxx',Numero='222',Bairro='xxxx',Cidade='xxxx',Estado='xx',CEP='xxxxxx',TelefoneFixo='xxxxxxxxxx') + self.moip.set_pagador(Nome='xxxx',Email='xxxxxx',Apelido='vitalbh',IdPagador='x',EnderecoCobranca=endereco) + + ChangeLog ---------- From 6be08788df2ce8f63e475fad36f5bec2b84a800c Mon Sep 17 00:00:00 2001 From: Victor Hugo Date: Sat, 22 Sep 2012 14:41:14 -0300 Subject: [PATCH 4/7] retirano key do teste --- test/test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test.py b/test/test.py index 6c5db8a..62c6aea 100644 --- a/test/test.py +++ b/test/test.py @@ -6,7 +6,7 @@ class MoipTestCase(unittest.TestCase): def setUp(self): self.moip = Moip('Razao do Pagamento') - self.moip.set_credenciais(token='PUMLYQSCI0JNCFGQQWGGKJNMG4QRX5DH',key='PHMLUTXWEJ0D5VJZDBFUFZYPZ4IWIC2AGUWMVRWE') + self.moip.set_credenciais(token='seu token',key='sua key') self.moip.set_ambiente('sandbox') From 737a9a2e8a26a4e9b9c0bcb23fa6d28e965fe6e3 Mon Sep 17 00:00:00 2001 From: Victor Hugo Date: Sat, 22 Sep 2012 17:21:37 -0300 Subject: [PATCH 5/7] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 18c2f50..b959f09 100644 --- a/README.md +++ b/README.md @@ -38,9 +38,9 @@ Uso Basta importar a classe do MoIP e sair brincando :-) - from moipy import MoIP + from moipy import Moip - moip = MoIP('Razao do Pagamento') + moip = Moip('Razao do Pagamento') moip.set_credenciais(token='seu_token',key='sua_key') moip.set_ambiente('sandbox') From be7abfc119e636dc32e7615c64566335552ed6ac Mon Sep 17 00:00:00 2001 From: Felipe Gubert Date: Tue, 15 Oct 2013 15:18:02 -0300 Subject: [PATCH 6/7] v0.4 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Troca do pyCurl por httplib - Melhorias no código/documentação - Adiciona arquivo de teste na raiz do projeto. --- README.md | 10 +++- moipy/moip.py | 136 ++++++++++++++++++++++++++------------------------ test.py | 12 +++++ 3 files changed, 92 insertions(+), 66 deletions(-) create mode 100644 test.py diff --git a/README.md b/README.md index b959f09..95d90af 100644 --- a/README.md +++ b/README.md @@ -7,8 +7,9 @@ Camada de abstração para integração via API com o MoIP em Python. - Contributor: Ale Borba - Contributor: Igor Hercowitz - Contributor: Victor Hugo + - Contributor: Felipe Gubert Cruz - - Version: v0.3 + - Version: v0.4 Dependências ------------ @@ -16,7 +17,7 @@ Dependências O MoIPy tem as seguintes dependências: - lxml - - pycurl + - httplib Instalação ---------- @@ -64,6 +65,11 @@ neste caso é obrigatorio passar os dados do pagador: ChangeLog ---------- + +v0.4 + - Troca do pyCurl por httplib + - Melhorias no código/documentação + - Adiciona arquivo de teste na raiz do projeto. v0.3 - Suporte a checkout transparente diff --git a/moipy/moip.py b/moipy/moip.py index c2b781d..8979dd0 100644 --- a/moipy/moip.py +++ b/moipy/moip.py @@ -1,90 +1,100 @@ #! /usr/bin/env python # -*- coding: utf-8 -*- import base64 -import pycurl - +import httplib from lxml import etree class Moip(): - def __init__(self, razao, xml_node = "EnviarInstrucao"): - + def __init__(self, razao, xml_node="EnviarInstrucao"): + if xml_node: self.xml_node = etree.Element(xml_node) - - self._monta_xml(self.xml_node, unique = True, InstrucaoUnica = dict(Razao=razao)) - - + + self._monta_xml(self.xml_node, unique=True, InstrucaoUnica=dict(Razao=razao)) + def _monta_xml(self, parent, unique=False, **kwargs): """Metodo interno que monta o XML utilizando os parametros passados por outros metodos.""" - + if isinstance(parent, etree._Element): node_parent = parent else: node_parent = etree.Element(parent) - - for k,v in kwargs.items(): + + for k, v in kwargs.items(): if unique and node_parent.find(k) is not None: - node = node_parent.find(k) + node = node_parent.find(k) else: node = etree.SubElement(node_parent, k) - + if isinstance(v, dict): self._monta_xml(node, **v) else: node.text = v - - return node_parent + return node_parent def set_credenciais(self, token, key): - + """Define as credenciais utilizadas para autenticar a chamada aos webservices + """ + self.token = token self.key = key - + return self - - def set_ambiente(self,ambiente): + def set_ambiente(self, ambiente): + """Define se o ambiente é o de homologação (sandbox) ou de produção + """ - if ambiente=="sandbox": + if ambiente == "sandbox": + self.host = 'desenvolvedor.moip.com.br' + self.post_url = '/sandbox/ws/alpha/EnviarInstrucao/Unica' self.url = "https://desenvolvedor.moip.com.br/sandbox/ws/alpha/EnviarInstrucao/Unica" - elif ambiente=="producao": + elif ambiente == "producao": + self.host = 'www.moip.com.br' + self.post_url = '/ws/alpha/EnviarInstrucao/Unica' self.url = "https://www.moip.com.br/ws/alpha/EnviarInstrucao/Unica" else: raise ValueError("Ambiente inválido") - - + def set_valor(self, valor): - + """Define o valor a ser enviado + """ + self._monta_xml(self.xml_node, unique=True, InstrucaoUnica=dict(Valores=dict(Valor=valor))) - - return self + return self def set_id_proprio(self, id): - + """Define o ID proprio da transação + """ + self._monta_xml(self.xml_node, unique=True, InstrucaoUnica=dict(IdProprio=id)) - + return self + def set_data_vencimento(self, data): + """Define a data de vencimento + """ - def set_data_vencimento(self,data): - self._monta_xml(self.xml_node, unique=True, InstrucaoUnica=dict(DataVencimento=data)) - + return self + def set_recebedor(self, login_moip, email, apelido): + """Define o recebedor + """ - def set_recebedor(self,login_moip,email,apelido): - self._monta_xml(self.xml_node, unique=True, InstrucaoUnica=dict(Recebedor=dict(LoginMoip=login_moip, Email=email, Apelido=apelido))) return self def set_pagador(self, **pagador): + """Define o pagador e endereço de cobrança + """ if not 'EnderecoCobranca' in pagador: return False @@ -97,49 +107,47 @@ def set_pagador(self, **pagador): return self def set_checkout_transparente(self): + """Define que o checkout sera transparente + """ instrucao = self._monta_xml(self.xml_node, unique=True, InstrucaoUnica=dict()) - instrucao.find('InstrucaoUnica').set('TipoValidacao','Transparente') + instrucao.find('InstrucaoUnica').set('TipoValidacao', 'Transparente') def envia(self): - resposta = RespostaMoIP() - - passwd = self.token + ":" + self.key + """Comunica com o webservice e envia a transação + """ + # base64 encode the username and password + auth = base64.encodestring('%s:%s' % (self.token, self.key)).replace('\n', '') - passwd64 = base64.b64encode(passwd) + webservice = httplib.HTTPSConnection(self.host) + # headers + webservice.putrequest("POST", self.post_url) + webservice.putheader("Host", self.host) + webservice.putheader("User-Agent", "Mozilla/4.0") + webservice.putheader("Content-type", "text/html; charset=\"UTF-8\"") + webservice.putheader("Content-length", "%d" % len(self._get_xml())) + webservice.putheader("Authorization", "Basic %s" % auth) - curl = pycurl.Curl() - curl.setopt(pycurl.URL,self.url) - curl.setopt(pycurl.HTTPHEADER,["Authorization: Basic " + passwd64]) - curl.setopt(pycurl.USERAGENT,"Mozilla/4.0") - curl.setopt(pycurl.USERPWD,passwd) - curl.setopt(pycurl.POST,True) - curl.setopt(pycurl.POSTFIELDS,self._get_xml()) - curl.setopt(pycurl.WRITEFUNCTION,resposta.callback) - curl.perform() - curl.close() + webservice.endheaders() + webservice.send(self._get_xml()) - self.retorno = resposta.conteudo + resposta = webservice.getresponse() - return self + self.status = resposta.status + self.retorno = resposta.read() + return self def _get_xml(self): """Metodo interno que retorna o objeto etree em formato string""" - + return etree.tostring(self.xml_node) - def get_resposta(self): - - resposta = etree.XML(self.retorno) - return {'sucesso':resposta[0][1].text,'token':resposta[0][2].text} - - -class RespostaMoIP: - def __init__(self): - self.conteudo = '' - - - def callback(self,buf): - self.conteudo = buf \ No newline at end of file + """Trata o retorno + """ + if self.status == 200: + resposta = etree.XML(self.retorno) + return {'sucesso': resposta[0][1].text, 'token': resposta[0][2].text} + else: + return {'sucesso': u'Falha', 'token': u'Não autorizado. Verifique seu Token/key'} diff --git a/test.py b/test.py new file mode 100644 index 0000000..a6814f5 --- /dev/null +++ b/test.py @@ -0,0 +1,12 @@ +from moipy import Moip + +moip = Moip('Razao do Pagamento') + +moip.set_credenciais(token='seu_token',key='sua_key') +moip.set_ambiente('sandbox') +moip.set_valor('12345') +moip.set_data_vencimento('yyyy-mm-dd') +moip.set_id_proprio('abc1234') +moip.envia() + +print moip.get_resposta() \ No newline at end of file From 48b0a353a6bc5111a1ac1c0054936dd8f1568344 Mon Sep 17 00:00:00 2001 From: Felipe Gubert Date: Tue, 15 Oct 2013 15:25:28 -0300 Subject: [PATCH 7/7] corrige setup.py --- setup.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/setup.py b/setup.py index 36ba025..a45cf97 100644 --- a/setup.py +++ b/setup.py @@ -3,10 +3,10 @@ from distutils.core import setup setup(name='Moipy', - version='0.2', + version='0.4', description='Python integration with MoIP payment gateway via API', - author=['Herberth Amaral','Ale Borba','Victor'], - author_email=['herberthamaral@gmail.com','ale.alvesborba@gmail.com','vitalbh@gmail.com'], + author=['Herberth Amaral','Ale Borba','Victor', 'Felipe Gubert'], + author_email=['herberthamaral@gmail.com','ale.alvesborba@gmail.com','vitalbh@gmail.com', 'felipe.gubert@gmail.com'], url='http://labs.moip.com.br/', packages=['moipy'], classifiers=[