@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 +13 -0
- package/README.md +3 -1
- package/dist/src/processing.js +1 -4
- package/dist/src/utils.d.ts +44 -5
- package/dist/src/utils.js +49 -23
- package/dist/src/version.d.ts +1 -1
- package/dist/src/version.js +1 -1
- package/package.json +1 -1
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
|
|
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
|
|
package/dist/src/processing.js
CHANGED
|
@@ -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),
|
package/dist/src/utils.d.ts
CHANGED
|
@@ -19,13 +19,30 @@ declare type ConstructorArguments = {
|
|
|
19
19
|
retryOptions: RetryOptions;
|
|
20
20
|
};
|
|
21
21
|
export declare function validateArguments(args: ConstructorArguments): void;
|
|
22
|
-
|
|
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", "
|
|
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
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
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
|
}
|
package/dist/src/version.d.ts
CHANGED
package/dist/src/version.js
CHANGED