diff --git a/server/vbv_lernwelt/shop/services.py b/server/vbv_lernwelt/shop/services.py index a9561d0e..0e7bd7b3 100644 --- a/server/vbv_lernwelt/shop/services.py +++ b/server/vbv_lernwelt/shop/services.py @@ -1,6 +1,5 @@ import hashlib import hmac -import uuid import requests import structlog @@ -72,6 +71,7 @@ def is_signature_valid( def init_datatrans_transaction( user: User, + refno: str, amount_chf_centimes: int, redirect_url_success: str, redirect_url_error: str, @@ -90,8 +90,8 @@ def init_datatrans_transaction( "amount": amount_chf_centimes, "currency": "CHF", "language": user.language, - "refno": str(uuid.uuid4()), - "refno2": refno2, + "refno": str(refno), + "refno2": str(refno2), "webhook": {"url": webhook_url}, "redirect": { "successUrl": redirect_url_success, diff --git a/server/vbv_lernwelt/shop/tests/test_checkout_api.py b/server/vbv_lernwelt/shop/tests/test_checkout_api.py index efbee5da..f5f46b37 100644 --- a/server/vbv_lernwelt/shop/tests/test_checkout_api.py +++ b/server/vbv_lernwelt/shop/tests/test_checkout_api.py @@ -71,9 +71,8 @@ class CheckoutAPITestCase(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"], + self.assertTrue( + response.json()["next_step_url"].endswith("v1/start/1234567890") ) ci = CheckoutInformation.objects.first() @@ -154,9 +153,11 @@ class CheckoutAPITestCase(APITestCase): ) self.assertEqual( - 0, + 1, CheckoutInformation.objects.count(), ) + ci = CheckoutInformation.objects.first() + self.assertEqual(ci.state, CheckoutState.FAILED) def test_checkout_already_paid(self): # GIVEN @@ -217,9 +218,8 @@ class CheckoutAPITestCase(APITestCase): # THEN self.assertEqual(response.status_code, status.HTTP_200_OK) - self.assertEqual( - f"https://pay.sandbox.datatrans.com/v1/start/{transaction_id_next}", - response.json()["next_step_url"], + self.assertTrue( + response.json()["next_step_url"].endswith(f"v1/start/{transaction_id_next}") ) # check that we have two checkouts @@ -277,9 +277,8 @@ class CheckoutAPITestCase(APITestCase): # THEN self.assertEqual(response.status_code, status.HTTP_200_OK) - self.assertEqual( - f"https://pay.sandbox.datatrans.com/v1/start/{transaction_id}", - response.json()["next_step_url"], + self.assertTrue( + response.json()["next_step_url"].endswith(f"v1/start/{transaction_id}") ) @patch("vbv_lernwelt.shop.views.init_datatrans_transaction") @@ -310,7 +309,6 @@ class CheckoutAPITestCase(APITestCase): # THEN self.assertEqual(response.status_code, status.HTTP_200_OK) - self.assertEqual( - f"https://pay.sandbox.datatrans.com/v1/start/{transaction_id}", - response.json()["next_step_url"], + self.assertTrue( + response.json()["next_step_url"].endswith(f"v1/start/{transaction_id}") ) diff --git a/server/vbv_lernwelt/shop/tests/test_datatrans_service.py b/server/vbv_lernwelt/shop/tests/test_datatrans_service.py index 6dc907fe..7f22c8ee 100644 --- a/server/vbv_lernwelt/shop/tests/test_datatrans_service.py +++ b/server/vbv_lernwelt/shop/tests/test_datatrans_service.py @@ -24,10 +24,8 @@ class DatatransServiceTest(TestCase): @override_settings(DATATRANS_BASIC_AUTH_KEY="BASIC_AUTH_KEY") @patch("vbv_lernwelt.shop.services.requests.post") - @patch("vbv_lernwelt.shop.services.uuid.uuid4") - def test_init_transaction_201(self, mock_uuid, mock_post): + def test_init_transaction_201(self, mock_post): # GIVEN - mock_uuid.return_value = uuid.uuid4() mock_post.return_value.status_code = 201 mock_post.return_value.json.return_value = { "transactionId": 1234567890, @@ -38,6 +36,7 @@ class DatatransServiceTest(TestCase): # WHEN transaction_id = init_datatrans_transaction( user=self.user, + refno="123321", amount_chf_centimes=324_30, redirect_url_success=f"{REDIRECT_URL}/success", redirect_url_error=f"{REDIRECT_URL}/error", @@ -64,11 +63,12 @@ class DatatransServiceTest(TestCase): with self.assertRaises(InitTransactionException): init_datatrans_transaction( user=self.user, + refno="123321", amount_chf_centimes=324_30, - redirect_url_success=f"/success", - redirect_url_error=f"/error", - redirect_url_cancel=f"/cancel", - webhook_url=f"/webhook", + redirect_url_success="/success", + redirect_url_error="/error", + redirect_url_cancel="/cancel", + webhook_url="/webhook", refno2="", ) @@ -80,7 +80,4 @@ class DatatransServiceTest(TestCase): url = get_payment_url(transaction_id) # THEN - self.assertEqual( - url, - f"https://pay.sandbox.datatrans.com/v1/start/{transaction_id}", - ) + self.assertTrue(url.endswith(f"v1/start/{transaction_id}")) diff --git a/server/vbv_lernwelt/shop/views.py b/server/vbv_lernwelt/shop/views.py index 1ce904a3..a245520a 100644 --- a/server/vbv_lernwelt/shop/views.py +++ b/server/vbv_lernwelt/shop/views.py @@ -93,7 +93,7 @@ def checkout_vv(request): sku = request.data["product"] base_redirect_url = request.data["redirect_url"] - log.info(f"Checkout requested: sku", user_id=request.user.id, sku=sku) + log.info("Checkout requested: sku", user_id=request.user.id, sku=sku) try: product = Product.objects.get(sku=sku) @@ -124,6 +124,38 @@ def checkout_vv(request): disable_save="fakeapi" in settings.DATATRANS_API_ENDPOINT ) + address_data = request.data["address"] + country_code = address_data.pop("country_code") + address_data["country_id"] = country_code + + organisation_country_code = "CH" + if "organisation_country_code" in address_data: + organisation_country_code = address_data.pop("organisation_country_code") + address_data["organisation_country_id"] = organisation_country_code + + if "birth_date" in address_data and address_data["birth_date"]: + address_data["birth_date"] = date.fromisoformat(address_data["birth_date"]) + + checkout_info = CheckoutInformation.objects.create( + user=request.user, + state=CheckoutState.ONGOING, + # product + product_sku=sku, + product_price=product.price, + product_name=product.name, + product_description=product.description, + email=email, + ip_address=ip_address, + cembra_byjuno_invoice=with_cembra_byjuno_invoice, + device_fingerprint_session_key=request.data.get( + "device_fingerprint_session_key", "" + ), + # address + **request.data["address"], + ) + + checkout_info.set_increment_abacus_order_id() + refno2 = f"{request.user.abacus_debitor_number}_{VV_PRODUCT_NUMBER}" try: @@ -138,10 +170,10 @@ def checkout_vv(request): "street": f'{request.data["address"]["street"]} {request.data["address"]["street_number"]}', "city": request.data["address"]["city"], "zipCode": request.data["address"]["postal_code"], - "country": request.data["address"]["country_code"], + "country": request.data["address"]["country_id"], "phone": request.data["address"]["phone_number"], "email": email, - "birthDate": request.data["address"]["birth_date"], + "birthDate": str(request.data["address"]["birth_date"]), "language": request.user.language, "ipAddress": ip_address, "type": "P", @@ -154,6 +186,7 @@ def checkout_vv(request): } transaction_id = init_datatrans_transaction( user=request.user, + refno=str(checkout_info.abacus_order_id), amount_chf_centimes=product.price, redirect_url_success=checkout_success_url( base_url=base_redirect_url, product_sku=sku @@ -170,6 +203,8 @@ def checkout_vv(request): with_cembra_byjuno_invoice=with_cembra_byjuno_invoice, ) except InitTransactionException as e: + checkout_info.state = CheckoutState.FAILED.value + checkout_info.save() if not settings.DEBUG: log.error("Transaction initiation failed", exc_info=True, error=str(e)) capture_exception(e) @@ -180,36 +215,8 @@ def checkout_vv(request): ), ) - address_data = request.data["address"] - country_code = address_data.pop("country_code") - address_data["country_id"] = country_code - - organisation_country_code = "CH" - if "organisation_country_code" in address_data: - organisation_country_code = address_data.pop("organisation_country_code") - address_data["organisation_country_id"] = organisation_country_code - - if "birth_date" in address_data and address_data["birth_date"]: - address_data["birth_date"] = date.fromisoformat(address_data["birth_date"]) - - checkout_info = CheckoutInformation.objects.create( - user=request.user, - state=CheckoutState.ONGOING, - transaction_id=transaction_id, - # product - product_sku=sku, - product_price=product.price, - product_name=product.name, - product_description=product.description, - email=email, - ip_address=ip_address, - cembra_byjuno_invoice=with_cembra_byjuno_invoice, - device_fingerprint_session_key=request.data.get( - "device_fingerprint_session_key", "" - ), - # address - **request.data["address"], - ) + checkout_info.transaction_id = transaction_id + checkout_info.save() return next_step_response(url=get_payment_url(transaction_id))