chore: get datatrans admin helper cleanup

This commit is contained in:
Livio Bieri 2023-11-27 16:59:21 +01:00 committed by Christian Cueni
parent 18385b6870
commit 6f90d381f3
4 changed files with 26 additions and 22 deletions

View File

@ -13,7 +13,6 @@ def generate_invoice(modeladmin, request, queryset):
def sync_transaction_state(modeladmin, request, queryset): def sync_transaction_state(modeladmin, request, queryset):
for checkout in queryset: for checkout in queryset:
state = get_transaction_state(transaction_id=checkout.transaction_id) state = get_transaction_state(transaction_id=checkout.transaction_id)
print(state)
checkout.state = state.value checkout.state = state.value
checkout.save( checkout.save(
update_fields=[ update_fields=[

View File

@ -101,7 +101,7 @@ def init_transaction(
def get_transaction_state( def get_transaction_state(
transaction_id: str, transaction_id: str,
) -> CheckoutState | None: ) -> CheckoutState:
response = requests.get( response = requests.get(
f"{settings.DATATRANS_API_ENDPOINT}/v1/transactions/{transaction_id}", f"{settings.DATATRANS_API_ENDPOINT}/v1/transactions/{transaction_id}",
headers={ headers={
@ -110,9 +110,6 @@ def get_transaction_state(
}, },
) )
if response.status_code != 200:
return None
transaction_state = response.json()["status"] transaction_state = response.json()["status"]
logger.info( logger.info(
@ -121,8 +118,23 @@ def get_transaction_state(
response=transaction_state, response=transaction_state,
) )
return CheckoutState(transaction_state) return datatrans_state_to_checkout_state(transaction_state)
def get_payment_url(transaction_id: str): def get_payment_url(transaction_id: str):
return f"{settings.DATATRANS_PAY_URL}/v1/start/{transaction_id}" return f"{settings.DATATRANS_PAY_URL}/v1/start/{transaction_id}"
def datatrans_state_to_checkout_state(
transaction_state: str,
) -> CheckoutState:
if transaction_state in ["settled", "transmitted"]:
return CheckoutState.PAID
elif transaction_state == "failed":
return CheckoutState.FAILED
elif transaction_state == "canceled":
return CheckoutState.CANCELED
else:
# An intermediate state such as "initialized", "challenge_ongoing", etc.
# -> we don't care about those states, we only care about final states here.
return CheckoutState.INITIALIZED

View File

@ -73,7 +73,7 @@ class DatatransWebhookTestCase(APITestCase):
) )
@patch("vbv_lernwelt.shop.views.is_signature_valid") @patch("vbv_lernwelt.shop.views.is_signature_valid")
def test_webhook_creates_course_session_user(self, mock_is_signature_valid): def test_webhook_settled_transmitted_paid(self, mock_is_signature_valid):
# GIVEN # GIVEN
transaction_id = "1234567890" transaction_id = "1234567890"

View File

@ -15,6 +15,7 @@ from vbv_lernwelt.shop.models import (
) )
from vbv_lernwelt.shop.serializers import BillingAddressSerializer from vbv_lernwelt.shop.serializers import BillingAddressSerializer
from vbv_lernwelt.shop.services import ( from vbv_lernwelt.shop.services import (
datatrans_state_to_checkout_state,
get_payment_url, get_payment_url,
init_transaction, init_transaction,
InitTransactionException, InitTransactionException,
@ -66,7 +67,6 @@ def transaction_webhook(request):
Otherwise, this webhook was/will not be called for "initialized" -> "failed" state changes Otherwise, this webhook was/will not be called for "initialized" -> "failed" state changes
For timed out transactions (cleaned up in 15 minute intervals, after 30 minutes by them), For timed out transactions (cleaned up in 15 minute intervals, after 30 minutes by them),
""" """
logger.info("Webhook: Datatrans called transaction webhook", body=request.body) logger.info("Webhook: Datatrans called transaction webhook", body=request.body)
if not is_signature_valid( if not is_signature_valid(
@ -78,26 +78,19 @@ def transaction_webhook(request):
transaction = request.data transaction = request.data
transaction_id = transaction["transactionId"] transaction_id = transaction["transactionId"]
transaction_status = transaction["status"]
# keep webhook history for debugging # keep webhook history (for debugging)
checkout_info = CheckoutInformation.objects.get(transaction_id=transaction_id) checkout_info = CheckoutInformation.objects.get(transaction_id=transaction_id)
checkout_info.webhook_history.append(transaction) checkout_info.webhook_history.append(transaction)
checkout_info.save(update_fields=["webhook_history"]) checkout_info.save(update_fields=["webhook_history"])
# be aware autoSettle has implications on possible transaction states we get! # update checkout state
# See https://api-reference.datatrans.ch/#tag/v1transactions/operation/status checkout_state = datatrans_state_to_checkout_state(transaction["status"])
if transaction_status in ["settled", "transmitted"]: update_checkout_state(checkout_info=checkout_info, state=checkout_state)
update_checkout_state(checkout_info=checkout_info, state=CheckoutState.PAID)
# handle paid
if checkout_state == CheckoutState.PAID:
create_vv_course_session_user(checkout_info=checkout_info) create_vv_course_session_user(checkout_info=checkout_info)
elif transaction_status == "failed":
update_checkout_state(checkout_info=checkout_info, state=CheckoutState.FAILED)
elif transaction_status == "canceled":
update_checkout_state(checkout_info=checkout_info, state=CheckoutState.CANCELED)
else:
logger.warning(
"Unhandled transaction status", transaction_status=transaction_status
)
return JsonResponse({"status": "ok"}) return JsonResponse({"status": "ok"})