chore: incomplete product setup error handling
This commit is contained in:
parent
809c45235f
commit
33bea6c08a
|
|
@ -11,7 +11,6 @@ from vbv_lernwelt.shop.models import (
|
|||
Product,
|
||||
VV_PRODUCT_SKU,
|
||||
)
|
||||
from vbv_lernwelt.shop.services import get_payment_url
|
||||
|
||||
USER_USERNAME = "testuser"
|
||||
USER_EMAIL = "test@example.com"
|
||||
|
|
@ -33,8 +32,10 @@ TEST_ADDRESS_DATA = {
|
|||
"company_country": "Test Company Country",
|
||||
}
|
||||
|
||||
REDIRECT_URL = "http://testserver/redirect-url"
|
||||
|
||||
class CheckoutAPIView(APITestCase):
|
||||
|
||||
class CheckoutAPITestCase(APITestCase):
|
||||
def setUp(self) -> None:
|
||||
Product.objects.create(
|
||||
sku=VV_PRODUCT_SKU,
|
||||
|
|
@ -53,17 +54,16 @@ class CheckoutAPIView(APITestCase):
|
|||
self.client.login(username=USER_USERNAME, password=USER_PASSWORD)
|
||||
|
||||
@patch("vbv_lernwelt.shop.views.init_transaction")
|
||||
def test_checkout(self, mock_init_transaction):
|
||||
def test_checkout_happy_case(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,
|
||||
"redirect_url": REDIRECT_URL,
|
||||
"address": TEST_ADDRESS_DATA,
|
||||
},
|
||||
)
|
||||
|
|
@ -71,8 +71,8 @@ class CheckoutAPIView(APITestCase):
|
|||
# THEN
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(
|
||||
f"https://pay.sandbox.datatrans.com/v1/start/1234567890",
|
||||
response.json()["next_step_url"],
|
||||
get_payment_url("1234567890"),
|
||||
)
|
||||
|
||||
self.assertTrue(
|
||||
|
|
@ -82,3 +82,38 @@ class CheckoutAPIView(APITestCase):
|
|||
state=CheckoutState.INITIALIZED.value,
|
||||
).exists()
|
||||
)
|
||||
|
||||
mock_init_transaction.assert_called_once_with(
|
||||
user=self.user,
|
||||
amount_chf_centimes=300_00,
|
||||
redirect_url_success=f"{REDIRECT_URL}/onboarding/vv/checkout/complete",
|
||||
redirect_url_error=f"{REDIRECT_URL}/onboarding/vv/checkout/address?error",
|
||||
redirect_url_cancel=f"{REDIRECT_URL}/",
|
||||
webhook_url=f"{REDIRECT_URL}/api/shop/transaction/webhook/",
|
||||
)
|
||||
|
||||
@patch("vbv_lernwelt.shop.views.init_transaction")
|
||||
def test_incomplete_setup(self, mock_init_transaction):
|
||||
# GIVEN
|
||||
Product.objects.all().delete()
|
||||
mock_init_transaction.return_value = "1234567890"
|
||||
|
||||
# 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)
|
||||
|
||||
expected = (
|
||||
f"{REDIRECT_URL}/onboarding/vv/checkout/address?error&"
|
||||
f"message=vv_product_does_not_exist_needs_to_be_created"
|
||||
)
|
||||
|
||||
self.assertEqual(expected, response.json()["next_step_url"])
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ from unittest import TestCase
|
|||
from vbv_lernwelt.shop.services import is_signature_valid
|
||||
|
||||
|
||||
class DatatransWebhookSigning(TestCase):
|
||||
class DatatransWebhookSigningTestCase(TestCase):
|
||||
# Key is from their example in the docs, not ours! :D
|
||||
HMAC_KEY_FROM_THE_DOCS_NOT_HAZARDOUS = (
|
||||
"861bbfc01e089259091927d6ad7f71c8"
|
||||
|
|
|
|||
|
|
@ -107,12 +107,18 @@ def checkout_vv(request):
|
|||
"""
|
||||
sku = VV_PRODUCT_SKU
|
||||
logger.info(f"Checkout requested: sku={sku}", user_id=request.user.id)
|
||||
base_redirect_url = request.data["redirect_url"]
|
||||
|
||||
try:
|
||||
product = Product.objects.get(sku=sku)
|
||||
except Product.DoesNotExist:
|
||||
raise Exception(
|
||||
f"Required Product not found: {sku} must be created in the admin interface first.",
|
||||
return JsonResponse(
|
||||
{
|
||||
"next_step_url": checkout_error_url(
|
||||
base_url=base_redirect_url,
|
||||
message="vv_product_does_not_exist_needs_to_be_created",
|
||||
)
|
||||
},
|
||||
)
|
||||
|
||||
checkouts = CheckoutInformation.objects.filter(
|
||||
|
|
@ -131,7 +137,6 @@ def checkout_vv(request):
|
|||
return JsonResponse({"next_step_url": get_payment_url(checkout.transaction_id)})
|
||||
|
||||
# not yet initialized at all, or canceled/failed
|
||||
base_redirect_url = request.data["redirect_url"]
|
||||
transaction_id = init_transaction(
|
||||
user=request.user,
|
||||
amount_chf_centimes=product.price,
|
||||
|
|
@ -162,8 +167,13 @@ def webhook_url(base_url: str) -> str:
|
|||
return f"{base_url}/api/shop/transaction/webhook/"
|
||||
|
||||
|
||||
def checkout_error_url(base_url: str) -> str:
|
||||
return f"{base_url}/onboarding/vv/checkout/address?error"
|
||||
def checkout_error_url(base_url: str, message: str | None = None) -> str:
|
||||
url = f"{base_url}/onboarding/vv/checkout/address?error"
|
||||
|
||||
if message:
|
||||
url += f"&message={message}"
|
||||
|
||||
return url
|
||||
|
||||
|
||||
def checkout_cancel_url(base_url: str) -> str:
|
||||
|
|
|
|||
Loading…
Reference in New Issue