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.
197 lines
8.3 KiB
197 lines
8.3 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 pay_ccavenue import CCAvenue
|
|
from odoo import api, models, _
|
|
from odoo.exceptions import ValidationError
|
|
from odoo.addons.payment import utils as payment_utils
|
|
|
|
_logger = logging.getLogger(__name__)
|
|
|
|
|
|
class PaymentTransaction(models.Model):
|
|
"""
|
|
Inherit the payment transactions, to add CCAvenue 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 CCAvenue.
|
|
execute_payment: Fetching data and Executing Payment.
|
|
_get_tx_from_notification_data: Get payment status from CCAvenue.
|
|
|
|
_handle_notification_data: Handle the notification data received
|
|
from CCAvenue.
|
|
|
|
_process_notification_data: Process the notification data received
|
|
from CCAvenue.
|
|
"""
|
|
_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 == 'avenue':
|
|
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 CCAvenue.
|
|
|
|
:param processing_values: The processing values dictionary.
|
|
:return: The rendering values."""
|
|
res = super()._get_specific_rendering_values(processing_values)
|
|
if self.provider_code != 'avenue':
|
|
return res
|
|
return self.execute_payment()
|
|
|
|
def execute_payment(self):
|
|
"""
|
|
Fetches necessary data and executes the payment using CCAvenue
|
|
:return:
|
|
A dictionary containing the encrypted data, access code, and API URL.
|
|
"""
|
|
# Initialize CCAvenue with credentials
|
|
self.ensure_one()
|
|
web_url = self.env['ir.config_parameter'].get_param('web.base.url')
|
|
sale_order = self.env['sale.order'].search(
|
|
[('id', '=', self.sale_order_ids.id)])
|
|
form_data = {
|
|
"order_id": self.reference,
|
|
"currency": self.currency_id.name,
|
|
"amount": self.amount,
|
|
"redirect_url": f"{web_url}/payment/ccavenue/return",
|
|
"cancel_url": f"{web_url}/payment/ccavenue/cancel",
|
|
"billing_name": self.partner_name,
|
|
"billing_tel": self.partner_phone,
|
|
"billing_address": self.partner_address,
|
|
"billing_city": self.partner_city,
|
|
"billing_state": self.partner_state_id.name,
|
|
"billing_country": self.partner_country_id.name,
|
|
"billing_zip": self.partner_zip,
|
|
"billing_email": self.partner_email
|
|
}
|
|
if self.provider_id.state == "test":
|
|
api_url = ("https://test.ccavenue.com/transaction/transaction.do?command=initiateTransaction")
|
|
else:
|
|
api_url = ("https://secure.ccavenue.com/transaction/transaction.do"
|
|
"?command=initiateTransaction")
|
|
ccavenue = CCAvenue(self.provider_id.working_key,
|
|
self.provider_id.access_code,
|
|
self.provider_id.merchant_key,
|
|
web_url + '/payment/ccavenue/return',
|
|
web_url + '/payment/ccavenue/cancel')
|
|
encrypted_data = ccavenue.encrypt(form_data)
|
|
response_content = {
|
|
"encrypted_data": encrypted_data,
|
|
"access_code": self.provider_id.access_code,
|
|
"api_url": api_url
|
|
}
|
|
return response_content
|
|
|
|
def _get_tx_from_notification_data(self, provider_code, notification_data):
|
|
"""
|
|
Get payment status from CCAvenue.
|
|
|
|
:param provider_code: The code of the provider handling the transaction.
|
|
:param notification_data: The data received from CCAvenue notification.
|
|
:return: The transaction matching the reference.
|
|
"""
|
|
tx = super()._get_tx_from_notification_data(provider_code,
|
|
notification_data)
|
|
if provider_code != 'avenue':
|
|
return tx
|
|
reference = notification_data.get('order_id', False)
|
|
if not reference:
|
|
raise ValidationError("CCAvenue: " + _("No reference found.", ))
|
|
tx = self.search(
|
|
[('reference', '=', reference), ('provider_code', '=', 'avenue')])
|
|
if not tx:
|
|
raise ValidationError("CCAvenue: " + _("No transaction found "
|
|
"matching reference %s.",
|
|
reference))
|
|
return tx
|
|
|
|
def _handle_notification_data(self, provider_code, notification_data):
|
|
"""
|
|
Handle the notification data received from CCAvenue.
|
|
|
|
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 CCAvenue 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 CCAvenue.
|
|
|
|
This method processes the notification data and updates the payment
|
|
state of the transaction accordingly.
|
|
|
|
:param notification_data: The data received from CCAvenue notification.
|
|
"""
|
|
super()._process_notification_data(notification_data)
|
|
if self.provider_code != 'avenue':
|
|
return
|
|
status = notification_data.get('order_status')
|
|
if status == 'Success':
|
|
self._set_done()
|
|
elif status == 'Aborted':
|
|
self._set_canceled(state_message="Error")
|
|
elif status == "Failure":
|
|
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("CCAVENUE: " + _("Invalid payment status."))
|
|
|