Skip to content

Commit

Permalink
add a use_renewal_triggered_by parameter
Browse files Browse the repository at this point in the history
  • Loading branch information
radekholy24 committed Apr 5, 2024
1 parent 1f61405 commit f202141
Show file tree
Hide file tree
Showing 5 changed files with 134 additions and 48 deletions.
2 changes: 1 addition & 1 deletion AUTHORS.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@ Development Lead
Contributors
------------

* Radek Holý
* BlenderKit <[email protected]>
5 changes: 5 additions & 0 deletions HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@
History
-------

Unreleased
**********
* add a use_renewal_triggered_by parameter
* deprecate False value of the use_renewal_triggered_by parameter; migrate to AbstractRecurringUserPlan.renewal_triggered_by and set use_renewal_triggered_by=True instead

1.3.1 (2024-03-19)
******************
* Fix description on PyPI
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, use_renewal_triggered_by=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,
'use_renewal_triggered_by': 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: A mandatory 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.
: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
:use_renewal_triggered_by: (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: A mandatory 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.
: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
22 changes: 20 additions & 2 deletions payments_payu/provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import json
import logging
import uuid
import warnings
from decimal import ROUND_HALF_UP, Decimal
from urllib.parse import urljoin

Expand Down Expand Up @@ -157,7 +158,14 @@ class PayuApiError(Exception):


class PayuProvider(BasicProvider):
def __init__(self, *args, **kwargs):
def __init__(self, *args, use_renewal_triggered_by=False, **kwargs):
# TODO: use_renewal_triggered_by=False deprecated. Remove in the next major release.
if not use_renewal_triggered_by:
warnings.warn(
"use_renewal_triggered_by=False is deprecated. Migrate to "
"AbstractRecurringUserPlan.renewal_triggered_by and set use_renewal_triggered_by=True instead.",
DeprecationWarning,
)
self.client_secret = kwargs.pop("client_secret")
self.second_key = kwargs.pop("second_key")
self.payu_sandbox = kwargs.pop("sandbox", False)
Expand Down Expand Up @@ -185,6 +193,7 @@ 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.__use_renewal_triggered_by = use_renewal_triggered_by
self.get_refund_description = kwargs.pop("get_refund_description")
self.get_refund_ext_id = kwargs.pop(
"get_refund_ext_id", lambda payment, amount: str(uuid.uuid4())
Expand Down Expand Up @@ -420,6 +429,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.__use_renewal_triggered_by:
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 @@ -431,7 +449,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 f202141

Please sign in to comment.