Skip to content

Commit

Permalink
✨(backend) payment backend refund action
Browse files Browse the repository at this point in the history
For now, we have added the refund action with Lyra backend
payment provider. It allows to refund transaction created
with this payment provider.
  • Loading branch information
jonathanreveille committed Oct 1, 2024
1 parent 2f0775c commit d92c32e
Show file tree
Hide file tree
Showing 10 changed files with 696 additions and 3 deletions.
8 changes: 8 additions & 0 deletions src/backend/joanie/payment/backends/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -265,3 +265,11 @@ def tokenize_card(self, order=None, billing_address=None, user=None):
raise NotImplementedError(
"subclasses of BasePaymentBackend must provide a tokenize_card() method."
)

def cancel_or_refund(self, amount, transaction, user_email):
"""
Method called to cancel or refund installments from an order payment schedule.
"""
raise NotImplementedError(
"subclasses of BasePaymentBackend must provide a cancel_or_refund() method."
)
6 changes: 6 additions & 0 deletions src/backend/joanie/payment/backends/dummy.py
Original file line number Diff line number Diff line change
Expand Up @@ -316,3 +316,9 @@ def tokenize_card(self, order=None, billing_address=None, user=None): # pylint:
"customer": str(user.id),
"card_token": f"card_{user.id}",
}

def cancel_or_refund(self, amount, transaction, user_email):
"""
Dummy method to mark installments has refunded.
"""
pass
46 changes: 45 additions & 1 deletion src/backend/joanie/payment/backends/lyra/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,12 @@ def _call_api(self, url, payload):
logger.info("Calling Lyra API %s", url, extra={"context": context})

try:
response = requests.post(url, json=payload, headers=self.headers, timeout=5)
response = requests.post(
url,
json=payload,
headers=self.headers,
timeout=settings.JOANIE_PAYMENT_TIMEOUT,
)
response.raise_for_status()
except requests.exceptions.RequestException as e:
context = context.copy()
Expand Down Expand Up @@ -480,3 +485,42 @@ def abort_payment(self, payment_id):
"""
Abort a payment, nothing to do for Lyra
"""

def cancel_or_refund(self, amount, transaction, user_email):
"""
Method to cancel or refund a transaction made on an order for a user.
This endpoint from Lyra will determine if the transaction can be canceled or refunded
depending on the expected capture date set on the transaction. If the money is not yet
captured on the user's bank account, the transaction it will be canceled, otherwise,
if the capture date has been reached it will trigger the refund of the transaction.
In Joanie's case, the capturedDate is set to 0, which means, the capture of the amount
will be effective the same day.
In a few words, this method cancels the transaction when its still eligible or
refunds the transaction if it has been captured already.
In the answer from the payment provider API : `REFUNDED` or `CANCELLED`
"""
url = f"{self.api_url}Transaction/CancelOrRefund"
payload = {
"amount": int(amount.sub_units),
"currency": settings.DEFAULT_CURRENCY,
"customer": {"email": f"{user_email}"},
"uuid": str(transaction.reference),
"resolutionMode": "AUTO",
}

response_json = self._call_api(url, payload)

if response_json.get("status") != "SUCCESS":
return False

return {
"status": "REFUNDED"
if response_json.get("answer").get("detailedStatus") == "AUTHORISED"
else "CANCELLED",
"reference": response_json.get("answer").get("uuid"),
"installment_id": response_json.get("answer")
.get("metadata")
.get("installment_id"),
}
2 changes: 1 addition & 1 deletion src/backend/joanie/payment/backends/payplug/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ def delete_credit_card(self, credit_card):
"Content-Type": "appliation/json",
"Payplug-Version": self.configuration.get("api_version"),
},
timeout=10,
timeout=settings.JOANIE_PAYMENT_TIMEOUT,
)

if not response.ok:
Expand Down
3 changes: 3 additions & 0 deletions src/backend/joanie/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,9 @@ class Base(Configuration):
environ_name="JOANIE_INSTALLMENT_REMINDER_DAYS_BEFORE",
environ_prefix=None,
)
JOANIE_PAYMENT_TIMEOUT = values.PositiveIntegerValue(
10, environ_name="JOANIE_PAYMENT_TIMEOUT", environ_prefix=None
)

# CORS
CORS_ALLOW_CREDENTIALS = True
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"amount": 10000,
"currency": "EUR",
"resolutionMode": "AUTO",
"uuid": "dbf4b89ae157499e83bea366c91daaa8"
}
Loading

0 comments on commit d92c32e

Please sign in to comment.