payment_provider.py 3.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. # Part of Odoo. See LICENSE file for full copyright and licensing details.
  2. from hashlib import md5
  3. from odoo import api, fields, models
  4. from odoo.tools.float_utils import float_split, float_repr
  5. SUPPORTED_CURRENCIES = ('ARS', 'BRL', 'CLP', 'COP', 'MXN', 'PEN', 'USD')
  6. class PaymentProvider(models.Model):
  7. _inherit = 'payment.provider'
  8. code = fields.Selection(
  9. selection_add=[('payulatam', 'PayU Latam')], ondelete={'payulatam': 'set default'})
  10. payulatam_merchant_id = fields.Char(
  11. string="PayU Latam Merchant ID",
  12. help="The ID solely used to identify the account with PayULatam",
  13. required_if_provider='payulatam')
  14. payulatam_account_id = fields.Char(
  15. string="PayU Latam Account ID",
  16. help="The ID solely used to identify the country-dependent shop with PayULatam",
  17. required_if_provider='payulatam')
  18. payulatam_api_key = fields.Char(
  19. string="PayU Latam API Key", required_if_provider='payulatam',
  20. groups='base.group_system')
  21. @api.model
  22. def _get_compatible_providers(self, *args, currency_id=None, **kwargs):
  23. """ Override of payment to unlist PayU Latam providers for unsupported currencies. """
  24. providers = super()._get_compatible_providers(*args, currency_id=currency_id, **kwargs)
  25. currency = self.env['res.currency'].browse(currency_id).exists()
  26. if currency and currency.name not in SUPPORTED_CURRENCIES:
  27. providers = providers.filtered(lambda p: p.code != 'payulatam')
  28. return providers
  29. def _payulatam_generate_sign(self, values, incoming=True):
  30. """ Generate the signature for incoming or outgoing communications.
  31. :param dict values: The values used to generate the signature
  32. :param bool incoming: Whether the signature must be generated for an incoming (PayU Latam to
  33. Odoo) or outgoing (Odoo to PayU Latam) communication.
  34. :return: The signature
  35. :rtype: str
  36. """
  37. if incoming:
  38. # "Confirmation" and "Response" pages have a different way to calculate what they call the `new_value`
  39. if self.env.context.get('payulatam_is_confirmation_page'):
  40. # https://developers.payulatam.com/latam/en/docs/integrations/webcheckout-integration/confirmation-page.html#signature-validation
  41. # For confirmation page, PayU Latam round to the first digit if the second one is a zero
  42. # to generate their signature.
  43. # e.g:
  44. # 150.00 -> 150.0
  45. # 150.26 -> 150.26
  46. # This happens to be Python 3's default behavior when casting to `float`.
  47. new_value = "%d.%d" % float_split(float(values.get('TX_VALUE')), 2)
  48. else:
  49. # https://developers.payulatam.com/latam/en/docs/integrations/webcheckout-integration/response-page.html#signature-validation
  50. # PayU Latam use the "Round half to even" rounding method
  51. # to generate their signature. This happens to be Python 3's
  52. # default rounding method.
  53. new_value = float_repr(float(values.get('TX_VALUE')), 1)
  54. data_string = '~'.join([
  55. self.payulatam_api_key,
  56. self.payulatam_merchant_id,
  57. values['referenceCode'],
  58. new_value,
  59. values['currency'],
  60. values.get('transactionState'),
  61. ])
  62. else:
  63. data_string = '~'.join([
  64. self.payulatam_api_key,
  65. self.payulatam_merchant_id,
  66. values['referenceCode'],
  67. float_repr(float(values['amount']), 2),
  68. values['currency'],
  69. ])
  70. return md5(data_string.encode('utf-8')).hexdigest()