Files
odoo_source/addons/payment_stripe/controllers/main.py
T
Toufik Benjaa 6ed44181d0 [IMP] payment_*: payment acquirers error handling
This commit aims to improve the user experience when using payment acquirers. There currently are no error feedback with some acquirers, which leaves the user wondering what is going on and what is the real status of its payment.
In some cases, the user is currently being redirected to the home page even though the payment has failed. We want to make it more obvious to the user that something unexpected has happened by redirecting to an intermediate page that will provide good feedback on payments status.

Another goal of this commit is to order acquirers by sequence instead of by flow and to select the first acquirer by default. This feature was already implmented in commit fe294fd43e521bd2d339e962f43acf46c3d4cb97, some UI adaptations were needed though.

Related to task #36680
Closes #26958
2018-09-19 18:25:32 +02:00

100 lines
3.9 KiB
Python

# -*- coding: utf-8 -*-
import logging
import pprint
import werkzeug
from odoo import http
from odoo.http import request
from odoo.addons.payment.controllers.portal import PaymentProcessing
_logger = logging.getLogger(__name__)
class StripeController(http.Controller):
@http.route(['/payment/stripe/s2s/create_json'], type='json', auth='public')
def stripe_s2s_create_json(self, **kwargs):
acquirer_id = int(kwargs.get('acquirer_id'))
acquirer = request.env['payment.acquirer'].browse(acquirer_id)
if not kwargs.get('partner_id'):
kwargs = dict(kwargs, partner_id=request.env.user.partner_id.id)
return acquirer.s2s_process(kwargs).id
@http.route(['/payment/stripe/s2s/create'], type='http', auth='public')
def stripe_s2s_create(self, **post):
acquirer_id = int(post.get('acquirer_id'))
acquirer = request.env['payment.acquirer'].browse(acquirer_id)
error = None
try:
acquirer.s2s_process(post)
except Exception as e:
error = e.message
return_url = post.get('return_url', '/')
if error:
separator = '?' if werkzeug.urls.url_parse(return_url).query == '' else '&'
return_url += '{}{}'.format(separator, werkzeug.urls.url_encode({'error': error}))
return werkzeug.utils.redirect(return_url)
@http.route(['/payment/stripe/s2s/create_json_3ds'], type='json', auth='public', csrf=False)
def stripe_s2s_create_json_3ds(self, verify_validity=False, **kwargs):
if not kwargs.get('partner_id'):
kwargs = dict(kwargs, partner_id=request.env.user.partner_id.id)
token = request.env['payment.acquirer'].browse(int(kwargs.get('acquirer_id'))).s2s_process(kwargs)
if not token:
res = {
'result': False,
}
return res
res = {
'result': True,
'id': token.id,
'short_name': token.short_name,
'3d_secure': False,
'verified': False,
}
if verify_validity != False:
token.validate()
res['verified'] = token.verified
return res
@http.route(['/payment/stripe/create_charge'], type='json', auth='public')
def stripe_create_charge(self, **post):
""" Create a payment transaction
Expects the result from the user input from checkout.js popup"""
TX = request.env['payment.transaction']
tx = None
if post.get('tx_ref'):
tx = TX.sudo().search([('reference', '=', post['tx_ref'])])
if not tx:
tx_id = (post.get('tx_id') or request.session.get('sale_transaction_id') or
request.session.get('website_payment_tx_id'))
tx = TX.sudo().browse(int(tx_id))
if not tx:
raise werkzeug.exceptions.NotFound()
stripe_token = post['token']
response = None
if tx.type == 'form_save' and tx.partner_id:
payment_token_id = request.env['payment.token'].sudo().create({
'acquirer_id': tx.acquirer_id.id,
'partner_id': tx.partner_id.id,
'stripe_token': stripe_token
})
tx.payment_token_id = payment_token_id
response = tx._create_stripe_charge(acquirer_ref=payment_token_id.acquirer_ref, email=stripe_token['email'])
else:
response = tx._create_stripe_charge(tokenid=stripe_token['id'], email=stripe_token['email'])
_logger.info('Stripe: entering form_feedback with post data %s', pprint.pformat(response))
if response:
request.env['payment.transaction'].sudo().with_context(lang=None).form_feedback(response, 'stripe')
# add the payment transaction into the session to let the page /payment/process to handle it
PaymentProcessing.add_payment_transaction(tx)
return "/payment/process"