Skip to content

Commit

Permalink
[FIX] payment_adyen: add 'amount' to adyen checkout configuration
Browse files Browse the repository at this point in the history
Steps to reproduce:
1. Create a company with currency as Euros.
2. Set up Adyen on that company with the test credentials and enable
paypal.
3. Create an invoice with the currency in Euros.
4. Generate a payment link.
5. Attempt to pay on that payment link with paypal.

After this commit the Adyen checkout configuration is correctly set up
which allows to pay with PayPal

opw-3543970

Part-of: odoo#140711
  • Loading branch information
vchu-odoo authored and AntoineVDV committed Nov 6, 2023
1 parent 09df480 commit b024dd7
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 19 deletions.
13 changes: 3 additions & 10 deletions addons/payment_adyen/controllers/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@

from odoo.addons.payment import utils as payment_utils
from odoo.addons.payment_adyen import utils as adyen_utils
from odoo.addons.payment_adyen.const import CURRENCY_DECIMALS

_logger = logging.getLogger(__name__)

Expand All @@ -26,22 +25,16 @@ class AdyenController(http.Controller):
_webhook_url = '/payment/adyen/notification'

@http.route('/payment/adyen/payment_methods', type='json', auth='public')
def adyen_payment_methods(self, provider_id, amount=None, currency_id=None, partner_id=None):
def adyen_payment_methods(self, provider_id, formatted_amount=None, partner_id=None):
""" Query the available payment methods based on the payment context.
:param int provider_id: The provider handling the transaction, as a `payment.provider` id
:param float amount: The transaction amount
:param int currency_id: The transaction currency, as a `res.currency` id
:param dict formatted_amount: The Adyen-formatted amount.
:param int partner_id: The partner making the transaction, as a `res.partner` id
:return: The JSON-formatted content of the response
:rtype: dict
"""
provider_sudo = request.env['payment.provider'].sudo().browse(provider_id)
currency = request.env['res.currency'].browse(currency_id)
currency_code = currency_id and currency.name
converted_amount = amount and currency_code and payment_utils.to_minor_currency_units(
amount, currency, CURRENCY_DECIMALS.get(currency_code)
)
partner_sudo = partner_id and request.env['res.partner'].sudo().browse(partner_id).exists()
# The lang is taken from the context rather than from the partner because it is not required
# to be logged in to make a payment, and because the lang is not always set on the partner.
Expand All @@ -52,7 +45,7 @@ def adyen_payment_methods(self, provider_id, amount=None, currency_id=None, part
shopper_reference = partner_sudo and f'ODOO_PARTNER_{partner_sudo.id}'
data = {
'merchantAccount': provider_sudo.adyen_merchant_account,
'amount': converted_amount,
'amount': formatted_amount,
'countryCode': partner_sudo.country_id.code or None, # ISO 3166-1 alpha-2 (e.g.: 'BE')
'shopperLocale': lang_code, # IETF language tag (e.g.: 'fr-BE')
'shopperReference': shopper_reference,
Expand Down
27 changes: 25 additions & 2 deletions addons/payment_adyen/models/payment_provider.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.

import json
import logging
import re
import json
import requests

from odoo import _, api, fields, models
from odoo.exceptions import ValidationError

from odoo.addons.payment import utils as payment_utils
from odoo.addons.payment_adyen import const

_logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -144,12 +145,14 @@ def _adyen_compute_shopper_reference(self, partner_id):

#=== BUSINESS METHODS - GETTERS ===#

def _adyen_get_inline_form_values(self, pm_code):
def _adyen_get_inline_form_values(self, pm_code, amount=None, currency=None):
""" Return a serialized JSON of the required values to render the inline form.
Note: `self.ensure_one()`
:param str pm_code: The code of the payment method whose inline form to render.
:param float amount: The transaction amount.
:param res.currency currency: The transaction currency.
:return: The JSON serial of the required values to render the inline form.
:rtype: str
"""
Expand All @@ -158,5 +161,25 @@ def _adyen_get_inline_form_values(self, pm_code):
inline_form_values = {
'client_key': self.adyen_client_key,
'adyen_pm_code': const.PAYMENT_METHODS_MAPPING.get(pm_code, pm_code),
'formatted_amount': self._adyen_get_formatted_amount(amount, currency),
}
return json.dumps(inline_form_values)

def _adyen_get_formatted_amount(self, amount=None, currency=None):
""" Return the amount in the format required by Adyen.
The formatted amount is a dict with keys 'value' and 'currency'.
:param float amount: The transaction amount.
:param res.currency currency: The transaction currency.
:return: The Adyen-formatted amount.
:rtype: dict
"""
currency_code = currency and currency.name
converted_amount = amount and currency_code and payment_utils.to_minor_currency_units(
amount, currency, const.CURRENCY_DECIMALS.get(currency_code)
)
return {
'value': converted_amount,
'currency': currency_code,
}
10 changes: 4 additions & 6 deletions addons/payment_adyen/static/src/js/payment_form.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,24 +48,22 @@ paymentForm.include({
// Extract and deserialize the inline form values.
const radio = document.querySelector('input[name="o_payment_radio"]:checked');
const inlineFormValues = JSON.parse(radio.dataset['inlineFormValues']);
const formatted_amount = inlineFormValues['formatted_amount'];
const formattedAmount = inlineFormValues['formatted_amount'];

// Create the checkout object if not already done for another payment method.
if (!this.adyenCheckout) {
await this.rpc('/payment/adyen/payment_methods', { // Await the RPC to let it create AdyenCheckout before using it.
'provider_id': providerId,
'partner_id': parseInt(this.paymentContext['partnerId']),
'amount': this.paymentContext['amount']
? parseFloat(this.paymentContext['amount'])
: undefined,
'currency_id': this.paymentContext['currencyId']
? parseInt(this.paymentContext['currencyId'])
: undefined,
'formatted_amount': formattedAmount,
}).then(async response => {
// Create the Adyen Checkout SDK.
const providerState = this._getProviderState(radio);
const configuration = {
paymentMethodsResponse: response,
clientKey: inlineFormValues['client_key'],
amount: formattedAmount,
locale: (this._getContext().lang || 'en-US').replace('_', '-'),
environment: providerState === 'enabled' ? 'live' : 'test',
onAdditionalDetails: this._adyenOnSubmitAdditionalDetails.bind(this),
Expand Down
2 changes: 1 addition & 1 deletion addons/payment_adyen/views/payment_form_templates.xml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
<template id="payment_adyen.method_form" inherit_id="payment.method_form">
<xpath expr="//input[@name='o_payment_radio']" position="attributes">
<attribute name="t-att-data-inline-form-values">
provider_sudo._adyen_get_inline_form_values(pm_sudo.code)
provider_sudo._adyen_get_inline_form_values(pm_sudo.code, amount, currency)
</attribute>
</xpath>
</template>
Expand Down

0 comments on commit b024dd7

Please sign in to comment.