From 9a54529ff4e584b37c9e7839a3b45fae6924a74c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Tue, 3 Dec 2013 14:51:48 +0100 Subject: [PATCH 01/15] [REM] [REF] website_payment: test pages not necessar anymore. Website_payment now only holds the jquery.payment library and some custom js/css to enable theuse of credit card forms, to be used in server 2 server communications. bzr revid: tde@openerp.com-20131203135148-ollsv2ljthksmory --- addons/website_payment/__init__.py | 2 - addons/website_payment/__openerp__.py | 40 ++----- .../website_payment/controllers/__init__.py | 1 - addons/website_payment/controllers/main.py | 95 ----------------- ...payment_acquirer.js => website_payment.js} | 0 .../views/website_payment_templates.xml | 100 ------------------ 6 files changed, 11 insertions(+), 227 deletions(-) delete mode 100644 addons/website_payment/controllers/__init__.py delete mode 100644 addons/website_payment/controllers/main.py rename addons/website_payment/static/src/js/{payment_acquirer.js => website_payment.js} (100%) delete mode 100644 addons/website_payment/views/website_payment_templates.xml diff --git a/addons/website_payment/__init__.py b/addons/website_payment/__init__.py index edccdf73182..ee70d6d3229 100644 --- a/addons/website_payment/__init__.py +++ b/addons/website_payment/__init__.py @@ -18,5 +18,3 @@ # along with this program. If not, see . # ############################################################################## - -import controllers diff --git a/addons/website_payment/__openerp__.py b/addons/website_payment/__openerp__.py index 01b69d33ddd..a0814e66a4d 100644 --- a/addons/website_payment/__openerp__.py +++ b/addons/website_payment/__openerp__.py @@ -1,42 +1,24 @@ # -*- coding: utf-8 -*- -############################################################################## -# -# OpenERP, Open Source Management Solution -# Copyright (C) 2013-Today OpenERP SA (). -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## { - 'name': 'Payment: Website Integration (Test Module)', + 'name': 'Payment: Website Bridge Integration', 'category': 'Website', - 'summary': 'Payment: Website Integration (Test Module)', + 'summary': 'Payment: Website Bridge Module', 'version': '1.0', - 'description': """Module installing all sub-payment modules and adding some - controllers and menu entries in order to test them.""", + 'description': """Bridge module between the payment acquirer module and the + website module.""", 'author': 'OpenERP SA', 'depends': [ 'website', 'payment_acquirer', - 'payment_acquirer_ogone', - 'payment_acquirer_paypal', - 'payment_acquirer_transfer', ], 'data': [ - 'views/website_payment_templates.xml', ], - 'installable': False, - 'active': False, + 'js': [ + 'static/lib/jquery.payment/jquery.payment.js', + 'static/src/js/website_payment.js' + ], + 'css': [ + 'static/src/css/website_payment.css' + ], } diff --git a/addons/website_payment/controllers/__init__.py b/addons/website_payment/controllers/__init__.py deleted file mode 100644 index 8ee9bae18d9..00000000000 --- a/addons/website_payment/controllers/__init__.py +++ /dev/null @@ -1 +0,0 @@ -import main diff --git a/addons/website_payment/controllers/main.py b/addons/website_payment/controllers/main.py deleted file mode 100644 index 4a971975d97..00000000000 --- a/addons/website_payment/controllers/main.py +++ /dev/null @@ -1,95 +0,0 @@ -# -*- coding: utf-8 -*- -############################################################################## -# -# OpenERP, Open Source Management Solution -# Copyright (C) 2013-Today OpenERP SA (). -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## - -from openerp.addons.web import http -from openerp.addons.web.http import request -from openerp.addons.website.models import website - - -class WebsitePayment(http.Controller): - - @website.route([ - '/payment/paypal/test', - ], type='http', auth="public") - def paypal_test(self, **post): - """ TODO - """ - cr, uid, context = request.cr, request.uid, request.context - acquirer_obj = request.registry['payment.acquirer'] - payment_obj = request.registry['payment.transaction'] - currency_obj = request.registry['res.currency'] - - paypal_id = acquirer_obj.search(cr, uid, [('name', '=', 'paypal')], limit=1, context=context)[0] - currency_id = currency_obj.search(cr, uid, [('name', '=', 'EUR')], limit=1, context=context)[0] - - nbr_tx = payment_obj.search(cr, uid, [], count=True, context=context) - tx_id = payment_obj.create(cr, uid, { - 'reference': 'test_ref_%s' % (nbr_tx), - 'amount': 1.95, - 'currency_id': currency_id, - 'acquirer_id': paypal_id, - 'partner_name': 'Norbert Buyer', - 'partner_email': 'norbert.buyer@example.com', - 'partner_lang': 'fr_FR', - }, context=context) - - paypal_form = acquirer_obj.render(cr, uid, paypal_id, None, None, None, tx_id=tx_id, context=context) - paypal = acquirer_obj.browse(cr, uid, paypal_id, context=context) - - values = { - 'acquirer': paypal, - 'acquirer_form': paypal_form, - } - return request.website.render("website_payment.index_paypal", values) - - @website.route([ - '/payment/ogone/test', - ], type='http', auth="public") - def ogone_test(self, **post): - """ TODO - """ - cr, uid, context = request.cr, request.uid, request.context - acquirer_obj = request.registry['payment.acquirer'] - payment_obj = request.registry['payment.transaction'] - currency_obj = request.registry['res.currency'] - - ogone_id = acquirer_obj.search(cr, uid, [('name', '=', 'ogone')], limit=1, context=context)[0] - currency_id = currency_obj.search(cr, uid, [('name', '=', 'EUR')], limit=1, context=context)[0] - - nbr_tx = payment_obj.search(cr, uid, [], count=True, context=context) - tx_id = payment_obj.create(cr, uid, { - 'reference': 'test_ref_%s' % (nbr_tx), - 'amount': 1.95, - 'currency_id': currency_id, - 'acquirer_id': ogone_id, - 'partner_name': 'Norbert Buyer', - 'partner_email': 'norbert.buyer@example.com', - 'partner_lang': 'fr_FR', - }, context=context) - - ogone_form = acquirer_obj.render(cr, uid, ogone_id, None, None, None, tx_id=tx_id, context=context) - ogone = acquirer_obj.browse(cr, uid, ogone_id, context=context) - - values = { - 'acquirer': ogone, - 'acquirer_form': ogone_form, - } - return request.website.render("website_payment.index_ogone", values) diff --git a/addons/website_payment/static/src/js/payment_acquirer.js b/addons/website_payment/static/src/js/website_payment.js similarity index 100% rename from addons/website_payment/static/src/js/payment_acquirer.js rename to addons/website_payment/static/src/js/website_payment.js diff --git a/addons/website_payment/views/website_payment_templates.xml b/addons/website_payment/views/website_payment_templates.xml deleted file mode 100644 index bf6b151326f..00000000000 --- a/addons/website_payment/views/website_payment_templates.xml +++ /dev/null @@ -1,100 +0,0 @@ - - - - - - - Paypal (Test) - /payment/paypal/test - - 90 - - - - Ogone (Test) - /payment/ogone/test - - 91 - - - - Transfer (Test) - /payment/transfer/test - - 92 - - - - - - - - - - - - - From 382829686def6cd1cc6a09f8cf61a7c6ba55a9c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Tue, 3 Dec 2013 15:25:01 +0100 Subject: [PATCH 02/15] [CLEAN] payment_acquirer and acquirer implementation: cleaned code, removing duplicate code for managing transaction and partner values. Also removed dependency towards requests library. Updated acquirers data, not in no update. bzr revid: tde@openerp.com-20131203142501-4cibxmcuvyp8uof9 --- .../models/payment_acquirer.py | 182 +++++++++++------- addons/payment_acquirer/tests/common.py | 8 +- addons/payment_acquirer_adyen/data/adyen.xml | 8 +- addons/payment_acquirer_adyen/models/adyen.py | 46 ++--- .../payment_acquirer_adyen/tests/__init__.py | 4 +- .../tests/test_adyen.py | 30 ++- addons/payment_acquirer_ogone/data/ogone.xml | 6 +- addons/payment_acquirer_ogone/models/ogone.py | 73 +++---- .../tests/test_ogone.py | 44 ++--- .../controllers/main.py | 19 +- .../payment_acquirer_paypal/models/paypal.py | 77 +++----- .../tests/test_paypal.py | 69 +++---- .../data/transfer.xml | 2 +- 13 files changed, 253 insertions(+), 315 deletions(-) diff --git a/addons/payment_acquirer/models/payment_acquirer.py b/addons/payment_acquirer/models/payment_acquirer.py index 101510501db..ce1c2010035 100644 --- a/addons/payment_acquirer/models/payment_acquirer.py +++ b/addons/payment_acquirer/models/payment_acquirer.py @@ -1,9 +1,9 @@ # -*- coding: utf-'8' "-*-" -from openerp.osv import osv, fields - import logging +from openerp.osv import osv, fields + _logger = logging.getLogger(__name__) @@ -22,8 +22,9 @@ class ValidationError(ValueError): class PaymentAcquirer(osv.Model): """ Acquirer Model. Each specific acquirer can extend the model by adding - its own fields. Using the required_if_provider='' attribute on fields - it is possible to have required fields that depend on a specific acquirer. + its own fields, using the acquirer_name as a prefix for the new fields. + Using the required_if_provider='' attribute on fields it is possible + to have required fields that depend on a specific acquirer. Each acquirer has a link to an ir.ui.view record that is a template of a button used to display the payment form. See examples in ``payment_acquirer_ogone`` @@ -36,7 +37,10 @@ class PaymentAcquirer(osv.Model): method that generates the values used to render the form button template. - ``_get_form_action_url(self, cr, uid, id, context=None):``: method that returns the url of the button form. It is used for example in - ecommerce application, if you want to repost some data to the acquirer. + ecommerce application, if you want to post some data to the acquirer. + - ``_compute_fees(self, cr, uid, id, amount, currency_id, country_id, + context=None)``: computed the fees of the acquirer, using generic fields + defined on the acquirer model (see fields definition). Each acquirer should also define controllers to handle communication between OpenERP and the acquirer. It generally consists in return urls given to the @@ -54,8 +58,9 @@ class PaymentAcquirer(osv.Model): 'env': fields.selection( [('test', 'Test'), ('prod', 'Production')], string='Environment'), - 'portal_published': fields.boolean('Visible in Portal', - help="Make this payment acquirer available (Customer invoices, etc.)"), + 'portal_published': fields.boolean( + 'Visible in Portal', + help="Make this payment acquirer available (Customer invoices, etc.)"), # Fees 'fees_active': fields.boolean('Compute fees'), 'fees_dom_fixed': fields.float('Fixed domestic fees'), @@ -89,27 +94,81 @@ class PaymentAcquirer(osv.Model): return getattr(self, '%s_get_form_action_url' % acquirer.name)(cr, uid, id, context=context) return False - def form_preprocess_values(self, cr, uid, id, reference, amount, currency_id, tx_id, partner_id, partner_values, tx_custom_values, context=None): - acquirer = self.browse(cr, uid, id, context=context) - tx_values = tx_custom_values + def form_preprocess_values(self, cr, uid, id, reference, amount, currency_id, tx_id, partner_id, partner_values, tx_values, context=None): + """ Pre process values before giving them to the acquirer-specific render + methods. Those methods will receive: - # compute country - if partner_id: - partner = self.pool['res.partner'].browse(cr, uid, partner_id, context=context) - tx_values['country_id'] = partner.country_id.id - elif partner_values and partner_values.get('country_name'): - country_ids = self.pool['res.country'].search(cr, uid, [('name', '=', partner_values.get('country_name'))], context=context) - tx_values['country_id'] = country_ids and country_ids[0] or None + - partner_values: will contain name, lang, email, zip, address, city, + country_id (int or False), country (browse or False), phone, reference + - tx_values: will contain refernece, amount, currency_id (int or False), + currency (browse or False), partner (browse or False) + """ + acquirer = self.browse(cr, uid, id, context=context) + + if tx_id: + tx = self.browse(cr, uid, id, context=context) + tx_data = { + 'reference': tx.reference, + 'amount': tx.amount, + 'currency_id': tx.currency_id.id, + 'currency': tx.currency_id, + 'partner': tx.partner_id, + } + partner_data = { + 'name': tx.partner_name, + 'lang': tx.partner_lang, + 'email': tx.partner_email, + 'zip': tx.partner_zip, + 'address': tx.partner_address, + 'city': tx.partner_city, + 'country_id': tx.partner_country_id.id, + 'country': tx.partner_country_id, + 'phone': tx.partner_phone, + 'reference': tx.partner_reference, + } else: - tx_values['country_id'] = False + if partner_id: + partner = self.pool['res.partner'].browse(cr, uid, partner_id, context=context) + partner_data = self.pool['payment.transaction'].on_change_partner_id(cr, uid, None, partner_id, context=context)['values'] + else: + partner, partner_data = False, {} + partner_data.update(partner_values) + + if currency_id: + currency = self.pool['res.currency'].browse(cr, uid, currency_id, context=context) + else: + currency = self.pool['res.users'].browse(cr, uid, uid, context=context).company_id.currency_id + tx_data = { + 'reference': reference, + 'amount': amount, + 'currency_id': currency.id, + 'currency': currency, + 'partner': partner, + } + + # update tx values + tx_data.update(tx_values) + + # update partner values + if not partner_data.get('address'): + partner_data['address'] = _partner_format_address(partner_data.get('street', ''), partner_data.get('street2', '')) + if not partner_data.get('country') and partner_data.get('country_id'): + partner_data['country'] = self.pool['res.country'].browse(cr, uid, partner_data.get('country_id'), context=context) + partner_data.update({ + 'first_name': _partner_split_name(partner_data['name'])[0], + 'last_name': _partner_split_name(partner_data['name'])[1], + }) # compute fees - if hasattr(self, '%s_compute_fees' % acquirer.name): - tx_values['fees'] = getattr(self, '%s_compute_fees' % acquirer.name)(cr, uid, id, amount, currency_id, tx_values.get('country_id'), context=None) + fees_method_name = '%s_compute_fees' % acquirer.name + if hasattr(self, fees_method_name): + tx_data['fees'] = getattr(self, fees_method_name)( + cr, uid, id, tx_data['amount'], tx_data['currency_id'], + partner_data['country_id'], context=None) - return tx_values + return (partner_data, tx_data) - def render(self, cr, uid, id, reference, amount, currency_id, tx_id=None, partner_id=False, partner_values=None, tx_custom_values=None, context=None): + def render(self, cr, uid, id, reference, amount, currency_id, tx_id=None, partner_id=False, partner_values=None, tx_values=None, context=None): """ Renders the form template of the given acquirer as a qWeb template. All templates will receive: @@ -120,9 +179,9 @@ class PaymentAcquirer(osv.Model): - reference: reference of the transaction - partner: the current partner browse record, if any (not necessarily set) - partner_values: a dictionary of partner-related values - - tx_custom_values: a dictionary of transaction related values that depends - on the acquirer. Some specific keys should be managed - in each provider, depending on the features it offers: + - tx_values: a dictionary of transaction related values that depends on + the acquirer. Some specific keys should be managed in each + provider, depending on the features it offers: - 'feedback_url': feedback URL, controler that manage answer of the acquirer (without base url) -> FIXME @@ -147,38 +206,36 @@ class PaymentAcquirer(osv.Model): """ if context is None: context = {} - if tx_custom_values is None: - tx_custom_values = {} - partner = None - if partner_id: - partner = self.pool['res.partner'].browse(cr, uid, partner_id, context=context) + if tx_values is None: + tx_values = {} + if partner_values is None: + partner_values = {} acquirer = self.browse(cr, uid, id, context=context) - currency = self.pool['res.currency'].browse(cr, uid, currency_id, context=context) # pre-process values - tx_values = self.form_preprocess_values(cr, uid, id, reference, amount, currency, tx_id, partner_id, partner_values, tx_custom_values, context=context) + partner_values, tx_values = self.form_preprocess_values( + cr, uid, id, reference, amount, currency_id, tx_id, partner_id, + partner_values, tx_values, context=context) # call _form_generate_values to update the tx dict with acqurier specific values cust_method_name = '%s_form_generate_values' % (acquirer.name) - if tx_id and hasattr(self.pool['payment.transaction'], cust_method_name): - method = getattr(self.pool['payment.transaction'], cust_method_name) - tx_values = method(cr, uid, tx_id, tx_values, context=context) - elif hasattr(self, cust_method_name): + if hasattr(self, cust_method_name): method = getattr(self, cust_method_name) - tx_values = method(cr, uid, id, reference, amount, currency, partner_id, partner_values, tx_values, context=context) + partner_values, tx_values = method(cr, uid, id, partner_values, tx_values, context=context) qweb_context = { 'acquirer': acquirer, 'user': self.pool.get("res.users").browse(cr, uid, uid, context=context), - 'reference': reference, - 'amount': amount, - 'currency': currency, - 'partner': partner, + 'reference': tx_values['reference'], + 'amount': tx_values['amount'], + 'currency': tx_values['currency'], + 'partner': tx_values.get('partner'), 'partner_values': partner_values, 'tx_values': tx_values, 'context': context, } - # because render accepts view ids but not qweb -> need to find the xml_id + + # because render accepts view ids but not qweb -> need to use the xml_id return self.pool['ir.ui.view'].render(cr, uid, acquirer.view_template_id.xml_id, qweb_context, engine='ir.qweb', context=context) @@ -186,12 +243,6 @@ class PaymentTransaction(osv.Model): """ Transaction Model. Each specific acquirer can extend the model by adding its own fields. - Methods that should be added in an acquirer-specific implementation: - - - ``_form_generate_values(self, cr, uid, id, tx_custom_values=None, - context=None)``: method that generates the values used to render the - form button template. - Methods that can be added in an acquirer-specific implementation: - ``_create``: method receiving values used when creating a new @@ -243,7 +294,7 @@ class PaymentTransaction(osv.Model): 'partner_zip': fields.char('Zip'), 'partner_address': fields.char('Address'), 'partner_city': fields.char('City'), - 'partner_country_id': fields.many2one('res.country', 'Country'), + 'partner_country_id': fields.many2one('res.country', 'Country', required=True), 'partner_phone': fields.char('Phone'), 'partner_reference': fields.char('Buyer Reference'), } @@ -283,30 +334,19 @@ class PaymentTransaction(osv.Model): return super(PaymentTransaction, self).create(cr, uid, values, context=context) def on_change_partner_id(self, cr, uid, ids, partner_id, context=None): + partner = None if partner_id: partner = self.pool['res.partner'].browse(cr, uid, partner_id, context=context) - values = { - 'partner_name': partner.name, - 'partner_lang': partner.lang, - 'partner_email': partner.email, - 'partner_zip': partner.zip, - 'partner_address': _partner_format_address(partner.street, partner.street2), - 'partner_city': partner.city, - 'partner_country_id': partner.country_id.id, - 'partner_phone': partner.phone, - } - else: - values = { - 'partner_name': False, - 'partner_lang': 'en_US', - 'partner_email': False, - 'partner_zip': False, - 'partner_address': False, - 'partner_city': False, - 'partner_country_id': False, - 'partner_phone': False, - } - return {'values': values} + return {'values': { + 'partner_name': partner and partner.name or False, + 'partner_lang': partner and partner.lang or 'en_US', + 'partner_email': partner and partner.email or False, + 'partner_zip': partner and partner.zip or False, + 'partner_address': _partner_format_address(partner.street, partner.street2), + 'partner_city': partner and partner.city or False, + 'partner_country_id': partner and partner.country_id.id or False, + 'partner_phone': partner and partner.phone or False, + }} # -------------------------------------------------- # FORM RELATED METHODS diff --git a/addons/payment_acquirer/tests/common.py b/addons/payment_acquirer/tests/common.py index 5c915f80cbf..93a1820a447 100644 --- a/addons/payment_acquirer/tests/common.py +++ b/addons/payment_acquirer/tests/common.py @@ -14,8 +14,10 @@ class PaymentAcquirerCommon(common.TransactionCase): self.cr, self.uid, [('name', '=', 'EUR')], limit=1)[0] self.currency_euro = self.registry('res.currency').browse( self.cr, self.uid, self.currency_euro_id) - country_belgium_id = self.registry('res.country').search( + self.country_belgium_id = self.registry('res.country').search( self.cr, self.uid, [('code', 'like', 'BE')], limit=1)[0] + self.country_france_id = self.registry('res.country').search( + self.cr, self.uid, [('code', 'like', 'FR')], limit=1)[0] # dict partner values self.buyer_values = { @@ -27,7 +29,7 @@ class PaymentAcquirerCommon(common.TransactionCase): 'phone': '0032 12 34 56 78', 'city': 'Sin City', 'zip': '1000', - 'country_id': country_belgium_id, + 'country_id': self.country_belgium_id, 'country_name': 'Belgium', } @@ -42,6 +44,6 @@ class PaymentAcquirerCommon(common.TransactionCase): 'phone': '0032 12 34 56 78', 'city': 'Sin City', 'zip': '1000', - 'country_id': country_belgium_id, + 'country_id': self.country_belgium_id, } ) diff --git a/addons/payment_acquirer_adyen/data/adyen.xml b/addons/payment_acquirer_adyen/data/adyen.xml index ec5cb3c7373..92b0cf178b5 100644 --- a/addons/payment_acquirer_adyen/data/adyen.xml +++ b/addons/payment_acquirer_adyen/data/adyen.xml @@ -1,14 +1,14 @@ - + adyen test - OpenERPCOM - cbqYWvVL - cbqYWvVL + dummy + dummy + dummy diff --git a/addons/payment_acquirer_adyen/models/adyen.py b/addons/payment_acquirer_adyen/models/adyen.py index 54c5cdfeb9f..4ba04b1bfe4 100644 --- a/addons/payment_acquirer_adyen/models/adyen.py +++ b/addons/payment_acquirer_adyen/models/adyen.py @@ -72,9 +72,7 @@ class AcquirerAdyen(osv.Model): key = acquirer.adyen_skin_hmac_key.encode('ascii') return base64.b64encode(hmac.new(key, sign, sha1).digest()) - def adyen_form_generate_values(self, cr, uid, id, reference, amount, currency, partner_id=False, partner_values=None, tx_custom_values=None, context=None): - if partner_values is None: - partner_values = {} + def adyen_form_generate_values(self, cr, uid, id, partner_values, tx_values, context=None): base_url = self.pool['ir.config_parameter'].get_param(cr, uid, 'web.base.url') acquirer = self.browse(cr, uid, id, context=context) # tmp @@ -82,27 +80,22 @@ class AcquirerAdyen(osv.Model): from dateutil import relativedelta tmp_date = datetime.date.today() + relativedelta.relativedelta(days=1) - partner = None - if partner_id: - partner = self.pool['res.partner'].browse(cr, uid, partner_id, context=context) - tx_values = { - 'merchantReference': reference, - 'paymentAmount': '%d' % int(float_round(amount, 2) * 100), - 'currencyCode': currency and currency.name or 'EUR', + adyen_tx_values = dict(tx_values) + adyen_tx_values.update({ + 'merchantReference': tx_values['reference'], + 'paymentAmount': '%d' % int(float_round(tx_values['amount'], 2) * 100), + 'currencyCode': tx_values['currency'] and tx_values['currency'].name or '', 'shipBeforeDate': tmp_date, 'skinCode': acquirer.adyen_skin_code, 'merchantAccount': acquirer.adyen_merchant_account, - 'shopperLocale': partner and partner.lang or partner_values.get('lang', 'en_US'), + 'shopperLocale': partner_values['lang'], 'sessionValidity': tmp_date, - 'merchantSig': 'oij', 'resURL': '%s' % urlparse.urljoin(base_url, AdyenController._return_url), - } - if tx_custom_values and tx_custom_values.get('return_url'): - tx_values['merchantReturnData'] = json.dumps({'return_url': '%s' % tx_custom_values.pop('return_url')}) - if tx_custom_values: - tx_values.update(tx_custom_values) - tx_values['merchantSig'] = self._adyen_generate_merchant_sig(acquirer, 'in', tx_values) - return tx_values + }) + if adyen_tx_values.get('return_url'): + adyen_tx_values['merchantReturnData'] = json.dumps({'return_url': '%s' % adyen_tx_values.pop('return_url')}) + adyen_tx_values['merchantSig'] = self._adyen_generate_merchant_sig(acquirer, 'in', adyen_tx_values) + return partner_values, adyen_tx_values def adyen_get_form_action_url(self, cr, uid, id, context=None): acquirer = self.browse(cr, uid, id, context=context) @@ -120,21 +113,6 @@ class TxAdyen(osv.Model): # FORM RELATED METHODS # -------------------------------------------------- - def adyen_form_generate_values(self, cr, uid, id, tx_custom_values=None, context=None): - tx = self.browse(cr, uid, id, context=context) - - tx_data = { - 'shopperLocale': tx.partner_lang, - } - if tx_custom_values: - tx_data.update(tx_custom_values) - return self.pool['payment.acquirer'].paypal_form_generate_values( - cr, uid, tx.acquirer_id.id, - tx.reference, tx.amount, tx.currency_id, - tx_custom_values=tx_data, - context=context - ) - def _adyen_form_get_tx_from_data(self, cr, uid, data, context=None): reference, pspReference = data.get('merchantReference'), data.get('pspReference') if not reference or not pspReference: diff --git a/addons/payment_acquirer_adyen/tests/__init__.py b/addons/payment_acquirer_adyen/tests/__init__.py index b201c351ca7..8c8e8249184 100644 --- a/addons/payment_acquirer_adyen/tests/__init__.py +++ b/addons/payment_acquirer_adyen/tests/__init__.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- -from . import test_adyen +# from . import test_adyen checks = [ - test_adyen, + # test_adyen, ] diff --git a/addons/payment_acquirer_adyen/tests/test_adyen.py b/addons/payment_acquirer_adyen/tests/test_adyen.py index 4fe53b6f2ca..14b5f8fd5e5 100644 --- a/addons/payment_acquirer_adyen/tests/test_adyen.py +++ b/addons/payment_acquirer_adyen/tests/test_adyen.py @@ -1,34 +1,24 @@ # -*- coding: utf-8 -*- +from lxml import objectify +import urlparse + from openerp.addons.payment_acquirer.models.payment_acquirer import ValidationError from openerp.addons.payment_acquirer.tests.common import PaymentAcquirerCommon from openerp.addons.payment_acquirer_adyen.controllers.main import AdyenController from openerp.osv.orm import except_orm from openerp.tools import mute_logger -from lxml import objectify -import urlparse - class AdyenCommon(PaymentAcquirerCommon): def setUp(self): super(AdyenCommon, self).setUp() cr, uid = self.cr, self.uid - self.base_url = self.registry('ir.config_parameter').get_param(cr, uid, 'web.base.url') - model, self.paypal_view_id = self.registry('ir.model.data').get_object_reference(cr, uid, 'payment_acquirer_adyen', 'adyen_acquirer_button') - # create a new ogone account - self.adyen_id = self.payment_acquirer.create( - cr, uid, { - 'name': 'adyen', - 'env': 'test', - 'view_template_id': self.paypal_view_id, - 'adyen_merchant_account': 'OpenERPCOM', - 'adyen_skin_code': 'cbqYWvVL', - 'adyen_skin_hmac_key': 'cbqYWvVL', - }) + # get the adyen account + model, self.adyen_id = self.registry('ir.model.data').get_object_reference(cr, uid, 'payment_acquirer_adyen', 'payment_acquirer_adyen') # some CC (always use expiration date 06 / 2016, cvc 737, cid 7373 (amex)) self.amex = (('370000000000002', '7373')) @@ -57,6 +47,9 @@ class AdyenForm(AdyenCommon): def test_10_adyen_form_render(self): cr, uid, context = self.cr, self.uid, {} + # be sure not to do stupid things + adyen = self.payment_acquirer.browse(self.cr, self.uid, self.adyen_id, None) + self.assertEqual(adyen.env, 'test', 'test without test env') # ---------------------------------------- # Test: button direct rendering @@ -74,7 +67,7 @@ class AdyenForm(AdyenCommon): # render the button res = self.payment_acquirer.render( cr, uid, self.adyen_id, - 'test_ref0', 0.01, self.currency_euro, + 'test_ref0', 0.01, self.currency_euro_id, partner_id=None, partner_values=self.buyer_values, context=context) @@ -88,12 +81,15 @@ class AdyenForm(AdyenCommon): self.assertEqual( form_input.get('value'), form_values[form_input.get('name')], - 'adyen: wrong value for form: received %s instead of %s' % (form_input.get('value'), form_values[form_input.get('name')]) + 'adyen: wrong value for input %s: received %s instead of %s' % (form_input.get('name'), form_input.get('value'), form_values[form_input.get('name')]) ) @mute_logger('openerp.addons.payment_acquirer_paypal.models.paypal', 'ValidationError') def test_20_paypal_form_management(self): cr, uid, context = self.cr, self.uid, {} + # be sure not to do stupid things + adyen = self.payment_acquirer.browse(self.cr, self.uid, self.adyen_id, None) + self.assertEqual(adyen.env, 'test', 'test without test env') # {'authResult': u'AUTHORISED', # 'merchantReference': u'SO014', diff --git a/addons/payment_acquirer_ogone/data/ogone.xml b/addons/payment_acquirer_ogone/data/ogone.xml index 51f67114b1f..2c57a361ef6 100644 --- a/addons/payment_acquirer_ogone/data/ogone.xml +++ b/addons/payment_acquirer_ogone/data/ogone.xml @@ -1,6 +1,6 @@ - + ogone @@ -9,8 +9,8 @@ dummy dummy dummy - tINY4Yv14789gUix1130 - tINYj885Tfvd4P471464 + dummy + dummy diff --git a/addons/payment_acquirer_ogone/models/ogone.py b/addons/payment_acquirer_ogone/models/ogone.py index b06505c1cdd..7decd389e95 100644 --- a/addons/payment_acquirer_ogone/models/ogone.py +++ b/addons/payment_acquirer_ogone/models/ogone.py @@ -1,6 +1,10 @@ # -*- coding: utf-'8' "-*-" from hashlib import sha1 +try: + import simplejson as json +except ImportError: + import json import logging from lxml import etree, objectify from pprint import pformat @@ -93,39 +97,34 @@ class PaymentAcquirerOgone(osv.Model): shasign = sha1(sign).hexdigest() return shasign - def ogone_form_generate_values(self, cr, uid, id, reference, amount, currency, partner_id=False, partner_values=None, tx_custom_values=None, context=None): - if partner_values is None: - partner_values = {} + def ogone_form_generate_values(self, cr, uid, id, partner_values, tx_values, context=None): base_url = self.pool['ir.config_parameter'].get_param(cr, uid, 'web.base.url') acquirer = self.browse(cr, uid, id, context=context) - partner = None - if partner_id: - partner = self.pool['res.partner'].browse(cr, uid, partner_id, context=context) - tx_values = { + + ogone_tx_values = dict(tx_values) + ogone_tx_values.update({ 'PSPID': acquirer.ogone_pspid, - 'ORDERID': reference, - 'AMOUNT': '%d' % int(float_round(amount, 2) * 100), - 'CURRENCY': currency and currency.name or 'EUR', - 'LANGUAGE': partner and partner.lang or partner_values.get('lang', ''), - 'CN': partner and partner.name or partner_values.get('name', ''), - 'EMAIL': partner and partner.email or partner_values.get('email', ''), - 'OWNERZIP': partner and partner.zip or partner_values.get('zip', ''), - 'OWNERADDRESS': partner and ' '.join((partner.street or '', partner.street2 or '')).strip() or ' '.join((partner_values.get('street', ''), partner_values.get('street2', ''))).strip(), - 'OWNERTOWN': partner and partner.city or partner_values.get('city', ''), - 'OWNERCTY': partner and partner.country_id and partner.country_id.name or partner_values.get('country_name', ''), - 'OWNERTELNO': partner and partner.phone or partner_values.get('phone', ''), + 'ORDERID': tx_values['reference'], + 'AMOUNT': '%d' % int(float_round(tx_values['amount'], 2) * 100), + 'CURRENCY': tx_values['currency'] and tx_values['currency'].name or '', + 'LANGUAGE': partner_values['lang'], + 'CN': partner_values['name'], + 'EMAIL': partner_values['email'], + 'OWNERZIP': partner_values['zip'], + 'OWNERADDRESS': partner_values['address'], + 'OWNERTOWN': partner_values['city'], + 'OWNERCTY': partner_values['country'] and partner_values['country'].name or '', + 'OWNERTELNO': partner_values['phone'], 'ACCEPTURL': '%s' % urlparse.urljoin(base_url, OgoneController._accept_url), 'DECLINEURL': '%s' % urlparse.urljoin(base_url, OgoneController._decline_url), 'EXCEPTIONURL': '%s' % urlparse.urljoin(base_url, OgoneController._exception_url), 'CANCELURL': '%s' % urlparse.urljoin(base_url, OgoneController._cancel_url), - } - if tx_custom_values and tx_custom_values.get('return_url'): - tx_values['PARAMPLUS'] = 'return_url=%s' % tx_custom_values.pop('return_url') - if tx_custom_values: - tx_values.update(tx_custom_values) + }) + if ogone_tx_values.get('return_url'): + ogone_tx_values['PARAMPLUS'] = json.dumps('{"return_url": %s}' % ogone_tx_values.pop('return_url')) shasign = self._ogone_generate_shasign(acquirer, 'in', tx_values) - tx_values['SHASIGN'] = shasign - return tx_values + ogone_tx_values['SHASIGN'] = shasign + return partner_values, ogone_tx_values def ogone_get_form_action_url(self, cr, uid, id, context=None): acquirer = self.browse(cr, uid, id, context=context) @@ -153,30 +152,6 @@ class PaymentTxOgone(osv.Model): # FORM RELATED METHODS # -------------------------------------------------- - def ogone_form_generate_values(self, cr, uid, id, tx_custom_values=None, context=None): - """ Ogone-specific value generation for rendering a transaction-based - form button. """ - tx = self.browse(cr, uid, id, context=context) - - tx_data = { - 'LANGUAGE': tx.partner_lang, - 'CN': tx.partner_name, - 'EMAIL': tx.partner_email, - 'OWNERZIP': tx.partner_zip, - 'OWNERADDRESS': tx.partner_address, - 'OWNERTOWN': tx.partner_city, - 'OWNERCTY': tx.partner_country_id and tx.partner_country_id.name or '', - 'OWNERTELNO': tx.partner_phone, - } - if tx_custom_values: - tx_data.update(tx_custom_values) - return self.pool['payment.acquirer'].ogone_form_generate_values( - cr, uid, tx.acquirer_id.id, - tx.reference, tx.amount, tx.currency_id, - tx_custom_values=tx_data, - context=context - ) - def _ogone_form_get_tx_from_data(self, cr, uid, data, context=None): """ Given a data dict coming from ogone, verify it and find the related transaction record. """ diff --git a/addons/payment_acquirer_ogone/tests/test_ogone.py b/addons/payment_acquirer_ogone/tests/test_ogone.py index 245cef73007..be1f534ea74 100644 --- a/addons/payment_acquirer_ogone/tests/test_ogone.py +++ b/addons/payment_acquirer_ogone/tests/test_ogone.py @@ -1,45 +1,30 @@ # -*- coding: utf-8 -*- +from lxml import objectify +import time +import urlparse + from openerp.addons.payment_acquirer.models.payment_acquirer import ValidationError from openerp.addons.payment_acquirer.tests.common import PaymentAcquirerCommon from openerp.addons.payment_acquirer_ogone.controllers.main import OgoneController from openerp.tools import mute_logger -from lxml import objectify -# import requests -import time -import urlparse - class OgonePayment(PaymentAcquirerCommon): def setUp(self): super(OgonePayment, self).setUp() cr, uid = self.cr, self.uid - self.base_url = self.registry('ir.config_parameter').get_param(cr, uid, 'web.base.url') - model, self.ogone_view_id = self.registry('ir.model.data').get_object_reference(cr, uid, 'payment_acquirer_ogone', 'ogone_acquirer_button') - # create a new ogone account - self.ogone_id = self.payment_acquirer.create( - cr, uid, { - 'name': 'ogone', - 'env': 'test', - 'view_template_id': self.ogone_view_id, - 'ogone_pspid': 'dummy', - 'ogone_userid': 'dummy', - 'ogone_password': 'dummy', - 'ogone_shakey_in': 'tINY4Yv14789gUix1130', - 'ogone_shakey_out': 'tINYj885Tfvd4P471464', - }) - self.ogone_url = self.payment_acquirer._get_ogone_urls(cr, uid, [self.ogone_id], None, None)[self.ogone_id]['ogone_standard_order_url'] - - def test_00_ogone_acquirer(self): - ogone = self.payment_acquirer.browse(self.cr, self.uid, self.ogone_id, None) - self.assertEqual(ogone.env, 'test', 'test without test env') + # get the adyen account + model, self.ogone_id = self.registry('ir.model.data').get_object_reference(cr, uid, 'payment_acquirer_ogone', 'payment_acquirer_ogone') def test_10_ogone_form_render(self): cr, uid, context = self.cr, self.uid, {} + # be sure not to do stupid thing + ogone = self.payment_acquirer.browse(self.cr, self.uid, self.ogone_id, None) + self.assertEqual(ogone.env, 'test', 'test without test env') # ---------------------------------------- # Test: button direct rendering + shasign @@ -68,7 +53,7 @@ class OgonePayment(PaymentAcquirerCommon): # render the button res = self.payment_acquirer.render( cr, uid, self.ogone_id, - 'test_ref0', 0.01, self.currency_euro, + 'test_ref0', 0.01, self.currency_euro_id, partner_id=None, partner_values=self.buyer_values, context=context) @@ -82,7 +67,7 @@ class OgonePayment(PaymentAcquirerCommon): self.assertEqual( form_input.get('value'), form_values[form_input.get('name')], - 'ogone: wrong value for form: received %s instead of %s' % (form_input.get('value'), form_values[form_input.get('name')]) + 'ogone: wrong value for input %s: received %s instead of %s' % (form_input.get('name'), form_input.get('value'), form_values[form_input.get('name')]) ) # ---------------------------------------- @@ -123,6 +108,9 @@ class OgonePayment(PaymentAcquirerCommon): @mute_logger('openerp.addons.payment_acquirer_ogone.models.ogone', 'ValidationError') def test_20_ogone_form_management(self): cr, uid, context = self.cr, self.uid, {} + # be sure not to do stupid thing + ogone = self.payment_acquirer.browse(self.cr, self.uid, self.ogone_id, None) + self.assertEqual(ogone.env, 'test', 'test without test env') # typical data posted by ogone after client has successfully paid ogone_post_data = { @@ -155,6 +143,7 @@ class OgonePayment(PaymentAcquirerCommon): 'currency_id': self.currency_euro_id, 'reference': 'test_ref_2', 'partner_name': 'Norbert Buyer', + 'partner_country_id': self.country_france_id, }, context=context ) # validate it @@ -183,6 +172,9 @@ class OgonePayment(PaymentAcquirerCommon): def test_30_ogone_s2s(self): test_ref = 'test_ref_%.15f' % time.time() cr, uid, context = self.cr, self.uid, {} + # be sure not to do stupid thing + ogone = self.payment_acquirer.browse(self.cr, self.uid, self.ogone_id, None) + self.assertEqual(ogone.env, 'test', 'test without test env') # create a new draft tx tx_id = self.payment_transaction.create( diff --git a/addons/payment_acquirer_paypal/controllers/main.py b/addons/payment_acquirer_paypal/controllers/main.py index 9e3c5868307..2fdb193dd1c 100644 --- a/addons/payment_acquirer_paypal/controllers/main.py +++ b/addons/payment_acquirer_paypal/controllers/main.py @@ -1,17 +1,17 @@ # -*- coding: utf-8 -*- -from openerp.addons.web import http -from openerp.addons.web.http import request -from openerp.addons.website.models import website - try: import simplejson as json except ImportError: import json import logging import pprint -import requests -from urllib import urlencode +import urllib +import urllib2 + +from openerp.addons.web import http +from openerp.addons.web.http import request +from openerp.addons.website.models import website _logger = logging.getLogger(__name__) @@ -32,9 +32,10 @@ class PaypalController(http.Controller): Once data is validated, process it. """ res = False - paypal_url = "https://www.sandbox.paypal.com/cgi-bin/webscr" - post_url = '%s?cmd=_notify-validate&%s' % (paypal_url, urlencode(post)) - resp = requests.post(post_url) + new_post = dict(post, cmd='_notify-validate') + urequest = urllib2.Request("https://www.sandbox.paypal.com/cgi-bin/webscr", urllib.urlencode(new_post)) + uopen = urllib2.urlopen(urequest) + resp = uopen.read() if resp.text == 'VERIFIED': _logger.info('Paypal: validated data') cr, uid, context = request.cr, request.uid, request.context diff --git a/addons/payment_acquirer_paypal/models/paypal.py b/addons/payment_acquirer_paypal/models/paypal.py index 8bbd540372b..e6b886a941b 100644 --- a/addons/payment_acquirer_paypal/models/paypal.py +++ b/addons/payment_acquirer_paypal/models/paypal.py @@ -1,11 +1,5 @@ # -*- coding: utf-'8' "-*-" -from openerp.addons.payment_acquirer.models import payment_acquirer -from openerp.addons.payment_acquirer.models.payment_acquirer import ValidationError -from openerp.addons.payment_acquirer_paypal.controllers.main import PaypalController -from openerp.osv import osv, fields -from openerp.tools.float_utils import float_compare - import base64 try: import simplejson as json @@ -16,6 +10,11 @@ import urlparse import urllib import urllib2 +from openerp.addons.payment_acquirer.models.payment_acquirer import ValidationError +from openerp.addons.payment_acquirer_paypal.controllers.main import PaypalController +from openerp.osv import osv, fields +from openerp.tools.float_utils import float_compare + _logger = logging.getLogger(__name__) @@ -65,40 +64,34 @@ class AcquirerPaypal(osv.Model): fees = amount * (1 + acquirer.fees_int_var / 100.0) + acquirer.fees_int_fixed - amount return fees - def paypal_form_generate_values(self, cr, uid, id, reference, amount, currency, partner_id=False, partner_values=None, tx_custom_values=None, context=None): - if partner_values is None: - partner_values = {} + def paypal_form_generate_values(self, cr, uid, id, partner_values, tx_values, context=None): base_url = self.pool['ir.config_parameter'].get_param(cr, uid, 'web.base.url') acquirer = self.browse(cr, uid, id, context=context) - partner = None - if partner_id: - partner = self.pool['res.partner'].browse(cr, uid, partner_id, context=context) - tx_values = { + paypal_tx_values = dict(tx_values) + paypal_tx_values.update({ 'cmd': '_xclick', 'business': acquirer.paypal_email_id, - 'item_name': reference, - 'item_number': reference, - 'amount': amount, - 'currency_code': currency and currency.name or 'EUR', - 'address1': payment_acquirer._partner_format_address(partner and partner.street or partner_values.get('street', ''), partner and partner.street2 or partner_values.get('street2', '')), - 'city': partner and partner.city or partner_values.get('city', ''), - 'country': partner and partner.country_id and partner.country_id.name or partner_values.get('country_name', ''), - 'email': partner and partner.email or partner_values.get('email', ''), - 'zip': partner and partner.zip or partner_values.get('zip', ''), - 'first_name': payment_acquirer._partner_split_name(partner and partner.name or partner_values.get('name', ''))[0], - 'last_name': payment_acquirer._partner_split_name(partner and partner.name or partner_values.get('name', ''))[1], + 'item_name': tx_values['reference'], + 'item_number': tx_values['reference'], + 'amount': tx_values['amount'], + 'currency_code': tx_values['currency'] and tx_values['currency'].name or '', + 'address1': partner_values['address'], + 'city': partner_values['city'], + 'country': partner_values['country'] and partner_values['country'].name or '', + 'email': partner_values['email'], + 'zip': partner_values['zip'], + 'first_name': partner_values['first_name'], + 'last_name': partner_values['last_name'], 'return': '%s' % urlparse.urljoin(base_url, PaypalController._return_url), 'notify_url': '%s' % urlparse.urljoin(base_url, PaypalController._notify_url), 'cancel_return': '%s' % urlparse.urljoin(base_url, PaypalController._cancel_url), - } + }) if acquirer.fees_active: - tx_values['handling'] = '%.2f' % tx_custom_values.pop('fees', 0.0) - if tx_custom_values and tx_custom_values.get('return_url'): - tx_values['custom'] = json.dumps({'return_url': '%s' % tx_custom_values.pop('return_url')}) - if tx_custom_values: - tx_values.update(tx_custom_values) - return tx_values + paypal_tx_values['handling'] = '%.2f' % paypal_tx_values.pop('fees', 0.0) + if paypal_tx_values.get('return_url'): + paypal_tx_values['custom'] = json.dumps({'return_url': '%s' % paypal_tx_values.pop('return_url')}) + return partner_values, paypal_tx_values def paypal_get_form_action_url(self, cr, uid, id, context=None): acquirer = self.browse(cr, uid, id, context=context) @@ -144,28 +137,6 @@ class TxPaypal(osv.Model): # FORM RELATED METHODS # -------------------------------------------------- - def paypal_form_generate_values(self, cr, uid, id, tx_custom_values=None, context=None): - tx = self.browse(cr, uid, id, context=context) - - tx_data = { - 'item_name': tx.name, - 'first_name': payment_acquirer._partner_split_name(tx.partner_name)[0], - 'last_name': payment_acquirer._partner_split_name(tx.partner_name)[0], - 'email': tx.partner_email, - 'zip': tx.partner_zip, - 'address1': tx.partner_address, - 'city': tx.partner_city, - 'country': tx.partner_country_id and tx.partner_country_id.name or '', - } - if tx_custom_values: - tx_data.update(tx_custom_values) - return self.pool['payment.acquirer'].paypal_form_generate_values( - cr, uid, tx.acquirer_id.id, - tx.reference, tx.amount, tx.currency_id, - tx_custom_values=tx_data, - context=context - ) - def _paypal_form_get_tx_from_data(self, cr, uid, data, context=None): reference, txn_id = data.get('item_number'), data.get('txn_id') if not reference or not txn_id: diff --git a/addons/payment_acquirer_paypal/tests/test_paypal.py b/addons/payment_acquirer_paypal/tests/test_paypal.py index c29e605e1c8..00dbe869e14 100644 --- a/addons/payment_acquirer_paypal/tests/test_paypal.py +++ b/addons/payment_acquirer_paypal/tests/test_paypal.py @@ -15,22 +15,10 @@ class PaypalCommon(PaymentAcquirerCommon): def setUp(self): super(PaypalCommon, self).setUp() cr, uid = self.cr, self.uid - self.base_url = self.registry('ir.config_parameter').get_param(cr, uid, 'web.base.url') - model, self.paypal_view_id = self.registry('ir.model.data').get_object_reference(cr, uid, 'payment_acquirer_paypal', 'paypal_acquirer_button') - # create a new ogone account - self.paypal_id = self.payment_acquirer.create( - cr, uid, { - 'name': 'paypal', - 'env': 'test', - 'view_template_id': self.paypal_view_id, - 'paypal_email_id': 'dummy', - 'paypal_username': 'dummy', - 'paypal_api_enabled': True, - 'paypal_api_username': 'dummy', - 'paypal_api_password': 'dummy', - }) + # get the paypal account + model, self.paypal_id = self.registry('ir.model.data').get_object_reference(cr, uid, 'payment_acquirer_paypal', 'payment_acquirer_paypal') # tde+seller@openerp.com - tde+buyer@openerp.com - tde+buyer-it@openerp.com # some CC @@ -50,6 +38,9 @@ class PaypalServer2Server(PaypalCommon): def test_00_tx_management(self): cr, uid, context = self.cr, self.uid, {} + # be sure not to do stupid things + paypal = self.payment_acquirer.browse(self.cr, self.uid, self.paypal_id, None) + self.assertEqual(paypal.env, 'test', 'test without test env') res = self.payment_acquirer._paypal_s2s_get_access_token(cr, uid, [self.paypal_id], context=context) self.assertTrue(res[self.paypal_id] is not False, 'paypal: did not generate access token') @@ -78,24 +69,10 @@ class PaypalServer2Server(PaypalCommon): class PaypalForm(PaypalCommon): - def test_00_paypal_acquirer(self): - cr, uid, context = self.cr, self.uid, {} - # forgot some mandatory fields: should crash - with self.assertRaises(except_orm): - self.payment_acquirer.create( - cr, uid, { - 'name': 'paypal', - 'env': 'test', - 'view_template_id': self.paypal_view_id, - 'paypal_email_id': 'tde+paypal-facilitator@openerp.com', - }, context=context) - - paypal = self.payment_acquirer.browse(self.cr, self.uid, self.paypal_id, None) - self.assertEqual(paypal.env, 'test', 'test without test env') - def test_10_paypal_form_render(self): cr, uid, context = self.cr, self.uid, {} # be sure not to do stupid things + self.payment_acquirer.write(cr, uid, self.paypal_id, {'fees_active': False}, context) paypal = self.payment_acquirer.browse(cr, uid, self.paypal_id, context) self.assertEqual(paypal.env, 'test', 'test without test env') @@ -103,6 +80,14 @@ class PaypalForm(PaypalCommon): # Test: button direct rendering # ---------------------------------------- + # render the button + res = self.payment_acquirer.render( + cr, uid, self.paypal_id, + 'test_ref0', 0.01, self.currency_euro_id, + partner_id=None, + partner_values=self.buyer_values, + context=context) + form_values = { 'cmd': '_xclick', 'business': 'tde+paypal-facilitator@openerp.com', @@ -122,14 +107,6 @@ class PaypalForm(PaypalCommon): 'cancel_return': '%s' % urlparse.urljoin(self.base_url, PaypalController._cancel_url), } - # render the button - res = self.payment_acquirer.render( - cr, uid, self.paypal_id, - 'test_ref0', 0.01, self.currency_euro, - partner_id=None, - partner_values=self.buyer_values, - context=context) - # check form result tree = objectify.fromstring(res) self.assertEqual(tree.get('action'), 'https://www.sandbox.paypal.com/cgi-bin/webscr', 'paypal: wrong form POST url') @@ -139,19 +116,24 @@ class PaypalForm(PaypalCommon): self.assertEqual( form_input.get('value'), form_values[form_input.get('name')], - 'paypal: wrong value for form: received %s instead of %s' % (form_input.get('value'), form_values[form_input.get('name')]) + 'paypal: wrong value for input %s: received %s instead of %s' % (form_input.get('name'), form_input.get('value'), form_values[form_input.get('name')]) ) def test_11_paypal_form_with_fees(self): cr, uid, context = self.cr, self.uid, {} - self.payment_acquirer.write(cr, uid, self.paypal_id, { - 'fees_active': True, - }, context) - # be sure not to do stupid things paypal = self.payment_acquirer.browse(self.cr, self.uid, self.paypal_id, None) self.assertEqual(paypal.env, 'test', 'test without test env') + # update acquirer: compute fees + self.payment_acquirer.write(cr, uid, self.paypal_id, { + 'fees_active': True, + 'fees_dom_fixed': 1.0, + 'fees_dom_var': 0.35, + 'fees_int_fixed': 1.5, + 'fees_int_var': 0.50, + }, context) + # render the button res = self.payment_acquirer.render( cr, uid, self.paypal_id, @@ -167,7 +149,7 @@ class PaypalForm(PaypalCommon): for form_input in tree.input: if form_input.get('name') in ['handling']: handling_found = True - self.assertEqual(form_input.get('value'), '0.84', 'paypal: wrong computed fees') + self.assertEqual(form_input.get('value'), '1.56', 'paypal: wrong computed fees') self.assertTrue(handling_found, 'paypal: fees_active did not add handling input in rendered form') @mute_logger('openerp.addons.payment_acquirer_paypal.models.paypal', 'ValidationError') @@ -233,6 +215,7 @@ class PaypalForm(PaypalCommon): 'currency_id': self.currency_euro_id, 'reference': 'test_ref_2', 'partner_name': 'Norbert Buyer', + 'partner_country_id': self.country_france_id, }, context=context ) # validate it diff --git a/addons/payment_acquirer_transfer/data/transfer.xml b/addons/payment_acquirer_transfer/data/transfer.xml index ce6e56be57d..ec81cd82719 100644 --- a/addons/payment_acquirer_transfer/data/transfer.xml +++ b/addons/payment_acquirer_transfer/data/transfer.xml @@ -1,6 +1,6 @@ - + transfer From b7e8b40fb23b3369554ff07c3d8d617d16f16c03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Wed, 4 Dec 2013 13:52:27 +0100 Subject: [PATCH 03/15] [IMP] payment_acquirer: improvements: - added acquirer_reference standard field on the transaction, valid for most of acquirers - fixed computation of partner_data before rendering the button, was broken when giving a partner_id - added support of tx_url to specify the form URL for the rendered button - added support of submit_txt and submit_class to customize the submit button of the rendered form bzr revid: tde@openerp.com-20131204125227-3g017gue72ujjyqz --- .../models/payment_acquirer.py | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/addons/payment_acquirer/models/payment_acquirer.py b/addons/payment_acquirer/models/payment_acquirer.py index ce1c2010035..89eb40e979f 100644 --- a/addons/payment_acquirer/models/payment_acquirer.py +++ b/addons/payment_acquirer/models/payment_acquirer.py @@ -129,7 +129,17 @@ class PaymentAcquirer(osv.Model): else: if partner_id: partner = self.pool['res.partner'].browse(cr, uid, partner_id, context=context) - partner_data = self.pool['payment.transaction'].on_change_partner_id(cr, uid, None, partner_id, context=context)['values'] + partner_data = { + 'name': partner.name, + 'lang': partner.lang, + 'email': partner.email, + 'zip': partner.zip, + 'city': partner.city, + 'address': _partner_format_address(partner.street, partner.street2), + 'country_id': partner.country_id.id, + 'country': partner.country_id, + 'phone': partner.phone, + } else: partner, partner_data = False, {} partner_data.update(partner_values) @@ -224,6 +234,9 @@ class PaymentAcquirer(osv.Model): partner_values, tx_values = method(cr, uid, id, partner_values, tx_values, context=context) qweb_context = { + 'tx_url': context.get('tx_url', self.get_form_action_url(cr, uid, id, context=context)), + 'submit_class': context.get('submit_class', 'btn btn-link'), + 'submit_txt': context.get('submit_txt'), 'acquirer': acquirer, 'user': self.pool.get("res.users").browse(cr, uid, uid, context=context), 'reference': tx_values['reference'], @@ -286,6 +299,8 @@ class PaymentTransaction(osv.Model): 'fees': fields.float('Fees', help='Fees amount; set by the system because depends on the acquirer'), 'currency_id': fields.many2one('res.currency', 'Currency', required=True), 'reference': fields.char('Order Reference', required=True), + 'acquirer_reference': fields.char('Acquirer Order Reference', + help='Reference of the TX as stored in the acquirer database'), # duplicate partner / transaction data to store the values at transaction time 'partner_id': fields.many2one('res.partner', 'Partner'), 'partner_name': fields.char('Partner Name'), @@ -342,7 +357,7 @@ class PaymentTransaction(osv.Model): 'partner_lang': partner and partner.lang or 'en_US', 'partner_email': partner and partner.email or False, 'partner_zip': partner and partner.zip or False, - 'partner_address': _partner_format_address(partner.street, partner.street2), + 'partner_address': _partner_format_address(partner and partner.street or '', partner and partner.street2 or ''), 'partner_city': partner and partner.city or False, 'partner_country_id': partner and partner.country_id.id or False, 'partner_phone': partner and partner.phone or False, From 77f6d91236f8c324aa3d0d01c52b035a361ebc53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Wed, 4 Dec 2013 13:52:50 +0100 Subject: [PATCH 04/15] [IMP] payment_acquirer: improved backend views bzr revid: tde@openerp.com-20131204125250-7p6gvofiu2sb89az --- addons/payment_acquirer/views/payment_acquirer.xml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/addons/payment_acquirer/views/payment_acquirer.xml b/addons/payment_acquirer/views/payment_acquirer.xml index 7377f4aedb3..1741c56f8d6 100644 --- a/addons/payment_acquirer/views/payment_acquirer.xml +++ b/addons/payment_acquirer/views/payment_acquirer.xml @@ -38,10 +38,10 @@
- This is an HTML form template to submit a payment through this acquirer. - The template will be rendered with qWeb, so it may use qWeb expressions. - The qWeb evaluation context provides: + This template renders the acquirer button with all necessary values. + It is be rendered with qWeb with the following evaluation context:
    +
  • tx_url: transaction URL to post the form
  • acquirer: payment.acquirer browse record
  • user: current user browse record
  • reference: the transaction reference number
  • @@ -49,7 +49,7 @@
  • amount: the transaction amount, a float
  • partner: the buyer partner browse record, not necessarily set
  • partner_values: specific values about the buyer, for example coming from a shipping form
  • -
  • tx_values: specific transaction values
  • +
  • tx_values: transaction values
  • context: the current context dictionary
