@payment-kit-js/vanilla 0.5.18 → 0.5.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -7,3 +7,17 @@ Vanilla JavaScript SDK for PaymentKit. A type-safe, framework-agnostic payment p
7
7
  For complete documentation, guides, and examples, visit:
8
8
 
9
9
  **[PaymentKit.js Documentation](https://docs.paymentkit.com/guides/integration/sdk-reference/payment-kit-js/getting-started)**
10
+
11
+ ## Content-Security-Policy Requirements
12
+
13
+ If your site uses a Content-Security-Policy header, you must add the following domains to your `script-src` directive to allow fraud prevention scripts:
14
+
15
+ - **Production:** `https://static.airwallex.com`
16
+ - **Sandbox:** `https://static-demo.airwallex.com`
17
+
18
+ Example:
19
+ ```
20
+ Content-Security-Policy: script-src 'self' https://static.airwallex.com;
21
+ ```
22
+
23
+ If these domains are blocked, PaymentKit.js will log an error to the console with the required domain.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * PaymentKit.js v0.5.18
2
+ * PaymentKit.js v0.5.19
3
3
  * https://paymentkit.com
4
4
  *
5
5
  * @license MIT
@@ -42,7 +42,7 @@ var PaymentKit = (() => {
42
42
  });
43
43
 
44
44
  // package.json
45
- var version = "0.5.18";
45
+ var version = "0.5.19";
46
46
 
47
47
  // src/analytics/mock-adapter.ts
48
48
  var MockAnalyticsAdapter = class {
@@ -6464,6 +6464,18 @@ var PaymentKit = (() => {
6464
6464
  }
6465
6465
 
6466
6466
  // src/index.ts
6467
+ function appendScriptToDOM(script) {
6468
+ const target = document.body ?? document.head;
6469
+ target.appendChild(script);
6470
+ }
6471
+ function getFraudScriptId(url) {
6472
+ if (url.includes("airwallex.com")) {
6473
+ return "airwallex-fraud-api";
6474
+ }
6475
+ const urlObj = new URL(url);
6476
+ const hash = btoa(urlObj.origin + urlObj.pathname).replace(/[^a-zA-Z0-9]/g, "").slice(0, 12);
6477
+ return `pk-fraud-script-${hash}`;
6478
+ }
6467
6479
  var createTunnelXConnection = (baseUrl, apiBaseUrl, token) => {
6468
6480
  const iframe = createCheckoutIFrame("tunnel-x", baseUrl, {
6469
6481
  checkout_token: token,
@@ -6472,9 +6484,12 @@ var PaymentKit = (() => {
6472
6484
  Object.assign(iframe.style, { width: "0", height: "0", position: "absolute", visibility: "hidden" });
6473
6485
  document.body.appendChild(iframe);
6474
6486
  const connection = connectToTunnelXIframe(iframe, {});
6487
+ let destroyed = false;
6475
6488
  const unmount = () => {
6489
+ if (destroyed) return;
6490
+ destroyed = true;
6476
6491
  connection.destroy();
6477
- document.body.removeChild(iframe);
6492
+ iframe.remove();
6478
6493
  };
6479
6494
  return { unmount, connection };
6480
6495
  };
@@ -6511,7 +6526,9 @@ var PaymentKit = (() => {
6511
6526
  cardTokenizationMode,
6512
6527
  vgsVaultId,
6513
6528
  vgsEnvironment,
6514
- _sessionConfigReady: void 0
6529
+ _sessionConfigReady: void 0,
6530
+ _fraudScriptIds: [],
6531
+ _fraudScriptsReady: void 0
6515
6532
  };
6516
6533
  if (cardTokenizationMode === void 0) {
6517
6534
  const sessionConfigUrl = `${apiBaseUrl}/api/checkout-sessions/token/${secureToken}`;
@@ -6542,6 +6559,48 @@ var PaymentKit = (() => {
6542
6559
  );
6543
6560
  paymentKitStates.cardTokenizationMode = "direct";
6544
6561
  }
6562
+ if (session?.fraud_script_urls?.length) {
6563
+ const loadPromises = [];
6564
+ session.fraud_script_urls.forEach((url) => {
6565
+ const scriptId = getFraudScriptId(url);
6566
+ if (document.getElementById(scriptId)) {
6567
+ console.log(`[PaymentKit] Fraud script already present: ${scriptId}`);
6568
+ loadPromises.push(Promise.resolve());
6569
+ return;
6570
+ }
6571
+ const script = document.createElement("script");
6572
+ script.type = "text/javascript";
6573
+ script.async = true;
6574
+ script.id = scriptId;
6575
+ script.src = url;
6576
+ script.dataset.orderSessionId = checkoutRequestId;
6577
+ const loadPromise2 = new Promise((resolve) => {
6578
+ script.onload = () => {
6579
+ console.log(`[PaymentKit] Fraud script loaded: ${scriptId}`);
6580
+ resolve();
6581
+ };
6582
+ script.onerror = () => {
6583
+ console.error(
6584
+ `[PaymentKit] Failed to load fraud prevention script. If using Content-Security-Policy, add to script-src: ${new URL(url).origin}`
6585
+ );
6586
+ resolve();
6587
+ };
6588
+ });
6589
+ loadPromises.push(loadPromise2);
6590
+ paymentKitStates._fraudScriptIds.push(scriptId);
6591
+ appendScriptToDOM(script);
6592
+ });
6593
+ paymentKitStates._fraudScriptsReady = Promise.all(loadPromises).then(() => {
6594
+ console.log(`[PaymentKit] All ${loadPromises.length} fraud fingerprinting script(s) ready`);
6595
+ });
6596
+ session.fraud_script_urls.forEach((url) => {
6597
+ const scriptId = getFraudScriptId(url);
6598
+ console.log(
6599
+ `[PaymentKit] Fraud script injected: id=${scriptId}, data-order-session-id=${checkoutRequestId}, src=${url}`
6600
+ );
6601
+ });
6602
+ console.log(`[PaymentKit] Injected ${session.fraud_script_urls.length} fraud fingerprinting script(s)`);
6603
+ }
6545
6604
  } else {
6546
6605
  console.log("[PaymentKit] Session response missing card_tokenization_mode \u2014 defaulting to direct mode");
6547
6606
  paymentKitStates.cardTokenizationMode = "direct";
@@ -6587,6 +6646,13 @@ var PaymentKit = (() => {
6587
6646
  });
6588
6647
  };
6589
6648
  const cleanup = () => {
6649
+ for (const scriptId of paymentKitStates._fraudScriptIds) {
6650
+ const script = document.getElementById(scriptId);
6651
+ if (script) {
6652
+ script.remove();
6653
+ }
6654
+ }
6655
+ paymentKitStates._fraudScriptIds = [];
6590
6656
  for (const pm of pmInstances) {
6591
6657
  if (pm.internalFuncs.cleanup) {
6592
6658
  pm.internalFuncs.cleanup();
@@ -7097,9 +7163,7 @@ var PaymentKit = (() => {
7097
7163
  container.style.opacity = "0";
7098
7164
  container.style.transform = "scale(0.95) translateY(10px)";
7099
7165
  setTimeout(() => {
7100
- if (overlay.parentNode) {
7101
- overlay.parentNode.removeChild(overlay);
7102
- }
7166
+ overlay.remove();
7103
7167
  }, 250);
7104
7168
  });
7105
7169
  };
@@ -8479,10 +8543,7 @@ var PaymentKit = (() => {
8479
8543
  cleanupDirect = () => {
8480
8544
  const connection = cardInputConnections[type];
8481
8545
  connection?.destroy();
8482
- try {
8483
- parent.removeChild(iframe);
8484
- } catch {
8485
- }
8546
+ iframe.remove();
8486
8547
  states.cardInputConnections[type] = void 0;
8487
8548
  };
8488
8549
  parent.appendChild(iframe);
@@ -8570,13 +8631,19 @@ var PaymentKit = (() => {
8570
8631
  }
8571
8632
  console.log("Card setup intent is set \u2705", cardSetupIntent);
8572
8633
  console.log("Fields", fields);
8634
+ const fraudMetadata = {
8635
+ ...collectFraudMetadata(),
8636
+ processorFraudInfo: {
8637
+ airwallexDeviceId: states.checkoutRequestId
8638
+ }
8639
+ };
8573
8640
  let currentResult = await tunnelX.publicEndpoints.cardCheckout(
8574
8641
  {
8575
8642
  checkoutToken: states.secureToken,
8576
8643
  publicCardCheckoutRequest: {
8577
8644
  cardSetupIntentId: states.cardSetupIntentId,
8578
8645
  customerInfo: mapFieldsToCustomerInfo(fields),
8579
- fraudMetadata: collectFraudMetadata()
8646
+ fraudMetadata
8580
8647
  }
8581
8648
  },
8582
8649
  requestOptions