summaryrefslogtreecommitdiff
path: root/addons/payment_payulatam/models
diff options
context:
space:
mode:
authorstephanchrst <stephanchrst@gmail.com>2022-05-10 21:51:50 +0700
committerstephanchrst <stephanchrst@gmail.com>2022-05-10 21:51:50 +0700
commit3751379f1e9a4c215fb6eb898b4ccc67659b9ace (patch)
treea44932296ef4a9b71d5f010906253d8c53727726 /addons/payment_payulatam/models
parent0a15094050bfde69a06d6eff798e9a8ddf2b8c21 (diff)
initial commit 2
Diffstat (limited to 'addons/payment_payulatam/models')
-rw-r--r--addons/payment_payulatam/models/__init__.py4
-rw-r--r--addons/payment_payulatam/models/payment.py145
2 files changed, 149 insertions, 0 deletions
diff --git a/addons/payment_payulatam/models/__init__.py b/addons/payment_payulatam/models/__init__.py
new file mode 100644
index 00000000..2ec5b9cd
--- /dev/null
+++ b/addons/payment_payulatam/models/__init__.py
@@ -0,0 +1,4 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+from . import payment
diff --git a/addons/payment_payulatam/models/payment.py b/addons/payment_payulatam/models/payment.py
new file mode 100644
index 00000000..fc0c618e
--- /dev/null
+++ b/addons/payment_payulatam/models/payment.py
@@ -0,0 +1,145 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+import decimal
+import logging
+import uuid
+
+from hashlib import md5
+from werkzeug import urls
+
+from odoo import api, fields, models, _
+from odoo.addons.payment.models.payment_acquirer import ValidationError
+from odoo.tools.float_utils import float_compare
+
+
+_logger = logging.getLogger(__name__)
+
+
+class PaymentAcquirerPayulatam(models.Model):
+ _inherit = 'payment.acquirer'
+
+ provider = fields.Selection(selection_add=[
+ ('payulatam', 'PayU Latam')
+ ], ondelete={'payulatam': 'set default'})
+ payulatam_merchant_id = fields.Char(string="PayU Latam Merchant ID", required_if_provider='payulatam', groups='base.group_user')
+ payulatam_account_id = fields.Char(string="PayU Latam Account ID", required_if_provider='payulatam', groups='base.group_user')
+ payulatam_api_key = fields.Char(string="PayU Latam API Key", required_if_provider='payulatam', groups='base.group_user')
+
+ def _get_payulatam_urls(self, environment):
+ """ PayUlatam URLs"""
+ if environment == 'prod':
+ return 'https://checkout.payulatam.com/ppp-web-gateway-payu/'
+ return 'https://sandbox.checkout.payulatam.com/ppp-web-gateway-payu/'
+
+ def _payulatam_generate_sign(self, inout, values):
+ if inout not in ('in', 'out'):
+ raise Exception("Type must be 'in' or 'out'")
+
+ if inout == 'in':
+ data_string = ('~').join((self.payulatam_api_key, self.payulatam_merchant_id, values['referenceCode'],
+ str(values['amount']), values['currency']))
+ else:
+ rounded_amount = decimal.Decimal(values.get('TX_VALUE')).quantize(decimal.Decimal('0.1'), decimal.ROUND_HALF_EVEN)
+ data_string = ('~').join((self.payulatam_api_key, self.payulatam_merchant_id, values['referenceCode'],
+ str(rounded_amount), values['currency'], values.get('transactionState')))
+ return md5(data_string.encode('utf-8')).hexdigest()
+
+ def payulatam_form_generate_values(self, values):
+ base_url = self.env['ir.config_parameter'].sudo().get_param('web.base.url')
+ tx = self.env['payment.transaction'].search([('reference', '=', values.get('reference'))])
+ # payulatam will not allow any payment twise even if payment was failed last time.
+ # so, replace reference code if payment is not done or pending.
+ if tx.state not in ['done', 'pending']:
+ tx.reference = str(uuid.uuid4())
+ payulatam_values = dict(
+ values,
+ merchantId=self.payulatam_merchant_id,
+ accountId=self.payulatam_account_id,
+ description=values.get('reference'),
+ referenceCode=tx.reference,
+ amount=values['amount'],
+ tax='0', # This is the transaction VAT. If VAT zero is sent the system, 19% will be applied automatically. It can contain two decimals. Eg 19000.00. In the where you do not charge VAT, it should should be set as 0.
+ taxReturnBase='0',
+ currency=values['currency'].name,
+ buyerEmail=values['partner_email'],
+ responseUrl=urls.url_join(base_url, '/payment/payulatam/response'),
+ )
+ payulatam_values['signature'] = self._payulatam_generate_sign("in", payulatam_values)
+ return payulatam_values
+
+ def payulatam_get_form_action_url(self):
+ self.ensure_one()
+ environment = 'prod' if self.state == 'enabled' else 'test'
+ return self._get_payulatam_urls(environment)
+
+
+class PaymentTransactionPayulatam(models.Model):
+ _inherit = 'payment.transaction'
+
+ @api.model
+ def _payulatam_form_get_tx_from_data(self, data):
+ """ Given a data dict coming from payulatam, verify it and find the related
+ transaction record. """
+ reference, txnid, sign = data.get('referenceCode'), data.get('transactionId'), data.get('signature')
+ if not reference or not txnid or not sign:
+ raise ValidationError(_('PayU Latam: received data with missing reference (%s) or transaction id (%s) or sign (%s)') % (reference, txnid, sign))
+
+ transaction = self.search([('reference', '=', reference)])
+
+ if not transaction:
+ error_msg = (_('PayU Latam: received data for reference %s; no order found') % (reference))
+ raise ValidationError(error_msg)
+ elif len(transaction) > 1:
+ error_msg = (_('PayU Latam: received data for reference %s; multiple orders found') % (reference))
+ raise ValidationError(error_msg)
+
+ # verify shasign
+ sign_check = transaction.acquirer_id._payulatam_generate_sign('out', data)
+ if sign_check.upper() != sign.upper():
+ raise ValidationError(('PayU Latam: invalid sign, received %s, computed %s, for data %s') % (sign, sign_check, data))
+ return transaction
+
+ def _payulatam_form_get_invalid_parameters(self, data):
+ invalid_parameters = []
+
+ if self.acquirer_reference and data.get('transactionId') != self.acquirer_reference:
+ invalid_parameters.append(('Reference code', data.get('transactionId'), self.acquirer_reference))
+ if float_compare(float(data.get('TX_VALUE', '0.0')), self.amount, 2) != 0:
+ invalid_parameters.append(('Amount', data.get('TX_VALUE'), '%.2f' % self.amount))
+ if data.get('merchantId') != self.acquirer_id.payulatam_merchant_id:
+ invalid_parameters.append(('Merchant Id', data.get('merchantId'), self.acquirer_id.payulatam_merchant_id))
+ return invalid_parameters
+
+ def _payulatam_form_validate(self, data):
+ self.ensure_one()
+
+ status = data.get('lapTransactionState') or data.find('transactionResponse').find('state').text
+ res = {
+ 'acquirer_reference': data.get('transactionId') or data.find('transactionResponse').find('transactionId').text,
+ 'state_message': data.get('message') or ""
+ }
+
+ if status == 'APPROVED':
+ _logger.info('Validated PayU Latam payment for tx %s: set as done' % (self.reference))
+ res.update(state='done', date=fields.Datetime.now())
+ self._set_transaction_done()
+ self.write(res)
+ self.execute_callback()
+ return True
+ elif status == 'PENDING':
+ _logger.info('Received notification for PayU Latam payment %s: set as pending' % (self.reference))
+ res.update(state='pending')
+ self._set_transaction_pending()
+ return self.write(res)
+ elif status in ['EXPIRED', 'DECLINED']:
+ _logger.info('Received notification for PayU Latam payment %s: set as Cancel' % (self.reference))
+ res.update(state='cancel')
+ self._set_transaction_cancel()
+ return self.write(res)
+ else:
+ error = 'Received unrecognized status for PayU Latam payment %s: %s, set as error' % (self.reference, status)
+ _logger.info(error)
+ res.update(state='cancel', state_message=error)
+ self._set_transaction_cancel()
+ return self.write(res)