@finteqhub/sdk-js 0.14.0 → 0.16.0-beta.1

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/CHANGELOG.md CHANGED
@@ -2,6 +2,19 @@
2
2
 
3
3
  Notable changes to `@finteqhub/sdk-js`. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
4
4
 
5
+ ## 0.16.0
6
+
7
+ ### Changed
8
+
9
+ - The SDK no longer sends the `x-merchant-id` header (previously on every request) or the `x-project-id` header (previously on `submit-form` and `operations` requests, taken from the session response). The constructor signature is unchanged: `merchantId` is still accepted, but it is no longer validated (the constructor does not throw when it is empty or missing) and is not transmitted. This release requires a backend that no longer expects these headers; against older backends `submit-form` and `sessions` requests are rejected with 400.
10
+
11
+ ## 0.15.0
12
+
13
+ ### Added
14
+
15
+ - Form submissions include `session.device.browser.clientHints` when `navigator.userAgentData` is available, for both regular and secure endpoints. The SDK forwards native browser keys and values, including the high-entropy device model, for backend device-brand detection; it does not send a device brand itself.
16
+ - If high-entropy values are unavailable or rejected, the SDK sends the available low-entropy `brands`, `mobile` and `platform` values. Browsers without the API omit `clientHints` entirely. The public SDK API is unchanged.
17
+
5
18
  ## 0.14.0
6
19
 
7
20
  ### Breaking changes
package/README.md CHANGED
@@ -6,7 +6,9 @@ Use `new FinteqHubProcessing(apiUrl: string, fingerprintVisitorId: string, merch
6
6
  const processing = new FinteqHubProcessing('api-url', 'fingerprint-visitor-id', 'merchant-id', 'session-id');
7
7
  ```
8
8
 
