diff --git a/addons/payment/__manifest__.py b/addons/payment/__manifest__.py index 0bc26ebfc9f..79fa3cecc0f 100644 --- a/addons/payment/__manifest__.py +++ b/addons/payment/__manifest__.py @@ -9,6 +9,7 @@ 'depends': ['account'], 'data': [ 'data/account_data.xml', + 'data/payment_icon_data.xml', 'data/payment_acquirer_data.xml', 'views/payment_views.xml', 'views/account_payment_views.xml', diff --git a/addons/payment/controllers/portal.py b/addons/payment/controllers/portal.py index dc402446ea3..c7fb34607ed 100644 --- a/addons/payment/controllers/portal.py +++ b/addons/payment/controllers/portal.py @@ -8,17 +8,18 @@ from odoo.http import request class WebsitePayment(http.Controller): @http.route(['/my/payment_method'], type='http', auth="user", website=True) def payment_method(self, **kwargs): - acquirers = list(request.env['payment.acquirer'].search([('website_published', '=', True), ('registration_view_template_id', '!=', False)])) + acquirers = list(request.env['payment.acquirer'].search([('website_published', '=', True), ('registration_view_template_id', '!=', False), ('payment_flow', '=', 's2s')])) partner = request.env.user.partner_id payment_tokens = partner.payment_token_ids payment_tokens |= partner.commercial_partner_id.sudo().payment_token_ids + return_url = request.params.get('redirect', '/my/payment_method') values = { 'pms': payment_tokens, - 'acquirers': acquirers + 'acquirers': acquirers, + 'return_url': return_url, + 'bootstrap_formatting': True, + 'partner_id': partner.id } - return_url = request.params.get('redirect', '/my/payment_method') - for acquirer in acquirers: - acquirer.form = acquirer.sudo()._registration_render(request.env.user.partner_id.id, {'error': {}, 'error_message': [], 'return_url': return_url, 'json': False, 'bootstrap_formatting': True}) return request.render("payment.pay_methods", values) @http.route(['/website_payment/pay'], type='http', auth='public', website=True) diff --git a/addons/payment/data/payment_acquirer_data.xml b/addons/payment/data/payment_acquirer_data.xml index 5908c6e5366..871ee7ef8e0 100644 --- a/addons/payment/data/payment_acquirer_data.xml +++ b/addons/payment/data/payment_acquirer_data.xml @@ -2,20 +2,14 @@ @@ -32,6 +26,12 @@
  • Payment Status Tracking
  • + +
    @@ -51,6 +51,11 @@
  • Save Cards
  • + +
    @@ -67,6 +72,15 @@
  • Payment Status Tracking
  • + +
    @@ -87,6 +101,13 @@
  • Manual Capture
  • + +
    @@ -117,6 +138,16 @@
  • Payment Status Tracking
  • + +
    @@ -134,6 +165,15 @@
  • Payment Status Tracking
  • + +
    @@ -150,7 +190,17 @@
  • Payment Status Tracking
  • - + +
    @@ -182,6 +232,13 @@
  • Payment Status Tracking
  • + +
    diff --git a/addons/payment/data/payment_icon_data.xml b/addons/payment/data/payment_icon_data.xml new file mode 100644 index 00000000000..4dc62d67e39 --- /dev/null +++ b/addons/payment/data/payment_icon_data.xml @@ -0,0 +1,57 @@ + + + + VISA + + + + + American Express + + + + + Cirrus + + + + + Diners Club International + + + + + Diners Club International + + + + + Discover + + + + + JCB + + + + + Maestro + + + + + MasterCard + + + + + UnionPay + + + + + Bancontact + + + \ No newline at end of file diff --git a/addons/payment/models/payment_acquirer.py b/addons/payment/models/payment_acquirer.py index 2e36d891344..d225dd8c801 100644 --- a/addons/payment/models/payment_acquirer.py +++ b/addons/payment/models/payment_acquirer.py @@ -5,7 +5,7 @@ import logging import datetime from odoo import api, exceptions, fields, models, _ -from odoo.tools import consteq, float_round, image_resize_images, ustr +from odoo.tools import consteq, float_round, image_resize_images, image_resize_image, ustr from odoo.addons.base.module import module from odoo.exceptions import ValidationError @@ -117,8 +117,8 @@ class PaymentAcquirer(models.Model): help='Message displayed, if error is occur during the payment process.') save_token = fields.Selection([ ('none', 'Never'), - ('ask', 'Let the customer decide (recommended for eCommerce)'), - ('always', 'Always (recommended for Subscriptions)')], + ('ask', 'Let the customer decide'), + ('always', 'Always')], string='Save Cards', default='none', help="This option allows customers to save their credit card as a payment token and to reuse it for a later purchase." "If you manage subscriptions (recurring invoicing), you need it to automatically charge the customer when you " @@ -150,6 +150,12 @@ class PaymentAcquirer(models.Model): "resized as a 64x64px image, with aspect ratio preserved. " "Use this field anywhere a small image is required.") + payment_icon_ids = fields.Many2many('payment.icon', string='Supported Payment Icons') + payment_flow = fields.Selection(selection=[('s2s','The customer encode his payment details on the website.'), + ('form', 'The customer is redirected to the website of the acquirer.')], + default='form', required=True, string='Payment flow', + help="""Note: Subscriptions does not take this field in account, it uses server to server by default.""") + def _search_is_tokenized(self, operator, value): tokenized = self._get_feature_support()['tokenize'] if (operator, value) in [('=', True), ('!=', False)]: @@ -344,16 +350,11 @@ class PaymentAcquirer(models.Model): return self.view_template_id.render(values, engine='ir.qweb') - @api.multi - def _registration_render(self, partner_id, qweb_context=None): - if qweb_context is None: - qweb_context = {} - qweb_context.update(id=self.ids[0], partner_id=partner_id) - method_name = '_%s_registration_form_generate_values' % (self.provider,) - if hasattr(self, method_name): - method = getattr(self, method_name) - qweb_context.update(method(qweb_context)) - return self.registration_view_template_id.render(qweb_context, engine='ir.qweb') + def get_s2s_form_xml_id(self): + if self.registration_view_template_id: + model_data = self.env['ir.model.data'].search([('model', '=', 'ir.ui.view'), ('res_id', '=', self.registration_view_template_id.id)]) + return ('%s.%s') % (model_data.module, model_data.name) + return False @api.multi def s2s_process(self, data): @@ -394,6 +395,32 @@ class PaymentAcquirer(models.Model): 'context': context, } +class PaymentIcon(models.Model): + _name = 'payment.icon' + _description = 'Payment Icon' + + name = fields.Char(string='Name') + acquirer_ids = fields.Many2many('payment.acquirer', string="Acquirers", help="List of Acquirers supporting this payment icon.") + image = fields.Binary( + "Image", attachment=True, + help="This field holds the image used for this payment icon, limited to 1024x1024px") + + image_payment_form = fields.Binary( + "Image displayed on the payment form", attachment=True) + + @api.model + def create(self, vals): + if 'image' in vals: + vals['image_payment_form'] = image_resize_image(vals['image'], size=(45,30)) + vals['image'] = image_resize_image(vals['image'], size=(64,64)) + return super(PaymentIcon, self).create(vals) + + @api.multi + def write(self, vals): + if 'image' in vals: + vals['image_payment_form'] = image_resize_image(vals['image'], size=(45,30)) + vals['image'] = image_resize_image(vals['image'], size=(64,64)) + return super(PaymentIcon, self).write(vals) class PaymentTransaction(models.Model): """ Transaction Model. Each specific acquirer can extend the model by adding diff --git a/addons/payment/security/ir.model.access.csv b/addons/payment/security/ir.model.access.csv index 2bfa46839a0..2982f1ab0c0 100644 --- a/addons/payment/security/ir.model.access.csv +++ b/addons/payment/security/ir.model.access.csv @@ -9,3 +9,6 @@ payment_method_all,payment.token.all,model_payment_token,,1,0,0,0 payment_method_user,payment.token.user,model_payment_token,base.group_user,1,1,1,1 payment_method_portal,payment.token.portal,model_payment_token,base.group_portal,1,1,1,1 payment_method_system,payment.token.system,model_payment_token,base.group_system,1,1,1,1 +payment_icon_all,payment.icon.all,model_payment_icon,,1,0,0,0 +payment_icon_user,payment.icon.user,model_payment_icon,base.group_user,1,1,1,0 +payment_icon_system,payment.icon.system,model_payment_icon,base.group_system,1,1,1,1 \ No newline at end of file diff --git a/addons/payment/static/img/american_express.png b/addons/payment/static/img/american_express.png new file mode 100644 index 00000000000..9f31d21ef20 Binary files /dev/null and b/addons/payment/static/img/american_express.png differ diff --git a/addons/payment/static/img/bancontact.png b/addons/payment/static/img/bancontact.png new file mode 100644 index 00000000000..7941a69cf64 Binary files /dev/null and b/addons/payment/static/img/bancontact.png differ diff --git a/addons/payment/static/img/cirrus.png b/addons/payment/static/img/cirrus.png new file mode 100644 index 00000000000..eb4b2aa81f6 Binary files /dev/null and b/addons/payment/static/img/cirrus.png differ diff --git a/addons/payment/static/img/diners_club_intl.png b/addons/payment/static/img/diners_club_intl.png new file mode 100644 index 00000000000..888860a140e Binary files /dev/null and b/addons/payment/static/img/diners_club_intl.png differ diff --git a/addons/payment/static/img/discover.png b/addons/payment/static/img/discover.png new file mode 100644 index 00000000000..d9222265651 Binary files /dev/null and b/addons/payment/static/img/discover.png differ diff --git a/addons/payment/static/img/jcb.png b/addons/payment/static/img/jcb.png new file mode 100644 index 00000000000..f3e3c5bfb06 Binary files /dev/null and b/addons/payment/static/img/jcb.png differ diff --git a/addons/payment/static/img/maestro.png b/addons/payment/static/img/maestro.png new file mode 100644 index 00000000000..a0a6b328380 Binary files /dev/null and b/addons/payment/static/img/maestro.png differ diff --git a/addons/payment/static/img/mastercard.png b/addons/payment/static/img/mastercard.png new file mode 100644 index 00000000000..2572a33b373 Binary files /dev/null and b/addons/payment/static/img/mastercard.png differ diff --git a/addons/payment/static/img/unionpay.png b/addons/payment/static/img/unionpay.png new file mode 100644 index 00000000000..8d830c5f944 Binary files /dev/null and b/addons/payment/static/img/unionpay.png differ diff --git a/addons/payment/static/img/visa.png b/addons/payment/static/img/visa.png new file mode 100644 index 00000000000..58cfab08725 Binary files /dev/null and b/addons/payment/static/img/visa.png differ diff --git a/addons/payment/static/src/js/payment_form.js b/addons/payment/static/src/js/payment_form.js index ae2d44c1cb7..491cafcf00c 100644 --- a/addons/payment/static/src/js/payment_form.js +++ b/addons/payment/static/src/js/payment_form.js @@ -18,7 +18,6 @@ odoo.define('payment.payment_form', function (require){ }, payEvent: function(ev) { - ev.stopPropagation(); ev.preventDefault(); var form = this.el; var checked_radio = this.$('input[type="radio"]:checked'); @@ -33,8 +32,28 @@ odoo.define('payment.payment_form', function (require){ var acquirer_id = this.getAcquirerIdFromRadio(checked_radio); var acquirer_form = this.$('#o_payment_add_token_acq_' + acquirer_id); // we retrieve all the input inside the acquirer form and 'serialize' them to an indexed array - var form_data = this.getFormData($('input', acquirer_form)); + var inputs_form = $('input', acquirer_form); + var form_data = this.getFormData(inputs_form); var ds = $('input[name="data_set"]', acquirer_form)[0]; + var empty_inputs = false; + + inputs_form.toArray().forEach(function(element) { + if(element.dataset.isRequired) { + if (element.value.length === 0) { + $(element).closest('div.form-group').addClass('has-error'); + } + else { + $(element).closest('div.form-group').removeClass('has-error'); + } + empty_inputs = true; + } + }); + + if(empty_inputs) { + this.error(_t('Missing values'), _t('

    Please fill all the inputs required.

    ')); + return; + } + $(button).attr('disabled', true); $(button).prepend(' '); @@ -59,7 +78,7 @@ odoo.define('payment.payment_form', function (require){ } // if the server has returned false, we display an error else { - self.error(_t('Error'), + self.error(_t('Server Error'), _t("

    We are not able to add your payment method at the moment.

    ")); } // here we remove the 'processing' icon from the 'add a new payment' button @@ -70,10 +89,62 @@ odoo.define('payment.payment_form', function (require){ $(button).attr('disabled', false); $(button).find('span.o_loader').remove(); - self.error(_t('Error'), + self.error(_t('Server Error'), _t("

    We are not able to add your payment method at the moment.

    ") + (core.debug ? data.data.message : '')); }); } + // if the user is going to pay with a form payment, then + else if(this.isFormPaymentRadio(checked_radio)) + { + var self = this; + // we retrieve the acquirer id and its form + var acquirer_id = this.getAcquirerIdFromRadio(checked_radio); + var acquirer_form = this.$('#o_payment_form_acq_' + acquirer_id); + var inputs_form = $('input', acquirer_form); + var ds = $('input[name="data_set"]', acquirer_form)[0]; + var form_save_token = false; + var $tx_url = this.$el.find('input[name="prepare_tx_url"]'); + + // if neither the dataset or the action url is defined, then we just stop the execution of the function + if(!ds || !ds.dataset.actionUrl) + return; + + // if there's a prepare tx url set + if($tx_url.length == 1) + { + // if the user wants to save his credit card info + form_save_token = $('input[name="o_payment_form_save_token"]').checked === true; + // then we call the route to prepare the transaction + ajax.jsonRpc($tx_url[0].value, 'call', { + 'acquirer_id': parseInt(acquirer_id), + 'save_token': form_save_token + }).then(function(result){ + if(result) { + // if the server sent us the html form, we create a form element + var newForm = document.createElement('form'); + newForm.setAttribute("method", "post"); // set it to post + newForm.setAttribute("action", ds.dataset.actionUrl); // set the action url + newForm.hidden = true; // hide it + newForm.innerHTML = result; // put the html sent by the server inside the form + document.getElementsByTagName('body')[0].appendChild(newForm); // append the form to the body + $(newForm).find('input[data-remove-me]').remove(); // remove all the input that should be removed + newForm.submit(); // and finally submit the form + } + else { + self.error(_t('Server Error'), + _t("

    We are not able to redirect you to the payment form.

    ")); + } + }).fail(function(message, data){ + self.error(_t('Server Error'), + _t("

    We are not able to redirect you to the payment form.

    ") + (core.debug ? data.data.message : '')); + }); + } + else + { + // we append the form to the body and send it. + this.error(_t("Cannot set-up the payment"), _t("

    We're unable to process your payment.

    ")); + } + } // if the user is using an old payment else { // then we just submit the form @@ -81,8 +152,8 @@ odoo.define('payment.payment_form', function (require){ } } else { - this.error(_t('Error'), - _t('

    Please select a payment method

    ')); + this.error(_t('No payment method selected'), + _t('

    Please select a payment method.

    ')); } }, // event handler when clicking on the button to add a new payment method @@ -96,16 +167,35 @@ odoo.define('payment.payment_form', function (require){ // we check if the user has selected a 'add a new payment' option if(checked_radio.length == 1 && this.isNewPaymentRadio(checked_radio[0])) { - // then we add a 'processing' icon into the 'add a new payment' button - $(button).attr('disabled', true); - $(button).prepend(' '); // we retrieve which acquirer is used checked_radio = checked_radio[0]; var acquirer_id = this.getAcquirerIdFromRadio(checked_radio); var acquirer_form = this.$('#o_payment_add_token_acq_' + acquirer_id); // we retrieve all the input inside the acquirer form and 'serialize' them to an indexed array - var form_data = this.getFormData($('input', acquirer_form)); + var inputs_form = $('input', acquirer_form); + var form_data = this.getFormData(inputs_form); var ds = $('input[name="data_set"]', acquirer_form)[0]; + var empty_inputs = false; + + inputs_form.toArray().forEach(function(element) { + if(element.dataset.isRequired) { + if (element.value.length === 0) { + $(element).closest('div.form-group').addClass('has-error'); + } + else { + $(element).closest('div.form-group').removeClass('has-error'); + } + empty_inputs = true; + } + }); + + if(empty_inputs) { + this.error(_t('Missing values'), _t('

    Please fill all the inputs required.

    ')); + return; + } + // We add a 'processing' icon into the 'add a new payment' button + $(button).attr('disabled', true); + $(button).prepend(' '); // we force the check when adding a card trough here form_data.verify_validity = true; @@ -132,7 +222,7 @@ odoo.define('payment.payment_form', function (require){ } // if the server has returned false, we display an error else { - self.error(_t('Error'), + self.error(_t('Server Error'), _t("

    We are not able to add your payment method at the moment.

    ")); } // here we remove the 'processing' icon from the 'add a new payment' button @@ -143,13 +233,13 @@ odoo.define('payment.payment_form', function (require){ $(button).attr('disabled', false); $(button).find('span.o_loader').remove(); - self.error(_t('Error'), + self.error(_t('Server error'), _t("

    We are not able to add your payment method at the moment.

    ") + (core.debug ? data.data.message : '')); }); } else { - this.error(_t('Error'), - _t('

    Please select the option to add a new payment method

    ')); + this.error(_t('No payment method selected'), + _t('

    Please select the option to add a new payment method.

    ')); } }, // event handler when clicking on a button to delete a payment method @@ -170,7 +260,7 @@ odoo.define('payment.payment_form', function (require){ ev.target.closest('div').remove(); } },function(type,err){ - self.error(_t('Error'), + self.error(_t('Server Error'), _t("

    We are not able to delete your payment method at the moment.

    ")); }); }; @@ -202,7 +292,7 @@ odoo.define('payment.payment_form', function (require){ Delete(); } }, function(type, err){ - self.error(_t('Error'), + self.error(_t('Server Error'), _t("

    We are not able to delete your payment method at the moment.

    ") + (core.debug ? err.data.message : '')); }); }, @@ -215,28 +305,43 @@ odoo.define('payment.payment_form', function (require){ var checked_radio = this.$('input[type="radio"]:checked'); // we hide all the acquirers form this.$('[id*="o_payment_add_token_acq_"]').addClass('hidden'); + this.$('[id*="o_payment_form_acq_"]').addClass('hidden'); + if(checked_radio.length != 1) { + return; + } + checked_radio = checked_radio[0]; // if we clicked on an add new payment radio - if(checked_radio.length == 1 && this.isNewPaymentRadio(checked_radio[0])) + if(this.isNewPaymentRadio(checked_radio)) { // then we retrieve the acquirer name - var acquirer_id = this.getAcquirerIdFromRadio(checked_radio[0]); + var acquirer_id = this.getAcquirerIdFromRadio(checked_radio); // and display its form this.$('#o_payment_add_token_acq_' + acquirer_id).removeClass('hidden'); } + else if(this.isFormPaymentRadio(checked_radio)) + { + // then we retrieve the acquirer name + var acquirer_id = this.getAcquirerIdFromRadio(checked_radio); + // and display its form + this.$('#o_payment_form_acq_' + acquirer_id).removeClass('hidden'); + } }, isNewPaymentRadio: function(element) { - return $(element).data('acquirer-id') !== undefined; + return $(element).data('s2s-payment') === 'True'; + }, + isFormPaymentRadio: function(element) { + return $(element).data('form-payment') === 'True'; }, getAcquirerIdFromRadio: function(element) { return $(element).data('acquirer-id'); }, error: function(title, message, url) { return new Dialog(null, { - title: title || "", - $content: $(core.qweb.render('website.error_dialog', { - message: message || "", - })), - }).open(); + title: _t('Error: ') + title, + size: 'medium', + $content: message || "", + buttons: [ + {text: _t('Ok'), close: true}]}).open(); }, getFormData: function($form){ var unindexed_array = $form.serializeArray(); @@ -249,13 +354,18 @@ odoo.define('payment.payment_form', function (require){ }, start: function() { this.updateNewPaymentDisplayStatus(); + $('[data-toggle="tooltip"]').tooltip(); + }, }); - $(document).ready(function (){ - var form = new PaymentForm(); - form.attachTo($('.o_payment_form')); - }); + require('web.dom_ready'); // only start this when dom is ready + if (!$('.o_payment_form').length) { + return $.Deferred().reject("DOM doesn't contain '.o_payment_form'"); + } + var form = new PaymentForm(); + form.attachTo($('.o_payment_form')); + }); diff --git a/addons/payment/static/src/js/payment_transaction.js b/addons/payment/static/src/js/payment_transaction.js deleted file mode 100644 index eb945f7a220..00000000000 --- a/addons/payment/static/src/js/payment_transaction.js +++ /dev/null @@ -1,81 +0,0 @@ -odoo.define('payment.transaction', function (require) { -"use strict"; - -var ajax = require('web.ajax'); - -$(document).ready(function () { - // When choosing an acquirer, display its Pay Now button - var $payment = $("#payment_method"); - $payment.on("click", "input[name='acquirer'], a.btn_payment_token", function (ev) { - var ico_off = 'fa-circle-o'; - var ico_on = 'fa-dot-circle-o'; - - var payment_id = $(ev.currentTarget).val() || $(this).data('acquirer'); - var token = $(ev.currentTarget).data('token') || ''; - - $("div.o_payment_acquirer_button[data-id='"+payment_id+"']", $payment).attr('data-token', token); - $("div.js_payment a.list-group-item").removeClass("list-group-item-info"); - $('span.js_radio').switchClass(ico_on, ico_off, 0); - if (token) { - $("div.o_payment_acquirer_button div.token_hide").hide(); - $(ev.currentTarget).find('span.js_radio').switchClass(ico_off, ico_on, 0); - $(ev.currentTarget).parents('li').find('input').prop("checked", true); - $(ev.currentTarget).addClass("list-group-item-info"); - } - else{ - $("div.o_payment_acquirer_button div.token_hide").show(); - } - $("div.o_payment_acquirer_button[data-id]", $payment).addClass("hidden"); - $("div.o_payment_acquirer_button[data-id='"+payment_id+"']", $payment).removeClass("hidden"); - - }) - .find("input[name='acquirer']:checked").click(); - - // When clicking on payment button: create the tx using json then continue to the acquirer - $payment.on("click", 'button[type="submit"], button[name="submit"]', function (ev) { - ev.preventDefault(); - ev.stopPropagation(); - var $form = $(ev.currentTarget).parents('form'); - var acquirer = $(ev.currentTarget).parents('div.o_payment_acquirer_button').first(); - var tx_data = acquirer.data(); - if (! tx_data.id || ! tx_data.callUrl) { - return false; - } - - var params = {"tx_type": tx_data.txType || acquirer.find('input[name="odoo_save_token"]').is(':checked') ? 'form_save': 'form'}; - var acquirer_token = acquirer.attr('data-token'); // !=data - if (acquirer_token) { - params.token = acquirer_token; - } - if (tx_data.access_token) { - params.access_token = tx_data.access_token; - } - $form.off('submit'); - ajax.jsonRpc(tx_data.callUrl, 'call', params).then(function (data) { - $(data).appendTo('body').submit(); - }); - return false; - }); - - $('div.oe_pay_token').on('click', 'a.js_btn_valid_tx', function() { - $('div.js_token_load').toggle(); - - var $form = $(this).parents('form'); - ajax.jsonRpc($form.attr('action'), 'call', $.deparam($form.serialize())).then(function (data) { - if (data.url) { - window.location = data.url; - } - else { - $('div.js_token_load').toggle(); - if (!data.success && data.error) { - $('div.oe_pay_token div.panel-body p').html(data.error + "

    " + _('Retry ? ')); - $('div.oe_pay_token div.panel-body').parents('div').removeClass('panel-info').addClass('panel-danger'); - } - } - }); - - }); - -}); - -}); diff --git a/addons/payment/static/src/less/payment_form.less b/addons/payment/static/src/less/payment_form.less index ce6b2aeab6e..b5aeb2e928e 100644 --- a/addons/payment/static/src/less/payment_form.less +++ b/addons/payment/static/src/less/payment_form.less @@ -1,10 +1,10 @@ .o_payment_form { - label > input[type="radio"]{ + label > input[type="radio"], input[type="checkbox"]{ vertical-align: bottom; margin-right: 5px; } - label { + .payment_option_name { font-size: 14px; font-weight: normal !important; font-family: Helvetica Neue, sans-serif; @@ -12,6 +12,10 @@ color: #4d4d4d; } + label { + font-weight: normal; + } + .panel-body:first-child { border-top: 0px; } @@ -29,4 +33,18 @@ border-top: 1px solid #ddd; padding: 1.14em !important; } + + .payment_icon_list { + li { + padding-left: 5px !important; + padding-right: 0px !important; + } + + .more_option { + font-size:10px; + } + + margin-top: 0px !important; + margin-bottom: -5px !important; + } } \ No newline at end of file diff --git a/addons/payment/views/assets.xml b/addons/payment/views/assets.xml index 2c1c6e5a072..c5639ba06d2 100644 --- a/addons/payment/views/assets.xml +++ b/addons/payment/views/assets.xml @@ -4,7 +4,6 @@ - diff --git a/addons/payment/views/payment_portal_templates.xml b/addons/payment/views/payment_portal_templates.xml index 3c8a5e3f5d3..f599329e5e1 100644 --- a/addons/payment/views/payment_portal_templates.xml +++ b/addons/payment/views/payment_portal_templates.xml @@ -19,6 +19,7 @@

    Manage your Payment Methods

    + diff --git a/addons/payment/views/payment_templates.xml b/addons/payment/views/payment_templates.xml index ae9a1501632..81e73aa464b 100644 --- a/addons/payment/views/payment_templates.xml +++ b/addons/payment/views/payment_templates.xml @@ -17,36 +17,100 @@ - 'checked_pm_id' the payment token that should be checked (for radio buttons) - 'mode' can take two values, either 'payment' or 'manage'. 'manage' displays the add a new card and delete buttons. 'payment' display a form that is used to pay and send the information to the form action url. - - 'acquirers' the list of the acquirers + - 's2s_acquirers' the list of the server2server acquirers + - 'form_acquirers' the list of the payment acquirers to pay with forms - 'verify_validity' if we need to verify if the payment method is valid when adding a new one + - 'prepare_tx_url' the url of the route which will handle the creation of a transaction for a form base payment (handles if the transaction is form or form_save) --> -
    + +
    - + + +
    +
    -
    +
    - + + +
    + +
    + + +
    +
    + + +
    +
    + + @@ -376,5 +378,45 @@ parent='root_payment_menu' groups='base.group_no_one'/> + + + payment.icon.form + payment.icon + + + + +
    +

    +
    + + + + + + + +
    + +
    +
    + + + Payment Icons + payment.icon + form + tree,form + +

    + Click to create a payment icon. +

    +
    +
    + + diff --git a/addons/payment_adyen/data/payment_acquirer_data.xml b/addons/payment_adyen/data/payment_acquirer_data.xml index 44d986b8fee..a0b6488663d 100644 --- a/addons/payment_adyen/data/payment_acquirer_data.xml +++ b/addons/payment_adyen/data/payment_acquirer_data.xml @@ -7,7 +7,7 @@ adyen - + test You will be redirected to the Adyen website after clicking on the payment button.

    ]]>
    diff --git a/addons/payment_adyen/views/payment_adyen_templates.xml b/addons/payment_adyen/views/payment_adyen_templates.xml index 4b8d178ef69..4f4d21811a2 100644 --- a/addons/payment_adyen/views/payment_adyen_templates.xml +++ b/addons/payment_adyen/views/payment_adyen_templates.xml @@ -1,36 +1,27 @@ - -