diff options
| author | tbe-odoo <tbe@odoo.com> | 2017-08-23 15:51:39 +0200 |
|---|---|---|
| committer | tbe-odoo <tbe@odoo.com> | 2017-08-29 17:11:23 +0200 |
| commit | 194d52e8fda35f7a6fd9a9e5c2e1af265e25ce4b (patch) | |
| tree | 925cb915000cdc0be69848d81a1864e1446ead4a | |
| parent | 3c062d934553bc4693bde6bd831fd2a3d6e9423c (diff) | |
[IMP] website_quote/sale,payment: Support of the new payment form
- Online quotation and e-commerce now use the new payment form.
- Added the ability to chose on an acquirer if it uses only form/s2s or both.
(Still need some code cleaning)
| -rw-r--r-- | addons/payment/controllers/portal.py | 2 | ||||
| -rw-r--r-- | addons/payment/models/payment_acquirer.py | 9 | ||||
| -rw-r--r-- | addons/payment/static/src/js/payment_form.js | 38 | ||||
| -rw-r--r-- | addons/payment/static/src/js/payment_transaction.js | 81 | ||||
| -rw-r--r-- | addons/payment/static/src/less/payment_form.less | 8 | ||||
| -rw-r--r-- | addons/payment/views/assets.xml | 1 | ||||
| -rw-r--r-- | addons/payment/views/payment_templates.xml | 39 | ||||
| -rw-r--r-- | addons/payment/views/payment_views.xml | 1 | ||||
| -rw-r--r-- | addons/website_quote/controllers/main.py | 81 | ||||
| -rw-r--r-- | addons/website_quote/views/website_quote_templates.xml | 56 | ||||
| -rw-r--r-- | addons/website_sale/controllers/main.py | 57 | ||||
| -rw-r--r-- | addons/website_sale/views/templates.xml | 6 |
12 files changed, 183 insertions, 196 deletions
diff --git a/addons/payment/controllers/portal.py b/addons/payment/controllers/portal.py index dc402446ea3..9d06665d021 100644 --- a/addons/payment/controllers/portal.py +++ b/addons/payment/controllers/portal.py @@ -8,7 +8,7 @@ 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), ('prefered_payment_type', 'in', ['s2s', 'both'])])) partner = request.env.user.partner_id payment_tokens = partner.payment_token_ids payment_tokens |= partner.commercial_partner_id.sudo().payment_token_ids diff --git a/addons/payment/models/payment_acquirer.py b/addons/payment/models/payment_acquirer.py index 325f58c3aff..365e8d14b37 100644 --- a/addons/payment/models/payment_acquirer.py +++ b/addons/payment/models/payment_acquirer.py @@ -151,6 +151,15 @@ class PaymentAcquirer(models.Model): "Use this field anywhere a small image is required.") payment_option_ids = fields.Many2many('payment.option', string='Supported Payment Option') + prefered_payment_type = fields.Selection(selection=[('s2s','Server to server'), + ('form', 'Form'), + ('both', 'Both') + ], default='form', required=True, string='Prefered payment type', help="""Which payment type you wish to use. + - Form: Redirect the user to the payment acquirer website to pay. + - Server to server: The user enter his credit card information on your website and is processed by Odoo. + - Both: Both are displayed to the user. + + 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'] diff --git a/addons/payment/static/src/js/payment_form.js b/addons/payment/static/src/js/payment_form.js index bf8f490a493..5da7cfbe2ea 100644 --- a/addons/payment/static/src/js/payment_form.js +++ b/addons/payment/static/src/js/payment_form.js @@ -77,23 +77,55 @@ odoo.define('payment.payment_form', function (require){ // 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"]'); // Here we take the values we need to send to the acquirer and generate a form with them var html_form = '<form method="post" action="' + ds.dataset.actionUrl + '" class="hidden">'; + var ignored_inputs = ['data_set', 'o_payment_form_save_token']; for(var i = 0; i < inputs_form.length; i ++) { - if(inputs_form[i].name != "data_set") { + if(ignored_inputs.indexOf(inputs_form[i].name) == -1) { html_form +='<input name="' + inputs_form[i].name + '" value="' + inputs_form[i].value + '"/>'; } + else if(inputs_form[i].name == 'o_payment_form_save_token') { + form_save_token = inputs_form[i].checked; + } } html_form += '</form>'; - // we append the form to the body and send it. - $(html_form).appendTo("body").submit(); + + // if there's a prepare tx url set + if($tx_url.length == 1) + { + // 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) { + // we append the form to the body and send it. + $(html_form).appendTo("body").submit(); + } + else { + self.error(_t('Server Error'), + _t("<p>We are not able to redirect you to the payment form.</p>")); + } + }).fail(function(message, data){ + self.error(_t('Server Error'), + _t("<p>We are not able to redirect you to the payment form.</p>") + (core.debug ? data.data.message : '')); + }); + } + else + { + // we append the form to the body and send it. + $(html_form).appendTo("body").submit(); + } } // if the user is using an old payment else { 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 + "<br/><br/>" + _('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..14bb9ef8559 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; } 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 @@ <xpath expr="." position="inside"> <link rel='stylesheet' href='/payment/static/src/css/portal_payment.css'/> <script type="text/javascript" src="/payment/static/lib/jquery.payment/jquery.payment.js"></script> - <script type="text/javascript" src="/payment/static/src/js/payment_transaction.js"></script> <script type="text/javascript" src="/payment/static/src/js/payment_portal.js"></script> <script type="text/javascript" src="/payment/static/src/js/payment_transaction_portal.js"></script> <script type="text/javascript" src="/payment/static/src/js/payment_form.js"></script> diff --git a/addons/payment/views/payment_templates.xml b/addons/payment/views/payment_templates.xml index 57bdae3b1c0..fd693681ae0 100644 --- a/addons/payment/views/payment_templates.xml +++ b/addons/payment/views/payment_templates.xml @@ -20,30 +20,44 @@ - '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) --> <form t-if="s2s_acquirers or pms or form_acquirers" method="post" t-att-action="form_action if form_action else '#'" class="o_payment_form"> <input type="hidden" name="csrf_token" t-att-value="request.csrf_token()"/> <input type="hidden" t-if="verify_validity==True" name="verify_validity" value="1"/> + <input type="hidden" t-if="prepare_tx_url" name="prepare_tx_url" t-att-value="prepare_tx_url"/> <div class="panel panel-default"> + <t t-set="acquirers_count" t-value="(len(s2s_acquirers) if s2s_acquirers else 0) + (len(form_acquirers) if form_acquirers else 0)"/> + <t t-set="pms_count" t-value="len(pms) if pms else 0"/> <t t-foreach="s2s_acquirers" t-as="acq"> <div class="panel-body"> <label> <t t-if="mode == 'manage'"> - <input type="radio" t-att-data-acquirer-id="acq.id" t-att-data-s2s-payment="true" name="pm_id" t-attf-value="new_{{acq.id}}" t-att-class="'hidden' if (len(s2s_acquirers)==1) else ''" t-att-checked="len(s2s_acquirers) == 1"/> + <input type="radio" t-att-data-acquirer-id="acq.id" + t-att-data-s2s-payment="true" + t-att-data-provider="acq.provider" + name="pm_id" t-attf-value="new_{{acq.id}}" + t-att-class="'hidden' if acquirers_count==1 else ''" + t-att-checked="acquirers_count == 1"/> </t> <t t-else=""> - <input type="radio" t-att-data-acquirer-id="acq.id" t-att-data-s2s-payment="true" name="pm_id" t-attf-value="new_{{acq.id}}" t-att-class="'hidden' if (len(s2s_acquirers)==1 and len(pms)==0) else ''" t-att-checked="len(s2s_acquirers)==1 and len(pms)==0"/> + <input type="radio" t-att-data-acquirer-id="acq.id" + t-att-data-s2s-payment="true" + t-att-data-provider="acq.provider" + name="pm_id" t-attf-value="new_{{acq.id}}" + t-att-class="'hidden' if (acquirers_count==1 and pms_count==0) else ''" + t-att-checked="acquirers_count==1 and pms_count==0"/> </t> - <t t-esc="acq.name"/> + <span class="payment_option_name" t-esc="acq.name"/> </label> - <ul class="pull-right list-inline"> + <!-- <ul class="pull-right list-inline"> <t t-foreach="acq.payment_option_ids" t-as="pm_option"> <li> <span t-field="pm_option.image_small" t-options='{"widget": "image", "alt-field": "name"}' /> </li> </t> - </ul> + </ul> --> </div> <div t-attf-id="o_payment_add_token_acq_{{acq.id}}" t-attf-class="panel-footer {{'hidden' if (len(s2s_acquirers)>1 and len(pms)==0 and s2s_acquirers[0]!=acq) else 'hidden' if len(pms)>0 else ''}}"> <div class="clearfix"> @@ -54,13 +68,18 @@ <t tif="mode == 'payment'" t-foreach="form_acquirers" t-as="acq"> <div class="panel-body"> <label> - <!-- TBE TODO: Tout le schmilblick du hidden et checked (pareil pour le s2s juste au dessus) --> - <input type="radio" t-att-data-acquirer-id="acq.id" t-att-data-form-payment="true" name="pm_id" t-attf-value="form_{{acq.id}}"/> - <t t-esc="acq.name"/> + <input type="radio" t-att-data-acquirer-id="acq.id" + t-att-data-form-payment="true" + t-att-data-provider="acq.provider" + t-att-class="'hidden' if (acquirers_count==1 and pms_count==0) else ''" + t-att-checked="acquirers_count==1 and pms_count==0" + name="pm_id" t-attf-value="form_{{acq.id}}"/> + <span class="payment_option_name" t-esc="acq.name"/> </label> </div> <div t-attf-id="o_payment_form_acq_{{acq.id}}" class="panel-footer hidden"> - You'll be redirected to the <t t-esc="acq.provider"/> website after clicking on the payment button. + <p>You'll be redirected to the <t t-esc="acq.provider"/> website after clicking on the payment button.</p> + <label t-if="acq.save_token == 'ask'"><input type="checkbox" name="o_payment_form_save_token"/> Save my payment data</label> <t t-raw="acq.form"/> </div> </t> @@ -68,7 +87,7 @@ <div class="panel-body"> <label> <input t-if="mode == 'payment'" type="radio" name="pm_id" t-att-value="pm.id" t-att-checked="checked_pm_id == pm.id"/> - <t t-esc="pm.name"/> + <span class="payment_option_name" t-esc="pm.name"/> <t t-if="pm.verified"> <i class="fa fa-check text-success" title="This payment method is verified by our system."></i> </t> diff --git a/addons/payment/views/payment_views.xml b/addons/payment/views/payment_views.xml index 6b67db74ec6..caf505edbed 100644 --- a/addons/payment/views/payment_views.xml +++ b/addons/payment/views/payment_views.xml @@ -113,6 +113,7 @@ </div> <field name="registration_view_template_id" groups="base.group_no_one"/> <field name="payment_option_ids" widget="many2many_tags"/> + <field name="prefered_payment_type"/> </group> </page> </notebook> diff --git a/addons/website_quote/controllers/main.py b/addons/website_quote/controllers/main.py index c0b0648bfd8..8098964c71e 100644 --- a/addons/website_quote/controllers/main.py +++ b/addons/website_quote/controllers/main.py @@ -64,23 +64,29 @@ class sale_quote(http.Controller): } if order_sudo.require_payment or values['need_payment']: - values['acquirers'] = list(request.env['payment.acquirer'].sudo().search([('website_published', '=', True), ('company_id', '=', order_sudo.company_id.id)])) - extra_context = { - 'submit_class': 'btn btn-primary', - 'submit_txt': _('Pay & Confirm') - } - values['buttons'] = {} - for acquirer in values['acquirers']: - values['buttons'][acquirer.id] = acquirer.with_context(**extra_context).render( - '/', - order_sudo.amount_total, - order_sudo.pricelist_id.currency_id.id, + acquirers = request.env['payment.acquirer'].sudo().search([('website_published', '=', True), ('company_id', '=', order_sudo.company_id.id)]) + + values['form_acquirers'] = [acq for acq in acquirers if acq.prefered_payment_type in ['form', 'both'] and acq.view_template_id] + values['s2s_acquirers'] = [acq for acq in acquirers if acq.prefered_payment_type in ['s2s', 'both'] and acq.registration_view_template_id] + values['pms'] = request.env['payment.token'].search( + [('partner_id', '=', order_sudo.partner_id.id), + ('acquirer_id', 'in', [acq.id for acq in values['s2s_acquirers']])]) + + for acq in values['form_acquirers']: + acq.form = acq.render('/', order_sudo.amount_total, order_sudo.pricelist_id.currency_id.id, values={ 'return_url': '/quote/%s/%s' % (order_id, token) if token else '/quote/%s' % order_id, 'type': 'form', 'alias_usage': _('If we store your payment information on our server, subscription payments will be made automatically.'), 'partner_id': order_sudo.partner_id.id, }) + + for acq in values['s2s_acquirers']: + acq.form = acq._registration_render(order_sudo.partner_id.id, { + 'return_url': '/shop/payment/validate', + 'bootstrap_formatting': True + }) + history = request.session.get('my_quotes_history', []) values.update(get_records_pager(history, order_sudo)) return request.render('website_quote.so_quotation', values) @@ -158,8 +164,8 @@ class sale_quote(http.Controller): return werkzeug.utils.redirect("/quote/%s/%s#pricing" % (Order.id, token)) # note dbo: website_sale code - @http.route(['/quote/<int:order_id>/transaction/<int:acquirer_id>'], type='json', auth="public", website=True) - def payment_transaction_token(self, acquirer_id, order_id, access_token=None, tx_type=None): + @http.route(['/quote/<int:order_id>/transaction/'], type='json', auth="public", website=True) + def payment_transaction_token(self, acquirer_id, order_id, save_token=False,access_token=None): """ Json method that creates a payment.transaction, used to create a transaction when the user clicks on 'pay now' button. After having created the transaction, the event continues and the user is redirected @@ -170,7 +176,8 @@ class sale_quote(http.Controller): """ order = request.env['sale.order'].sudo().browse(order_id) if not order or not order.order_line or acquirer_id is None: - return request.redirect("/quote/%s" % order_id) + return False + # return request.redirect("/quote/%s" % order_id) # find an already existing transaction acquirer = request.env['payment.acquirer'].browse(int(acquirer_id)) @@ -184,8 +191,44 @@ class sale_quote(http.Controller): }) request.session['quote_%s_transaction_id' % order.id] = tx.id - return tx.render_sale_button(order, '/quote/%s/%s' % (order_id, token) if token else '/quote/%s' % order_id, - submit_txt=_('Pay & Confirm'), render_values={ - 'type': order._get_payment_type(), - 'alias_usage': _('If we store your payment information on our server, subscription payments will be made automatically.'), - }) + return True + # return tx.render_sale_button(order, '/quote/%s/%s' % (order_id, token) if token else '/quote/%s' % order_id, + # submit_txt=_('Pay & Confirm'), render_values={ + # 'type': order._get_payment_type(), + # 'alias_usage': _('If we store your payment information on our server, subscription payments will be made automatically.'), + # }) + + @http.route('/quote/<int:order_id>/transaction/token', type='http', auth='public', website=True) + def payment_token(self, order_id, pm_id=None, **kwargs): + + order = request.env['sale.order'].sudo().browse(order_id) + if not order or not order.order_line or pm_id is None: + return request.redirect("/quote/%s" % order_id) + + # try to convert pm_id into an integer, if it doesn't work redirect the user to the quote + try: + pm_id = int(pm_id) + except ValueError: + return request.redirect('/quote/%s' % order_id) + + # retrieve the token from its id + token = request.env['payment.token'].sudo().browse(pm_id) + if not token: + return request.redirect('/quote/%s' % order_id) + + # find an already existing transaction + tx = request.env['payment.transaction'].sudo().search([('reference', '=', order.name)], limit=1) + # set the transaction type to server2server + tx_type = 'server2server' + # check if the transaction exists, if not then it create one + tx = tx.check_or_create_sale_tx(order, token.acquirer_id, payment_token=token, tx_type=tx_type, add_tx_values={ + 'callback_model_id': request.env['ir.model'].sudo().search([('model', '=', order._name)], limit=1).id, + 'callback_res_id': order.id, + 'callback_method': '_confirm_online_quote', + }) + # set the transaction id into the session + request.session['quote_%s_transaction_id' % order_id] = tx.id + # proceed to the payment + tx.confirm_sale_token() + # redirect the user to the online quote + return request.redirect('/quote/%s/%s' % (order_id, order.access_token)) diff --git a/addons/website_quote/views/website_quote_templates.xml b/addons/website_quote/views/website_quote_templates.xml index 92e9dbbc846..6931631528c 100644 --- a/addons/website_quote/views/website_quote_templates.xml +++ b/addons/website_quote/views/website_quote_templates.xml @@ -306,7 +306,7 @@ </div> </div> <div class="modal-footer"> - <div t-if="not acquirers"> + <div t-if="not (pms or s2s_acquirers or form_acquirers)"> <button type="submit" t-attf-class="btn btn-primary">Sign & Confirm</button> <button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button> </div> @@ -327,48 +327,18 @@ t-options='{"widget": "monetary", "display_currency": quotation.pricelist_id.currency_id}'/> <span>with payment terms: </span><b t-field="quotation.payment_term_id"/>. </p> - </div> - <div class="modal-footer"> - <!-- begin website_sale code --> - <div t-if="acquirers" id="payment_method" class="row text-left"> - <div class="col-md-6"> - <h4>Payment Acquirer:</h4> - <ul class="list-unstyled"> - <t t-set="payment_methods_available" t-value="False"/> - <li t-foreach="acquirers or []" t-as="acquirer"> - <t t-if="not acquirer.country_ids or quotation and quotation.partner_id.country_id in acquirer.country_ids"> - <label t-if="buttons.get(acquirer.id)"> - <input t-att-value="acquirer.id" type="radio" name="acquirer" t-att-checked="acquirers[0] == acquirer"/> - <img class="media-object" style="width: 60px; display: inline-block;" - t-att-title="acquirer.name" - t-att-src="'/payment_%s/static/src/img/%s_icon.png' % (acquirer.provider, acquirer.provider)"/> - <span t-field="acquirer.name"/> - </label> - <t t-set="payment_methods_available" t-value="True"/> - </t> - </li> - <li t-if="not payment_methods_available"> - <div class="alert alert-warning"> - <span>No payment gateway is available for your country</span> - </div> - </li> - </ul> - </div> - <div class="col-md-6"> - <t t-foreach="acquirers or []" t-as="acquirer"> - <div class="o_payment_acquirer_button hidden pull-right" - t-att-data-id="acquirer.id" - t-att-data-access-token="token or ''" - t-att-data-tx-type="form" - t-att-data-call-url="'/quote/%s/transaction/%s' % (quotation.id, acquirer.id)"> - <div t-raw="buttons.get(acquirer.id)"/> - <div t-field="acquirer.pre_msg"/> - </div> - </t> - <button type="button" class="btn btn-link" data-dismiss="modal" style="padding: 0">Cancel</button> - </div> - </div> - <!-- end website_sale code --> + </div> + <div class="modal-footer"> + <div t-if="pms or s2s_acquirers or form_acquirers" id="payment_method" class="text-left col-md-13"> + <h3 class="mb24">Pay with</h3> + <t t-call="payment.payment_tokens_list"> + <t t-set="mode" t-value="'payment'"/> + <t t-set="submit_txt" t-value="'Pay & Confirm'"/> + <t t-set="icon_class" t-value="'fa-lock'"/> + <t t-set="form_action" t-value="'/quote/' + str(quotation.id) + '/transaction/token'"/> + <t t-set="prepare_tx_url" t-value="'/quote/' + str(quotation.id) + '/transaction/'"/> + </t> + </div> </div> </div> </div> diff --git a/addons/website_sale/controllers/main.py b/addons/website_sale/controllers/main.py index 567c875b12d..9bd4ce76b1d 100644 --- a/addons/website_sale/controllers/main.py +++ b/addons/website_sale/controllers/main.py @@ -714,8 +714,11 @@ class WebsiteSale(http.Controller): [('website_published', '=', True), ('company_id', '=', order.company_id.id)] ) - values['form_acquirers'] = [acq for acq in acquirers if acq.view_template_id] - values['s2s_acquirers'] = [acq for acq in acquirers if acq.registration_view_template_id] + values['form_acquirers'] = [acq for acq in acquirers if acq.prefered_payment_type in ['form', 'both'] and acq.view_template_id] + values['s2s_acquirers'] = [acq for acq in acquirers if acq.prefered_payment_type in ['s2s', 'both'] and acq.registration_view_template_id] + values['tokens'] = request.env['payment.token'].search( + [('partner_id', '=', order.partner_id.id), + ('acquirer_id', 'in', [acq.id for acq in values['s2s_acquirers']])]) for acq in values['form_acquirers']: acq.form = acq.with_context(submit_class='btn btn-primary', submit_txt=_('Pay Now')).sudo().render( @@ -730,30 +733,11 @@ class WebsiteSale(http.Controller): ) for acq in values['s2s_acquirers']: - acq.form = acq.sudo()._registration_render(order.partner_id.id, { + acq.form = acq._registration_render(order.partner_id.id, { 'return_url': '/shop/payment/validate', 'bootstrap_formatting': True }) - - values['acquirers'] = [] - for acquirer in acquirers: - acquirer_button = acquirer.with_context(submit_class='btn btn-primary', submit_txt=_('Pay Now')).sudo().render( - '/', - order.amount_total, - order.pricelist_id.currency_id.id, - values={ - 'return_url': '/shop/payment/validate', - 'partner_id': shipping_partner_id, - 'billing_partner_id': order.partner_invoice_id.id, - } - ) - acquirer.button = acquirer_button #TBE TODO: remove this line - acquirer.form = acquirer_button - # values['acquirers'].append(acquirer) - - values['tokens'] = request.env['payment.token'].search([('partner_id', '=', order.partner_id.id), ('acquirer_id', 'in', acquirers.ids)]) - return values @http.route(['/shop/payment'], type='http', auth="public", website=True) @@ -801,8 +785,10 @@ class WebsiteSale(http.Controller): else: return request.redirect("/shop/payment?error=no_token_or_missmatch_tx") - @http.route(['/shop/payment/transaction/<int:acquirer_id>'], type='json', auth="public", website=True) - def payment_transaction(self, acquirer_id, tx_type='form', token=None, **kwargs): + @http.route(['/shop/payment/transaction/', + '/shop/payment/transaction/<int:so_id>', + '/shop/payment/transaction/<int:so_id>/<string:access_token>'], type='json', auth="public", website=True) + def payment_transaction(self, acquirer_id, save_token=False, so_id=None, access_token=None, token=None, **kwargs): """ Json method that creates a payment.transaction, used to create a transaction when the user clicks on 'pay now' button. After having created the transaction, the event continues and the user is redirected @@ -811,10 +797,11 @@ class WebsiteSale(http.Controller): :param int acquirer_id: id of a payment.acquirer record. If not set the user is redirected to the checkout page """ + tx_type = 'form' + if save_token: + tx_type = 'form_save' # In case the route is called directly from the JS (as done in Stripe payment method) - so_id = kwargs.get('so_id') - access_token = kwargs.get('access_token') if so_id and access_token: order = request.env['sale.order'].sudo().search([('id', '=', so_id), ('access_token', '=', access_token)]) elif so_id: @@ -822,7 +809,8 @@ class WebsiteSale(http.Controller): else: order = request.website.sale_get_order() if not order or not order.order_line or acquirer_id is None: - return request.redirect("/shop/checkout") + # return request.redirect("/shop/checkout") + return False assert order.partner_id.id != request.website.partner_id.id @@ -833,13 +821,14 @@ class WebsiteSale(http.Controller): tx = tx.check_or_create_sale_tx(order, acquirer, payment_token=payment_token, tx_type=tx_type) request.session['sale_transaction_id'] = tx.id - if token: - return request.env.ref('website_sale.payment_token_form').render(dict(tx=tx), engine='ir.qweb') + # if token: + # return request.env.ref('website_sale.payment_token_form').render(dict(tx=tx), engine='ir.qweb') - return tx.render_sale_button(order, '/shop/payment/validate') + return True + # return tx.render_sale_button(order, '/shop/payment/validate') @http.route('/shop/payment/token', type='http', auth='public', website=True) - def payment_token(self, pm_id=None, **kw): + def payment_token(self, pm_id=None, **kwargs): """ Method that handles payment using saved tokens :param int pm_id: id of the payment.token that we want to use to pay. @@ -854,13 +843,13 @@ class WebsiteSale(http.Controller): try: pm_id = int(pm_id) except ValueError: - pm_id = False - - if not pm_id: return request.redirect('/shop/?error=invalid_token_id') # We retrieve the token the user want to use to pay token = request.env['payment.token'].browse(pm_id) + if not token: + return request.redirect('/shop/?error=token_not_found') + # we retrieve an existing transaction (if it exists obviously) tx = request.website.sale_get_transaction() or request.env['payment.transaction'].sudo() # we check if the transaction is Ok, if not then we create it diff --git a/addons/website_sale/views/templates.xml b/addons/website_sale/views/templates.xml index 60d66e7ef03..af10178c691 100644 --- a/addons/website_sale/views/templates.xml +++ b/addons/website_sale/views/templates.xml @@ -1333,10 +1333,12 @@ <t t-set="icon_class" t-value="'fa-lock'"/> <t t-set="pms" t-value="tokens"/> <t t-set="form_action" t-value="'/shop/payment/token'"/> + <t t-set="prepare_tx_url" t-value="'/shop/payment/transaction/'"/> </t> </div> - <div class="js_payment mb64 col-md-12 row" t-if="acquirers and website_sale_order.amount_total" id="payment_method"> + <!-- TBE TODO: Virer tout ce qu'il y a en bas et qui est inutile maintenant --> + <!-- <div class="js_payment mb64 col-md-12 row" t-if="acquirers and website_sale_order.amount_total" id="payment_method"> <div class="col-lg-7 col-sm-8"> <h4>Choose a payment acquirer</h4> <ul class="list-unstyled"> @@ -1412,7 +1414,7 @@ </a> </form> </div> - </div> + </div> --> </div> </div> |
