1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
|
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import http, _
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), ('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,
'error_message': [kwargs['error']] if kwargs.get('error') else False,
'return_url': return_url,
'bootstrap_formatting': True,
'partner_id': partner.id
}
return request.render("payment.pay_methods", values)
@http.route(['/website_payment/pay'], type='http', auth='public', website=True)
def pay(self, reference='', amount=False, currency_id=None, acquirer_id=None, **kw):
env = request.env
user = env.user.sudo()
currency_id = currency_id and int(currency_id) or user.company_id.currency_id.id
currency = env['res.currency'].browse(currency_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
values = {
'reference': reference,
'currency': currency,
'amount': float(amount),
'return_url': '/website_payment/confirm',
'partner_id': partner_id,
'bootstrap_formatting': True,
'error_msg': kw.get('error_msg')
}
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/<string:reference>/<string:amount>/<string:currency_id>',
'/website_payment/transaction/v2/<string:amount>/<string:currency_id>/<path:reference>',], 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,
'type': 'form_save' if acquirer.save_token != 'none' and partner_id else 'form',
}
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/<string:reference>/<string:amount>/<string:currency_id>',
'/website_payment/token/v2/<string:amount>/<string:currency_id>/<path:reference>'], 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': token.acquirer_id.id,
'reference': reference,
'amount': float(amount),
'currency_id': int(currency_id),
'partner_id': partner_id,
'payment_token_id': pm_id,
'type': 'form_save' if token.acquirer_id.save_token != 'none' and partner_id else 'form',
}
tx = request.env['payment.transaction'].sudo().create(values)
request.session['website_payment_tx_id'] = 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 = 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':
status = 'success'
message = tx.acquirer_id.done_msg
elif tx.state == 'pending':
status = 'warning'
message = tx.acquirer_id.pending_msg
else:
status = 'danger'
message = tx.acquirer_id.error_msg
return request.render('payment.confirm', {'tx': tx, 'status': status, 'message': message})
else:
return request.redirect('/my/home')
|