Files
odoo_source/addons/payment_ogone/models/payment_acquirer.py
T
Nicolas (vin) f7b45aa032 [FIX] payment: suitable payment token and acquirer fix
Fix two issues:

The search of suitable payment token was searching on the journal_id
field of the payment acquirer that is no longer stored.
Change it to now search on the acquirer_id directly, since we have
this information.

The _inverse_journal_id method on payment acquirers would create
new payment line with the manual payment method when no provider
are given to an acquirer, or no payment method is existing for
a given provider. This would cause issues with the creation of
multiple line with the same name on a same journal, which would
trigger the constrains blocking that.

closes odoo/odoo#74990

X-original-commit: a3a2fcb0b299fafbf359ec9015da5c85cdb57b3a
Related: odoo/enterprise#20193
Signed-off-by: Laurent Smet <smetl@users.noreply.github.com>
2021-08-12 07:56:16 +00:00

124 lines
5.1 KiB
Python

# Part of Odoo. See LICENSE file for full copyright and licensing details.
import logging
from hashlib import sha1
import requests
from odoo import _, api, fields, models
from odoo.exceptions import ValidationError
from .const import VALID_KEYS
_logger = logging.getLogger(__name__)
class PaymentAcquirer(models.Model):
_inherit = 'payment.acquirer'
provider = fields.Selection(
selection_add=[('ogone', "Ogone")], ondelete={'ogone': 'set default'})
ogone_pspid = fields.Char(
string="PSPID", help="The ID solely used to identify the account with Ogone",
required_if_provider='ogone')
ogone_userid = fields.Char(
string="API User ID", help="The ID solely used to identify the API user with Ogone",
required_if_provider='ogone')
ogone_password = fields.Char(
string="API User Password", required_if_provider='ogone', groups='base.group_system')
ogone_shakey_in = fields.Char(
string="SHA Key IN", size=32, required_if_provider='ogone', groups='base.group_system')
ogone_shakey_out = fields.Char(
string="SHA Key OUT", size=32, required_if_provider='ogone', groups='base.group_system')
@api.model
def _get_compatible_acquirers(self, *args, is_validation=False, **kwargs):
""" Override of payment to unlist Ogone acquirers for validation operations. """
acquirers = super()._get_compatible_acquirers(*args, is_validation=is_validation, **kwargs)
if is_validation:
acquirers = acquirers.filtered(lambda a: a.provider != 'ogone')
return acquirers
def _ogone_get_api_url(self, api_key):
""" Return the appropriate URL of the requested API for the acquirer state.
Note: self.ensure_one()
:param str api_key: The API whose URL to get: 'hosted_payment_page' or 'directlink'
:return: The API URL
:rtype: str
"""
self.ensure_one()
if self.state == 'enabled':
api_urls = {
'hosted_payment_page': 'https://secure.ogone.com/ncol/prod/orderstandard_utf8.asp',
'directlink': 'https://secure.ogone.com/ncol/prod/orderdirect_utf8.asp',
}
else: # 'test'
api_urls = {
'hosted_payment_page': 'https://ogone.test.v-psp.com/ncol/test/orderstandard_utf8.asp',
'directlink': 'https://ogone.test.v-psp.com/ncol/test/orderdirect_utf8.asp',
}
return api_urls.get(api_key)
def _ogone_generate_signature(self, values, incoming=True, format_keys=False):
""" Generate the signature for incoming or outgoing communications.
:param dict values: The values used to generate the signature
:param bool incoming: Whether the signature must be generated for an incoming (Ogone to
Odoo) or outgoing (Odoo to Ogone) communication.
:param bool format_keys: Whether the keys must be formatted as uppercase, dot-separated
strings to comply with Ogone APIs. This must be used when the keys
are formatted as underscore-separated strings to be compliant with
QWeb's `t-att-value`.
:return: The signature
:rtype: str
"""
def _filter_key(_key):
return not incoming or _key in VALID_KEYS
key = self.ogone_shakey_out if incoming else self.ogone_shakey_in # Swapped for Ogone's POV
if format_keys:
formatted_items = [(k.upper().replace('_', '.'), v) for k, v in values.items()]
else:
formatted_items = [(k.upper(), v) for k, v in values.items()]
sorted_items = sorted(formatted_items)
signing_string = ''.join(f'{k}={v}{key}' for k, v in sorted_items if _filter_key(k) and v)
shasign = sha1(signing_string.encode()).hexdigest()
return shasign
def _ogone_make_request(self, payload=None, method='POST'):
""" Make a request to one of Ogone APIs.
Note: self.ensure_one()
:param dict payload: The payload of the request
:param str method: The HTTP method of the request
:return The content of the response
:rtype: bytes
:raise: ValidationError if an HTTP error occurs
"""
self.ensure_one()
url = self._ogone_get_api_url('directlink')
try:
response = requests.request(method, url, data=payload, timeout=60)
response.raise_for_status()
except requests.exceptions.ConnectionError:
_logger.exception("unable to reach endpoint at %s", url)
raise ValidationError("Ogone: " + _("Could not establish the connection to the API."))
except requests.exceptions.HTTPError:
_logger.exception("invalid API request at %s with data %s", url, payload)
raise ValidationError("Ogone: " + _("The communication with the API failed."))
return response.content
def _get_default_payment_method_id(self):
self.ensure_one()
if self.provider != 'ogone':
return super()._get_default_payment_method_id()
return self.env.ref('payment_ogone.payment_method_ogone').id