Skip to content

Commit

Permalink
add a renewal_triggered_by_use parameter
Browse files Browse the repository at this point in the history
  • Loading branch information
radekholy24 committed Apr 9, 2024
1 parent 9c7454c commit 4226f82
Show file tree
Hide file tree
Showing 4 changed files with 227 additions and 49 deletions.
2 changes: 2 additions & 0 deletions HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@ History
Unreleased
**********
* fix backward compatibility by making PayuProvider's get_refund_description argument optional
* add a renewal_triggered_by_use parameter
* make PayuProvider.refund fail if get_refund_description is not provided
* make PayuProvider.refund raise PayuApiError if an unexpected response is received
* deprecate the default value of get_refund_description; set it to a callable instead
* deprecate False value of the renewal_triggered_by_use parameter; migrate to AbstractRecurringUserPlan.renewal_triggered_by and set renewal_triggered_by_use=True instead

1.3.1 (2024-03-19)
******************
Expand Down
28 changes: 15 additions & 13 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ Quickstart

Install `django-payments <https://github.com/mirumee/django-payments>`_ and set up PayU payment provider backend according to `django-payments documentation <https://django-payments.readthedocs.io/en/latest/modules.html>`_:

.. class:: payments_payu.provider.PayuProvider(client_secret, second_key, pos_id, get_refund_description, [sandbox=False, endpoint="https://secure.payu.com/", recurring_payments=False, express_payments=False, widget_branding=False, get_refund_ext_id=_DEFAULT_GET_REFUND_EXT_ID])
.. class:: payments_payu.provider.PayuProvider(client_secret, second_key, pos_id, get_refund_description, [sandbox=False, endpoint="https://secure.payu.com/", recurring_payments=False, renewal_triggered_by_use=False, express_payments=False, widget_branding=False, get_refund_ext_id=_DEFAULT_GET_REFUND_EXT_ID])

This backend implements payments using `PayU.com <https://payu.com>`_.

Expand All @@ -42,24 +42,26 @@ Example::
'client_secret': 'peopleiseedead',
'sandbox': True,
'capture': False,
'renewal_triggered_by_use': True,
'get_refund_description': lambda payment, amount: 'My refund',
'get_refund_ext_id': lambda payment, amount: str(uuid.uuid4()),
}),
}

Here are valid parameters for the provider:
:client_secret: PayU OAuth protocol client secret
:pos_id: PayU POS ID
:second_key: PayU second key (MD5)
:shop_name: Name of the shop send to the API
:sandbox: if ``True``, set the endpoint to sandbox
:endpoint: endpoint URL, if not set, the will be automatically set based on `sandbox` settings
:recurring_payments: enable recurring payments, only valid with ``express_payments=True``, see bellow for additional setup, that is needed
:express_payments: use PayU express form
:widget_branding: tell express form to show PayU branding
:store_card: (default: False) whether PayU should store the card
:get_refund_description: An optional callable that is called with two keyword arguments `payment` and `amount` in order to get the string description of the particular refund whenever ``provider.refund(payment, amount)`` is called. The callable is optional because of backwards compatibility. However, if it is not set, an attempt to refund raises an exception. A default value of `get_refund_description` is deprecated.
:get_refund_ext_id: An optional callable that is called with two keyword arguments `payment` and `amount` in order to get the External string refund ID of the particular refund whenever ``provider.refund(payment, amount)`` is called. If ``None`` is returned, no External refund ID is set. An External refund ID is not necessary if partial refunds won't be performed more than once per second. Otherwise, a unique ID is recommended since `PayuProvider.refund` is idempotent and if exactly same data will be provided, it will return the result of the already previously performed refund instead of performing a new refund. Defaults to a random UUID version 4 in the standard form.
:client_secret: PayU OAuth protocol client secret
:pos_id: PayU POS ID
:second_key: PayU second key (MD5)
:shop_name: Name of the shop send to the API
:sandbox: if ``True``, set the endpoint to sandbox
:endpoint: endpoint URL, if not set, the will be automatically set based on `sandbox` settings
:recurring_payments: enable recurring payments, only valid with ``express_payments=True``, see bellow for additional setup, that is needed
:renewal_triggered_by_use: (default: False) Pass the ``renewal_triggered_by`` argument instead of the ``automatic_renewal`` argument to ``Payment.set_renew_token()``
:express_payments: use PayU express form
:widget_branding: tell express form to show PayU branding
:store_card: (default: False) whether PayU should store the card
:get_refund_description: An optional callable that is called with two keyword arguments `payment` and `amount` in order to get the string description of the particular refund whenever ``provider.refund(payment, amount)`` is called. The callable is optional because of backwards compatibility. However, if it is not set, an attempt to refund raises an exception. A default value of `get_refund_description` is deprecated.
:get_refund_ext_id: An optional callable that is called with two keyword arguments `payment` and `amount` in order to get the External string refund ID of the particular refund whenever ``provider.refund(payment, amount)`` is called. If ``None`` is returned, no External refund ID is set. An External refund ID is not necessary if partial refunds won't be performed more than once per second. Otherwise, a unique ID is recommended since `PayuProvider.refund` is idempotent and if exactly same data will be provided, it will return the result of the already previously performed refund instead of performing a new refund. Defaults to a random UUID version 4 in the standard form.


NOTE: notifications about the payment status from PayU are requested to be sent to `django-payments` `process_payment` url. The request from PayU can fail for several reasons (i.e. it can be blocked by proxy). Use "Show reports" page in PayU administration to get more information about the requests.
Expand Down
19 changes: 18 additions & 1 deletion payments_payu/provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,14 @@ def __init__(self, *args, **kwargs):
self.payu_shop_name = kwargs.pop("shop_name", "")
self.grant_type = kwargs.pop("grant_type", "client_credentials")
self.recurring_payments = kwargs.pop("recurring_payments", False)
self.__renewal_triggered_by_use = kwargs.pop("renewal_triggered_by_use", False)
# TODO: renewal_triggered_by_use=False deprecated. Remove in the next major release.
if not self.__renewal_triggered_by_use:
warnings.warn(
"renewal_triggered_by_use=False is deprecated. Migrate to "
"AbstractRecurringUserPlan.renewal_triggered_by and set renewal_triggered_by_use=True instead.",
DeprecationWarning,
)
self.get_refund_description = kwargs.pop(
"get_refund_description",
# TODO: The default is deprecated. Remove in the next major release.
Expand Down Expand Up @@ -430,6 +438,15 @@ def create_order(self, payment, payment_processor, auto_renew=False):
payment.transaction_id = response_dict["orderId"]

if "payMethods" in response_dict:
set_renew_token_kwargs = {}
if self.__renewal_triggered_by_use:
set_renew_token_kwargs["renewal_triggered_by"] = (
"task" if self.recurring_payments else "user"
)
else:
set_renew_token_kwargs["automatic_renewal"] = (
self.recurring_payments
)
payment.set_renew_token(
response_dict["payMethods"]["payMethod"]["value"],
card_expire_year=response_dict["payMethods"]["payMethod"]["card"][
Expand All @@ -441,7 +458,7 @@ def create_order(self, payment, payment_processor, auto_renew=False):
card_masked_number=response_dict["payMethods"]["payMethod"]["card"][
"number"
],
automatic_renewal=self.recurring_payments,
**set_renew_token_kwargs,
)
add_extra_data(payment, {"card_response": response_dict})

Expand Down
Loading

0 comments on commit 4226f82

Please sign in to comment.