[IMP] payment_adyen: replace API URLs with an account-specific URL prefix
Before this commit, users were required to compute the API URLs, which is specific to each Adyen account, themselves. After this commit, users will be able to copy their account prefix from Adyen to automatically generate the API URLs. task-3338126 closes odoo/odoo#126831 Related: odoo/upgrade#4876 Signed-off-by: Antoine Vandevenne (anv) <anv@odoo.com>
This commit is contained in:
committed by
Antoine Vandevenne (anv)
parent
bad4eea5d3
commit
428a2cda67
@@ -59,10 +59,7 @@ class AdyenController(http.Controller):
|
||||
'channel': 'Web',
|
||||
}
|
||||
response_content = provider_sudo._adyen_make_request(
|
||||
url_field_name='adyen_checkout_api_url',
|
||||
endpoint='/paymentMethods',
|
||||
payload=data,
|
||||
method='POST'
|
||||
endpoint='/paymentMethods', payload=data, method='POST'
|
||||
)
|
||||
_logger.info("paymentMethods request response:\n%s", pprint.pformat(response_content))
|
||||
return response_content
|
||||
@@ -139,10 +136,7 @@ class AdyenController(http.Controller):
|
||||
|
||||
# Make the payment request to Adyen
|
||||
response_content = provider_sudo._adyen_make_request(
|
||||
url_field_name='adyen_checkout_api_url',
|
||||
endpoint='/payments',
|
||||
payload=data,
|
||||
method='POST'
|
||||
endpoint='/payments', payload=data, method='POST'
|
||||
)
|
||||
|
||||
# Handle the payment request response
|
||||
@@ -171,10 +165,7 @@ class AdyenController(http.Controller):
|
||||
# Make the payment details request to Adyen
|
||||
provider_sudo = request.env['payment.provider'].browse(provider_id).sudo()
|
||||
response_content = provider_sudo._adyen_make_request(
|
||||
url_field_name='adyen_checkout_api_url',
|
||||
endpoint='/payments/details',
|
||||
payload=payment_details,
|
||||
method='POST'
|
||||
endpoint='/payments/details', payload=payment_details, method='POST'
|
||||
)
|
||||
|
||||
# Handle the payment details request response
|
||||
|
||||
@@ -31,35 +31,35 @@ class PaymentProvider(models.Model):
|
||||
adyen_hmac_key = fields.Char(
|
||||
string="HMAC Key", help="The HMAC key of the webhook", required_if_provider='adyen',
|
||||
groups='base.group_system')
|
||||
adyen_checkout_api_url = fields.Char(
|
||||
string="Checkout API URL", help="The base URL for the Checkout API endpoints",
|
||||
required_if_provider='adyen')
|
||||
adyen_recurring_api_url = fields.Char(
|
||||
string="Recurring API URL", help="The base URL for the Recurring API endpoints",
|
||||
required_if_provider='adyen')
|
||||
adyen_api_url_prefix = fields.Char(
|
||||
string="API URL Prefix",
|
||||
help="The base URL for the API endpoints",
|
||||
required_if_provider='adyen',
|
||||
)
|
||||
|
||||
#=== CRUD METHODS ===#
|
||||
|
||||
@api.model_create_multi
|
||||
def create(self, values_list):
|
||||
for values in values_list:
|
||||
self._adyen_trim_api_urls(values)
|
||||
self._adyen_extract_prefix_from_api_url(values)
|
||||
return super().create(values_list)
|
||||
|
||||
def write(self, values):
|
||||
self._adyen_trim_api_urls(values)
|
||||
self._adyen_extract_prefix_from_api_url(values)
|
||||
return super().write(values)
|
||||
|
||||
@api.model
|
||||
def _adyen_trim_api_urls(self, values):
|
||||
""" Remove the version and the endpoint from the url of Adyen API fields.
|
||||
def _adyen_extract_prefix_from_api_url(self, values):
|
||||
""" Update the create or write values with the prefix extracted from the API URL.
|
||||
|
||||
:param dict values: The create or write values
|
||||
:param dict values: The create or write values.
|
||||
:return: None
|
||||
"""
|
||||
for field_name in ('adyen_checkout_api_url', 'adyen_recurring_api_url'):
|
||||
if values.get(field_name): # Test the value in case we're duplicating a provider
|
||||
values[field_name] = re.sub(r'[vV]\d+(/.*)?', '', values[field_name])
|
||||
if values.get('adyen_api_url_prefix'): # Test if we're duplicating a provider.
|
||||
values['adyen_api_url_prefix'] = re.sub(
|
||||
r'(?:https://)?(\w+-\w+).*', r'\1', values['adyen_api_url_prefix']
|
||||
)
|
||||
|
||||
#=== COMPUTE METHODS ===#
|
||||
|
||||
@@ -74,14 +74,11 @@ class PaymentProvider(models.Model):
|
||||
|
||||
#=== BUSINESS METHODS - PAYMENT FLOW ===#
|
||||
|
||||
def _adyen_make_request(
|
||||
self, url_field_name, endpoint, endpoint_param=None, payload=None, method='POST'
|
||||
):
|
||||
def _adyen_make_request(self, endpoint, endpoint_param=None, payload=None, method='POST'):
|
||||
""" Make a request to Adyen API at the specified endpoint.
|
||||
|
||||
Note: self.ensure_one()
|
||||
|
||||
:param str url_field_name: The name of the field holding the base URL for the request
|
||||
:param str endpoint: The endpoint to be reached by the request
|
||||
:param str endpoint_param: A variable required by some endpoints which are interpolated with
|
||||
it if provided. For example, the provider reference of the source
|
||||
@@ -93,27 +90,28 @@ class PaymentProvider(models.Model):
|
||||
:raise: ValidationError if an HTTP error occurs
|
||||
"""
|
||||
|
||||
def _build_url(_base_url, _version, _endpoint):
|
||||
def _build_url(prefix_, version_, endpoint_):
|
||||
""" Build an API URL by appending the version and endpoint to a base URL.
|
||||
|
||||
The final URL follows this pattern: `<_base>/V<_version>/<_endpoint>`.
|
||||
|
||||
:param str _base_url: The base of the url prefixed with `https://`
|
||||
:param int _version: The version of the endpoint
|
||||
:param str _endpoint: The endpoint of the URL.
|
||||
:return: The final URL
|
||||
:param str prefix_: The API URL prefix of the account.
|
||||
:param int version_: The version of the endpoint.
|
||||
:param str endpoint_: The endpoint of the URL.
|
||||
:return: The final URL.
|
||||
:rtype: str
|
||||
"""
|
||||
_base = _base_url.rstrip('/') # Remove potential trailing slash
|
||||
_endpoint = _endpoint.lstrip('/') # Remove potential leading slash
|
||||
return f'{_base}/V{_version}/{_endpoint}'
|
||||
prefix_ = prefix_.rstrip('/') # Remove potential trailing slash
|
||||
endpoint_ = endpoint_.lstrip('/') # Remove potential leading slash
|
||||
test_mode_ = self.state == 'test'
|
||||
prefix_ = f'{prefix_}.adyen' if test_mode_ else f'{prefix_}-checkout-live.adyenpayments'
|
||||
return f'https://{prefix_}.com/checkout/V{version_}/{endpoint_}'
|
||||
|
||||
self.ensure_one()
|
||||
|
||||
base_url = self[url_field_name] # Restrict request URL to the stored API URL fields
|
||||
version = const.API_ENDPOINT_VERSIONS[endpoint]
|
||||
endpoint = endpoint if not endpoint_param else endpoint.format(endpoint_param)
|
||||
url = _build_url(base_url, version, endpoint)
|
||||
url = _build_url(self.adyen_api_url_prefix, version, endpoint)
|
||||
headers = {'X-API-Key': self.adyen_api_key}
|
||||
try:
|
||||
response = requests.request(method, url, json=payload, headers=headers, timeout=60)
|
||||
|
||||
@@ -96,10 +96,7 @@ class PaymentTransaction(models.Model):
|
||||
# Make the payment request to Adyen
|
||||
try:
|
||||
response_content = self.provider_id._adyen_make_request(
|
||||
url_field_name='adyen_checkout_api_url',
|
||||
endpoint='/payments',
|
||||
payload=data,
|
||||
method='POST',
|
||||
endpoint='/payments', payload=data, method='POST'
|
||||
)
|
||||
except ValidationError as e:
|
||||
if self.operation == 'offline':
|
||||
@@ -143,7 +140,6 @@ class PaymentTransaction(models.Model):
|
||||
'reference': refund_tx.reference,
|
||||
}
|
||||
response_content = refund_tx.provider_id._adyen_make_request(
|
||||
url_field_name='adyen_checkout_api_url',
|
||||
endpoint='/payments/{}/refunds',
|
||||
endpoint_param=self.provider_reference,
|
||||
payload=data,
|
||||
@@ -183,7 +179,6 @@ class PaymentTransaction(models.Model):
|
||||
'reference': self.reference,
|
||||
}
|
||||
response_content = self.provider_id._adyen_make_request(
|
||||
url_field_name='adyen_checkout_api_url',
|
||||
endpoint='/payments/{}/captures',
|
||||
endpoint_param=self.provider_reference,
|
||||
payload=data,
|
||||
@@ -219,7 +214,6 @@ class PaymentTransaction(models.Model):
|
||||
'reference': self.reference,
|
||||
}
|
||||
response_content = self.provider_id._adyen_make_request(
|
||||
url_field_name='adyen_checkout_api_url',
|
||||
endpoint='/payments/{}/cancels',
|
||||
endpoint_param=self.provider_reference,
|
||||
payload=data,
|
||||
|
||||
@@ -14,8 +14,7 @@ class AdyenCommon(PaymentCommon):
|
||||
'adyen_api_key': 'dummy',
|
||||
'adyen_client_key': 'dummy',
|
||||
'adyen_hmac_key': '12345678',
|
||||
'adyen_checkout_api_url': 'https://this.is.an.url',
|
||||
'adyen_recurring_api_url': 'https://this.is.an.url',
|
||||
'adyen_api_url_prefix': 'prefix',
|
||||
})
|
||||
|
||||
# Override default values
|
||||
|
||||
@@ -12,8 +12,7 @@
|
||||
<field name="adyen_api_key" required="code == 'adyen' and state != 'disabled'" password="True"/>
|
||||
<field name="adyen_client_key" required="code == 'adyen' and state != 'disabled'"/>
|
||||
<field name="adyen_hmac_key" required="code == 'adyen' and state != 'disabled'" password="True"/>
|
||||
<field name="adyen_checkout_api_url" required="code == 'adyen' and state != 'disabled'"/>
|
||||
<field name="adyen_recurring_api_url" required="code == 'adyen' and state != 'disabled'"/>
|
||||
<field name="adyen_api_url_prefix" required="code == 'adyen' and state != 'disabled'"/>
|
||||
</group>
|
||||
</group>
|
||||
<group name="provider_config" position='before'>
|
||||
|
||||
Reference in New Issue
Block a user