You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							202 lines
						
					
					
						
							8.4 KiB
						
					
					
				
			
		
		
		
			
			
			
		
		
	
	
							202 lines
						
					
					
						
							8.4 KiB
						
					
					
				
								# -*- coding: utf-8 -*-
							 | 
						|
								###############################################################################
							 | 
						|
								#
							 | 
						|
								#    Cybrosys Technologies Pvt. Ltd.
							 | 
						|
								#
							 | 
						|
								#    Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
							 | 
						|
								#    Author: Cybrosys Techno Solutions (odoo@cybrosys.com)
							 | 
						|
								#
							 | 
						|
								#    You can modify it under the terms of the GNU LESSER
							 | 
						|
								#    GENERAL PUBLIC LICENSE (LGPL v3), Version 3.
							 | 
						|
								#
							 | 
						|
								#    This program is distributed in the hope that it will be useful,
							 | 
						|
								#    but WITHOUT ANY WARRANTY; without even the implied warranty of
							 | 
						|
								#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
							 | 
						|
								#    GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details.
							 | 
						|
								#
							 | 
						|
								#    You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE
							 | 
						|
								#    (LGPL v3) along with this program.
							 | 
						|
								#    If not, see <http://www.gnu.org/licenses/>.
							 | 
						|
								#
							 | 
						|
								###############################################################################
							 | 
						|
								import logging
							 | 
						|
								from werkzeug import urls
							 | 
						|
								from odoo import api, models, _
							 | 
						|
								from odoo.exceptions import ValidationError
							 | 
						|
								from odoo.addons.payment import utils as payment_utils
							 | 
						|
								from odoo.addons.payment_paytabs_odoo.controllers.payment_paytabs_odoo import PaymentPaytabs
							 | 
						|
								
							 | 
						|
								_logger = logging.getLogger(__name__)
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								class PaymentTransaction(models.Model):
							 | 
						|
								    """
							 | 
						|
								       Inherit the payment transactions, to add Paytabs specific functionality.
							 | 
						|
								
							 | 
						|
								       Methods:
							 | 
						|
								           _compute_reference: Override of `payment` to ensure that APS'
							 | 
						|
								       requirements for references are satisfied.
							 | 
						|
								       _get_specific_rendering_values: Override of
							 | 
						|
								       `_get_specific_rendering_values` to handle specific rendering values
							 | 
						|
								       for Paytabs.
							 | 
						|
								       execute_payment: Fetching data and Executing Payment.
							 | 
						|
								       _get_tx_from_notification_data: Get payment status from Paytabs.
							 | 
						|
								
							 | 
						|
								       _handle_notification_data: Handle the notification data received
							 | 
						|
								       from Paytabs.
							 | 
						|
								
							 | 
						|
								       _process_notification_data: Process the notification data received
							 | 
						|
								       from Paytabs.
							 | 
						|
								       """
							 | 
						|
								    _inherit = 'payment.transaction'
							 | 
						|
								
							 | 
						|
								    @api.model
							 | 
						|
								    def _compute_reference(self, provider_code, prefix=None, separator='-',
							 | 
						|
								                           **kwargs):
							 | 
						|
								        """ Override of `payment` to ensure that APS' requirements for
							 | 
						|
								        references are satisfied.
							 | 
						|
								
							 | 
						|
								        APS' requirements for transaction are as follows: - References can
							 | 
						|
								        only be made of alphanumeric characters and/or '-' and '_'. The
							 | 
						|
								        prefix is generated with 'tx' as default. This prevents the prefix
							 | 
						|
								        from being generated based on document names that may contain
							 | 
						|
								        non-allowed characters (eg: INV/2020/...).
							 | 
						|
								
							 | 
						|
								        :param str provider_code: The code of the provider handling the
							 | 
						|
								        transaction.
							 | 
						|
								        :param str prefix: The custom prefix used to compute the
							 | 
						|
								        full reference.
							 | 
						|
								        :param str separator: The custom separator used to separate the prefix
							 | 
						|
								        from the suffix.
							 | 
						|
								        :return: The unique reference
							 | 
						|
								        for the transaction.
							 | 
						|
								        :rtype: str
							 | 
						|
								        """
							 | 
						|
								        if provider_code == 'paytabs':
							 | 
						|
								            prefix = payment_utils.singularize_reference_prefix()
							 | 
						|
								        return super()._compute_reference(provider_code, prefix=prefix,
							 | 
						|
								                                          separator=separator, **kwargs)
							 | 
						|
								
							 | 
						|
								    def _get_specific_rendering_values(self, processing_values):
							 | 
						|
								        """ Override of `_get_specific_rendering_values` to handle specific
							 | 
						|
								        rendering values for PayTabs.
							 | 
						|
								
							 | 
						|
								        :param processing_values: The processing values dictionary.
							 | 
						|
								        :return: The rendering values."""
							 | 
						|
								        res = super()._get_specific_rendering_values(processing_values)
							 | 
						|
								        if self.provider_code != 'paytabs':
							 | 
						|
								            return res
							 | 
						|
								        return self.execute_payment()
							 | 
						|
								
							 | 
						|
								    def execute_payment(self):
							 | 
						|
								        """Fetching data and Executing Payment
							 | 
						|
								        :return: The response content."""
							 | 
						|
								        api_url = self.env['payment.provider'].search(
							 | 
						|
								            [('code', '=', 'paytabs')]).domain
							 | 
						|
								        base_url = self.env['ir.config_parameter'].get_param('web.base.url')
							 | 
						|
								        sale_order = self.env['payment.transaction'].search(
							 | 
						|
								            [('id', '=', self.id)]).sale_order_ids
							 | 
						|
								        paytabs_values = {
							 | 
						|
								            "profile_id": int(self.provider_id.profile_key),
							 | 
						|
								            "tran_type": "sale",
							 | 
						|
								            "tran_class": "ecom",
							 | 
						|
								            "cart_description": self.reference,
							 | 
						|
								            "cart_id": self.reference,
							 | 
						|
								            "cart_currency": self.currency_id.name,
							 | 
						|
								            "cart_amount": (self.amount - sale_order.amount_tax),
							 | 
						|
								            'return': urls.url_join(base_url,
							 | 
						|
								                                    PaymentPaytabs._return_url),
							 | 
						|
								            'callback': urls.url_join(base_url,
							 | 
						|
								                                      PaymentPaytabs._return_url),
							 | 
						|
								            "api_url": api_url,
							 | 
						|
								            "customer_details": {
							 | 
						|
								                "name": self.partner_name,
							 | 
						|
								                "email": self.partner_email,
							 | 
						|
								                "street1": self.partner_address,
							 | 
						|
								                "city": self.partner_city,
							 | 
						|
								                "state": self.partner_state_id.code,
							 | 
						|
								                "country": self.partner_country_id.code,
							 | 
						|
								                "zip": self.partner_zip
							 | 
						|
								            },
							 | 
						|
								            "shipping_details": {
							 | 
						|
								                "name": self.partner_name,
							 | 
						|
								                "email": self.partner_email,
							 | 
						|
								                "street1": self.partner_address,
							 | 
						|
								                "city": self.partner_city,
							 | 
						|
								                "state": self.partner_state_id.code,
							 | 
						|
								                "country": self.partner_country_id.code,
							 | 
						|
								                "zip": self.partner_zip
							 | 
						|
								            },
							 | 
						|
								        }
							 | 
						|
								        response_content = self.provider_id._paytabs_make_request(
							 | 
						|
								            api_url, paytabs_values)
							 | 
						|
								        response_content['api_url'] = response_content.get('redirect_url')
							 | 
						|
								        return response_content
							 | 
						|
								
							 | 
						|
								    def _get_tx_from_notification_data(self, provider_code, notification_data):
							 | 
						|
								        """
							 | 
						|
								        Get payment status from Paytabs.
							 | 
						|
								
							 | 
						|
								        :param provider_code: The code of the provider handling the transaction.
							 | 
						|
								        :param notification_data: The data received from Paytabs notification.
							 | 
						|
								        :return: The transaction matching the reference.
							 | 
						|
								        """
							 | 
						|
								        tx = super()._get_tx_from_notification_data(provider_code,
							 | 
						|
								                                                    notification_data)
							 | 
						|
								        if provider_code != 'paytabs':
							 | 
						|
								            return tx
							 | 
						|
								        reference = notification_data.get('cartId', False)
							 | 
						|
								        if not reference:
							 | 
						|
								            raise ValidationError(_("PayTabs: No reference found."))
							 | 
						|
								        tx = self.search(
							 | 
						|
								            [('reference', '=', reference), ('provider_code', '=', 'paytabs')])
							 | 
						|
								        if not tx:
							 | 
						|
								            raise ValidationError(
							 | 
						|
								                _("PayTabs: No transaction found matching reference"
							 | 
						|
								                  "%s.") % reference)
							 | 
						|
								        return tx
							 | 
						|
								
							 | 
						|
								    def _handle_notification_data(self, provider_code, notification_data):
							 | 
						|
								        """
							 | 
						|
								        Handle the notification data received from Paytabs.
							 | 
						|
								
							 | 
						|
								        This method retrieves the transaction corresponding to the
							 | 
						|
								        notification data, processes the notification data, and executes the
							 | 
						|
								        callback.
							 | 
						|
								
							 | 
						|
								        :param provider_code: The code of the provider handling the transaction.
							 | 
						|
								        :param notification_data: The data received from Paytabs notification.
							 | 
						|
								        :return: The transaction object.
							 | 
						|
								        """
							 | 
						|
								        tx = self._get_tx_from_notification_data(provider_code,
							 | 
						|
								                                                 notification_data)
							 | 
						|
								        tx._process_notification_data(notification_data)
							 | 
						|
								        tx._execute_callback()
							 | 
						|
								        return tx
							 | 
						|
								
							 | 
						|
								    def _process_notification_data(self, notification_data):
							 | 
						|
								        """
							 | 
						|
								        Process the notification data received from PayTabs.
							 | 
						|
								
							 | 
						|
								        This method processes the notification data and updates the payment
							 | 
						|
								        state of the transaction accordingly.
							 | 
						|
								
							 | 
						|
								        :param notification_data: The data received from PayTabs notification.
							 | 
						|
								            """
							 | 
						|
								        super()._process_notification_data(notification_data)
							 | 
						|
								        if self.provider_code != 'paytabs':
							 | 
						|
								            return
							 | 
						|
								
							 | 
						|
								        status = notification_data.get('respStatus')
							 | 
						|
								        if status == 'A':
							 | 
						|
								            self._set_done(state_message="Authorised")
							 | 
						|
								        elif status == 'APPROVED':
							 | 
						|
								            self._set_pending(state_message="Authorised but on hold for "
							 | 
						|
								                                            "further anti-fraud review")
							 | 
						|
								        elif status in ('E', 'D'):
							 | 
						|
								            self._set_canceled(state_message="Error")
							 | 
						|
								        else:
							 | 
						|
								            _logger.warning("Received unrecognized payment state %s for "
							 | 
						|
								                            "transaction with reference %s",
							 | 
						|
								                            status, self.reference)
							 | 
						|
								            self._set_error("PayTabs: " + _("Invalid payment status."))
							 | 
						|
								
							 |