diff --git a/__openerp__.py b/__openerp__.py index a72353d..a7ce35b 100644 --- a/__openerp__.py +++ b/__openerp__.py @@ -1,27 +1,31 @@ # -*- coding: utf-8 -*- { - 'name': 'Webpay Payment Acquirer', - 'category': 'Accounting', - 'author': 'Daniel Santibáñez Polanco', - 'summary': 'Payment Acquirer: Webpay Implementation', - 'website': 'https://odoocoop.cl', - 'version': "9.1.0.2", - 'description': """Webpay Payment Acquirer""", - 'depends': ['payment'], - 'python-depends':[ - 'suds', - 'py-wsse', - # En Debian/Ubuntu: - # sudo apt-get install libssl-dev libxml2-dev libxmlsec1-dev - # Sistemas basados en RedHat: - # sudo yum install openssl-devel libxml2-devel xmlsec1-devel xmlsec1-openssl-devel libtool-ltdl-devel - ], - 'data': [ - 'views/webpay.xml', - 'views/payment_acquirer.xml', - 'views/payment_transaction.xml', - 'data/webpay.xml', - ], - 'installable': True, + 'name': 'Webpay Payment Acquirer', + 'category': 'Accounting', + 'author': 'Daniel Santibáñez Polanco', + 'summary': 'Payment Acquirer: Webpay Implementation', + 'website': 'https://odoocoop.cl', + 'version': "8.1.0.0", + 'description': """Webpay Payment Acquirer""", + 'depends': ['payment'], + 'python-depends':[ + 'suds', + 'py-wsse', + # En Debian/Ubuntu: + # sudo apt-get install libssl-dev libxml2-dev libxmlsec1-dev + # Sistemas basados en RedHat: + # sudo yum install openssl-devel libxml2-devel xmlsec1-devel xmlsec1-openssl-devel libtool-ltdl-devel + ], + 'data': [ + 'views/webpay.xml', + 'views/payment_acquirer.xml', + 'views/payment_transaction.xml', +# 'views/website_sale_tempate.xml', + 'views/success.xml', + 'views/failure.xml', + 'data/webpay.xml' + ], + 'installable': True, + 'contributors': ['David Acevedo Toledo '] } diff --git a/controllers/main.py b/controllers/main.py index c7c2541..38432eb 100644 --- a/controllers/main.py +++ b/controllers/main.py @@ -5,6 +5,7 @@ import urllib2 from openerp import http, SUPERUSER_ID +#from openerp.exceptions import UserError from openerp.addons.web.http import request from openerp.addons.payment.models.payment_acquirer import ValidationError @@ -18,10 +19,11 @@ class WebpayController(http.Controller): _cancel_url = '/payment/webpay/test/cancel' def _webpay_form_get_tx_from_data(self, cr, uid, data, context=None): + _logger.info('Webpay: entering form_get_tx with post data %s', pprint.pformat(data)) # debug reference, txn_id = data.get('item_number'), data.get('txn_id') if not reference or not txn_id: error_msg = _('Paypal: received data with missing reference (%s) or txn_id (%s)') % (reference, txn_id) - _logger.warning(error_msg) + _logger.info(error_msg) raise ValidationError(error_msg) # find tx -> @TDENOTE use txn_id ? @@ -32,11 +34,12 @@ def _webpay_form_get_tx_from_data(self, cr, uid, data, context=None): error_msg += '; no order found' else: error_msg += '; multiple order found' - _logger.warning(error_msg) + _logger.info(error_msg) raise ValidationError(error_msg) return self.browse(cr, uid, tx_ids[0], context=context) def _webpay_form_validate(self, cr, uid, tx, data, context=None): + _logger.info('Webpay: entering form_validate with post data %s', pprint.pformat(data)) # debug status = data.get('payment_status') res = { 'acquirer_reference': data.get('txn_id'), @@ -47,12 +50,12 @@ def _webpay_form_validate(self, cr, uid, tx, data, context=None): res.update(state='done', date_validate=data.get('payment_date', fields.datetime.now())) return tx.write(res) elif status in ['Pending', 'Expired']: - _logger.warning('Received notification for Paypal payment %s: set as pending' % (tx.reference)) + _logger.info('Received notification for Paypal payment %s: set as pending' % (tx.reference)) res.update(state='pending', state_message=data.get('pending_reason', '')) return tx.write(res) else: error = 'Received unrecognized status for Paypal payment %s: %s, set as error' % (tx.reference, status) - _logger.warning(error) + _logger.info(error) res.update(state='error', state_message=error) return tx.write(res) @@ -63,8 +66,13 @@ def _webpay_form_validate(self, cr, uid, tx, data, context=None): def webpay_form_feedback(self, acquirer_id=None, **post): """ Webpay contacts using GET, at least for accept """ _logger.info('Webpay: entering form_feedback with post data %s', pprint.pformat(post)) # debug - cr, uid, context = request.cr, SUPERUSER_ID, request.context - resp = request.registry['payment.transaction'].getTransaction(cr, uid, [], acquirer_id, post['token_ws'], context=context) + token_ws = post.get('token_ws') or post.get('TBK_TOKEN') + try: + resp = request.env['payment.transaction'].getTransaction(acquirer_id, token_ws) + except: + resp = False + if not post.get('TBK_TOKEN'): + return request.render('payment_webpay.fracaso') ''' TSY: Autenticación exitosa TSN: Autenticación fallida. @@ -73,26 +81,33 @@ def webpay_form_feedback(self, acquirer_id=None, **post): U3: Error interno en la autenticación. Puede ser vacío si la transacción no se autenticó. ''' - request.registry['payment.transaction'].form_feedback(cr, uid, resp, 'webpay', context=context) - urequest = urllib2.Request(resp.urlRedirection, werkzeug.url_encode({'token_ws': post['token_ws'], })) - uopen = urllib2.urlopen(urequest) - feedback = uopen.read() - if resp.VCI in ['TSY'] and str(resp.detailOutput[0].responseCode) in [ '0' ]: - values={ - 'webpay_redirect': feedback, - } - return request.website.render('payment_webpay.webpay_redirect', values) - return werkzeug.utils.redirect('/shop/payment') - + if resp: + request.env['payment.transaction'].sudo().form_feedback( resp, 'webpay') + if resp.VCI in ['TSY'] and str(resp.detailOutput[0].responseCode) in [ '0' ]: + urequest = urllib2.Request(resp.urlRedirection, werkzeug.url_encode({'token_ws': token_ws }).encode()) + uopen = urllib2.urlopen(urequest) + feedback = uopen.read() + values={ + 'webpay_redirect': feedback, + } + return request.render('payment_webpay.exito', values) + return request.render('payment_webpay.webpay_redirect', values) + request.website.sale_reset() + elif post.get('TBK_ORDEN_COMPRA'): + tx = request.env['payment.transaction'].sudo().search([('reference', '=', post.get('TBK_ORDEN_COMPRA'))]) + tx.write({'state': 'error', 'state_message': 'Pago cancelado (abortado en formulario Webpay)'}) + return request.render('payment_webpay.fracaso') @http.route([ '/payment/webpay/final', '/payment/webpay/test/final', + '/payment/webpay/final/' ], type='http', auth='public', csrf=False, website=True) - def final(self, **post): + def final(self, acquirer_id=False, **post): """ Webpay contacts using GET, at least for accept """ _logger.info('Webpay: entering End with post data %s', pprint.pformat(post)) # debug - cr, uid, context = request.cr, SUPERUSER_ID, request.context + if post.get('TBK_TOKEN'): + return self.webpay_form_feedback(acquirer_id, **post) return werkzeug.utils.redirect('/shop/payment/validate') @@ -127,7 +142,7 @@ def feedback(self, **kwargs): def redirect_webpay(self, **post): acquirer_id = int(post.get('acquirer_id')) acquirer = request.env['payment.acquirer'].browse(acquirer_id) - result = acquirer.initTransaction(post) + result = acquirer.initTransaction(post) urequest = urllib2.Request(result['url'], werkzeug.url_encode({'token_ws': result['token']})) uopen = urllib2.urlopen(urequest) resp = uopen.read() diff --git a/models/webpay.py b/models/webpay.py index 195921a..1b51843 100644 --- a/models/webpay.py +++ b/models/webpay.py @@ -18,43 +18,30 @@ from .wsse.suds import WssePlugin from suds.transport.https import HttpTransport except: - _logger.warning("No Load suds or wsse") + _logger.info("No Load suds or wsse") URLS ={ 'integ': 'https://webpay3gint.transbank.cl/WSWebpayTransaction/cxf/WSWebpayService?wsdl', 'test': 'https://webpay3gint.transbank.cl/WSWebpayTransaction/cxf/WSWebpayService?wsdl', - 'prod': 'https://webpay3g.transbank.cl//WSWebpayTransaction/cxf/WSWebpayService?wsdl', + 'prod': 'https://webpay3g.transbank.cl/WSWebpayTransaction/cxf/WSWebpayService?wsdl' } class PaymentAcquirerWebpay(models.Model): _inherit = 'payment.acquirer' @api.model - def _get_providers(self,): + def _get_providers(self): providers = super(PaymentAcquirerWebpay, self)._get_providers() providers.append(['webpay', 'Webpay']) return providers - webpay_commer_code = fields.Char( - string="Commerce Code",) - webpay_private_key = fields.Binary( - string="User Private Key",) - webpay_public_cert = fields.Binary( - string="User Public Cert",) - webpay_cert = fields.Binary( - string='Webpay Cert',) - webpay_mode = fields.Selection( - [ - ('normal', "Normal"), - ('mall', "Normal Mall"), - ('oneclick', "OneClick"), - ('completa', "Completa"), - ], - string="Webpay Mode", - ) - environment = fields.Selection( - selection_add=[('integ', 'Integración')], - ) + webpay_commer_code = fields.Char('Commerce Code') + webpay_private_key = fields.Binary('User Private Key') + webpay_public_cert = fields.Binary('User Public Cert') + webpay_cert = fields.Binary('Webpay Cert') + webpay_mode = fields.Selection([('normal', 'Normal'),('mall', 'Normal Mall'), + ('oneclick', 'OneClick'),('completa', 'Completa')], 'Webpay Mode') + environment = fields.Selection(selection_add=[('integ', 'Integracion')]) @api.multi def _get_feature_support(self): @@ -67,28 +54,31 @@ def _get_webpay_urls(self): return url @api.multi - def webpay_form_generate_values(self, values): + def webpay_form_generate_values(self, partner_values, tx_values): base_url = self.env['ir.config_parameter'].sudo().get_param('web.base.url') - values.update({ + + tx_values.update({ 'business': self.company_id.name, - 'item_name': '%s: %s' % (self.company_id.name, values['reference']), - 'item_number': values['reference'], - 'amount': values['amount'], - 'currency_code': values['currency'] and values['currency'].name or '', - 'address1': values.get('partner_address'), - 'city': values.get('partner_city'), - 'country': values.get('partner_country') and values.get('partner_country').code or '', - 'state': values.get('partner_state') and (values.get('partner_state').code or values.get('partner_state').name) or '', - 'email': values.get('partner_email'), - 'zip_code': values.get('partner_zip'), - 'first_name': values.get('partner_first_name'), - 'last_name': values.get('partner_last_name'), - 'return_url': base_url + '/payment/webpay/final' - }) - return values + 'item_name': '%s: %s' % (self.company_id.name, tx_values.get('reference', False)), + 'item_number': tx_values.get('reference', False), + 'amount': tx_values.get('amount', False), + 'currency_code': tx_values.get('currency', False) and tx_values.get('currency').name or '', + 'return_url': base_url + '/payment/webpay/final', + + 'address1': partner_values.get('address'), + 'city': partner_values.get('city'), + 'country': partner_values.get('country') and partner_values.get('country').code or '', + 'state': partner_values.get('state') and (partner_values.get('state').code \ + or partner_values.get('state').name) or '', + 'email': partner_values.get('email'), + 'zip_code': partner_values.get('zip'), + 'first_name': partner_values.get('first_name'), + 'last_name': partner_values.get('last_name') + }) + return partner_values, tx_values @api.multi - def webpay_get_form_action_url(self,): + def webpay_get_form_action_url(self): base_url = self.env['ir.config_parameter'].sudo().get_param('web.base.url') return base_url +'/payment/webpay/redirect' @@ -101,19 +91,19 @@ def get_public_cert(self): def get_WebPay_cert(self): return b64decode(self.webpay_cert) - def get_client(self,): - transport=HttpTransport() + def get_client(self): + transport = HttpTransport() wsse = Security() return Client( self._get_webpay_urls(), - transport=transport, - wsse=wsse, - plugins=[ + transport = transport, + wsse = wsse, + plugins = [ WssePlugin( - keyfile=self.get_private_key(), - certfile=self.get_public_cert(), - their_certfile=self.get_WebPay_cert(), + keyfile = self.get_private_key(), + certfile = self.get_public_cert(), + their_certfile = self.get_WebPay_cert(), ), ], ) @@ -137,7 +127,7 @@ def initTransaction(self, post): init.buyOrder = post['item_number'] init.sessionId = self.company_id.id init.returnURL = base_url + '/payment/webpay/return/'+str(self.id) - init.finalURL = post['return_url'] + init.finalURL = '%s/%s' % (post['return_url'], self.id) detail = client.factory.create('wsTransactionDetail') detail.amount = post['amount'] @@ -151,6 +141,7 @@ def initTransaction(self, post): wsInitTransactionOutput = client.service.initTransaction(init) return wsInitTransactionOutput +PaymentAcquirerWebpay() class PaymentTxWebpay(models.Model): @@ -177,8 +168,8 @@ def getTransaction(self, acquirer_id, token): client = acquirer_id.get_client() client.options.cache.clear() - transactionResultOutput = client.service.getTransactionResult(token) - acknowledge = self.acknowledgeTransaction(acquirer_id, token) + transactionResultOutput = client.service.getTransactionResult(token) + acknowledge = self.acknowledgeTransaction(acquirer_id, token) return transactionResultOutput @@ -234,7 +225,7 @@ def _webpay_form_validate(self, cr, uid, tx, data, context=None): res.update(state='done', date_validate=data.transactionDate) return tx.write(res) elif status in ['-6', '-7']: - _logger.warning('Received notification for webpay payment %s: set as pending' % (tx.reference)) + _logger.info('Received notification for webpay payment %s: set as pending' % (tx.reference)) res.update(state='pending', state_message=data.get('pending_reason', '')) return tx.write(res) else: @@ -242,6 +233,4 @@ def _webpay_form_validate(self, cr, uid, tx, data, context=None): _logger.warning(error) res.update(state='error', state_message=error) return tx.write(res) - -class PaymentMethod(models.Model): - _inherit = 'payment.method' +PaymentTxWebpay() diff --git a/models/wsse/signing.py b/models/wsse/signing.py index 92abe60..b1e6491 100644 --- a/models/wsse/signing.py +++ b/models/wsse/signing.py @@ -179,10 +179,10 @@ def verify(envelope, certfile): ctx.register_id(referenced, 'Id', WSU_NS) try : - key = xmlsec.Key.from_memory(certfile, xmlsec.KeyFormat.CERT_PEM, None) - ctx.key = key + key = xmlsec.Key.from_memory(certfile, xmlsec.KeyFormat.CERT_PEM, None) + ctx.key = key except : - sys.exit() + sys.exit() try: ctx.verify(signature) diff --git a/views/failure.xml b/views/failure.xml new file mode 100644 index 0000000..6cf7ec5 --- /dev/null +++ b/views/failure.xml @@ -0,0 +1,30 @@ + + + + + + diff --git a/views/payment_acquirer.xml b/views/payment_acquirer.xml index 51ad572..bf87078 100644 --- a/views/payment_acquirer.xml +++ b/views/payment_acquirer.xml @@ -1,29 +1,24 @@ - - - - acquirer.form.webpay - payment.acquirer - - - - - - - - - - - - - - How to configure your Webpay account? - - - - - - - + + + acquirer.form.webpay + payment.acquirer + + + + + + + + + + + + + + + + + diff --git a/views/payment_transaction.xml b/views/payment_transaction.xml index a8e74ef..3adc7a1 100644 --- a/views/payment_transaction.xml +++ b/views/payment_transaction.xml @@ -1,19 +1,19 @@ - - - transaction.form.webpay - payment.transaction - - - - - - - - - - - - + + + transaction.form.webpay + payment.transaction + + + + + + + + + + + + diff --git a/views/success.xml b/views/success.xml new file mode 100644 index 0000000..386837f --- /dev/null +++ b/views/success.xml @@ -0,0 +1,176 @@ + + + + + + diff --git a/views/webpay.xml b/views/webpay.xml index 424d95e..d02eb6a 100644 --- a/views/webpay.xml +++ b/views/webpay.xml @@ -1,73 +1,73 @@ - - + + - + - - + +