chore: test for checkout flow
This commit is contained in:
parent
2bb62a2b4f
commit
809c45235f
|
|
@ -62,10 +62,6 @@ def init_transaction(
|
||||||
webhook_url = overwrite
|
webhook_url = overwrite
|
||||||
|
|
||||||
payload = {
|
payload = {
|
||||||
# See https://api-reference.datatrans.ch/#tag/v1transactions:
|
|
||||||
# -> It _should_ be unique for each transaction (according to docs)
|
|
||||||
# -> We use transaction id for checking transaction state
|
|
||||||
"refno": str(uuid.uuid4()),
|
|
||||||
# We use autoSettle=True, so that we don't have to settle the transaction:
|
# We use autoSettle=True, so that we don't have to settle the transaction:
|
||||||
# -> Be aware that autoSettle has implications of the possible transaction states
|
# -> Be aware that autoSettle has implications of the possible transaction states
|
||||||
# -> see CheckoutState docstring.
|
# -> see CheckoutState docstring.
|
||||||
|
|
@ -73,6 +69,7 @@ def init_transaction(
|
||||||
"amount": amount_chf_centimes,
|
"amount": amount_chf_centimes,
|
||||||
"currency": "CHF",
|
"currency": "CHF",
|
||||||
"language": user.language,
|
"language": user.language,
|
||||||
|
"refno": str(uuid.uuid4()),
|
||||||
"webhook": {"url": webhook_url},
|
"webhook": {"url": webhook_url},
|
||||||
"redirect": {
|
"redirect": {
|
||||||
"successUrl": redirect_url_success,
|
"successUrl": redirect_url_success,
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,84 @@
|
||||||
|
from unittest.mock import patch
|
||||||
|
|
||||||
|
from django.urls import reverse
|
||||||
|
from rest_framework import status
|
||||||
|
from rest_framework.test import APITestCase
|
||||||
|
|
||||||
|
from vbv_lernwelt.core.admin import User
|
||||||
|
from vbv_lernwelt.shop.models import (
|
||||||
|
CheckoutInformation,
|
||||||
|
CheckoutState,
|
||||||
|
Product,
|
||||||
|
VV_PRODUCT_SKU,
|
||||||
|
)
|
||||||
|
from vbv_lernwelt.shop.services import get_payment_url
|
||||||
|
|
||||||
|
USER_USERNAME = "testuser"
|
||||||
|
USER_EMAIL = "test@example.com"
|
||||||
|
USER_PASSWORD = "testpassword"
|
||||||
|
|
||||||
|
TEST_ADDRESS_DATA = {
|
||||||
|
"first_name": "Test",
|
||||||
|
"last_name": "User",
|
||||||
|
"street": "Test Street",
|
||||||
|
"street_number": "1",
|
||||||
|
"postal_code": "1234",
|
||||||
|
"city": "Test City",
|
||||||
|
"country": "Test Country",
|
||||||
|
"company_name": "Test Company",
|
||||||
|
"company_street": "Test Company Street",
|
||||||
|
"company_street_number": "1",
|
||||||
|
"company_postal_code": "1234",
|
||||||
|
"company_city": "Test Company City",
|
||||||
|
"company_country": "Test Company Country",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class CheckoutAPIView(APITestCase):
|
||||||
|
def setUp(self) -> None:
|
||||||
|
Product.objects.create(
|
||||||
|
sku=VV_PRODUCT_SKU,
|
||||||
|
price=300_00,
|
||||||
|
description="VV",
|
||||||
|
name="VV",
|
||||||
|
)
|
||||||
|
|
||||||
|
self.user = User.objects.create_user(
|
||||||
|
username=USER_USERNAME,
|
||||||
|
email=USER_EMAIL,
|
||||||
|
password=USER_PASSWORD,
|
||||||
|
is_active=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
self.client.login(username=USER_USERNAME, password=USER_PASSWORD)
|
||||||
|
|
||||||
|
@patch("vbv_lernwelt.shop.views.init_transaction")
|
||||||
|
def test_checkout(self, mock_init_transaction):
|
||||||
|
# GIVEN
|
||||||
|
mock_init_transaction.return_value = "1234567890"
|
||||||
|
redirect_url = "http://testserver/redirect-url"
|
||||||
|
|
||||||
|
# WHEN
|
||||||
|
response = self.client.post(
|
||||||
|
path=reverse("checkout-vv"),
|
||||||
|
format="json",
|
||||||
|
data={
|
||||||
|
"redirect_url": redirect_url,
|
||||||
|
"address": TEST_ADDRESS_DATA,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
# THEN
|
||||||
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||||
|
self.assertEqual(
|
||||||
|
response.json()["next_step_url"],
|
||||||
|
get_payment_url("1234567890"),
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertTrue(
|
||||||
|
CheckoutInformation.objects.filter(
|
||||||
|
user=self.user,
|
||||||
|
product_sku=VV_PRODUCT_SKU,
|
||||||
|
state=CheckoutState.INITIALIZED.value,
|
||||||
|
).exists()
|
||||||
|
)
|
||||||
|
|
@ -32,8 +32,8 @@ def get_billing_address(request):
|
||||||
data = BillingAddressSerializer(billing_address).data
|
data = BillingAddressSerializer(billing_address).data
|
||||||
except BillingAddress.DoesNotExist:
|
except BillingAddress.DoesNotExist:
|
||||||
data = BillingAddressSerializer().data
|
data = BillingAddressSerializer().data
|
||||||
data["first_name"] = request.user.first_name
|
data["first_name"] = request.user.first_name # noqa
|
||||||
data["last_name"] = request.user.last_name
|
data["last_name"] = request.user.last_name # noqa
|
||||||
|
|
||||||
return Response(data)
|
return Response(data)
|
||||||
|
|
||||||
|
|
@ -128,10 +128,6 @@ def checkout_vv(request):
|
||||||
|
|
||||||
# already initialized -> redirect to payment page again
|
# already initialized -> redirect to payment page again
|
||||||
if checkout := checkouts.filter(state=CheckoutState.INITIALIZED).first():
|
if checkout := checkouts.filter(state=CheckoutState.INITIALIZED).first():
|
||||||
# FIXME: Ask datatrans how they advice to handle this case:
|
|
||||||
# - 1. Why is the payment url not reusable? Calling the payment url again
|
|
||||||
# with the same transaction id results in a blank page.
|
|
||||||
# - 2. After 30 minutes, the transaction is fails but our webhook is not called?
|
|
||||||
return JsonResponse({"next_step_url": get_payment_url(checkout.transaction_id)})
|
return JsonResponse({"next_step_url": get_payment_url(checkout.transaction_id)})
|
||||||
|
|
||||||
# not yet initialized at all, or canceled/failed
|
# not yet initialized at all, or canceled/failed
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue