diff --git a/client/src/components/onboarding/DatatransCembraDeviceFingerprint.vue b/client/src/components/onboarding/DatatransCembraDeviceFingerprint.vue
new file mode 100644
index 00000000..3ff87c27
--- /dev/null
+++ b/client/src/components/onboarding/DatatransCembraDeviceFingerprint.vue
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
+
diff --git a/client/src/main.ts b/client/src/main.ts
index 84ad3781..900b094d 100644
--- a/client/src/main.ts
+++ b/client/src/main.ts
@@ -9,6 +9,7 @@ import type { Router } from "vue-router";
import "../tailwind.css";
import App from "./App.vue";
import router from "./router";
+import { generateLocalSessionKey } from "@/statistics";
declare module "pinia" {
export interface PiniaCustomProperties {
@@ -24,6 +25,8 @@ if (appEnv.startsWith("prod")) {
log.setLevel("trace");
}
+generateLocalSessionKey();
+
const commit = "VBV_VERSION_BUILD_NUMBER_VBV";
log.warn(`application started appEnv=${appEnv}, build=${commit}`);
diff --git a/client/src/pages/onboarding/vv/CheckoutAddress.vue b/client/src/pages/onboarding/vv/CheckoutAddress.vue
index 3b5b8049..ad72cc85 100644
--- a/client/src/pages/onboarding/vv/CheckoutAddress.vue
+++ b/client/src/pages/onboarding/vv/CheckoutAddress.vue
@@ -10,6 +10,8 @@ import { useRoute } from "vue-router";
import { useTranslation } from "i18next-vue";
import { getVVCourseName } from "./composables";
import ItToggleSwitch from "@/components/ui/ItToggleSwitch.vue";
+import DatatransCembraDeviceFingerprint from "@/components/onboarding/DatatransCembraDeviceFingerprint.vue";
+import { getLocalSessionKey } from "@/statistics";
const props = defineProps({
courseType: {
@@ -178,6 +180,7 @@ const executePayment = async () => {
address: address.value,
product: props.courseType,
with_cembra_invoice: withCembraInvoice.value,
+ device_fingerprint_session_key: getLocalSessionKey(),
}).then((res: any) => {
console.log("Going to next page", res.next_step_url);
window.location.href = res.next_step_url;
@@ -188,6 +191,7 @@ const executePayment = async () => {
+
{{ $t("a.Lehrgang kaufen") }}
diff --git a/client/src/statistics.ts b/client/src/statistics.ts
new file mode 100644
index 00000000..58a7245d
--- /dev/null
+++ b/client/src/statistics.ts
@@ -0,0 +1,46 @@
+let statisticsLocalSessionKey = "";
+let statisticsLocalSessionRef = "";
+
+export function uuidv4() {
+ // copied from https://stackoverflow.com/a/2117523/669561
+ // @ts-ignore
+ return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, (c) =>
+ (c ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))).toString(16)
+ );
+}
+
+export function getLocalSessionKey() {
+ return (
+ window.sessionStorage.getItem("statisticsLocalSessionKey") ||
+ statisticsLocalSessionKey ||
+ ""
+ );
+}
+
+export function generateLocalSessionKey() {
+ let localSessionKey =
+ window.sessionStorage.getItem("statisticsLocalSessionKey") ||
+ statisticsLocalSessionKey;
+ if (!localSessionKey) {
+ localSessionKey = uuidv4();
+ }
+ statisticsLocalSessionKey = localSessionKey;
+ window.sessionStorage.setItem("statisticsLocalSessionKey", localSessionKey);
+
+ return localSessionKey;
+}
+
+export function getLocalSessionRef() {
+ return (
+ window.sessionStorage.getItem("statisticsLocalSessionRef") ||
+ statisticsLocalSessionRef ||
+ ""
+ );
+}
+
+export function setLocalSessionRef(sessionRef: string) {
+ if (sessionRef) {
+ statisticsLocalSessionRef = sessionRef;
+ window.sessionStorage.setItem("statisticsLocalSessionRef", sessionRef);
+ }
+}
diff --git a/cypress/e2e/checkout-vv/checkout.cy.js b/cypress/e2e/checkout-vv/checkout.cy.js
index 41006853..8a480d85 100644
--- a/cypress/e2e/checkout-vv/checkout.cy.js
+++ b/cypress/e2e/checkout-vv/checkout.cy.js
@@ -119,6 +119,8 @@ describe("checkout.cy.js", () => {
"contain",
"Lehrgang kaufen"
);
+ cy.get('[data-cy="cembra-switch"]').click();
+
cy.get("#street-address").type("Eggersmatt");
cy.get("#street-number").type("32");
cy.get("#postal-code").type("1719");
@@ -127,8 +129,6 @@ describe("checkout.cy.js", () => {
cy.get("#phone").type("+41 79 201 85 86");
cy.get("#birth-date").type("1982-06-09");
- cy.get('[data-cy="cembra-switch"]').click();
-
cy.get('[data-cy="continue-pay"]').click();
// check that results are stored on server
@@ -151,6 +151,9 @@ describe("checkout.cy.js", () => {
expect(ci.product_price).to.equal(32400);
expect(ci.state).to.equal("ongoing");
+
+ expect(ci.ip_address).to.not.be.empty;
+ expect(ci.device_fingerprint_session_key).to.not.be.empty;
});
});
});
diff --git a/server/vbv_lernwelt/shop/migrations/0015_auto_cembra_fields.py b/server/vbv_lernwelt/shop/migrations/0015_cembra_fields.py
similarity index 87%
rename from server/vbv_lernwelt/shop/migrations/0015_auto_cembra_fields.py
rename to server/vbv_lernwelt/shop/migrations/0015_cembra_fields.py
index 6de9f51a..06fa2a94 100644
--- a/server/vbv_lernwelt/shop/migrations/0015_auto_cembra_fields.py
+++ b/server/vbv_lernwelt/shop/migrations/0015_cembra_fields.py
@@ -1,4 +1,4 @@
-# Generated by Django 3.2.20 on 2024-06-21 08:47
+# Generated by Django 3.2.20 on 2024-06-21 09:54
from django.db import migrations, models
@@ -22,8 +22,8 @@ class Migration(migrations.Migration):
),
migrations.AddField(
model_name='checkoutinformation',
- name='device_fingerprint',
- field=models.TextField(blank=True, default=''),
+ name='device_fingerprint_session_key',
+ field=models.CharField(blank=True, default='', max_length=255),
),
migrations.AddField(
model_name='checkoutinformation',
diff --git a/server/vbv_lernwelt/shop/models.py b/server/vbv_lernwelt/shop/models.py
index 84bd177b..0bd11045 100644
--- a/server/vbv_lernwelt/shop/models.py
+++ b/server/vbv_lernwelt/shop/models.py
@@ -83,7 +83,9 @@ class CheckoutInformation(models.Model):
birth_date = models.DateField(null=True, blank=True)
phone_number = models.CharField(max_length=255, blank=True, default="")
email = models.CharField(max_length=255, blank=True, default="")
- device_fingerprint = models.TextField(blank=True, default="")
+ device_fingerprint_session_key = models.CharField(
+ max_length=255, blank=True, default=""
+ )
ip_address = models.CharField(max_length=255, blank=True, default="")
invoice_address = models.CharField(
diff --git a/server/vbv_lernwelt/shop/views.py b/server/vbv_lernwelt/shop/views.py
index 7d758e24..485afbaa 100644
--- a/server/vbv_lernwelt/shop/views.py
+++ b/server/vbv_lernwelt/shop/views.py
@@ -140,7 +140,7 @@ def checkout_vv(request):
"subtype": "INVOICE",
"riskOwner": "IJ",
"repaymentType": 3,
- "deviceFingerprintId": "TODO",
+ "deviceFingerprintId": request.data["device_fingerprint_session_key"],
}
transaction_id = init_datatrans_transaction(
user=request.user,
@@ -190,6 +190,7 @@ def checkout_vv(request):
email=email,
ip_address=ip_address,
cembra_invoice=with_cembra_invoice,
+ device_fingerprint_session_key=request.data["device_fingerprint_session_key"],
# address
**request.data["address"],
)