From 46055085675e2ac4626b65780e50f19f9e44e346 Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Thu, 10 Oct 2013 16:24:15 +0200 Subject: [PATCH 01/58] [ADD] payment_acquirer bzr revid: chm@openerp.com-20131010142415-3dy4chf6kithshtt --- addons/payment_acquirer/__init__.py | 23 ++++++ addons/payment_acquirer/__openerp__.py | 34 ++++++++ .../payment_acquirer/controllers/__init__.py | 1 + addons/payment_acquirer/controllers/main.py | 32 ++++++++ addons/payment_acquirer/payment_acquirer.py | 82 +++++++++++++++++++ .../payment_acquirer_data.xml | 23 ++++++ .../payment_acquirer/views/acquirer_view.xml | 63 ++++++++++++++ 7 files changed, 258 insertions(+) create mode 100644 addons/payment_acquirer/__init__.py create mode 100644 addons/payment_acquirer/__openerp__.py create mode 100644 addons/payment_acquirer/controllers/__init__.py create mode 100644 addons/payment_acquirer/controllers/main.py create mode 100644 addons/payment_acquirer/payment_acquirer.py create mode 100644 addons/payment_acquirer/payment_acquirer_data.xml create mode 100644 addons/payment_acquirer/views/acquirer_view.xml diff --git a/addons/payment_acquirer/__init__.py b/addons/payment_acquirer/__init__.py new file mode 100644 index 00000000000..e5619fd9c83 --- /dev/null +++ b/addons/payment_acquirer/__init__.py @@ -0,0 +1,23 @@ +# -*- 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 . +# +############################################################################## + +import controllers +import payment_acquirer diff --git a/addons/payment_acquirer/__openerp__.py b/addons/payment_acquirer/__openerp__.py new file mode 100644 index 00000000000..0b3aa2e89f0 --- /dev/null +++ b/addons/payment_acquirer/__openerp__.py @@ -0,0 +1,34 @@ +# -*- 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 acquirer', + 'category': 'Hidden', + 'summary': 'Payment acquirer, display and validate payments', + 'version': '0.1', + 'description': """Payment acquirer module, use to display payment method and validate the payments.""", + 'author': 'OpenERP SA', + 'data': [ + 'views/acquirer_view.xml', + 'payment_acquirer_data.xml', + ], + 'installable': True, +} diff --git a/addons/payment_acquirer/controllers/__init__.py b/addons/payment_acquirer/controllers/__init__.py new file mode 100644 index 00000000000..8ee9bae18d9 --- /dev/null +++ b/addons/payment_acquirer/controllers/__init__.py @@ -0,0 +1 @@ +import main diff --git a/addons/payment_acquirer/controllers/main.py b/addons/payment_acquirer/controllers/main.py new file mode 100644 index 00000000000..d8f7a7d8a98 --- /dev/null +++ b/addons/payment_acquirer/controllers/main.py @@ -0,0 +1,32 @@ +# -*- 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 import SUPERUSER_ID +from openerp.addons.web import http +from openerp.addons.web.http import request +from openerp.addons.website.models import website + + +class PaymentAcquirer(http.Controller): + + @website.route(['/payment_acquirer/'], type='json', auth="public") + def payment_acquirer(self, **post): + return False diff --git a/addons/payment_acquirer/payment_acquirer.py b/addons/payment_acquirer/payment_acquirer.py new file mode 100644 index 00000000000..455b0270d7f --- /dev/null +++ b/addons/payment_acquirer/payment_acquirer.py @@ -0,0 +1,82 @@ +# -*- 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 . +# +############################################################################## + +import openerp +from openerp.osv import osv, fields +from openerp.tools import float_repr + + +class type(osv.Model): + _name = 'payment.acquirer.type' + _columns = { + 'name': fields.char('Name', required=True), + } + + +class acquirer(osv.Model): + _name = 'payment.acquirer' + _description = 'Online Payment Acquirer' + + _columns = { + 'name': fields.char('Name', required=True), + 'type_id': fields.many2one('payment.acquirer.type', required=True), + 'form_template_id': fields.many2one('ir.ui.view', translate=True, required=True), + 'visible': fields.boolean('Visible', help="Make this payment acquirer available (Customer invoices, etc.)"), + } + + _defaults = { + 'visible': True, + } + + def render(self, cr, uid, ids, object, reference, currency, amount, context=None): + """ Renders the form template of the given acquirer as a qWeb template """ + view = self.pool.get("ir.ui.view") + user = self.pool.get("res.users") + precision = self.pool.get("decimal.precision").precision_get(cr, uid, 'Account') + + qweb_context = {} + qweb_context.update( + object=object, + reference=reference, + currency=currency, + amount=amount, + amount_str=float_repr(amount, precision), + user_id=user.browse(cr, uid, uid), + context=context + ) + + res = [] + for pay in self.browse(cr, uid, ids, context=context): + res[pay.id] = view.render(cr, uid, pay.form_template_id.id, qweb_context.copy(), context=context) + return res + + def validate_payement(self, cr, uid, ids, object, reference, currency, amount, context=None): + res = [] + for pay in self.browse(cr, uid, ids, context=context): + method = getattr(self, '_validate_payement_%s' % pay.type_id.name) + res[pay.id] = method(cr, uid, ids, object, reference, currency, amount, context=context) + return res + + def _validate_payement_paypal(self, cr, uid, ids, object, reference, currency, amount, context=None): + payment = "pending" # "validated" or "refused" or "pending" + retry_time = False + + return (payment, retry_time) \ No newline at end of file diff --git a/addons/payment_acquirer/payment_acquirer_data.xml b/addons/payment_acquirer/payment_acquirer_data.xml new file mode 100644 index 00000000000..6e842cab45d --- /dev/null +++ b/addons/payment_acquirer/payment_acquirer_data.xml @@ -0,0 +1,23 @@ + + + + + paypal + + + + Paypal + +
+ + + + + + +
+
+ +
+
+
diff --git a/addons/payment_acquirer/views/acquirer_view.xml b/addons/payment_acquirer/views/acquirer_view.xml new file mode 100644 index 00000000000..b6f783f82ec --- /dev/null +++ b/addons/payment_acquirer/views/acquirer_view.xml @@ -0,0 +1,63 @@ + + + + + payment.acquirer + +
+ +
+
+ +
+

+ 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: +

    +
  • reference: the reference number of the document to pay
  • +
  • currency: the currency record in which the document is issued (e.g. currency.name could be EUR)
  • +
  • amount: the total amount to pay, as a float
  • +
  • amount_str: the total amount to pay, as a string with the account precision
  • +
  • object: the browse record on which the payment form is rendered (usually an invoice or sales order record)
  • +
  • user_id: the current user browse record
  • +
  • context: the current context dictionary
  • +
+ If the template renders to an empty result in a certain context it will be ignored, as if it was inactive. +

