diff --git a/addons/payment/controllers/portal.py b/addons/payment/controllers/portal.py index 4047ef7d30a..444d936429b 100644 --- a/addons/payment/controllers/portal.py +++ b/addons/payment/controllers/portal.py @@ -31,49 +31,110 @@ class WebsitePayment(http.Controller): currency_id = currency_id and int(currency_id) or user.company_id.currency_id.id currency = env['res.currency'].browse(currency_id) - # Try default one then fallback on first - acquirer_id = acquirer_id and int(acquirer_id) or \ - env['ir.default'].get('payment.transaction', 'acquirer_id', company_id=user.company_id.id) or \ - env['payment.acquirer'].search([('website_published', '=', True), ('company_id', '=', user.company_id.id)])[0].id - - acquirer = env['payment.acquirer'].with_context(submit_class='btn btn-primary pull-right', - submit_txt=_('Pay Now')).browse(acquirer_id) + acquirers = None + if acquirer_id: + acquirers = env['payment.acquirer'].browse(int(acquirer_id)) + if not acquirers: + acquirers = env['payment.acquirer'].search([('website_published', '=', True), ('company_id', '=', user.company_id.id)]) # auto-increment reference with a number suffix if the reference already exists reference = request.env['payment.transaction'].get_next_reference(reference) partner_id = user.partner_id.id if not user._is_public() else False - payment_form = acquirer.sudo().render(reference, float(amount), currency.id, values={'return_url': '/website_payment/confirm', 'partner_id': partner_id}) values = { 'reference': reference, - 'acquirer': acquirer, 'currency': currency, 'amount': float(amount), - 'payment_form': payment_form, + 'return_url': '/website_payment/confirm', + 'partner_id': partner_id, + 'bootstrap_formatting': True, + 'error_msg': kw.get('error_msg') } - # TODO: remove return when payment is implemented with refactored payments, i.e. use of - # payment.payment_tokens_list in the template. - # return request.render('payment.pay', values) - return request.render('website.404') - @http.route(['/website_payment/transaction'], type='json', auth="public", website=True) - def transaction(self, reference, amount, currency_id, acquirer_id): + values['s2s_acquirers'] = [acq for acq in acquirers if acq.payment_flow == 's2s'] + values['form_acquirers'] = [acq for acq in acquirers if acq.payment_flow == 'form'] + values['pms'] = request.env['payment.token'].search([('acquirer_id', 'in', [acq.id for acq in values['s2s_acquirers']])]) + + return request.render('payment.pay', values) + + def _get_existing_transaction(self, reference, amount, partner_id, currency_id, acquirer_id, tx_id): + PaymentTransaction = request.env['payment.transaction'] + tx = None + if tx_id: + tx = PaymentTransaction.sudo().browse(tx_id) + if not tx.exists() or tx.reference != reference or tx.acquirer_id.id != acquirer_id: + tx = None + + if not tx: + tx = PaymentTransaction.sudo().search([('reference', '=', reference), ('acquirer_id', '=', acquirer_id)]) + + if tx and (tx.state != 'draft' or tx.partner_id.id != partner_id or tx.amount != amount or tx.currency_id.id != currency_id): + tx = None + + return tx + + @http.route(['/website_payment/transaction///',], type='json', auth='public') + def transaction(self, acquirer_id, reference, amount, currency_id, **kwargs): partner_id = request.env.user.partner_id.id if not request.env.user._is_public() else False + acquirer = request.env['payment.acquirer'].browse(acquirer_id) + + tx = self._get_existing_transaction(reference, float(amount), partner_id, + int(currency_id), int(acquirer_id), request.session.get('website_payment_tx_id')) + + if not tx: + values = { + 'acquirer_id': int(acquirer_id), + 'reference': reference, + 'amount': float(amount), + 'currency_id': currency_id, + 'partner_id': partner_id, + } + + tx = request.env['payment.transaction'].sudo().create(values) + request.session['website_payment_tx_id'] = tx.id + + render_values = { + 'return_url': '/website_payment/confirm?tx_id=%d' % tx.id, + 'partner_id': partner_id, + } + + return acquirer.sudo().render(reference, float(amount), int(currency_id), values=render_values) + + @http.route(['/website_payment/token///'], type='http', auth='public', website=True) + def payment_token(self, pm_id, reference, amount, currency_id, return_url=None, **kwargs): + token = request.env['payment.token'].browse(int(pm_id)) + + if not token: + return request.redirect('/website_payment/pay?error_msg=%s' % _('Cannot setup the payment.')) + + partner_id = request.env.user.partner_id.id if not request.env.user._is_public() else False + values = { - 'acquirer_id': int(acquirer_id), + 'acquirer_id': token.acquirer_id.id, 'reference': reference, 'amount': float(amount), 'currency_id': int(currency_id), 'partner_id': partner_id, + 'payment_token_id': pm_id } tx = request.env['payment.transaction'].sudo().create(values) request.session['website_payment_tx_id'] = tx.id - return tx.id + + try: + res = tx.s2s_do_transaction() + except Exception as e: + return request.redirect('/website_payment/pay?error_msg=%s' % _('Payment transaction failed.')) + + valid_state = 'authorized' if tx.acquirer_id.capture_manually else 'done' + if not res or tx.state != valid_state: + return request.redirect('/website_payment/pay?error_msg=%s' % _('Payment transaction failed.')) + + return request.redirect(return_url if return_url else '/website_payment/confirm?tx_id=%d' % tx.id) @http.route(['/website_payment/confirm'], type='http', auth='public', website=True) def confirm(self, **kw): - tx_id = request.session.pop('website_payment_tx_id', False) + tx_id = int(kw.get('tx_id', 0)) or request.session.pop('website_payment_tx_id', 0) if tx_id: tx = request.env['payment.transaction'].browse(tx_id) if tx.state == 'done': diff --git a/addons/payment/static/src/js/payment_transaction_portal.js b/addons/payment/static/src/js/payment_transaction_portal.js index 26c0fb35d1e..094149b6274 100644 --- a/addons/payment/static/src/js/payment_transaction_portal.js +++ b/addons/payment/static/src/js/payment_transaction_portal.js @@ -1,24 +1,2 @@ -odoo.define('payment.website_payment', function (require) { -"use strict"; - -require('web.dom_ready'); -var ajax = require('web.ajax'); - - if (!$('.o_website_payment').length) { - return $.Deferred().reject("DOM doesn't contain '.o_website_payment'"); - } - - // When clicking on payment button: create the tx using json then continue to the acquirer - var $payment = $(".o_website_payment_form"); - $payment.on("click", 'button[type="submit"],button[name="submit"]', function (ev) { - ev.preventDefault(); - ev.stopPropagation(); - $(ev.currentTarget).attr('disabled', true); - $(ev.currentTarget).prepend(' '); - var $form = $(ev.currentTarget).parents('form'); - var data =$("div[class~='o_website_payment_new_payment']").data(); - ajax.jsonRpc('/website_payment/transaction/', 'call', data).then(function (result) { - $form.submit(); - }); - }); -}); +// This file is kept to avoid breaking assets compilation on instance that didn't run "-u payment". +// TBE TODO: Remove me in master \ No newline at end of file diff --git a/addons/payment/views/payment_portal_templates.xml b/addons/payment/views/payment_portal_templates.xml index d2fa3c1c4cd..166cd429718 100644 --- a/addons/payment/views/payment_portal_templates.xml +++ b/addons/payment/views/payment_portal_templates.xml @@ -46,32 +46,22 @@