9
- The constructor validates its arguments and throws a `TypeError` when `apiUrl`, `fingerprintVisitorId`, `merchantId` or `sessionId` is missing, empty or not a string, when `isSecure` is not a boolean, or when `retryOptions` is malformed (see [Retries and error diagnostics](#retries-and-error-diagnostics)).
9
+ The constructor validates its arguments and throws a `TypeError` when `apiUrl`, `fingerprintVisitorId` or `sessionId` is missing, empty or not a string, when `isSecure` is not a boolean, or when `retryOptions` is malformed (see [Retries and error diagnostics](#retries-and-error-diagnostics)).
10
+
11
+ `merchantId` is accepted for compatibility but is neither validated nor sent to the API since 0.16.0.
10
12
 
11
13
  ## Retries and error diagnostics
12
14
 
@@ -43,7 +43,6 @@ export class FinteqHubProcessing {
43
43
  method: "GET",
44
44
  headers: {
45
45
  "Content-Type": "application/json;charset=UTF-8",
46
- "x-merchant-id": this.merchantId,
47
46
  "x-request-id": uuid(),
48
47
  [SDK_HEADER_NAME]: SDK_HEADER_VALUE,
49
48
  },
@@ -60,7 +59,7 @@ export class FinteqHubProcessing {
60
59
  return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
61
60
  try {
62
61
  const url = this.isSecure ? `${this.apiUrl}/v1/secure/transactions/submit-form` : `${this.apiUrl}/v1/transactions/submit-form`;
63
- const result = yield this.sendPost(url, Object.assign({ session: Object.assign({ fingerprint: this.fingerprintVisitorId }, getDeviceData()) }, data));
62
+ const result = yield this.sendPost(url, Object.assign({ session: Object.assign({ fingerprint: this.fingerprintVisitorId }, (yield getDeviceData())) }, data));
64
63
  const operationUrl = this.isSecure ? `${this.apiUrl}/v1/secure/operations/${result.operationId}` : `${this.apiUrl}/v1/operations/${result.operationId}`;
65
64
  this.processOperation(operationUrl, resolve, reject);
66
65
  }
@@ -108,11 +107,9 @@ export class FinteqHubProcessing {
108
107
  method: "POST",
109
108
  headers: {
110
109
  "Content-Type": "application/json;charset=UTF-8",
111
- "x-merchant-id": this.merchantId,
112
110
  "x-request-id": uuid(),
113
111
  "x-fingerprint": this.fingerprintVisitorId,
114
112
  "x-session-id": this.sessionId,
115
- "x-project-id": this.projectId,
116
113
  [SDK_HEADER_NAME]: SDK_HEADER_VALUE,
117
114
  },
118
115
  body: JSON.stringify(data),
@@ -19,13 +19,30 @@ declare type ConstructorArguments = {
19
19
  retryOptions: RetryOptions;
20
20
  };
21
21
  export declare function validateArguments(args: ConstructorArguments): void;
22
- export declare function getDeviceData(): {
22
+ /** Returns native browser hints, falling back to low entropy values if needed. */
23
+ export declare function getClientHints(): Promise<{
24
+ architecture?: string;
25
+ bitness?: string;
26
+ brands?: {
27
+ brand: string;
28
+ version: string;
29
+ }[];
30
+ formFactors?: string[];
31
+ fullVersionList?: {
32
+ brand: string;
33
+ version: string;
34
+ }[];
35
+ mobile?: boolean;
36
+ model?: string;
37
+ platform?: string;
38
+ platformVersion?: string;
39
+ uaFullVersion?: string;
40
+ wow64?: boolean;
41
+ }>;
42
+ export declare function getDeviceData(): Promise<{
23
43
  device: {
24
44
  type: string;
25
45
  browser: {
26
- platform: string;
27
- acceptHeader: string;
28
- userAgent: string;
29
46
  javaEnabled: boolean;
30
47
  javaScriptEnabled: boolean;
31
48
  language: string;
@@ -38,7 +55,29 @@ export declare function getDeviceData(): {
38
55
  windowInnerWidth: number;
39
56
  timeZoneOffset: number;
40
57
  timeZoneName: string;
58
+ clientHints?: {
59
+ architecture?: string;
60
+ bitness?: string;
61
+ brands?: {
62
+ brand: string;
63
+ version: string;
64
+ }[];
65
+ formFactors?: string[];
66
+ fullVersionList?: {
67
+ brand: string;
68
+ version: string;
69
+ }[];
70
+ mobile?: boolean;
71
+ model?: string;
72
+ platform?: string;
73
+ platformVersion?: string;
74
+ uaFullVersion?: string;
75
+ wow64?: boolean;
76
+ };
77
+ platform: string;
78
+ acceptHeader: string;
79
+ userAgent: string;
41
80
  };
42
81
  };
43
- };
82
+ }>;
44
83
  export {};
package/dist/src/utils.js CHANGED
@@ -1,3 +1,12 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
1
10
  export const DeviceType = {
2
11
  Unknown: "unknown",
3
12
  Computer: "computer",
@@ -13,7 +22,7 @@ export function uuid() {
13
22
  seed += performance.now();
14
23
  }
15
24
  return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) {
16
- const random = (seed + Math.random() * 16) % 16 | 0;
25
+ const random = ((seed + Math.random() * 16) % 16) | 0;
17
26
  seed = Math.floor(seed / 16);
18
27
  return (c === "x" ? random : random & (0x3 | 0x8)).toString(16);
19
28
  });
@@ -40,7 +49,7 @@ export function getDeviceType() {
40
49
  }
41
50
  return DeviceType.Unknown;
42
51
  }
43
- const REQUIRED_STRINGS = ["apiUrl", "fingerprintVisitorId", "merchantId", "sessionId"];
52
+ const REQUIRED_STRINGS = ["apiUrl", "fingerprintVisitorId", "sessionId"];
44
53
  export function validateArguments(args) {
45
54
  for (const key of REQUIRED_STRINGS) {
46
55
  if (typeof args[key] !== "string" || args[key] === "") {
@@ -62,28 +71,45 @@ export function validateArguments(args) {
62
71
  throw new TypeError("sdk-js: retryOptions.retryStatusCode must be a function");
63
72
  }
64
73
  }
74
+ const HIGH_ENTROPY_HINTS = [
75
+ "architecture",
76
+ "bitness",
77
+ "formFactors",
78
+ "fullVersionList",
79
+ "model",
80
+ "platformVersion",
81
+ "uaFullVersion",
82
+ "wow64",
83
+ ];
84
+ function userAgentData() {
85
+ return navigator.userAgentData;
86
+ }
87
+ /** Returns native browser hints, falling back to low entropy values if needed. */
88
+ export function getClientHints() {
89
+ var _a, _b;
90
+ return __awaiter(this, void 0, void 0, function* () {
91
+ const uaData = userAgentData();
92
+ if (!uaData) {
93
+ return {};
94
+ }
95
+ const { brands, mobile, platform } = uaData;
96
+ try {
97
+ return (_b = (yield ((_a = uaData.getHighEntropyValues) === null || _a === void 0 ? void 0 : _a.call(uaData, HIGH_ENTROPY_HINTS)))) !== null && _b !== void 0 ? _b : { brands, mobile, platform };
98
+ }
99
+ catch (_c) {
100
+ return { brands, mobile, platform };
101
+ }
102
+ });
103
+ }
65
104
  export function getDeviceData() {
66
105
  var _a, _b, _c;
67
- return {
68
- device: {
69
- type: getDeviceType(),
70
- browser: {
71
- platform: (_c = (_b = (_a = navigator.userAgentData) === null || _a === void 0 ? void 0 : _a.platform) !== null && _b !== void 0 ? _b : navigator.platform) !== null && _c !== void 0 ? _c : "unknown",
72
- acceptHeader: "application/json",
73
- userAgent: navigator.userAgent,
74
- javaEnabled: !!(navigator === null || navigator === void 0 ? void 0 : navigator.javaEnabled) && navigator.javaEnabled() ? navigator.javaEnabled() : false,
75
- javaScriptEnabled: true,
76
- language: navigator.language,
77
- colorDepth: screen.colorDepth,
78
- screenHeight: screen.height,
79
- screenWidth: screen.width,
80
- windowHeight: window.outerHeight,
81
- windowWidth: window.outerWidth,
82
- windowInnerHeight: window.innerHeight,
83
- windowInnerWidth: window.innerWidth,
84
- timeZoneOffset: new Date().getTimezoneOffset(),
85
- timeZoneName: Intl.DateTimeFormat().resolvedOptions().timeZone,
106
+ return __awaiter(this, void 0, void 0, function* () {
107
+ const clientHints = yield getClientHints();
108
+ return {
109
+ device: {
110
+ type: getDeviceType(),
111
+ browser: Object.assign(Object.assign({ platform: (_c = (_b = (_a = userAgentData()) === null || _a === void 0 ? void 0 : _a.platform) !== null && _b !== void 0 ? _b : navigator.platform) !== null && _c !== void 0 ? _c : "unknown", acceptHeader: "application/json", userAgent: navigator.userAgent }, (Object.keys(clientHints).length > 0 ? { clientHints } : {})), { javaEnabled: !!(navigator === null || navigator === void 0 ? void 0 : navigator.javaEnabled) && navigator.javaEnabled() ? navigator.javaEnabled() : false, javaScriptEnabled: true, language: navigator.language, colorDepth: screen.colorDepth, screenHeight: screen.height, screenWidth: screen.width, windowHeight: window.outerHeight, windowWidth: window.outerWidth, windowInnerHeight: window.innerHeight, windowInnerWidth: window.innerWidth, timeZoneOffset: new Date().getTimezoneOffset(), timeZoneName: Intl.DateTimeFormat().resolvedOptions().timeZone }),
86
112
  },
87
- },
88
- };
113
+ };
114
+ });
89
115
  }
@@ -1,3 +1,3 @@
1
1
  export declare const SDK_HEADER_NAME = "x-pgw-sdk";
2
- export declare const SDK_VERSION = "0.14.0";
2
+ export declare const SDK_VERSION = "0.16.0-beta.1";
3
3
  export declare const SDK_HEADER_VALUE: string;
@@ -1,3 +1,3 @@
1
1
  export const SDK_HEADER_NAME = "x-pgw-sdk";
2
- export const SDK_VERSION = "0.14.0";
2
+ export const SDK_VERSION = "0.16.0-beta.1";
3
3
  export const SDK_HEADER_VALUE = `sdk-js/${SDK_VERSION}`;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@finteqhub/sdk-js",
3
- "version": "0.14.0",
3
+ "version": "0.16.0-beta.1",
4
4
  "description": "SDK for interacting with FinteqHub processing API",
5
5
  "main": "./dist/index.js",
6
6
  "typings": "./dist/index.d.ts",