+
+ +
+
+
+
+
+ + payment.acquirer + + + + + + + + + portal.payment.acquirer + + + + + + + + + + Payment Acquirers + payment.acquirer + + + +
+
From 74d22347653476b643c705a9c2c91bec558c8aea Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Thu, 10 Oct 2013 16:26:37 +0200 Subject: [PATCH 02/58] [WIP] bzr revid: chm@openerp.com-20131010142637-oz1lk2nsmnebrlsn --- addons/payment_acquirer/payment_acquirer.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/addons/payment_acquirer/payment_acquirer.py b/addons/payment_acquirer/payment_acquirer.py index 455b0270d7f..f598f768b95 100644 --- a/addons/payment_acquirer/payment_acquirer.py +++ b/addons/payment_acquirer/payment_acquirer.py @@ -48,7 +48,6 @@ class acquirer(osv.Model): def render(self, cr, uid, ids, object, reference, currency, amount, context=None): """ Renders the form template of the given acquirer as a qWeb template """ - view = self.pool.get("ir.ui.view") user = self.pool.get("res.users") precision = self.pool.get("decimal.precision").precision_get(cr, uid, 'Account') @@ -65,7 +64,7 @@ class acquirer(osv.Model): res = [] for pay in self.browse(cr, uid, ids, context=context): - res[pay.id] = view.render(cr, uid, pay.form_template_id.id, qweb_context.copy(), context=context) + res[pay.id] = pay.form_template_id.render(qweb_context.copy(), context=context) return res def validate_payement(self, cr, uid, ids, object, reference, currency, amount, context=None): From 70a28e97b46110428e6e14b91dba240d968148fa Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Thu, 10 Oct 2013 17:54:47 +0200 Subject: [PATCH 03/58] [WIP] bzr revid: chm@openerp.com-20131010155447-b0ys8arhhbhb211e --- addons/payment_acquirer/payment_acquirer.py | 5 ++- .../payment_acquirer_data.xml | 34 +++++++++++++------ 2 files changed, 28 insertions(+), 11 deletions(-) diff --git a/addons/payment_acquirer/payment_acquirer.py b/addons/payment_acquirer/payment_acquirer.py index f598f768b95..e0f0aaf2922 100644 --- a/addons/payment_acquirer/payment_acquirer.py +++ b/addons/payment_acquirer/payment_acquirer.py @@ -78,4 +78,7 @@ class acquirer(osv.Model): payment = "pending" # "validated" or "refused" or "pending" retry_time = False - return (payment, retry_time) \ No newline at end of file + return (payment, retry_time) + + def _validate_payement_virement(self, cr, uid, ids, object, reference, currency, amount, context=None): + return ("pending", False) diff --git a/addons/payment_acquirer/payment_acquirer_data.xml b/addons/payment_acquirer/payment_acquirer_data.xml index 6e842cab45d..b857a41e38b 100644 --- a/addons/payment_acquirer/payment_acquirer_data.xml +++ b/addons/payment_acquirer/payment_acquirer_data.xml @@ -4,20 +4,34 @@ paypal + + virement + Paypal - -
- - - - - - -
-
+ + + + + + + + + ]]>
+ + + Virement + + Numero de compte: + Communication: + + ]]> + + From 6e4c0f9068e518d1cab9c94f7dcfc11daec092e1 Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Wed, 16 Oct 2013 17:08:37 +0200 Subject: [PATCH 04/58] [WIP] website_sale use payment_acquirer bzr revid: chm@openerp.com-20131016150837-1zo80gd1pmlvy2im --- addons/payment_acquirer/__openerp__.py | 1 + addons/payment_acquirer/payment_acquirer.py | 22 ++++--- .../payment_acquirer_data.xml | 57 +++++++++++-------- .../payment_acquirer/views/acquirer_view.xml | 2 +- addons/website_sale/__openerp__.py | 2 +- addons/website_sale/controllers/main.py | 4 +- .../static/src/js/website_sale.js | 6 +- addons/website_sale/views/website_sale.xml | 24 +++++--- 8 files changed, 72 insertions(+), 46 deletions(-) diff --git a/addons/payment_acquirer/__openerp__.py b/addons/payment_acquirer/__openerp__.py index 0b3aa2e89f0..b4c5d552696 100644 --- a/addons/payment_acquirer/__openerp__.py +++ b/addons/payment_acquirer/__openerp__.py @@ -26,6 +26,7 @@ 'version': '0.1', 'description': """Payment acquirer module, use to display payment method and validate the payments.""", 'author': 'OpenERP SA', + 'depends': ['website', 'decimal_precision'], 'data': [ 'views/acquirer_view.xml', 'payment_acquirer_data.xml', diff --git a/addons/payment_acquirer/payment_acquirer.py b/addons/payment_acquirer/payment_acquirer.py index e0f0aaf2922..55a3cf6f023 100644 --- a/addons/payment_acquirer/payment_acquirer.py +++ b/addons/payment_acquirer/payment_acquirer.py @@ -24,21 +24,21 @@ from openerp.osv import osv, fields from openerp.tools import float_repr -class type(osv.Model): +class type(osv.osv): _name = 'payment.acquirer.type' _columns = { 'name': fields.char('Name', required=True), } -class acquirer(osv.Model): +class acquirer(osv.osv): _name = 'payment.acquirer' _description = 'Online Payment Acquirer' _columns = { 'name': fields.char('Name', required=True), 'type_id': fields.many2one('payment.acquirer.type', required=True), - 'form_template_id': fields.many2one('ir.ui.view', translate=True, required=True), + 'form_template_id': fields.many2one('ir.ui.view', required=True), 'visible': fields.boolean('Visible', help="Make this payment acquirer available (Customer invoices, etc.)"), } @@ -51,6 +51,9 @@ class acquirer(osv.Model): user = self.pool.get("res.users") precision = self.pool.get("decimal.precision").precision_get(cr, uid, 'Account') + if not context: + context = {} + qweb_context = {} qweb_context.update( object=object, @@ -62,10 +65,15 @@ class acquirer(osv.Model): context=context ) - res = [] - for pay in self.browse(cr, uid, ids, context=context): - res[pay.id] = pay.form_template_id.render(qweb_context.copy(), context=context) - return res + pays = self.browse(cr, uid, ids, context=context) + + if isinstance(ids, list): + res = [] + for pay in pays: + res[pay.id] = pay.form_template_id.render(qweb_context.copy(), engine='ir.qweb', context=context) + return res + else: + return pays.form_template_id.render(qweb_context, engine='ir.qweb', context=context) def validate_payement(self, cr, uid, ids, object, reference, currency, amount, context=None): res = [] diff --git a/addons/payment_acquirer/payment_acquirer_data.xml b/addons/payment_acquirer/payment_acquirer_data.xml index b857a41e38b..62ba7a2530a 100644 --- a/addons/payment_acquirer/payment_acquirer_data.xml +++ b/addons/payment_acquirer/payment_acquirer_data.xml @@ -1,37 +1,48 @@ - + paypal + + + + + + + Paypal + + + + + + virement - - Paypal - - - - - - - - - ]]> - - + - + Virement - - Numero de compte: - Communication: - - ]]> - + + diff --git a/addons/payment_acquirer/views/acquirer_view.xml b/addons/payment_acquirer/views/acquirer_view.xml index b6f783f82ec..d5dfc88c537 100644 --- a/addons/payment_acquirer/views/acquirer_view.xml +++ b/addons/payment_acquirer/views/acquirer_view.xml @@ -44,7 +44,7 @@ - portal.payment.acquirer + payment.acquirer diff --git a/addons/website_sale/__openerp__.py b/addons/website_sale/__openerp__.py index 634078fe149..f3e370d989d 100644 --- a/addons/website_sale/__openerp__.py +++ b/addons/website_sale/__openerp__.py @@ -9,7 +9,7 @@ OpenERP E-Commerce """, 'author': 'OpenERP SA', - 'depends': ['website', 'sale', 'product'], + 'depends': ['website', 'sale', 'product', 'payment_acquirer'], 'data': [ 'website_sale_data.xml', 'views/website_sale.xml', diff --git a/addons/website_sale/controllers/main.py b/addons/website_sale/controllers/main.py index 8756b6f6722..32fb9d28ca9 100644 --- a/addons/website_sale/controllers/main.py +++ b/addons/website_sale/controllers/main.py @@ -624,12 +624,12 @@ class Ecommerce(http.Controller): 'order': order } - payment_obj = request.registry.get('portal.payment.acquirer') + payment_obj = request.registry.get('payment.acquirer') payment_ids = payment_obj.search(request.cr, SUPERUSER_ID, [('visible', '=', True)], context=request.context) values['payments'] = payment_obj.browse(request.cr, SUPERUSER_ID, payment_ids, request.context) for payment in values['payments']: content = payment_obj.render(request.cr, SUPERUSER_ID, payment.id, order, order.name, order.pricelist_id.currency_id, order.amount_total) - payment._content = content + payment._content = content.strip() 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 ab10c04ad9b..78aa6042b5c 100644 --- a/addons/website_sale/static/src/js/website_sale.js +++ b/addons/website_sale/static/src/js/website_sale.js @@ -58,11 +58,11 @@ $(document).ready(function () { $('form.js_add_cart_json label').on('mouseup', function (ev) { ev.preventDefault(); var $label = $(ev.currentTarget); - var $price = $label.parent("form").find(".oe_price"); + var $price = $label.parent("form").find(".oe_price .oe_currency_value"); if (!$price.data("price")) { - $price.data("price", parseFloat($price.html())); + $price.data("price", parseFloat($price.text())); } - $price.html($price.data("price")+parseFloat($label.find(".badge span").html() || 0)); + $price.html($price.data("price")+parseFloat($label.find(".badge span").text() || 0)); }); $(document).on('click', '.js_publish_management .js_go_to_top,.js_publish_management .js_go_to_bottom', function (event) { diff --git a/addons/website_sale/views/website_sale.xml b/addons/website_sale/views/website_sale.xml index a263a01ed2e..b7a053b2599 100644 --- a/addons/website_sale/views/website_sale.xml +++ b/addons/website_sale/views/website_sale.xml @@ -286,14 +286,20 @@

- € - - - € -   +
-

€

+
@@ -866,13 +872,13 @@

Select your payment method:

- -
- + diff --git a/addons/website_sale/controllers/main.py b/addons/website_sale/controllers/main.py index 32fb9d28ca9..8d31ff54159 100644 --- a/addons/website_sale/controllers/main.py +++ b/addons/website_sale/controllers/main.py @@ -613,31 +613,63 @@ class Ecommerce(http.Controller): return request.redirect("/shop/payment/") @website.route(['/shop/payment/'], type='http', auth="public", multilang=True) - def payment(self, **post): + def payment(self, payment_acquirer_id=None, **post): + payment_obj = request.registry.get('payment.acquirer') order = get_current_order() if not order or not order.order_line: - return self.mycart(**post) + return request.redirect("/shop/checkout/") values = { 'partner': False, + 'payment_acquirer_id': payment_acquirer_id, 'order': order } - payment_obj = request.registry.get('payment.acquirer') - payment_ids = payment_obj.search(request.cr, SUPERUSER_ID, [('visible', '=', True)], context=request.context) - values['payments'] = payment_obj.browse(request.cr, SUPERUSER_ID, payment_ids, request.context) - for payment in values['payments']: - content = payment_obj.render(request.cr, SUPERUSER_ID, payment.id, order, order.name, order.pricelist_id.currency_id, order.amount_total) - payment._content = content.strip() + if payment_acquirer_id: + values['validation'] = self.payment_validation(payment_acquirer_id) + if values['validation'][0] == "validated" or (values['validation'][0] == "pending" and values['validation'][1] == False): + return request.redirect("/shop/confirmation/") + elif values['validation'][0] == "refused": + values['payment_acquirer_id'] = None + + if not values['payment_acquirer_id']: + payment_ids = payment_obj.search(request.cr, SUPERUSER_ID, [('visible', '=', True)], context=request.context) + values['payments'] = payment_obj.browse(request.cr, request.uid, payment_ids, context=request.context) + for pay in values['payments']: + pay._content = payment_obj.render(request.cr, request.uid, pay.id, + object=order, + reference=order.name, + currency=order.pricelist_id.currency_id, + amount=order.amount_total, + cancel_url=request.httprequest.base_url, + return_url="%sshop/payment/?payment_acquirer_id=%s" % (request.httprequest.host_url, pay.id), + context=request.context) return request.website.render("website_sale.payment", values) - @website.route(['/shop/payment_validate/'], type='http', auth="public", multilang=True) - def payment_validate(self, **post): + @website.route(['/shop/payment_validation/'], type='json', auth="public", multilang=True) + def payment_validation(self, payment_acquirer_id=None): + payment_obj = request.registry.get('payment.acquirer') + order = get_current_order() + return payment_obj.validate_payement(request.cr, request.uid, int(payment_acquirer_id), + object=order, + reference=order.name, + currency=order.pricelist_id.currency_id, + amount=order.amount_total, + context=request.context) + + @website.route(['/shop/confirmation/'], type='http', auth="public", multilang=True) + def confirmation(self, **post): + order = get_current_order() + + if not order or not order.order_line: + return request.redirect("/shop/") + + res = request.website.render("website_sale.confirmation", {'order': order}) request.httprequest.session['ecommerce_order_id'] = False request.httprequest.session['ecommerce_pricelist'] = False - return request.redirect("/shop/") + return res @website.route(['/shop/change_sequence/'], type='json', auth="public") def change_sequence(self, id, top): diff --git a/addons/website_sale/models/product_attributes.py b/addons/website_sale/models/product_attributes.py index e89763946f8..57657968daa 100644 --- a/addons/website_sale/models/product_attributes.py +++ b/addons/website_sale/models/product_attributes.py @@ -35,8 +35,8 @@ class attributes(osv.Model): 'value_ids': fields.one2many('product.attribute.value', 'attribute_id', 'Values'), 'product_ids': fields.one2many('product.attribute.product', 'attribute_id', 'Products'), - 'float_max': fields.function(_get_float_max, type='float', string="Max", relation='product.attribute.product',store=True), - 'float_min': fields.function(_get_float_min, type='float', string="Min", relation='product.attribute.product',store=True), + 'float_max': fields.function(_get_float_max, type='float', string="Max", relation='product.attribute.product'), + 'float_min': fields.function(_get_float_min, type='float', string="Min", relation='product.attribute.product'), } _defaults = { 'type': 'distinct' diff --git a/addons/website_sale/views/website_sale.xml b/addons/website_sale/views/website_sale.xml index b7a053b2599..de8738cc610 100644 --- a/addons/website_sale/views/website_sale.xml +++ b/addons/website_sale/views/website_sale.xml @@ -789,7 +789,7 @@

Validate Order

-
+
@@ -869,7 +869,7 @@ -
+

Select your payment method:

@@ -881,9 +881,115 @@ +
+ Please wait, we validate your payment. +
+ +
+
+ +
+
+
+ + + + + - Paypal + paypal - - virement - - - Virement + virement diff --git a/addons/product/product.py b/addons/product/product.py index 7216b88b33f..82afbcab6b1 100644 --- a/addons/product/product.py +++ b/addons/product/product.py @@ -642,6 +642,7 @@ class product_product(osv.osv): _table = "product_product" _inherits = {'product.template': 'product_tmpl_id'} _inherit = ['mail.thread'] + _inherit = ['mail.thread'] _order = 'default_code,name_template' _columns = { 'qty_available': fields.function(_product_qty_available, type='float', string='Quantity On Hand'), diff --git a/addons/website_sale/views/website_sale.xml b/addons/website_sale/views/website_sale.xml index de8738cc610..41e4663e3b6 100644 --- a/addons/website_sale/views/website_sale.xml +++ b/addons/website_sale/views/website_sale.xml @@ -230,7 +230,7 @@
From 367190fc82368d0415c3056a824f3ac4bbfde483 Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Fri, 18 Oct 2013 14:11:23 +0200 Subject: [PATCH 07/58] [ADD] payment_acquirer controllers bzr revid: chm@openerp.com-20131018121123-or4sxzu1jdv5tjbd --- .../payment_acquirer/controllers/__init__.py | 1 + addons/payment_acquirer/controllers/main.py | 32 +++++++++++++++++++ .../security/ir.model.access.csv | 1 + 3 files changed, 34 insertions(+) create mode 100644 addons/payment_acquirer/controllers/__init__.py create mode 100644 addons/payment_acquirer/controllers/main.py create mode 100644 addons/payment_acquirer/security/ir.model.access.csv diff --git a/addons/payment_acquirer/controllers/__init__.py b/addons/payment_acquirer/controllers/__init__.py new file mode 100644 index 00000000000..039d9715fab --- /dev/null +++ b/addons/payment_acquirer/controllers/__init__.py @@ -0,0 +1 @@ +import main \ No newline at end of file diff --git a/addons/payment_acquirer/controllers/main.py b/addons/payment_acquirer/controllers/main.py new file mode 100644 index 00000000000..1aa84ebdbbc --- /dev/null +++ b/addons/payment_acquirer/controllers/main.py @@ -0,0 +1,32 @@ +# -*- 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 website_project(http.Controller): + + @website.route(['/payment_acquirer//'], type='http', auth="public") + def project(self, acquirer=None, **post): + obj = request.registry['payment.acquirer'] + return obj.transaction_feedback(request.cr, request.uid, acquirer, context=request.context, **post) diff --git a/addons/payment_acquirer/security/ir.model.access.csv b/addons/payment_acquirer/security/ir.model.access.csv new file mode 100644 index 00000000000..97dd8b917b8 --- /dev/null +++ b/addons/payment_acquirer/security/ir.model.access.csv @@ -0,0 +1 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink From 005a00ad509cabf9e184ee9eff61979c3020869b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Thu, 24 Oct 2013 15:58:54 +0200 Subject: [PATCH 08/58] [REF] payment_acquirer: refactored module according to new OpenERP addon guidelines : - models -> for model-related files - data -> all data Updated init / openerp files accordingly bzr revid: tde@openerp.com-20131024135854-ve8d5yw1umcwz2b0 --- addons/payment_acquirer/__init__.py | 2 +- addons/payment_acquirer/__openerp__.py | 4 ++-- .../{ => data}/payment_acquirer_data.xml | 0 addons/payment_acquirer/models/__init__.py | 22 +++++++++++++++++++ .../{ => models}/payment_acquirer.py | 0 5 files changed, 25 insertions(+), 3 deletions(-) rename addons/payment_acquirer/{ => data}/payment_acquirer_data.xml (100%) create mode 100644 addons/payment_acquirer/models/__init__.py rename addons/payment_acquirer/{ => models}/payment_acquirer.py (100%) diff --git a/addons/payment_acquirer/__init__.py b/addons/payment_acquirer/__init__.py index 8de510372ee..dde6f25c728 100644 --- a/addons/payment_acquirer/__init__.py +++ b/addons/payment_acquirer/__init__.py @@ -19,5 +19,5 @@ # ############################################################################## -import payment_acquirer +import models import controllers diff --git a/addons/payment_acquirer/__openerp__.py b/addons/payment_acquirer/__openerp__.py index 4ea55f6befb..1452489c876 100644 --- a/addons/payment_acquirer/__openerp__.py +++ b/addons/payment_acquirer/__openerp__.py @@ -26,10 +26,10 @@ 'version': '0.1', 'description': """Payment acquirer module, use to display payment method and validate the payments.""", 'author': 'OpenERP SA', - 'depends': ['website', 'decimal_precision'], + 'depends': ['decimal_precision'], 'data': [ 'views/acquirer_view.xml', - 'payment_acquirer_data.xml', + 'data/payment_acquirer_data.xml', 'security/ir.model.access.csv', ], 'installable': True, diff --git a/addons/payment_acquirer/payment_acquirer_data.xml b/addons/payment_acquirer/data/payment_acquirer_data.xml similarity index 100% rename from addons/payment_acquirer/payment_acquirer_data.xml rename to addons/payment_acquirer/data/payment_acquirer_data.xml diff --git a/addons/payment_acquirer/models/__init__.py b/addons/payment_acquirer/models/__init__.py new file mode 100644 index 00000000000..0ce2de595b2 --- /dev/null +++ b/addons/payment_acquirer/models/__init__.py @@ -0,0 +1,22 @@ +# -*- 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 . +# +############################################################################## + +import payment_acquirer diff --git a/addons/payment_acquirer/payment_acquirer.py b/addons/payment_acquirer/models/payment_acquirer.py similarity index 100% rename from addons/payment_acquirer/payment_acquirer.py rename to addons/payment_acquirer/models/payment_acquirer.py From 25d3f4b1a51d04386a9f0f535d3f176aad354a05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Thu, 24 Oct 2013 16:20:50 +0200 Subject: [PATCH 09/58] [ADD] [CLEAN] payment_acquirer: - lint / cleanup of models/payment_acquirer.py. No changes made, only link cleanup such as missing imports, typos, missing methods. Added ogone_errors file containing the ogone errors description that was called but missing in the module. It is taken from openerp-custom module. bzr revid: tde@openerp.com-20131024142050-a9b9tjzw9y5qjhia --- .../payment_acquirer/models/ogone_errors.py | 497 ++++++++++++++++++ .../models/payment_acquirer.py | 67 ++- 2 files changed, 546 insertions(+), 18 deletions(-) create mode 100644 addons/payment_acquirer/models/ogone_errors.py diff --git a/addons/payment_acquirer/models/ogone_errors.py b/addons/payment_acquirer/models/ogone_errors.py new file mode 100644 index 00000000000..3a2500ee24b --- /dev/null +++ b/addons/payment_acquirer/models/ogone_errors.py @@ -0,0 +1,497 @@ +# -*- coding: utf-8 -*- + +OGONE_ERROR_MAP = { + '0020001001': "Authorization failed, please retry", + '0020001002': "Authorization failed, please retry", + '0020001003': "Authorization failed, please retry", + '0020001004': "Authorization failed, please retry", + '0020001005': "Authorization failed, please retry", + '0020001006': "Authorization failed, please retry", + '0020001007': "Authorization failed, please retry", + '0020001008': "Authorization failed, please retry", + '0020001009': "Authorization failed, please retry", + '0020001010': "Authorization failed, please retry", + '0030001999': "Our payment system is currently under maintenance, please try later", + '0050001005': "Expiry date error", + '0050001007': "Requested Operation code not allowed", + '0050001008': "Invalid delay value", + '0050001010': "Input date in invalid format", + '0050001013': "Unable to parse socket input stream", + '0050001014': "Error in parsing stream content", + '0050001015': "Currency error", + '0050001016': "Transaction still posted at end of wait", + '0050001017': "Sync value not compatible with delay value", + '0050001019': "Transaction duplicate of a pre-existing transaction", + '0050001020': "Acceptation code empty while required for the transaction", + '0050001024': "Maintenance acquirer differs from original transaction acquirer", + '0050001025': "Maintenance merchant differs from original transaction merchant", + '0050001028': "Maintenance operation not accurate for the original transaction", + '0050001031': "Host application unknown for the transaction", + '0050001032': "Unable to perform requested operation with requested currency", + '0050001033': "Maintenance card number differs from original transaction card number", + '0050001034': "Operation code not allowed", + '0050001035': "Exception occurred in socket input stream treatment", + '0050001036': "Card length does not correspond to an acceptable value for the brand", + '0050001036': "Card length does not correspond to an acceptable value for the brand", + '0050001068': "A technical problem occurred, please contact helpdesk", + '0050001069': "Invalid check for CardID and Brand", + '0050001070': "A technical problem occurred, please contact helpdesk", + '0050001116': "Unknown origin IP", + '0050001117': "No origin IP detected", + '0050001118': "Merchant configuration problem, please contact support", + '10001001': "Communication failure", + '10001002': "Communication failure", + '10001003': "Communication failure", + '10001004': "Communication failure", + '10001005': "Communication failure", + '20001001': "We received an unknown status for the transaction. We will contact your acquirer and update the status of the transaction within one working day. Please check the status later.", + '20001002': "We received an unknown status for the transaction. We will contact your acquirer and update the status of the transaction within one working day. Please check the status later.", + '20001003': "We received an unknown status for the transaction. We will contact your acquirer and update the status of the transaction within one working day. Please check the status later.", + '20001004': "We received an unknown status for the transaction. We will contact your acquirer and update the status of the transaction within one working day. Please check the status later.", + '20001005': "We received an unknown status for the transaction. We will contact your acquirer and update the status of the transaction within one working day. Please check the status later.", + '20001006': "We received an unknown status for the transaction. We will contact your acquirer and update the status of the transaction within one working day. Please check the status later.", + '20001007': "We received an unknown status for the transaction. We will contact your acquirer and update the status of the transaction within one working day. Please check the status later.", + '20001008': "We received an unknown status for the transaction. We will contact your acquirer and update the status of the transaction within one working day. Please check the status later.", + '20001009': "We received an unknown status for the transaction. We will contact your acquirer and update the status of the transaction within one working day. Please check the status later.", + '20001010': "We received an unknown status for the transaction. We will contact your acquirer and update the status of the transaction within one working day. Please check the status later.", + '20001101': "A technical problem occurred, please contact helpdesk", + '20001105': "We received an unknown status for the transaction. We will contact your acquirer and update the status of the transaction within one working day. Please check the status later.", + '20001111': "A technical problem occurred, please contact helpdesk", + '20002001': "Origin for the response of the bank can not be checked", + '20002002': "Beneficiary account number has been modified during processing", + '20002003': "Amount has been modified during processing", + '20002004': "Currency has been modified during processing", + '20002005': "No feedback from the bank server has been detected", + '30001001': "Payment refused by the acquirer", + '30001002': "Duplicate request", + '30001010': "A technical problem occurred, please contact helpdesk", + '30001011': "A technical problem occurred, please contact helpdesk", + '30001012': "Card black listed - Contact acquirer", + '30001015': "Your merchant's acquirer is temporarily unavailable, please try later or choose another payment method.", + '30001051': "A technical problem occurred, please contact helpdesk", + '30001054': "A technical problem occurred, please contact helpdesk", + '30001057': "Your merchant's acquirer is temporarily unavailable, please try later or choose another payment method.", + '30001058': "Your merchant's acquirer is temporarily unavailable, please try later or choose another payment method.", + '30001060': "Aquirer indicates that a failure occured during payment processing", + '30001070': "RATEPAY Invalid Response Type (Failure)", + '30001071': "RATEPAY Missing Mandatory status code field (failure)", + '30001072': "RATEPAY Missing Mandatory Result code field (failure)", + '30001073': "RATEPAY Response parsing Failed", + '30001090': "CVC check required by front end and returned invalid by acquirer", + '30001091': "ZIP check required by front end and returned invalid by acquirer", + '30001092': "Address check required by front end and returned as invalid by acquirer.", + '30001100': "Unauthorized buyer's country", + '30001101': "IP country <> card country", + '30001102': "Number of different countries too high", + '30001103': "unauthorized card country", + '30001104': "unauthorized ip address country", + '30001105': "Anonymous proxy", + '30001110': "If the problem persists, please contact Support, or go to paysafecard's card balance page (https://customer.cc.at.paysafecard.com/psccustomer/GetWelcomePanelServlet?language=en) to see when the amount reserved on your card will be available again.", + '30001120': "IP address in merchant's black list", + '30001130': "BIN in merchant's black list", + '30001131': "Wrong BIN for 3xCB", + '30001140': "Card in merchant's card blacklist", + '30001141': "Email in blacklist", + '30001142': "Passenger name in blacklist", + '30001143': "Card holder name in blacklist", + '30001144': "Passenger name different from owner name", + '30001145': "Time to departure too short", + '30001149': "Card Configured in Card Supplier Limit for another relation (CSL)", + '30001150': "Card not configured in the system for this customer (CSL)", + '30001151': "REF1 not allowed for this relationship (Contract number", + '30001152': "Card/Supplier Amount limit reached (CSL)", + '30001153': "Card not allowed for this supplier (Date out of contract bounds)", + '30001154': "You have reached the usage limit allowed", + '30001155': "You have reached the usage limit allowed", + '30001156': "You have reached the usage limit allowed", + '30001157': "Unauthorized IP country for itinerary", + '30001158': "email usage limit reached", + '30001159': "Unauthorized card country/IP country combination", + '30001160': "Postcode in highrisk group", + '30001161': "generic blacklist match", + '30001162': "Billing Address is a PO Box", + '30001180': "maximum scoring reached", + '30001997': "Authorization canceled by simulation", + '30001998': "A technical problem occurred, please try again.", + '30001999': "Your merchant's acquirer is temporarily unavailable, please try later or choose another payment method.", + '30002001': "Payment refused by the financial institution", + '30002001': "Payment refused by the financial institution", + '30021001': "Call acquirer support call number.", + '30022001': "Payment must be approved by the acquirer before execution.", + '30031001': "Invalid merchant number.", + '30041001': "Retain card.", + '30051001': "Authorization declined", + '30071001': "Retain card - special conditions.", + '30121001': "Invalid transaction", + '30131001': "Invalid amount", + '30131002': "You have reached the total amount allowed", + '30141001': "Invalid card number", + '30151001': "Unknown acquiring institution.", + '30171001': "Payment method cancelled by the buyer", + '30171002': "The maximum time allowed is elapsed.", + '30191001': "Try again later.", + '30201001': "A technical problem occurred, please contact helpdesk", + '30301001': "Invalid format", + '30311001': "Unknown acquirer ID.", + '30331001': "Card expired.", + '30341001': "Suspicion of fraud.", + '30341002': "Suspicion of fraud (3rdMan)", + '30341003': "Suspicion of fraud (Perseuss)", + '30341004': "Suspicion of fraud (ETHOCA)", + '30381001': "A technical problem occurred, please contact helpdesk", + '30401001': "Invalid function.", + '30411001': "Lost card.", + '30431001': "Stolen card, pick up", + '30511001': "Insufficient funds.", + '30521001': "No Authorization. Contact the issuer of your card.", + '30541001': "Card expired.", + '30551001': "Invalid PIN.", + '30561001': "Card not in authorizer's database.", + '30571001': "Transaction not permitted on card.", + '30581001': "Transaction not allowed on this terminal", + '30591001': "Suspicion of fraud.", + '30601001': "The merchant must contact the acquirer.", + '30611001': "Amount exceeds card ceiling.", + '30621001': "Restricted card.", + '30631001': "Security policy not respected.", + '30641001': "Amount changed from ref. trn.", + '30681001': "Tardy response.", + '30751001': "PIN entered incorrectly too often", + '30761001': "Card holder already contesting.", + '30771001': "PIN entry required.", + '30811001': "Message flow error.", + '30821001': "Authorization center unavailable", + '30831001': "Authorization center unavailable", + '30901001': "Temporary system shutdown.", + '30911001': "Acquirer unavailable.", + '30921001': "Invalid card type for acquirer.", + '30941001': "Duplicate transaction", + '30961001': "Processing temporarily not possible", + '30971001': "A technical problem occurred, please contact helpdesk", + '30981001': "A technical problem occurred, please contact helpdesk", + '31011001': "Unknown acceptance code", + '31021001': "Invalid currency", + '31031001': "Acceptance code missing", + '31041001': "Inactive card", + '31051001': "Merchant not active", + '31061001': "Invalid expiration date", + '31071001': "Interrupted host communication", + '31081001': "Card refused", + '31091001': "Invalid password", + '31101001': "Plafond transaction (majoré du bonus) dépassé", + '31111001': "Plafond mensuel (majoré du bonus) dépassé", + '31121001': "Plafond centre de facturation dépassé", + '31131001': "Plafond entreprise dépassé", + '31141001': "Code MCC du fournisseur non autorisé pour la carte", + '31151001': "Numéro SIRET du fournisseur non autorisé pour la carte", + '31161001': "This is not a valid online banking account", + '32001004': "A technical problem occurred, please try again.", + '34011001': "Bezahlung mit RatePAY nicht möglich.", + '39991001': "A technical problem occurred, please contact the helpdesk of your acquirer", + '40001001': "A technical problem occurred, please try again.", + '40001002': "A technical problem occurred, please try again.", + '40001003': "A technical problem occurred, please try again.", + '40001004': "A technical problem occurred, please try again.", + '40001005': "A technical problem occurred, please try again.", + '40001006': "A technical problem occurred, please try again.", + '40001007': "A technical problem occurred, please try again.", + '40001008': "A technical problem occurred, please try again.", + '40001009': "A technical problem occurred, please try again.", + '40001010': "A technical problem occurred, please try again.", + '40001011': "A technical problem occurred, please contact helpdesk", + '40001012': "Your merchant's acquirer is temporarily unavailable, please try later or choose another payment method.", + '40001013': "A technical problem occurred, please contact helpdesk", + '40001016': "A technical problem occurred, please contact helpdesk", + '40001018': "A technical problem occurred, please try again.", + '40001019': "Sorry, an error occurred during processing. Please retry the operation (use back button of the browser). If problem persists, contact your merchant's helpdesk.", + '40001020': "Sorry, an error occurred during processing. Please retry the operation (use back button of the browser). If problem persists, contact your merchant's helpdesk.", + '40001050': "A technical problem occurred, please contact helpdesk", + '40001133': "Authentication failed, the signature of your bank access control server is incorrect", + '40001134': "Authentication failed, please retry or cancel.", + '40001135': "Authentication temporary unavailable, please retry or cancel.", + '40001136': "Technical problem with your browser, please retry or cancel", + '40001137': "Your bank access control server is temporary unavailable, please retry or cancel", + '40001998': "Temporary technical problem. Please retry a little bit later.", + '50001001': "Unknown card type", + '50001002': "Card number format check failed for given card number.", + '50001003': "Merchant data error", + '50001004': "Merchant identification missing", + '50001005': "Expiry date error", + '50001006': "Amount is not a number", + '50001007': "A technical problem occurred, please contact helpdesk", + '50001008': "A technical problem occurred, please contact helpdesk", + '50001009': "A technical problem occurred, please contact helpdesk", + '50001010': "A technical problem occurred, please contact helpdesk", + '50001011': "Brand not supported for that merchant", + '50001012': "A technical problem occurred, please contact helpdesk", + '50001013': "A technical problem occurred, please contact helpdesk", + '50001014': "A technical problem occurred, please contact helpdesk", + '50001015': "Invalid currency code", + '50001016': "A technical problem occurred, please contact helpdesk", + '50001017': "A technical problem occurred, please contact helpdesk", + '50001018': "A technical problem occurred, please contact helpdesk", + '50001019': "A technical problem occurred, please contact helpdesk", + '50001020': "A technical problem occurred, please contact helpdesk", + '50001021': "A technical problem occurred, please contact helpdesk", + '50001022': "A technical problem occurred, please contact helpdesk", + '50001023': "A technical problem occurred, please contact helpdesk", + '50001024': "A technical problem occurred, please contact helpdesk", + '50001025': "A technical problem occurred, please contact helpdesk", + '50001026': "A technical problem occurred, please contact helpdesk", + '50001027': "A technical problem occurred, please contact helpdesk", + '50001028': "A technical problem occurred, please contact helpdesk", + '50001029': "A technical problem occurred, please contact helpdesk", + '50001030': "A technical problem occurred, please contact helpdesk", + '50001031': "A technical problem occurred, please contact helpdesk", + '50001032': "A technical problem occurred, please contact helpdesk", + '50001033': "A technical problem occurred, please contact helpdesk", + '50001034': "A technical problem occurred, please contact helpdesk", + '50001035': "A technical problem occurred, please contact helpdesk", + '50001036': "Card length does not correspond to an acceptable value for the brand", + '50001037': "Purchasing card number for a regular merchant", + '50001038': "Non Purchasing card for a Purchasing card merchant", + '50001039': "Details sent for a non-Purchasing card merchant, please contact helpdesk", + '50001040': "Details not sent for a Purchasing card transaction, please contact helpdesk", + '50001041': "Payment detail validation failed", + '50001042': "Given transactions amounts (tax,discount,shipping,net,etc…) do not compute correctly together", + '50001043': "A technical problem occurred, please contact helpdesk", + '50001044': "No acquirer configured for this operation", + '50001045': "No UID configured for this operation", + '50001046': "Operation not allowed for the merchant", + '50001047': "A technical problem occurred, please contact helpdesk", + '50001048': "A technical problem occurred, please contact helpdesk", + '50001049': "A technical problem occurred, please contact helpdesk", + '50001050': "A technical problem occurred, please contact helpdesk", + '50001051': "A technical problem occurred, please contact helpdesk", + '50001052': "A technical problem occurred, please contact helpdesk", + '50001053': "A technical problem occurred, please contact helpdesk", + '50001054': "Card number incorrect or incompatible", + '50001055': "A technical problem occurred, please contact helpdesk", + '50001056': "A technical problem occurred, please contact helpdesk", + '50001057': "A technical problem occurred, please contact helpdesk", + '50001058': "A technical problem occurred, please contact helpdesk", + '50001059': "A technical problem occurred, please contact helpdesk", + '50001060': "A technical problem occurred, please contact helpdesk", + '50001061': "A technical problem occurred, please contact helpdesk", + '50001062': "A technical problem occurred, please contact helpdesk", + '50001063': "Card Issue Number does not correspond to range or not present", + '50001064': "Start Date not valid or not present", + '50001066': "Format of CVC code invalid", + '50001067': "The merchant is not enrolled for 3D-Secure", + '50001068': "The card number or account number (PAN) is invalid", + '50001069': "Invalid check for CardID and Brand", + '50001070': "The ECI value given is either not supported, or in conflict with other data in the transaction", + '50001071': "Incomplete TRN demat", + '50001072': "Incomplete PAY demat", + '50001073': "No demat APP", + '50001074': "Authorisation too old", + '50001075': "VERRes was an error message", + '50001076': "DCP amount greater than authorisation amount", + '50001077': "Details negative amount", + '50001078': "Details negative quantity", + '50001079': "Could not decode/decompress received PARes (3D-Secure)", + '50001080': "Received PARes was an erereor message from ACS (3D-Secure)", + '50001081': "Received PARes format was invalid according to the 3DS specifications (3D-Secure)", + '50001082': "PAReq/PARes reconciliation failure (3D-Secure)", + '50001084': "Maximum amount reached", + '50001087': "The transaction type requires authentication, please check with your bank.", + '50001090': "CVC missing at input, but CVC check asked", + '50001091': "ZIP missing at input, but ZIP check asked", + '50001092': "Address missing at input, but Address check asked", + '50001095': "Invalid date of birth", + '50001096': "Invalid commodity code", + '50001097': "The requested currency and brand are incompatible.", + '50001111': "Data validation error", + '50001113': "This order has already been processed", + '50001114': "Error pre-payment check page access", + '50001115': "Request not received in secure mode", + '50001116': "Unknown IP address origin", + '50001117': "NO IP address origin", + '50001118': "Pspid not found or not correct", + '50001119': "Password incorrect or disabled due to numbers of errors", + '50001120': "Invalid currency", + '50001121': "Invalid number of decimals for the currency", + '50001122': "Currency not accepted by the merchant", + '50001123': "Card type not active", + '50001124': "Number of lines don't match with number of payments", + '50001125': "Format validation error", + '50001126': "Overflow in data capture requests for the original order", + '50001127': "The original order is not in a correct status", + '50001128': "missing authorization code for unauthorized order", + '50001129': "Overflow in refunds requests", + '50001130': "Error access to original order", + '50001131': "Error access to original history item", + '50001132': "The Selected Catalog is empty", + '50001133': "Duplicate request", + '50001134': "Authentication failed, please retry or cancel.", + '50001135': "Authentication temporary unavailable, please retry or cancel.", + '50001136': "Technical problem with your browser, please retry or cancel", + '50001137': "Your bank access control server is temporary unavailable, please retry or cancel", + '50001150': "Fraud Detection, Technical error (IP not valid)", + '50001151': "Fraud detection : technical error (IPCTY unknown or error)", + '50001152': "Fraud detection : technical error (CCCTY unknown or error)", + '50001153': "Overflow in redo-authorisation requests", + '50001170': "Dynamic BIN check failed", + '50001171': "Dynamic country check failed", + '50001172': "Error in Amadeus signature", + '50001174': "Card Holder Name is too long", + '50001175': "Name contains invalid characters", + '50001176': "Card number is too long", + '50001177': "Card number contains non-numeric info", + '50001178': "Card Number Empty", + '50001179': "CVC too long", + '50001180': "CVC contains non-numeric info", + '50001181': "Expiration date contains non-numeric info", + '50001182': "Invalid expiration month", + '50001183': "Expiration date must be in the future", + '50001184': "SHA Mismatch", + '50001205': "Missing mandatory fields for billing address.", + '50001206': "Missing mandatory field date of birth.", + '50001207': "Missing required shopping basket details.", + '50001208': "Missing social security number", + '50001209': "Invalid country code", + '50001210': "Missing yearly salary", + '50001211': "Missing gender", + '50001212': "Missing email", + '50001213': "Missing IP address", + '50001214': "Missing part payment campaign ID", + '50001215': "Missing invoice number", + '50001216': "The alias must be different than the card number", + '60000001': "account number unknown", + '60000003': "not credited dd-mm-yy", + '60000005': "name/number do not correspond", + '60000007': "account number blocked", + '60000008': "specific direct debit block", + '60000009': "account number WKA", + '60000010': "administrative reason", + '60000011': "account number expired", + '60000012': "no direct debit authorisation given", + '60000013': "debit not approved", + '60000014': "double payment", + '60000018': "name/address/city not entered", + '60001001': "no original direct debit for revocation", + '60001002': "payer’s account number format error", + '60001004': "payer’s account at different bank", + '60001005': "payee’s account at different bank", + '60001006': "payee’s account number format error", + '60001007': "payer’s account number blocked", + '60001008': "payer’s account number expired", + '60001009': "payee’s account number expired", + '60001010': "direct debit not possible", + '60001011': "creditor payment not possible", + '60001012': "payer’s account number unknown WKA-number", + '60001013': "payee’s account number unknown WKA-number", + '60001014': "impermissible WKA transaction", + '60001015': "period for revocation expired", + '60001017': "reason for revocation not correct", + '60001018': "original run number not numeric", + '60001019': "payment ID incorrect", + '60001020': "amount not numeric", + '60001021': "amount zero not permitted", + '60001022': "negative amount not permitted", + '60001023': "payer and payee giro account number", + '60001025': "processing code (verwerkingscode) incorrect", + '60001028': "revocation not permitted", + '60001029': "guaranteed direct debit on giro account number", + '60001030': "NBC transaction type incorrect", + '60001031': "description too large", + '60001032': "book account number not issued", + '60001034': "book account number incorrect", + '60001035': "payer’s account number not numeric", + '60001036': "payer’s account number not eleven-proof", + '60001037': "payer’s account number not issued", + '60001039': "payer’s account number of DNB/BGC/BLA", + '60001040': "payee’s account number not numeric", + '60001041': "payee’s account number not eleven-proof", + '60001042': "payee’s account number not issued", + '60001044': "payee’s account number unknown", + '60001050': "payee’s name missing", + '60001051': "indicate payee’s bank account number instead of 3102", + '60001052': "no direct debit contract", + '60001053': "amount beyond bounds", + '60001054': "selective direct debit block", + '60001055': "original run number unknown", + '60001057': "payer’s name missing", + '60001058': "payee’s account number missing", + '60001059': "restore not permitted", + '60001060': "bank’s reference (navraaggegeven) missing", + '60001061': "BEC/GBK number incorrect", + '60001062': "BEC/GBK code incorrect", + '60001087': "book account number not numeric", + '60001090': "cancelled on request", + '60001091': "cancellation order executed", + '60001092': "cancelled instead of bended", + '60001093': "book account number is a shortened account number", + '60001094': "instructing party account number not identical with payer", + '60001095': "payee unknown GBK acceptor", + '60001097': "instructing party account number not identical with payee", + '60001099': "clearing not permitted", + '60001101': "payer’s account number not spaces", + '60001102': "PAN length not numeric", + '60001103': "PAN length outside limits", + '60001104': "track number not numeric", + '60001105': "track number not valid", + '60001106': "PAN sequence number not numeric", + '60001107': "domestic PAN not numeric", + '60001108': "domestic PAN not eleven-proof", + '60001109': "domestic PAN not issued", + '60001110': "foreign PAN not numeric", + '60001111': "card valid date not numeric", + '60001112': "book period number (boekperiodenr) not numeric", + '60001113': "transaction number not numeric", + '60001114': "transaction time not numeric", + '60001115': "transaction no valid time", + '60001116': "transaction date not numeric", + '60001117': "transaction no valid date", + '60001118': "STAN not numeric", + '60001119': "instructing party’s name missing", + '60001120': "foreign amount (bedrag-vv) not numeric", + '60001122': "rate (verrekenkoers) not numeric", + '60001125': "number of decimals (aantaldecimalen) incorrect", + '60001126': "tariff (tarifering) not B/O/S", + '60001127': "domestic costs (kostenbinnenland) not numeric", + '60001128': "domestic costs (kostenbinnenland) not higher than zero", + '60001129': "foreign costs (kostenbuitenland) not numeric", + '60001130': "foreign costs (kostenbuitenland) not higher than zero", + '60001131': "domestic costs (kostenbinnenland) not zero", + '60001132': "foreign costs (kostenbuitenland) not zero", + '60001134': "Euro record not fully filled in", + '60001135': "Client currency incorrect", + '60001136': "Amount NLG not numeric", + '60001137': "Amount NLG not higher than zero", + '60001138': "Amount NLG not equal to Amount", + '60001139': "Amount NLG incorrectly converted", + '60001140': "Amount EUR not numeric", + '60001141': "Amount EUR not greater than zero", + '60001142': "Amount EUR not equal to Amount", + '60001143': "Amount EUR incorrectly converted", + '60001144': "Client currency not NLG", + '60001145': "rate euro-vv (Koerseuro-vv) not numeric", + '60001146': "comma rate euro-vv (Kommakoerseuro-vv) incorrect", + '60001147': "acceptgiro distributor not valid", + '60001148': "Original run number and/or BRN are missing", + '60001149': "Amount/Account number/ BRN different", + '60001150': "Direct debit already revoked/restored", + '60001151': "Direct debit already reversed/revoked/restored", + '60001153': "Payer’s account number not known", +} + +DATA_VALIDATION_ERROR = '50001111' + + +def retryable(error): + return error in [ + '0020001001', '0020001002', '0020001003', '0020001004', '0020001005', + '0020001006', '0020001007', '0020001008', '0020001009', '0020001010', + '30001010', '30001011', '30001015', + '30001057', '30001058', + '30001998', '30001999', + #'30611001', # amount exceeds card limit + '30961001', + '40001001', '40001002', '40001003', '40001004', '40001005', + '40001006', '40001007', '40001008', '40001009', '40001010', + '40001012', + '40001018', '40001019', '40001020', + '40001134', '40001135', '40001136', '40001137', + #'50001174', # cardholder name too long + ] diff --git a/addons/payment_acquirer/models/payment_acquirer.py b/addons/payment_acquirer/models/payment_acquirer.py index b5404043ec2..7ef78b7b2e6 100644 --- a/addons/payment_acquirer/models/payment_acquirer.py +++ b/addons/payment_acquirer/models/payment_acquirer.py @@ -20,15 +20,46 @@ ############################################################################## import openerp +from openerp.addons.payment_acquirer.models import ogone_errors from openerp.osv import osv, fields from openerp.tools import float_repr -import urlparse -import requests +from openerp.tools.safe_eval import safe_eval + +from hashlib import sha1 +from lxml import etree, objectify import logging +from pprint import pformat +import requests +import urlparse +import time +from urllib import urlencode +import urllib2 _logger = logging.getLogger(__name__) +def _generate_ogone_shasign(acc, inout, values): + assert inout in ('in', 'out') + assert acc.provider == 'ogone' + key = acc['ogone_shakey_' + inout] + + def filter_key(key): + if inout == 'in': + return True + else: + keys = "ORDERID CURRENCY AMOUNT PM ACCEPTANCE STATUS CARDNO ALIAS ED CN TRXDATE PAYID NCERROR BRAND ECI IP COMPLUS".split() + return key.upper() in keys + + items = sorted((k.upper(), v) for k, v in values.items()) + sign = ''.join('%s=%s%s' % (k, v, key) for k, v in items if v and filter_key(k)) + shasign = sha1(sign).hexdigest() + return shasign + + +class ValidationError(ValueError): + pass + + class Payment(osv.Model): _name = 'payment.transaction' _inherit = ['mail.thread'] @@ -41,7 +72,7 @@ class Payment(osv.Model): 'currency_id': fields.many2one('res.currency', 'Currency', required=True), 'reference': fields.char('Order Reference'), 'acquirer_ref': fields.char('Payment Acquirer Ref'), - 'state': fields.selection([("pending", "Pending"),("validated", "Validated"),("refused", "Refused")], 'Status', required=True), + 'state': fields.selection([("pending", "Pending"), ("validated", "Validated"), ("refused", "Refused")], 'Status', required=True), 'res_model': fields.char('Object Model'), 'res_id': fields.char('Object Id'), } @@ -50,14 +81,14 @@ class Payment(osv.Model): class acquirer(osv.Model): _name = 'payment.acquirer' _description = 'Online Payment Acquirer' - + def list_acquirers(self, cr, uid, context=None): return [("virement", "Virement")] _columns = { 'name': fields.char('Name', required=True), 'acquirer': fields.selection(lambda self, *a, **k: self.list_acquirers(*a, **k), 'Acquirer', required=True), - 'form_template_id': fields.many2one('ir.ui.view', required=True), + 'form_template_id': fields.many2one('ir.ui.view', required=True), 'visible': fields.boolean('Visible', help="Make this payment acquirer available (Customer invoices, etc.)"), } @@ -118,22 +149,23 @@ class acquirer(osv.Model): method = getattr(self, '_validate_payement_%s' % pay.acquirer) status, retry_time, log = method(object, reference, currency, amount, context=context) - # log transaction and payment if getattr(object, 'message_post'): - object.message_post(cr, uid, False, + object.message_post( + cr, uid, False, body=log or "", subject="%s%s" % (status, retry_time and ": %s" % retry_time or ""), type='notification', - context=context) + context=context + ) if status == "validated": - _logger.info("Payment Validate for %s:%s" % (object._name, reference) ) + _logger.info("Payment Validate for %s:%s" % (object._name, reference)) elif status == "pending": - _logger.debug("Payment Pending for %s:%s. Reason: %s" % (object._name, reference, log) ) + _logger.debug("Payment Pending for %s:%s. Reason: %s" % (object._name, reference, log)) else: - _logger.error("Payment Refused for %s:%s. Reason: %s" % (object._name, reference, log) ) - + _logger.error("Payment Refused for %s:%s. Reason: %s" % (object._name, reference, log)) + return (status, retry_time, log) def _validate_payement_virement(self, object, reference, currency, amount, context=None): @@ -156,7 +188,6 @@ class acquirer_paypal(osv.osv): return l def _validate_payement_paypal(self, object, reference, currency, amount, context=None): - parameters = {} parameters.update( cmd='_notify-validate', @@ -186,8 +217,8 @@ class acquirer_paypal(osv.osv): retry_time = 60 return (status, retry_time, "payment_status=%s&pending_reason=%s&reason_code=%s" % ( - response["payment_status"], - response.get("pending_reason"), + response["payment_status"], + response.get("pending_reason"), response.get("reason_code"))) def _transaction_feedback_paypal(self, **values): @@ -320,11 +351,11 @@ class acquirer_ogone(osv.Model): return check_status(tree, tries - 1) else: error_code = tree.get('NCERROR') - if tries and retryable(error_code): + if tries and ogone_errors.retryable(error_code): return check_status(tree, tries - 1) error_str = tree.get('NCERRORPLUS') - error_msg = OGONE_ERROR_MAP.get(error_code) + error_msg = ogone_errors.OGONE_ERROR_MAP.get(error_code) error = 'ERROR: %s\n\n%s: %s' % (error_str, error_code, error_msg) _logger.info(error) raise Exception(error) @@ -379,7 +410,7 @@ class acquirer_ogone(osv.Model): else: error_code = data.get('NCERROR') error_str = data.get('NCERRORPLUS') - error_msg = OGONE_ERROR_MAP.get(error_code) + error_msg = ogone_errors.OGONE_ERROR_MAP.get(error_code) error = 'ERROR: %s\n\n%s: %s' % (error_str, error_code, error_msg) _logger.info(error) payment.write({'state': 'error', 'error': error}) From 3d0ac6643e8a3a3a257f3ba72f63c3852b9a3a3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Thu, 7 Nov 2013 18:15:58 +0100 Subject: [PATCH 10/58] [IMP] payment_acquirer: continuing base model. Two main models : payment.acquirer and payment.transaction. payment.acquirer models the acquirer: paypal, ogone. Each specific acquirer will inherit from the class and add specific fields. payment.transaction models the transaction itself. It has basic fields for a transaction: date, partner, partner fields (to hold data at transaction time), reference, state and its message, amount, currency. Class methods are not finished and still quite WIP. payment.acqurier has a render method that is used to render its form. The form is the 'pay now' button with the specific sementic of each acquirer. This model is supposed to work on form-based and server-to-server implementation methods. bzr revid: tde@openerp.com-20131107171558-jrwrj3ll9kol6bav --- addons/payment_acquirer/__openerp__.py | 8 +- addons/payment_acquirer/controllers/main.py | 74 ++- .../data/payment_acquirer_data.xml | 31 +- addons/payment_acquirer/models/__init__.py | 2 + .../models/payment_acquirer.py | 530 ++++++------------ .../payment_acquirer/views/acquirer_view.xml | 63 --- .../views/payment_acquirer_views.xml | 136 +++++ 7 files changed, 415 insertions(+), 429 deletions(-) delete mode 100644 addons/payment_acquirer/views/acquirer_view.xml create mode 100644 addons/payment_acquirer/views/payment_acquirer_views.xml diff --git a/addons/payment_acquirer/__openerp__.py b/addons/payment_acquirer/__openerp__.py index 1452489c876..6fd1d82489a 100644 --- a/addons/payment_acquirer/__openerp__.py +++ b/addons/payment_acquirer/__openerp__.py @@ -26,10 +26,14 @@ 'version': '0.1', 'description': """Payment acquirer module, use to display payment method and validate the payments.""", 'author': 'OpenERP SA', - 'depends': ['decimal_precision'], + 'depends': ['decimal_precision', 'mail'], 'data': [ - 'views/acquirer_view.xml', + 'views/payment_acquirer_views.xml', + 'views/ogone.xml', + 'views/paypal.xml', 'data/payment_acquirer_data.xml', + 'data/ogone.xml', + 'data/paypal.xml', 'security/ir.model.access.csv', ], 'installable': True, diff --git a/addons/payment_acquirer/controllers/main.py b/addons/payment_acquirer/controllers/main.py index 1aa84ebdbbc..9f1dcdc0f58 100644 --- a/addons/payment_acquirer/controllers/main.py +++ b/addons/payment_acquirer/controllers/main.py @@ -21,12 +21,76 @@ from openerp.addons.web import http from openerp.addons.web.http import request +# from openerp.addons.payment_acquirer.models.payment_acquirer import ValidationError from openerp.addons.website.models import website +import logging +import requests +from urllib import urlencode -class website_project(http.Controller): +_logger = logging.getLogger(__name__) - @website.route(['/payment_acquirer//'], type='http', auth="public") - def project(self, acquirer=None, **post): - obj = request.registry['payment.acquirer'] - return obj.transaction_feedback(request.cr, request.uid, acquirer, context=request.context, **post) + +class PaypalController(http.Controller): + _notify_url = '/payment/paypal/ipn/' + _return_url = '/payment/paypal/dpn/' + _cancel_url = '/payment/paypal/cancel/' + # _ipn_url2 = '/payment/paypal//ipn/' + + @website.route('/payment/paypal//ipn/', type='http', auth='admin') + def paypal_ipn(self, **post): + print 'Entering paypal_ipn with post', post + # step 1: return an empty HTTP 200 response -> will be done at the end by returning '' + + # step 2: POST the complete, unaltered message back to Paypal (preceded by cmd=_notify-validate), with same encoding + 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) + print '\tReceived response', resp, resp.text + + # step 3: paypal send either VERIFIED or INVALID (single word) + if resp.text == 'VERIFIED': + # _logger.warning('') + cr, uid, context = request.cr, request.uid, request.context + # payment_transaction = request.registry['payment.transaction'] + # payment_transaction.validate() + elif resp.text == 'INVALID': + # _logger.warning('') + pass + else: + # _logger.warning('') -> something went wrong + pass + + return '' + + @website.route([ + '/payment/paypal/test/dpn', + ], type='http', auth="public") + def paypal_test_success(self, **post): + """ TODO + """ + cr, uid, context = request.cr, request.uid, request.context + print post + return '' + + +class OgoneController(http.Controller): + _accept_url = '/payment/ogone/test/accept' + _decline_url = '/payment/ogone/test/decline' + _exception_url = '/payment/ogone/test/exception' + _cancel_url = '/payment/ogone/test/cancel' + + @website.route([ + '/payment/ogone/feedback', '/payment/ogone/test/accept', + '/payment/ogone/decline', '/payment/ogone/test/decline', + '/payment/ogone/exception', '/payment/ogone/test/exception', + '/payment/ogone/cancel', '/payment/ogone/test/cancel', + ], type='http', auth='admin') + def feedback(self, **post): + cr, uid, context = request.cr, request.uid, request.context + Payment = request.registry['payment.transaction'] + print 'Entering ogone feedback with', post + + res = Payment.tx_ogone_feedback(cr, uid, post, context) + print res + return '' diff --git a/addons/payment_acquirer/data/payment_acquirer_data.xml b/addons/payment_acquirer/data/payment_acquirer_data.xml index dd8df209b59..e99186dc922 100644 --- a/addons/payment_acquirer/data/payment_acquirer_data.xml +++ b/addons/payment_acquirer/data/payment_acquirer_data.xml @@ -3,7 +3,7 @@ - + - + + + + + -