diff --git a/addons/payment/wizards/payment_onboarding_wizard.py b/addons/payment/wizards/payment_onboarding_wizard.py
index a81d134daa8..331634b9f3c 100644
--- a/addons/payment/wizards/payment_onboarding_wizard.py
+++ b/addons/payment/wizards/payment_onboarding_wizard.py
@@ -13,12 +13,7 @@ class PaymentWizard(models.TransientModel):
('paypal', "PayPal"),
('manual', "Custom payment instructions"),
], string="Payment Method", default=lambda self: self._get_default_payment_provider_onboarding_value('payment_method'))
-
- paypal_user_type = fields.Selection([
- ('new_user', "I don't have a Paypal account"),
- ('existing_user', 'I have a Paypal account')], string="Paypal User Type", default='new_user')
paypal_email_account = fields.Char("Email", default=lambda self: self._get_default_payment_provider_onboarding_value('paypal_email_account'))
- paypal_seller_account = fields.Char("Merchant Account ID", default=lambda self: self._get_default_payment_provider_onboarding_value('paypal_seller_account'))
paypal_pdt_token = fields.Char("PDT Identity Token", default=lambda self: self._get_default_payment_provider_onboarding_value('paypal_pdt_token'))
# Account-specific logic. It's kept here rather than moved in `account_payment` as it's not used by `account` module.
@@ -65,9 +60,10 @@ class PaymentWizard(models.TransientModel):
if 'payment_paypal' in installed_modules:
provider = self.env.ref('payment.payment_provider_paypal')
- self._payment_provider_onboarding_cache['paypal_email_account'] = provider['paypal_email_account'] or self.env.user.email or ''
- self._payment_provider_onboarding_cache['paypal_seller_account'] = provider['paypal_seller_account']
+ self._payment_provider_onboarding_cache['paypal_email_account'] = provider['paypal_email_account'] or self.env.company.email
self._payment_provider_onboarding_cache['paypal_pdt_token'] = provider['paypal_pdt_token']
+ else:
+ self._payment_provider_onboarding_cache['paypal_email_account'] = self.env.company.email
manual_payment = self._get_manual_payment_provider()
journal = manual_payment.journal_id
@@ -94,11 +90,16 @@ class PaymentWizard(models.TransientModel):
new_env = api.Environment(self.env.cr, self.env.uid, self.env.context)
if self.payment_method == 'paypal':
+ provider = new_env.ref('payment.payment_provider_paypal', raise_if_not_found=False)
+ default_journal = new_env['account.journal'].search(
+ [('type', '=', 'bank'), ('company_id', '=', new_env.company.id)], limit=1
+ )
new_env.ref('payment.payment_provider_paypal').write({
'paypal_email_account': self.paypal_email_account,
- 'paypal_seller_account': self.paypal_seller_account,
'paypal_pdt_token': self.paypal_pdt_token,
'state': 'enabled',
+ 'is_published': 'True',
+ 'journal_id': provider.journal_id or default_journal
})
elif self.payment_method == 'manual':
manual_provider = self._get_manual_payment_provider(new_env)
diff --git a/addons/payment_paypal/__manifest__.py b/addons/payment_paypal/__manifest__.py
index 7565eec6128..7a310a375a8 100644
--- a/addons/payment_paypal/__manifest__.py
+++ b/addons/payment_paypal/__manifest__.py
@@ -13,7 +13,6 @@
'views/payment_transaction_views.xml',
'data/payment_provider_data.xml',
- 'data/payment_paypal_email_data.xml',
],
'post_init_hook': 'post_init_hook',
'uninstall_hook': 'uninstall_hook',
diff --git a/addons/payment_paypal/controllers/main.py b/addons/payment_paypal/controllers/main.py
index 9897028d783..47292158ebc 100644
--- a/addons/payment_paypal/controllers/main.py
+++ b/addons/payment_paypal/controllers/main.py
@@ -12,12 +12,15 @@ from odoo.exceptions import ValidationError
from odoo.http import request
from odoo.tools import html_escape
+from odoo.addons.payment import utils as payment_utils
+
_logger = logging.getLogger(__name__)
class PaypalController(http.Controller):
_return_url = '/payment/paypal/return/'
+ _cancel_url = '/payment/paypal/cancel/'
_webhook_url = '/payment/paypal/webhook/'
@http.route(
@@ -33,8 +36,7 @@ class PaypalController(http.Controller):
The route accepts both GET and POST requests because PayPal seems to switch between the two
depending on whether PDT is enabled, whether the customer pays anonymously (without logging
- in on PayPal), whether the customer cancels the payment, whether they click on "Return to
- Merchant" after paying, etc.
+ in on PayPal), whether they click on "Return to Merchant" after paying, etc.
The route is flagged with `save_session=False` to prevent Odoo from assigning a new session
to the user if they are redirected to this route with a POST request. Indeed, as the session
@@ -43,22 +45,43 @@ class PaypalController(http.Controller):
request from the payment provider to Odoo. As the redirection to the '/payment/status' page
will satisfy any specification of the `SameSite` attribute, the session of the user will be
retrieved and with it the transaction which will be immediately post-processed.
+
+ :param dict pdt_data: The PDT notification data send by PayPal.
"""
- _logger.info("handling redirection from PayPal with data:\n%s", pprint.pformat(pdt_data))
- if not pdt_data: # The customer has canceled or paid then clicked on "Return to Merchant"
- pass # Redirect them to the status page to browse the (currently) draft transaction
+ _logger.info("Handling redirection from PayPal with data:\n%s", pprint.pformat(pdt_data))
+
+ tx_sudo = request.env['payment.transaction'].sudo()._get_tx_from_notification_data(
+ 'paypal', pdt_data
+ )
+ try:
+ notification_data = self._verify_pdt_notification_origin(pdt_data, tx_sudo)
+ except Forbidden:
+ _logger.exception("Could not verify the origin of the PDT; discarding it.")
else:
- # Check the origin of the notification
- tx_sudo = request.env['payment.transaction'].sudo()._get_tx_from_notification_data(
- 'paypal', pdt_data
- )
- try:
- notification_data = self._verify_pdt_notification_origin(pdt_data, tx_sudo)
- except Forbidden:
- _logger.exception("could not verify the origin of the PDT; discarding it")
- else:
- # Handle the notification data
- tx_sudo._handle_notification_data('paypal', notification_data)
+ tx_sudo._handle_notification_data('paypal', notification_data)
+
+ return request.redirect('/payment/status')
+
+ @http.route(
+ _cancel_url, type='http', auth='public', methods=['GET'], csrf=False, save_session=False
+ )
+ def paypal_return_from_canceled_checkout(self, tx_ref, access_token):
+ """ Process the transaction after the customer has canceled the payment.
+
+ :param str tx_ref: The reference of the transaction having been canceled.
+ :param str access_token: The access token to verify the authenticity of the request.
+ """
+ _logger.info(
+ "Handling redirection from Paypal for cancellation of transaction with reference %s",
+ tx_ref,
+ )
+
+ tx_sudo = request.env['payment.transaction'].sudo()._get_tx_from_notification_data(
+ 'paypal', {'item_number': tx_ref}
+ )
+ if not payment_utils.check_access_token(access_token, tx_ref):
+ raise Forbidden()
+ tx_sudo._handle_notification_data('paypal', {})
return request.redirect('/payment/status')
@@ -77,7 +100,7 @@ class PaypalController(http.Controller):
See https://developer.paypal.com/docs/api-basics/notifications/payment-data-transfer/.
- :param dict pdt_data: The PDT whose authenticity must be checked.
+ :param dict pdt_data: The PDT data whose authenticity must be checked.
:param recordset tx_sudo: The sudoed transaction referenced in the PDT, as a
`payment.transaction` record
:return: The retrieved notification data
@@ -90,34 +113,24 @@ class PaypalController(http.Controller):
ref=tx_sudo.reference,
))
raise Forbidden("PayPal: PDT are not enabled; cannot verify data origin")
- else:
+ else: # The PayPal account is configured to send PDT data.
+ # Request a PDT data authenticity check and the notification data to PayPal.
provider_sudo = tx_sudo.provider_id
- if not provider_sudo.paypal_pdt_token: # We received PDT data but can't verify them
- record_link = f'{html_escape(provider_sudo.name)}'
- tx_sudo._log_message_on_linked_documents(_(
- "The status of transaction with reference %(ref)s was not synchronized because "
- "the PDT Identify Token is not configured on the provider %(record_link)s.",
- ref=tx_sudo.reference, record_link=record_link
- ))
- raise Forbidden("PayPal: The PDT token is not set; cannot verify data origin")
- else: # The PayPal account is configured to receive PDT data, and the PDT token is set
- # Request a PDT data authenticity check and the notification data to PayPal
- url = provider_sudo._paypal_get_api_url()
- payload = {
- 'cmd': '_notify-synch',
- 'tx': pdt_data['tx'],
- 'at': tx_sudo.provider_id.paypal_pdt_token,
- }
- try:
- response = requests.post(url, data=payload, timeout=10)
- response.raise_for_status()
- except (requests.exceptions.ConnectionError, requests.exceptions.HTTPError):
- raise Forbidden("PayPal: Encountered an error when verifying PDT origin")
- else:
- notification_data = self._parse_pdt_validation_response(response.text)
- if notification_data is None:
- raise Forbidden("PayPal: The PDT origin was not verified by PayPal")
+ url = provider_sudo._paypal_get_api_url()
+ payload = {
+ 'cmd': '_notify-synch',
+ 'tx': pdt_data['tx'],
+ 'at': tx_sudo.provider_id.paypal_pdt_token,
+ }
+ try:
+ response = requests.post(url, data=payload, timeout=10)
+ response.raise_for_status()
+ except (requests.exceptions.ConnectionError, requests.exceptions.HTTPError):
+ raise Forbidden("PayPal: Encountered an error when verifying PDT origin")
+ else:
+ notification_data = self._parse_pdt_validation_response(response.text)
+ if notification_data is None:
+ raise Forbidden("PayPal: The PDT origin was not verified by PayPal")
return notification_data
diff --git a/addons/payment_paypal/data/neutralize.sql b/addons/payment_paypal/data/neutralize.sql
index 5e56d33b333..83c898f0a9a 100644
--- a/addons/payment_paypal/data/neutralize.sql
+++ b/addons/payment_paypal/data/neutralize.sql
@@ -1,5 +1,4 @@
-- disable paypal payment provider
UPDATE payment_provider
SET paypal_email_account = NULL,
- paypal_seller_account = NULL,
paypal_pdt_token = NULL;
diff --git a/addons/payment_paypal/data/payment_paypal_email_data.xml b/addons/payment_paypal/data/payment_paypal_email_data.xml
deleted file mode 100644
index 83b25b2448a..00000000000
--- a/addons/payment_paypal/data/payment_paypal_email_data.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-
-
-
-
-
-
- Hello,
-
- You have received a payment through PayPal.
- Kindly follow the instructions given by PayPal to create your account.
- Then, help us complete your Paypal credentials in Odoo.