@@ -112,6 +112,7 @@ + From 88b7b449cb720276cf7bce1a1d1d7b22544df790 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Wed, 4 Dec 2013 14:05:05 +0100 Subject: [PATCH 05/15] [IMP] acquirers: added support of context-based submit button customize + transaction url. Also removed all fields holding transaction URLS; calling a method should be sufficient. Also standardized acquirer buttons. bzr revid: tde@openerp.com-20131204130505-webiutb22kb7t4il --- addons/payment_acquirer_adyen/models/adyen.py | 20 +++++---- .../static/description/icon.png | Bin 11578 -> 11002 bytes .../static/src/img/adyen_icon.png | Bin 0 -> 6831 bytes .../static/src/img/logo.jpg | Bin 4095 -> 0 bytes .../static/src/img/logo.png | Bin 0 -> 11002 bytes addons/payment_acquirer_adyen/views/adyen.xml | 12 +++--- .../views/payment_acquirer.xml | 8 ++-- addons/payment_acquirer_ogone/models/ogone.py | 38 +++++------------- .../static/src/img/ogone_icon.png | Bin 0 -> 8748 bytes .../static/src/img/ogone_logo.png | Bin 8506 -> 0 bytes .../static/src/img/ogone_logo_plain.gif | Bin 3156 -> 0 bytes addons/payment_acquirer_ogone/views/ogone.xml | 10 +++-- .../views/payment_acquirer.xml | 11 ++--- .../payment_acquirer_paypal/data/paypal.xml | 2 + .../payment_acquirer_paypal/models/paypal.py | 17 ++++++-- .../static/src/img/paypal_icon.png | Bin 0 -> 7234 bytes .../views/payment_acquirer.xml | 18 +++++---- .../payment_acquirer_paypal/views/paypal.xml | 29 +++++++------ .../static/src/img/transfer_icon.png | Bin 0 -> 14605 bytes .../views/transfer.xml | 11 +++-- 20 files changed, 91 insertions(+), 85 deletions(-) create mode 100644 addons/payment_acquirer_adyen/static/src/img/adyen_icon.png delete mode 100644 addons/payment_acquirer_adyen/static/src/img/logo.jpg create mode 100644 addons/payment_acquirer_adyen/static/src/img/logo.png create mode 100644 addons/payment_acquirer_ogone/static/src/img/ogone_icon.png delete mode 100644 addons/payment_acquirer_ogone/static/src/img/ogone_logo.png delete mode 100644 addons/payment_acquirer_ogone/static/src/img/ogone_logo_plain.gif create mode 100644 addons/payment_acquirer_paypal/static/src/img/paypal_icon.png create mode 100644 addons/payment_acquirer_transfer/static/src/img/transfer_icon.png diff --git a/addons/payment_acquirer_adyen/models/adyen.py b/addons/payment_acquirer_adyen/models/adyen.py index 4ba04b1bfe4..d76419c30cb 100644 --- a/addons/payment_acquirer_adyen/models/adyen.py +++ b/addons/payment_acquirer_adyen/models/adyen.py @@ -21,26 +21,24 @@ _logger = logging.getLogger(__name__) class AcquirerAdyen(osv.Model): _inherit = 'payment.acquirer' - def _get_adyen_urls(self, cr, uid, ids, name, args, context=None): + def _get_adyen_urls(self, cr, uid, env, context=None): """ Adyen URLs - yhpp: hosted payment page: pay.shtml for single, select.shtml for multiple """ - res = {} - for acquirer in self.browse(cr, uid, ids, context=context): - qualif = acquirer.env - res[acquirer.id] = { - 'adyen_form_url': 'https://%s.adyen.com/hpp/pay.shtml' % qualif, + if env == 'prod': + return { + 'adyen_form_url': 'https://prod.adyen.com/hpp/pay.shtml', + } + else: + return { + 'adyen_form_url': 'https://test.adyen.com/hpp/pay.shtml', } - return res _columns = { 'adyen_merchant_account': fields.char('Merchant Account', required_if_provider='adyen'), 'adyen_skin_code': fields.char('Skin Code', required_if_provider='adyen'), 'adyen_skin_hmac_key': fields.char('Skin HMAC Key', required_if_provider='adyen'), - 'adyen_form_url': fields.function( - _get_adyen_urls, multi='_get_adyen_urls', - type='char', string='Transaction URL', required_if_provider='adyen'), } def _adyen_generate_merchant_sig(self, acquirer, inout, values): @@ -99,7 +97,7 @@ class AcquirerAdyen(osv.Model): def adyen_get_form_action_url(self, cr, uid, id, context=None): acquirer = self.browse(cr, uid, id, context=context) - return acquirer.adyen_form_url + return self._get_adyen_urls(cr, uid, acquirer.env, context=context)['adyen_form_url'] class TxAdyen(osv.Model): diff --git a/addons/payment_acquirer_adyen/static/description/icon.png b/addons/payment_acquirer_adyen/static/description/icon.png index ccbc55b8c5dc88dcd11a9aefb3c90979ba8b7775..e18898088552c4a82a9a6c2a1d544a99129f882b 100644 GIT binary patch literal 11002 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 ZgAq0IgczfI_lAuq0d% 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 diff --git a/addons/payment_acquirer_adyen/static/src/img/logo.png b/addons/payment_acquirer_adyen/static/src/img/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..e18898088552c4a82a9a6c2a1d544a99129f882b GIT binary patch literal 11002 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 o6hkd3Fj diff --git a/addons/payment_acquirer_adyen/views/payment_acquirer.xml b/addons/payment_acquirer_adyen/views/payment_acquirer.xml index 9b75828f315..82cc70c9972 100644 --- a/addons/payment_acquirer_adyen/views/payment_acquirer.xml +++ b/addons/payment_acquirer_adyen/views/payment_acquirer.xml @@ -7,10 +7,12 @@ payment.acquirer - - + + + + + diff --git a/addons/payment_acquirer_ogone/models/ogone.py b/addons/payment_acquirer_ogone/models/ogone.py index 7decd389e95..eed9c2cc347 100644 --- a/addons/payment_acquirer_ogone/models/ogone.py +++ b/addons/payment_acquirer_ogone/models/ogone.py @@ -25,23 +25,19 @@ _logger = logging.getLogger(__name__) class PaymentAcquirerOgone(osv.Model): _inherit = 'payment.acquirer' - def _get_ogone_urls(self, cr, uid, ids, name, args, context=None): + def _get_ogone_urls(self, cr, uid, env, context=None): """ Ogone URLS: - standard order: POST address for form-based @TDETODO: complete me """ - res = {} - for acquirer in self.browse(cr, uid, ids, context=context): - qualif = acquirer.env - res[acquirer.id] = { - 'ogone_standard_order_url': 'https://secure.ogone.com/ncol/%s/orderstandard.asp' % qualif, - 'ogone_direct_order_url': 'https://secure.ogone.com/ncol/%s/orderdirect.asp' % qualif, - 'ogone_direct_query_url': 'https://secure.ogone.com/ncol/%s/querydirect.asp' % qualif, - 'ogone_afu_agree_url': 'https://secure.ogone.com/ncol/%s/AFU_agree.asp' % qualif, - } - return res + return { + 'ogone_standard_order_url': 'https://secure.ogone.com/ncol/%s/orderstandard.asp' % env, + 'ogone_direct_order_url': 'https://secure.ogone.com/ncol/%s/orderdirect.asp' % env, + 'ogone_direct_query_url': 'https://secure.ogone.com/ncol/%s/querydirect.asp' % env, + 'ogone_afu_agree_url': 'https://secure.ogone.com/ncol/%s/AFU_agree.asp' % env, + } _columns = { 'ogone_pspid': fields.char( @@ -54,19 +50,6 @@ class PaymentAcquirerOgone(osv.Model): 'SHA Key IN', size=32, required_if_provider='ogone'), 'ogone_shakey_out': fields.char( 'SHA Key OUT', size=32, required_if_provider='ogone'), - # store ogone contact URLs -> not necessary IMHO - 'ogone_standard_order_url': fields.function( - _get_ogone_urls, type='char', multi='_get_ogone_urls', - string='Stanrd Order URL (form)'), - 'ogone_direct_order_url': fields.function( - _get_ogone_urls, type='char', multi='_get_ogone_urls', - string='Direct Order URL (2)'), - 'ogone_direct_query_url': fields.function( - _get_ogone_urls, type='char', multi='_get_ogone_urls', - string='Direct Query URL'), - 'ogone_afu_agree_url': fields.function( - _get_ogone_urls, type='char', multi='_get_ogone_urls', - string='AFU Agree URL'), } def _ogone_generate_shasign(self, acquirer, inout, values): @@ -128,7 +111,7 @@ class PaymentAcquirerOgone(osv.Model): def ogone_get_form_action_url(self, cr, uid, id, context=None): acquirer = self.browse(cr, uid, id, context=context) - return acquirer.ogone_standard_order_url + return self._get_ogone_urls(cr, uid, acquirer.env, context=context)['ogone_standard_order_url'] class PaymentTxOgone(osv.Model): @@ -140,10 +123,8 @@ class PaymentTxOgone(osv.Model): _ogone_cancel_tx_status = [1] _columns = { - 'ogone_3ds': fields.dummy('3ds Activated'), + 'ogone_3ds': fields.boolean('3DS Activated'), 'ogone_3ds_html': fields.html('3DS HTML'), - 'ogone_feedback_model': fields.char(), - 'ogone_feedback_eval': fields.char(), 'ogone_complus': fields.char('Complus'), 'ogone_payid': fields.char('PayID', help='Payment ID, generated by Ogone') } @@ -243,6 +224,7 @@ class PaymentTxOgone(osv.Model): 'PROCESS_MODE': 'CHECKANDPROCESS', } + # TODO: fix URL computation request = urllib2.Request(tx.acquirer_id.ogone_afu_agree_url, urlencode(tx_data)) result = urllib2.urlopen(request).read() diff --git a/addons/payment_acquirer_ogone/static/src/img/ogone_icon.png b/addons/payment_acquirer_ogone/static/src/img/ogone_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..f82747245290cfb9037ce32929c0b6217259405d GIT binary patch literal 8748 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 z zI<5m99IUkjRfQ~(U1B(t1m0NAK()EZc8WcO*XXz*)5ck$Gw--qov(OMk0L31A+7Ly z)i0l=D%UI`n||+_Y@;I(|Ab)$rLx`?^Y1p%+-S$kZDsB#tqQybNl5SjF#wJP}@S-@ZIl+s7iT7P;$9;VNgyYFB?*Y&5qd%Q#b9=$F z2Or_U+t(D$0ZD9}G;MTS`3ne*gbzBQ`0T!|!i!u+BEru!!!R%~YyQUq7+SR}xNG@J z)hIk)Z}+5-&{fe7uI=&*lTi2upWA9^<}Yds4I6BdH0mglp#~o|pzcxd{hqoBHTT01?yz3jbULAiqREAm_FxpvtTI>)HetJ0X z(F65M=^DUL-~Q2{+dqjXgHGUy+n0M{bXr}jPflNf>N?92Ge}i>zdryc$T3qL#2KIf zJfYth&SOW<9y42~Q9pmL<+nr(kJlq$(O?@g{OOnVOVLd;!x*X0k!fM3&KwjGs_^@v zE-q*7`*gaPm)f3}!WWJAr^K$!7?gJ1&P>u-di-ricd2zH|IGUxVr8wY616j8;4-sV z%Bry>e-^iT$6bZqXLEMO=lCZ4k7oG)1vvbVX86Bj5dSa0A^I{DlarczWwi$!@gLWL Op{AszSSxQ4@qYofbme{k literal 0 HcmV?d00001 diff --git a/addons/payment_acquirer_ogone/static/src/img/ogone_logo.png b/addons/payment_acquirer_ogone/static/src/img/ogone_logo.png deleted file mode 100644 index 89e0ef6816f571ac80547902a1fbd0a8977d9836..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8506 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 diff --git a/addons/payment_acquirer_ogone/static/src/img/ogone_logo_plain.gif b/addons/payment_acquirer_ogone/static/src/img/ogone_logo_plain.gif deleted file mode 100644 index e7833ec3b6deb848de0c1d15945802f97c8c13ab..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3156 zcmWlb`$LTR!oa`JWiCz4%rjj_y3FVzyVWLL2H}||Q^+dp$|XBuR!l<+(?X|CsbDYX9Mvp1aTg%GbY$yV}?BYC>?R zWy#5h9A)E&PhT+A{gxN+ZuI?k->t!0{clrmJf~&W`ycOoH$5Y->a$fhEkA8I*FF+i z@g%u=;F94F+J5~v+BT1)t)kM-BaJV8OFDdt+b2KH1fT87y#4zN({yReE3o_5HRas} z^)IcJjiVEv=4zVD+DD)M`Cd&88Ac}ln)>`^@>BoVhpNYKzQ6eRr+@bv|C++jbRp?f z+Rf+ie!aK0t+4SWw4b{AWNco+1GhshyK9~uxbyqe=P#C74Urcghn;@}XXt+&cw5!| z=38x>RrY;2?Ke2}9!RIaK0Vk+A({11I`#h3m$u<|bMl&Z==z}y{rL3E!8=BbX#DN@ zU-+qqQI~sCY6pI<8w7jqfz*4mv$J5o{%;FEq7VQFfhYKz|8D{qv&2Ew!7O!do+kg$ z;esPa3$;bXn(X6hEB8?DnX~80&XeUAE>>LnrwaPCp}Ml`xu!ijX7ENE{wk6SFcA#U+>IZoEHK8 zG5&6%t^NH(C*wO?wXNdi1ZNE5uUm^`K5nd%x$h7L@5pGe_U(%AxZ@WnDoG??gXZj= zkE#|cWW(YWPG3@k$oQ2x$2>NFO7!tQ(tb2C9uDs_#;#tG8N6*(H{fW?7JbP%+uR%~ zT$*8$m-F27wKhv?rqVV1ZIh zFLQOi+R`Eqp`*?s-(gJyt$FUZj%_~EM14EYLs;B?GKCJGF#kEC5>r7_M_rdS;#UN+ zyrZr*PS{$-1tJgQ{%G76tf+B%NWQwVn8yHBOIZS(!Y^5%bKDBtaflUSf|8vzdWz1X z_5h1bXbQ~2N@n#(;%7-UY$C_5JeXtr=lr(lPLcoPmh6b734s%_v{ zhG}TSO5620x;!pT0qHrLQd4qgSq^td9Eq;O5rzmG7ds#xB!Xm;s2qdq0O8msb2HCQlvQDX$c_cP*33s3$y!Q(ad5D4dW98$eP8Pwe3Q3?mL_7-bEBUnx}E zA~=uX5I3q*Vac(E?6snTaV2}|ssX3lF!w>|-04W1wzESgMr~rrhYW9Oh%xK5NTbcQ zPc}wETNxhY%J1JLw7ipo%h>)4S((t+8qfJDLKNKSHct9hiq76 z=?ta5{WwDAIZ}=T>8u=IoDjf^4u;(vz(>Er(B-$70W&pA{0lZoy4i5S zHDa#1PA+D6gpmLA%iJiJIN*HQm-oFp{_|ySczR@uLs&!vHOu<%g6k^yDL0bl>_4fM zuUe@&zYiorbw2l-Q*Jg920Os1um2>=vy?%N?(=0SwB?62U zF-=gKLSuy*%^ah0EL$V)ElVC^4#qUjl^I0we9Ydrjev;FU>_0j#`Kt;Nye8+lxVfps&6{yIp(T$Z|k{cRXD z&yRvCE(zJ<(E?#Eb{t8TX|kf~tyJ3DJplsd5`j{<5ft9nk00<8<-lbl1^(d>dcIZ< zb!usnD2lmzQUXK@4P0r)S?PnqK8A;IHGaNqPAJl@jg-U+p;jUc;uN`;h=wqyN7{W-$tR^Q9vdgJ}b2>{w z@Y9BG@8DN<^Z7C|v+v*?3QwxnI~pZ+TNCw4iaRLCu@1Wo)OsU_r0&E7K1_>wr4NhmMx}T6n<|@8~q2XUjbZ7YPsRPu9H!Ql~{ob2=!@1LvYHkM3$@8 z)SHL-4g^<7nY|rX)2@9+Z7XxGrggt&kx?2phPl}hmuXVGgee%pHumW`z7+AJbc*h} zpuy4%?@vHU7+%}Yvfavb*V)-KJQ_AR_Y!=MO$;%9b~a~z(9p!6#ojNMp=SB3dxC>x z^MxdE{A^U$ekex*6E3rh`+na+9HZ3f^>{6KXf2Z`XDakU)JO^)VEWOHCUxXHurXja zH(=B)f2FCWJnq3g4UX??xvaMf(U-gR7OjSXQj%aioI&V?#n>?5-@xQ2J)P1DHlsUl z&5>MvEo{Pz<1M^k4pT?(5D@O|<(Rnww*{nXehzN2Ag;;2U)LABtu(eUqh7PQEzf)I z1+Z(o#D*!;xKTp_Hc=&XC9>OXHVU})c>mz&hFzt`ySae!9gkvg@SB(;AFAxojs%M! z#&?)xWXp}4_sxbdR}ad1$?VesZ=x34uYCYnm>xJ{x|>CA1pkivNaRCVPuYY76)9k} zl2l9RtLf5bD2-`ku6c6hr)|?Y56v;SQhLOCIepEGPub)rL~AsT8xpXX5i+d_>}GJ zM=wl^ib{A20^+pbtgJriwd32LCZ#qeqz^Zo`QhCM2ZB&B0fZF)Jz3~IuDKxGFCcKN zVtkjqV{ww(!SzQ{5AI@ZO#d)sv$jAz?ak4Yj0@pqA`#5)Cyh*fgc$ zPVec8qklcY@oiv4FN6al=m8P*Kp(i`l6%Os3L>}oHU%bOmVRPOZY}-L9(86na8tyo zjlexLH+h=K(0Tk0z%DFyS5)3R%v?rFn+yyK9jzLd6MT(Iq{)fWv%UFc)A{F_=vs<(+{Cs?Jydz}(7);q diff --git a/addons/payment_acquirer_ogone/views/payment_acquirer.xml b/addons/payment_acquirer_ogone/views/payment_acquirer.xml index 8ec958a5351..8a64f801dce 100644 --- a/addons/payment_acquirer_ogone/views/payment_acquirer.xml +++ b/addons/payment_acquirer_ogone/views/payment_acquirer.xml @@ -7,9 +7,8 @@ payment.acquirer - - + + @@ -29,8 +28,10 @@ - + + + + diff --git a/addons/payment_acquirer_paypal/data/paypal.xml b/addons/payment_acquirer_paypal/data/paypal.xml index 117a32dd39f..15a5c4dfcf7 100644 --- a/addons/payment_acquirer_paypal/data/paypal.xml +++ b/addons/payment_acquirer_paypal/data/paypal.xml @@ -6,6 +6,8 @@ paypal test + You will be redirected to the Paypal website after cliking on the payment button.

]]>
https://www.sandbox.paypal.com/cgi-bin/webscr dummy dummy diff --git a/addons/payment_acquirer_paypal/models/paypal.py b/addons/payment_acquirer_paypal/models/paypal.py index e6b886a941b..371b4423eda 100644 --- a/addons/payment_acquirer_paypal/models/paypal.py +++ b/addons/payment_acquirer_paypal/models/paypal.py @@ -21,10 +21,22 @@ _logger = logging.getLogger(__name__) class AcquirerPaypal(osv.Model): _inherit = 'payment.acquirer' + def _get_paypal_urls(self, cr, uid, env, context=None): + """ Paypal URLS """ + if env == 'prod': + return { + 'paypal_form_url': 'https://www.sandbox.paypal.com/cgi-bin/webscr', + 'paypal_rest_url': 'https://api.sandbox.paypal.com/v1/oauth2/token', + } + else: + return { + 'paypal_form_url': 'https://www.sandbox.paypal.com/cgi-bin/webscr', + 'paypal_rest_url': 'https://api.sandbox.paypal.com/v1/oauth2/token', + } + _columns = { 'paypal_email_id': fields.char('Email ID', required_if_provider='paypal'), 'paypal_username': fields.char('Username', required_if_provider='paypal'), - 'paypal_tx_url': fields.char('Transaction URL', required_if_provider='paypal'), 'paypal_use_ipn': fields.boolean('Use IPN'), # Server 2 server 'paypal_api_enabled': fields.boolean('Use Rest API'), @@ -35,7 +47,6 @@ class AcquirerPaypal(osv.Model): } _defaults = { - 'paypal_tx_url': 'https://www.sandbox.paypal.com/cgi-bin/webscr', 'paypal_use_ipn': True, 'fees_active': False, 'fees_dom_fixed': 0.35, @@ -95,7 +106,7 @@ class AcquirerPaypal(osv.Model): def paypal_get_form_action_url(self, cr, uid, id, context=None): acquirer = self.browse(cr, uid, id, context=context) - return acquirer.paypal_tx_url + return self._get_paypal_urls(cr, uid, acquirer.env, context=context)['paypal_form_url'] def _paypal_s2s_get_access_token(self, cr, uid, ids, context=None): """ diff --git a/addons/payment_acquirer_paypal/static/src/img/paypal_icon.png b/addons/payment_acquirer_paypal/static/src/img/paypal_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..9d0534b3fa8be2714517f582868aa7364e2bf65e GIT binary patch literal 7234 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⪙mc(Ml>Jg2`XG$BjpJm>p2rGMwm*KB& zMEL0(F>axBRQ9K~K*1R!J$6GjG)-?I%-Ibe69N^L4~`aOBzu= zNt)|g>WVxQ%Z|==N)F#v`z+|UJC2{ZvXV#&b|0LHDG!P4+O{Q{%^jfsDVs-!i&oAG zI>%4MCj;0LIOR6TL?=nF^O6828qa*i5Y z1bgtlRpO*Z6mg>J>ja$kIZjJfBrwL}a2!|~*n~+JhFPQY$Ho@gfc43U9a*?7CKTAa zBHXo}GN*n@<=X^8>RV2oOANi)8Mg5@Van-zraCwPxjv@U^%W3f$X%W%_;s0>`!+=! z^`a~4n+Ek&XqVUTHkuk`z5{Fo%b8X>@0XY_hy*9X{Q?HydV70lzY2G1Khzo8j9bay z-RCLg5BY*#Taa+QGzNH4WZv_Gjir<9;%xWWGW1FmM8xePpJnP1Y|Y|`cq)`?tdav_ z!QzP@P`z*jB`x;$-E#I+b?9CHz3B(e<7VNu+L}gsV7#c8y+H$z+!uL4&wY1HFeP+A zM!xg#Z9rt#*A1y`V=G$g$d-!X)Z8)0oM@qOu`$G&D{98K5)-(hkY-wa3TYot$PsU) zjfr64E2amn1cDxtjIf>7kmu`$-ZWgg#zd#6S!gcMMp?KUSiXTq)3ol6!3%W6kM$ba zG=tq3?4spzV6MIU&C92U)<8Im&jzWHpzJt*>>k&NPx*UY*Ul>$NU`?wibTWLBtC=vZ?tl+{=dcB^F1HJ3a{yG-(GF@sbvs9f{c_dpf(r>AWyz`-8 zngXb$r?VGzdwvxb=Rk;aL1N67w@OSi-Q*}69GyKemDrH~LRB9*V?t}8NPh!R{@}CL zcstmlD8ptH_vwqOe)aJm0x@H&M`v@3QhYZ0ny72ee6=)lo^FSP<>RucS!1wyFkZ8S z4t_jeD(+h*; zRGBKNY$vd=(0!_aSM)xEGb2t&o0t5^fI)} z&w8O?9$ZtQCdyiJSBR}hur0GiOf9>o1kw;VnwcmZDquqV5gJbZD~HIFmB3z*^H>O^AWew5DK>aN)%v!(m|?P%jNy%D{2$_u?CO-csE8!nV}XWsrgF?*5NP z{#NrHn0i9yEVZZD4Y>gFHTy1e0VVpGUR|;G&cJHl5n-e=p&nb8NL0-}NGNJAQE)Y6 zx8}$yj3q4KI%cF)XiuQW7Xv)v5pBkE)_vbYafx2+(GJKN+ZOy9Ocs(@z&GOF;rmcg>Ibiw)^~CSne9E5t*7D~_v- z?SpM%$IUI{=^prg=6186K0&2lxn-rvn;$+K1o1Sy&;Zg6@y8{tf5E8Zqd!o~;b=To z&|2-o>6=)X9gV+!(Tq;h+qVuM2(HdLn=p8y4eRb-LEo5qiwqe7ig= z)+w%Ht+`6B`dDXkVckhactiRvw6gI`$2-8$QGwX%JZV zvdE?Bgq{aA{t-RT93OBsR8_gZJ3W1jek{Z`Ru z_g8cLj-bWeRZ`_w;V&T2^NJN67tif;4gPPM$2+6nq?*|uwFZ9t^zPIb=3;p2WHXHY zEkzquj((#=SglRYNENfYd@lO;7+Jm|0ny2J0_puG&LVj0|LC^r*R_9VL4;9er(tQe z{b~`}rjiy - - - - - - + + + + + + + +
diff --git a/addons/payment_acquirer_paypal/views/paypal.xml b/addons/payment_acquirer_paypal/views/paypal.xml index a6f401f6c3c..186d45fc452 100644 --- a/addons/payment_acquirer_paypal/views/paypal.xml +++ b/addons/payment_acquirer_paypal/views/paypal.xml @@ -3,16 +3,14 @@ diff --git a/addons/payment_acquirer_transfer/static/src/img/transfer_icon.png b/addons/payment_acquirer_transfer/static/src/img/transfer_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..63b10e383ec509983104972688335a9d172b672a GIT binary patch literal 14605 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 Dfgn+& literal 0 HcmV?d00001 diff --git a/addons/payment_acquirer_transfer/views/transfer.xml b/addons/payment_acquirer_transfer/views/transfer.xml index af5c6fcef0f..75912a30f42 100644 --- a/addons/payment_acquirer_transfer/views/transfer.xml +++ b/addons/payment_acquirer_transfer/views/transfer.xml @@ -3,16 +3,19 @@ From 9f0b5a7c5336d8caee319bcedeaddf30f9c0e235 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Wed, 4 Dec 2013 14:06:28 +0100 Subject: [PATCH 06/15] [IMP] website_sale: improved the choice of acquirer. Now all acquirer are displayed using a small icon; a Pay Now button is located on the right that is the next step for the payment. All acquirers are rendered with a Pay Now button, but only the currently chosen one is displayed. This allows to display several acquirers without having to do javascript-based hacks to tune the form, its action or content. bzr revid: tde@openerp.com-20131204130628-eeqpfhoqaavhv6nk --- addons/website_sale/controllers/main.py | 20 ++++++++++--------- .../static/src/js/website_sale.js | 7 ------- .../static/src/js/website_sale_payment.js | 17 +++++++--------- addons/website_sale/views/website_sale.xml | 18 +++++++++-------- 4 files changed, 28 insertions(+), 34 deletions(-) diff --git a/addons/website_sale/controllers/main.py b/addons/website_sale/controllers/main.py index f160a25cfe1..8de4712c579 100644 --- a/addons/website_sale/controllers/main.py +++ b/addons/website_sale/controllers/main.py @@ -580,21 +580,23 @@ class Ecommerce(http.Controller): # fetch all registered payment means if tx: - payment_ids = [tx.acquirer_id.id] + acquirer_ids = [tx.acquirer_id.id] else: - payment_ids = payment_obj.search(cr, SUPERUSER_ID, [('portal_published', '=', True)], context=context) - values['payments'] = payment_obj.browse(cr, uid, payment_ids, context=context) - for pay in values['payments']: - pay._content = payment_obj.render( - cr, uid, pay.id, + acquirer_ids = payment_obj.search(cr, SUPERUSER_ID, [('portal_published', '=', True)], context=context) + values['acquirers'] = payment_obj.browse(cr, uid, acquirer_ids, context=context) + render_ctx = dict(context, submit_class='btn btn-primary', submit_txt='Pay Now') + for acquirer in values['acquirers']: + render_ctx['tx_url'] = '/shop/payment/transaction/%s' % acquirer.id + acquirer.button = payment_obj.render( + cr, uid, acquirer.id, order.name, order.amount_total, - order.pricelist_id.currency_id, + order.pricelist_id.currency_id.id, partner_id=shipping_partner_id, - tx_custom_values={ + tx_values={ 'return_url': '/shop/payment/validate', }, - context=context) + context=render_ctx) return request.website.render("website_sale.payment", values) diff --git a/addons/website_sale/static/src/js/website_sale.js b/addons/website_sale/static/src/js/website_sale.js index 856c8bd1aa6..46a360c5761 100644 --- a/addons/website_sale/static/src/js/website_sale.js +++ b/addons/website_sale/static/src/js/website_sale.js @@ -7,13 +7,6 @@ $(document).ready(function () { $(".oe_website_sale .js_shipping").toggle(); }); - var $payment = $(".oe_website_sale .js_payment"); - $payment.find("input[name='payment_type']").click(function (ev) { - var payment_id = $(ev.currentTarget).val(); - $("div[data-id]", $payment).addClass("hidden"); - $("a.btn:last, div[data-id='"+payment_id+"']", $payment).removeClass("hidden"); - }); - // change for css $(document).on('mouseup', '.js_publish', function (ev) { $(ev.currentTarget).parents(".thumbnail").toggleClass("disabled"); diff --git a/addons/website_sale/static/src/js/website_sale_payment.js b/addons/website_sale/static/src/js/website_sale_payment.js index 3da753c03f9..2821f6380a1 100644 --- a/addons/website_sale/static/src/js/website_sale_payment.js +++ b/addons/website_sale/static/src/js/website_sale_payment.js @@ -1,14 +1,11 @@ $(document).ready(function () { - /* Hitting the payment button: payment transaction process begins - * We redirect the user to a custom shop page in oder to create the - * transaction. The form POST data will be used to perform the post - * query. - */ - $('input#payment_submit').on('click', function (ev) { // TDEFIXME: change input#ID to input inside payment form, less strict - var acquirer_id = $(this).closest('form').closest('div.oe_payment_acquirer').data().id || 0; - var form_action = $(this).closest("form").attr('action'); - console.log('cliking on submit for payment - redirecting from', form_action, 'to shop with acqurier_id', acquirer_id); - $(this).closest("form").attr("action", '/shop/payment/transaction/' + acquirer_id); + // When choosing an acquirer, display its Pay Now button + var $payment = $("#payment_method"); + $payment.find("input[name='acquirer']").click(function (ev) { + var payment_id = $(ev.currentTarget).val(); + $("div.oe_sale_acquirer_button[data-id]", $payment).addClass("hidden"); + $("div.oe_sale_acquirer_button[data-id='"+payment_id+"']", $payment).removeClass("hidden"); }); + }); diff --git a/addons/website_sale/views/website_sale.xml b/addons/website_sale/views/website_sale.xml index 32d43f2dafa..8b6e91c9720 100644 --- a/addons/website_sale/views/website_sale.xml +++ b/addons/website_sale/views/website_sale.xml @@ -878,20 +878,22 @@
-
+

Choose your payment method

- -