Payment

-
-
-
-
-
-
- -
- -
-
-
- -
- -
-
-
-
-
- - Processed by . -
-
+
+ +
+
+
+

Reference:

+

Amount:

+ + + + + +
+

No payment acquirer found.

+

Please configure a payment acquirer.

-
diff --git a/addons/payment_stripe/static/src/js/stripe.js b/addons/payment_stripe/static/src/js/stripe.js index a9395ea7bd6..7ecf25284f6 100644 --- a/addons/payment_stripe/static/src/js/stripe.js +++ b/addons/payment_stripe/static/src/js/stripe.js @@ -108,11 +108,14 @@ odoo.define('payment_stripe.stripe', function(require) { if ($('.o_website_payment').length !== 0) { - var create_tx = ajax.jsonRpc('/website_payment/transaction', 'call', { - reference: $("input[name='invoice_num']").val(), - amount: amount, // exact amount, not stripe cents - currency_id: currency_id, + var invoice_num = $("input[name='invoice_num']").val(); + var url = _.str.sprintf("/website_payment/transaction/%s/%f/%s", + invoice_num, amount, currency_id); + + var create_tx = ajax.jsonRpc(url, 'call', { acquirer_id: acquirer_id + }).then(function (data) { + try { provider_form[0].innerHTML = data; } catch (e) {} }); } else if ($('.o_website_quote').length !== 0) {