@flonkid/kyc 1.6.0 → 1.6.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/dist/index.cjs +337 -189
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +337 -189
- package/dist/index.js.map +1 -1
- package/dist/server.cjs +45 -20
- package/dist/server.cjs.map +1 -1
- package/dist/server.js +45 -20
- package/dist/server.js.map +1 -1
- package/package.json +1 -1
package/dist/server.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/shared/constants.ts","../src/shared/errors.ts","../src/server/http-client.ts","../src/server/webhooks.ts","../src/server/index.ts"],"names":["crypto"],"mappings":"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","file":"server.cjs","sourcesContent":["export const SDK_VERSION = '1.6.0';\r\nexport const DEFAULT_WIDGET_URL = 'https://widget.flonk.id';\r\nexport const DEFAULT_API_BASE = 'https://api.flonk.id/v1';\r\n\r\nexport const WIDGET_EVENTS = {\r\n READY: 'KYC_WIDGET_READY',\r\n COMPLETE: 'KYC_COMPLETE',\r\n CANCEL: 'KYC_CANCEL',\r\n ERROR: 'KYC_ERROR',\r\n} as const;\r\n","export class FlonkError extends Error {\r\n constructor(\r\n message: string,\r\n public readonly code: string,\r\n public readonly statusCode?: number,\r\n ) {\r\n super(message);\r\n this.name = 'FlonkError';\r\n }\r\n}\r\n\r\nexport class FlonkAPIError extends FlonkError {\r\n constructor(\r\n message: string,\r\n statusCode: number,\r\n public readonly body?: unknown,\r\n ) {\r\n super(message, 'api_error', statusCode);\r\n this.name = 'FlonkAPIError';\r\n }\r\n}\r\n\r\nexport class FlonkAuthenticationError extends FlonkError {\r\n constructor(message = 'Invalid or missing secret key') {\r\n super(message, 'authentication_error', 401);\r\n this.name = 'FlonkAuthenticationError';\r\n }\r\n}\r\n\r\nexport class FlonkValidationError extends FlonkError {\r\n constructor(message: string) {\r\n super(message, 'validation_error', 400);\r\n this.name = 'FlonkValidationError';\r\n }\r\n}\r\n\r\nexport class FlonkWebhookSignatureError extends FlonkError {\r\n constructor(message = 'Invalid webhook signature') {\r\n super(message, 'webhook_signature_error');\r\n this.name = 'FlonkWebhookSignatureError';\r\n }\r\n}\r\n","import { SDK_VERSION } from '../shared/constants';\r\nimport { FlonkAPIError, FlonkAuthenticationError } from '../shared/errors';\r\n\r\nexport class HttpClient {\r\n constructor(\r\n private readonly baseUrl: string,\r\n private readonly secretKey: string,\r\n private readonly timeout = 30_000,\r\n ) {}\r\n\r\n async get<T>(path: string): Promise<T> {\r\n return this.request<T>('GET', path);\r\n }\r\n\r\n async post<T>(path: string, body?: unknown): Promise<T> {\r\n return this.request<T>('POST', path, body);\r\n }\r\n\r\n async patch<T>(path: string, body?: unknown): Promise<T> {\r\n return this.request<T>('PATCH', path, body);\r\n }\r\n\r\n private async request<T>(method: string, path: string, body?: unknown): Promise<T> {\r\n const controller = new AbortController();\r\n const timer = setTimeout(() => controller.abort(), this.timeout);\r\n\r\n try {\r\n const res = await fetch(`${this.baseUrl}${path}`, {\r\n method,\r\n headers: {\r\n 'Authorization': `Bearer ${this.secretKey}`,\r\n 'Content-Type': 'application/json',\r\n 'User-Agent': `flonk-kyc-node/${SDK_VERSION}`,\r\n },\r\n body: body ? JSON.stringify(body) : undefined,\r\n signal: controller.signal,\r\n });\r\n\r\n const json = await res.json().catch(() => null);\r\n\r\n if (!res.ok) {\r\n if (res.status === 401) throw new FlonkAuthenticationError();\r\n throw new FlonkAPIError(\r\n json?.message || `Request failed: ${res.status}`,\r\n res.status,\r\n json,\r\n );\r\n }\r\n\r\n return json as T;\r\n } catch (err) {\r\n if (err instanceof FlonkAPIError || err instanceof FlonkAuthenticationError) throw err;\r\n throw new FlonkAPIError((err as Error).message, 0);\r\n } finally {\r\n clearTimeout(timer);\r\n }\r\n }\r\n}\r\n","import * as crypto from 'crypto';\r\nimport { FlonkWebhookSignatureError } from '../shared/errors';\r\nimport type { WebhookEvent, WebhookVerifyOptions } from '../shared/types';\r\n\r\nexport class Webhooks {\r\n /**\r\n * Verify X-Signature-256 header: \"sha256=<hex>\"\r\n */\r\n verifySignature(payload: string, signature: string, secret: string): WebhookEvent {\r\n const expected =\r\n 'sha256=' + crypto.createHmac('sha256', secret).update(payload).digest('hex');\r\n\r\n if (!this.safeEqual(signature, expected)) {\r\n throw new FlonkWebhookSignatureError();\r\n }\r\n\r\n return this.parsePayload(payload);\r\n }\r\n\r\n /**\r\n * Verify Stripe-like header: \"t=<unix>, v1=<hex>\"\r\n */\r\n verifyTimestampSignature(\r\n payload: string,\r\n header: string,\r\n secret: string,\r\n options?: WebhookVerifyOptions,\r\n ): WebhookEvent {\r\n const maxSkew = options?.maxSkewSeconds ?? 300;\r\n const parts = this.parseHeader(header);\r\n const ts = Number(parts['t']);\r\n const v1 = parts['v1'];\r\n\r\n if (!ts || !v1) {\r\n throw new FlonkWebhookSignatureError('Missing timestamp or signature');\r\n }\r\n\r\n if (Math.abs(Math.floor(Date.now() / 1000) - ts) > maxSkew) {\r\n throw new FlonkWebhookSignatureError(`Timestamp skew exceeds ${maxSkew}s`);\r\n }\r\n\r\n const expected = crypto\r\n .createHmac('sha256', secret)\r\n .update(`${ts}.${payload}`)\r\n .digest('hex');\r\n\r\n if (!this.safeEqual(v1, expected)) {\r\n throw new FlonkWebhookSignatureError();\r\n }\r\n\r\n return this.parsePayload(payload);\r\n }\r\n\r\n /**\r\n * Auto-detect signature format and verify.\r\n */\r\n constructEvent(payload: string, signature: string, secret: string): WebhookEvent {\r\n if (signature.startsWith('sha256=')) {\r\n return this.verifySignature(payload, signature, secret);\r\n }\r\n if (signature.includes('t=') && signature.includes('v1=')) {\r\n return this.verifyTimestampSignature(payload, signature, secret);\r\n }\r\n throw new FlonkWebhookSignatureError('Unrecognized signature format');\r\n }\r\n\r\n private parsePayload(payload: string): WebhookEvent {\r\n try {\r\n return JSON.parse(payload) as WebhookEvent;\r\n } catch {\r\n throw new FlonkWebhookSignatureError('Malformed JSON payload');\r\n }\r\n }\r\n\r\n private parseHeader(header: string): Record<string, string> {\r\n const result: Record<string, string> = {};\r\n for (const part of header.split(',')) {\r\n const [k, v] = part.trim().split('=');\r\n if (k && v) result[k] = v;\r\n }\r\n return result;\r\n }\r\n\r\n private safeEqual(a: string, b: string): boolean {\r\n if (a.length !== b.length) return false;\r\n return crypto.timingSafeEqual(Buffer.from(a), Buffer.from(b));\r\n }\r\n}\r\n","import { SDK_VERSION, DEFAULT_API_BASE } from '../shared/constants';\r\nimport { FlonkAuthenticationError, FlonkValidationError } from '../shared/errors';\r\nimport type {\r\n FlonkKYCServerOptions,\r\n CreateSessionParams,\r\n Session,\r\n SessionDetails,\r\n UpdateSessionParams,\r\n} from '../shared/types';\r\nimport { HttpClient } from './http-client';\r\nimport { Webhooks } from './webhooks';\r\n\r\nconst SK_PATTERN = /^sk_(live|sandbox|test_sandbox|test_live)_[A-Za-z0-9]{16,}$/;\r\n\r\nexport class FlonkKYCServer {\r\n static readonly version = SDK_VERSION;\r\n\r\n private readonly http: HttpClient;\r\n public readonly webhooks = new Webhooks();\r\n\r\n constructor(options: FlonkKYCServerOptions) {\r\n if (!options.secretKey) throw new FlonkAuthenticationError('secretKey is required');\r\n if (!SK_PATTERN.test(options.secretKey)) {\r\n throw new FlonkAuthenticationError('Invalid secret key format. Expected: sk_live_*, sk_sandbox_*, sk_test_sandbox_*, sk_test_live_*');\r\n }\r\n\r\n const base = (options.apiBase || DEFAULT_API_BASE).replace(/\\/$/, '');\r\n this.http = new HttpClient(base, options.secretKey, options.timeout);\r\n }\r\n\r\n async createSession(params?: CreateSessionParams): Promise<Session> {\r\n return this.http.post<Session>('/sessions', params ?? {});\r\n }\r\n\r\n async getSession(sessionId: string): Promise<SessionDetails> {\r\n if (!sessionId) throw new FlonkValidationError('sessionId is required');\r\n return this.http.get<SessionDetails>(`/sessions/${sessionId}`);\r\n }\r\n\r\n async updateSession(sessionId: string, params: UpdateSessionParams): Promise<SessionDetails> {\r\n if (!sessionId) throw new FlonkValidationError('sessionId is required');\r\n return this.http.patch<SessionDetails>(`/sessions/${sessionId}`, params);\r\n }\r\n}\r\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/shared/constants.ts","../src/shared/errors.ts","../src/server/http-client.ts","../src/server/webhooks.ts","../src/server/index.ts"],"names":["SDK_VERSION","DEFAULT_API_BASE","FlonkError","Error","message","code","statusCode","name","FlonkAPIError","body","FlonkAuthenticationError","FlonkValidationError","FlonkWebhookSignatureError","HttpClient","baseUrl","secretKey","timeout","get","path","request","post","patch","method","controller","AbortController","timer","setTimeout","abort","res","fetch","headers","JSON","stringify","undefined","signal","json","catch","ok","status","err","clearTimeout","Webhooks","verifySignature","payload","signature","secret","expected","createHmac","update","digest","safeEqual","parsePayload","verifyTimestampSignature","header","options","maxSkew","maxSkewSeconds","parts","parseHeader","ts","Number","v1","Math","abs","floor","Date","now","constructEvent","startsWith","includes","parse","result","part","split","k","v","trim","a","b","length","timingSafeEqual","Buffer","from","SK_PATTERN","FlonkKYCServer","version","http","webhooks","test","base","apiBase","replace","createSession","params","getSession","sessionId","updateSession"],"mappings":"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","file":"server.cjs","sourcesContent":["export const SDK_VERSION = '1.6.0';\r\nexport const DEFAULT_WIDGET_URL = 'https://widget.flonk.id';\r\nexport const DEFAULT_API_BASE = 'https://api.flonk.id/v1';\r\n\r\nexport const WIDGET_EVENTS = {\r\n READY: 'KYC_WIDGET_READY',\r\n COMPLETE: 'KYC_COMPLETE',\r\n CANCEL: 'KYC_CANCEL',\r\n ERROR: 'KYC_ERROR',\r\n} as const;\r\n","export class FlonkError extends Error {\r\n constructor(\r\n message: string,\r\n public readonly code: string,\r\n public readonly statusCode?: number,\r\n ) {\r\n super(message);\r\n this.name = 'FlonkError';\r\n }\r\n}\r\n\r\nexport class FlonkAPIError extends FlonkError {\r\n constructor(\r\n message: string,\r\n statusCode: number,\r\n public readonly body?: unknown,\r\n ) {\r\n super(message, 'api_error', statusCode);\r\n this.name = 'FlonkAPIError';\r\n }\r\n}\r\n\r\nexport class FlonkAuthenticationError extends FlonkError {\r\n constructor(message = 'Invalid or missing secret key') {\r\n super(message, 'authentication_error', 401);\r\n this.name = 'FlonkAuthenticationError';\r\n }\r\n}\r\n\r\nexport class FlonkValidationError extends FlonkError {\r\n constructor(message: string) {\r\n super(message, 'validation_error', 400);\r\n this.name = 'FlonkValidationError';\r\n }\r\n}\r\n\r\nexport class FlonkWebhookSignatureError extends FlonkError {\r\n constructor(message = 'Invalid webhook signature') {\r\n super(message, 'webhook_signature_error');\r\n this.name = 'FlonkWebhookSignatureError';\r\n }\r\n}\r\n","import { SDK_VERSION } from '../shared/constants';\r\nimport { FlonkAPIError, FlonkAuthenticationError } from '../shared/errors';\r\n\r\nexport class HttpClient {\r\n constructor(\r\n private readonly baseUrl: string,\r\n private readonly secretKey: string,\r\n private readonly timeout = 30_000,\r\n ) {}\r\n\r\n async get<T>(path: string): Promise<T> {\r\n return this.request<T>('GET', path);\r\n }\r\n\r\n async post<T>(path: string, body?: unknown): Promise<T> {\r\n return this.request<T>('POST', path, body);\r\n }\r\n\r\n async patch<T>(path: string, body?: unknown): Promise<T> {\r\n return this.request<T>('PATCH', path, body);\r\n }\r\n\r\n private async request<T>(method: string, path: string, body?: unknown): Promise<T> {\r\n const controller = new AbortController();\r\n const timer = setTimeout(() => controller.abort(), this.timeout);\r\n\r\n try {\r\n const res = await fetch(`${this.baseUrl}${path}`, {\r\n method,\r\n headers: {\r\n 'Authorization': `Bearer ${this.secretKey}`,\r\n 'Content-Type': 'application/json',\r\n 'User-Agent': `flonk-kyc-node/${SDK_VERSION}`,\r\n },\r\n body: body ? JSON.stringify(body) : undefined,\r\n signal: controller.signal,\r\n });\r\n\r\n const json = await res.json().catch(() => null);\r\n\r\n if (!res.ok) {\r\n if (res.status === 401) throw new FlonkAuthenticationError();\r\n throw new FlonkAPIError(\r\n json?.message || `Request failed: ${res.status}`,\r\n res.status,\r\n json,\r\n );\r\n }\r\n\r\n return json as T;\r\n } catch (err) {\r\n if (err instanceof FlonkAPIError || err instanceof FlonkAuthenticationError) throw err;\r\n throw new FlonkAPIError((err as Error).message, 0);\r\n } finally {\r\n clearTimeout(timer);\r\n }\r\n }\r\n}\r\n","import * as crypto from 'crypto';\r\nimport { FlonkWebhookSignatureError } from '../shared/errors';\r\nimport type { WebhookEvent, WebhookVerifyOptions } from '../shared/types';\r\n\r\nexport class Webhooks {\r\n /**\r\n * Verify X-Signature-256 header: \"sha256=<hex>\"\r\n */\r\n verifySignature(payload: string, signature: string, secret: string): WebhookEvent {\r\n const expected =\r\n 'sha256=' + crypto.createHmac('sha256', secret).update(payload).digest('hex');\r\n\r\n if (!this.safeEqual(signature, expected)) {\r\n throw new FlonkWebhookSignatureError();\r\n }\r\n\r\n return this.parsePayload(payload);\r\n }\r\n\r\n /**\r\n * Verify Stripe-like header: \"t=<unix>, v1=<hex>\"\r\n */\r\n verifyTimestampSignature(\r\n payload: string,\r\n header: string,\r\n secret: string,\r\n options?: WebhookVerifyOptions,\r\n ): WebhookEvent {\r\n const maxSkew = options?.maxSkewSeconds ?? 300;\r\n const parts = this.parseHeader(header);\r\n const ts = Number(parts['t']);\r\n const v1 = parts['v1'];\r\n\r\n if (!ts || !v1) {\r\n throw new FlonkWebhookSignatureError('Missing timestamp or signature');\r\n }\r\n\r\n if (Math.abs(Math.floor(Date.now() / 1000) - ts) > maxSkew) {\r\n throw new FlonkWebhookSignatureError(`Timestamp skew exceeds ${maxSkew}s`);\r\n }\r\n\r\n const expected = crypto\r\n .createHmac('sha256', secret)\r\n .update(`${ts}.${payload}`)\r\n .digest('hex');\r\n\r\n if (!this.safeEqual(v1, expected)) {\r\n throw new FlonkWebhookSignatureError();\r\n }\r\n\r\n return this.parsePayload(payload);\r\n }\r\n\r\n /**\r\n * Auto-detect signature format and verify.\r\n */\r\n constructEvent(payload: string, signature: string, secret: string): WebhookEvent {\r\n if (signature.startsWith('sha256=')) {\r\n return this.verifySignature(payload, signature, secret);\r\n }\r\n if (signature.includes('t=') && signature.includes('v1=')) {\r\n return this.verifyTimestampSignature(payload, signature, secret);\r\n }\r\n throw new FlonkWebhookSignatureError('Unrecognized signature format');\r\n }\r\n\r\n private parsePayload(payload: string): WebhookEvent {\r\n try {\r\n return JSON.parse(payload) as WebhookEvent;\r\n } catch {\r\n throw new FlonkWebhookSignatureError('Malformed JSON payload');\r\n }\r\n }\r\n\r\n private parseHeader(header: string): Record<string, string> {\r\n const result: Record<string, string> = {};\r\n for (const part of header.split(',')) {\r\n const [k, v] = part.trim().split('=');\r\n if (k && v) result[k] = v;\r\n }\r\n return result;\r\n }\r\n\r\n private safeEqual(a: string, b: string): boolean {\r\n if (a.length !== b.length) return false;\r\n return crypto.timingSafeEqual(Buffer.from(a), Buffer.from(b));\r\n }\r\n}\r\n","import { SDK_VERSION, DEFAULT_API_BASE } from '../shared/constants';\r\nimport { FlonkAuthenticationError, FlonkValidationError } from '../shared/errors';\r\nimport type {\r\n FlonkKYCServerOptions,\r\n CreateSessionParams,\r\n Session,\r\n SessionDetails,\r\n UpdateSessionParams,\r\n} from '../shared/types';\r\nimport { HttpClient } from './http-client';\r\nimport { Webhooks } from './webhooks';\r\n\r\nconst SK_PATTERN = /^sk_(live|sandbox|test_sandbox|test_live)_[A-Za-z0-9]{16,}$/;\r\n\r\nexport class FlonkKYCServer {\r\n static readonly version = SDK_VERSION;\r\n\r\n private readonly http: HttpClient;\r\n public readonly webhooks = new Webhooks();\r\n\r\n constructor(options: FlonkKYCServerOptions) {\r\n if (!options.secretKey) throw new FlonkAuthenticationError('secretKey is required');\r\n if (!SK_PATTERN.test(options.secretKey)) {\r\n throw new FlonkAuthenticationError('Invalid secret key format. Expected: sk_live_*, sk_sandbox_*, sk_test_sandbox_*, sk_test_live_*');\r\n }\r\n\r\n const base = (options.apiBase || DEFAULT_API_BASE).replace(/\\/$/, '');\r\n this.http = new HttpClient(base, options.secretKey, options.timeout);\r\n }\r\n\r\n async createSession(params?: CreateSessionParams): Promise<Session> {\r\n return this.http.post<Session>('/sessions', params ?? {});\r\n }\r\n\r\n async getSession(sessionId: string): Promise<SessionDetails> {\r\n if (!sessionId) throw new FlonkValidationError('sessionId is required');\r\n return this.http.get<SessionDetails>(`/sessions/${sessionId}`);\r\n }\r\n\r\n async updateSession(sessionId: string, params: UpdateSessionParams): Promise<SessionDetails> {\r\n if (!sessionId) throw new FlonkValidationError('sessionId is required');\r\n return this.http.patch<SessionDetails>(`/sessions/${sessionId}`, params);\r\n }\r\n}\r\n"]}
|
package/dist/server.js
CHANGED
|
@@ -1,38 +1,56 @@
|
|
|
1
1
|
import * as crypto from 'crypto';
|
|
2
2
|
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
5
|
+
|
|
3
6
|
// src/shared/constants.ts
|
|
4
7
|
var SDK_VERSION = "1.6.0";
|
|
5
8
|
var DEFAULT_API_BASE = "https://api.flonk.id/v1";
|
|
6
9
|
|
|
7
10
|
// src/shared/errors.ts
|
|
8
11
|
var FlonkError = class extends Error {
|
|
12
|
+
static {
|
|
13
|
+
__name(this, "FlonkError");
|
|
14
|
+
}
|
|
15
|
+
code;
|
|
16
|
+
statusCode;
|
|
9
17
|
constructor(message, code, statusCode) {
|
|
10
|
-
super(message);
|
|
11
|
-
this.code = code;
|
|
12
|
-
this.statusCode = statusCode;
|
|
18
|
+
super(message), this.code = code, this.statusCode = statusCode;
|
|
13
19
|
this.name = "FlonkError";
|
|
14
20
|
}
|
|
15
21
|
};
|
|
16
22
|
var FlonkAPIError = class extends FlonkError {
|
|
23
|
+
static {
|
|
24
|
+
__name(this, "FlonkAPIError");
|
|
25
|
+
}
|
|
26
|
+
body;
|
|
17
27
|
constructor(message, statusCode, body) {
|
|
18
|
-
super(message, "api_error", statusCode);
|
|
19
|
-
this.body = body;
|
|
28
|
+
super(message, "api_error", statusCode), this.body = body;
|
|
20
29
|
this.name = "FlonkAPIError";
|
|
21
30
|
}
|
|
22
31
|
};
|
|
23
32
|
var FlonkAuthenticationError = class extends FlonkError {
|
|
33
|
+
static {
|
|
34
|
+
__name(this, "FlonkAuthenticationError");
|
|
35
|
+
}
|
|
24
36
|
constructor(message = "Invalid or missing secret key") {
|
|
25
37
|
super(message, "authentication_error", 401);
|
|
26
38
|
this.name = "FlonkAuthenticationError";
|
|
27
39
|
}
|
|
28
40
|
};
|
|
29
41
|
var FlonkValidationError = class extends FlonkError {
|
|
42
|
+
static {
|
|
43
|
+
__name(this, "FlonkValidationError");
|
|
44
|
+
}
|
|
30
45
|
constructor(message) {
|
|
31
46
|
super(message, "validation_error", 400);
|
|
32
47
|
this.name = "FlonkValidationError";
|
|
33
48
|
}
|
|
34
49
|
};
|
|
35
50
|
var FlonkWebhookSignatureError = class extends FlonkError {
|
|
51
|
+
static {
|
|
52
|
+
__name(this, "FlonkWebhookSignatureError");
|
|
53
|
+
}
|
|
36
54
|
constructor(message = "Invalid webhook signature") {
|
|
37
55
|
super(message, "webhook_signature_error");
|
|
38
56
|
this.name = "FlonkWebhookSignatureError";
|
|
@@ -41,6 +59,12 @@ var FlonkWebhookSignatureError = class extends FlonkError {
|
|
|
41
59
|
|
|
42
60
|
// src/server/http-client.ts
|
|
43
61
|
var HttpClient = class {
|
|
62
|
+
static {
|
|
63
|
+
__name(this, "HttpClient");
|
|
64
|
+
}
|
|
65
|
+
baseUrl;
|
|
66
|
+
secretKey;
|
|
67
|
+
timeout;
|
|
44
68
|
constructor(baseUrl, secretKey, timeout = 3e4) {
|
|
45
69
|
this.baseUrl = baseUrl;
|
|
46
70
|
this.secretKey = secretKey;
|
|
@@ -72,11 +96,7 @@ var HttpClient = class {
|
|
|
72
96
|
const json = await res.json().catch(() => null);
|
|
73
97
|
if (!res.ok) {
|
|
74
98
|
if (res.status === 401) throw new FlonkAuthenticationError();
|
|
75
|
-
throw new FlonkAPIError(
|
|
76
|
-
json?.message || `Request failed: ${res.status}`,
|
|
77
|
-
res.status,
|
|
78
|
-
json
|
|
79
|
-
);
|
|
99
|
+
throw new FlonkAPIError(json?.message || `Request failed: ${res.status}`, res.status, json);
|
|
80
100
|
}
|
|
81
101
|
return json;
|
|
82
102
|
} catch (err) {
|
|
@@ -88,9 +108,12 @@ var HttpClient = class {
|
|
|
88
108
|
}
|
|
89
109
|
};
|
|
90
110
|
var Webhooks = class {
|
|
111
|
+
static {
|
|
112
|
+
__name(this, "Webhooks");
|
|
113
|
+
}
|
|
91
114
|
/**
|
|
92
|
-
|
|
93
|
-
|
|
115
|
+
* Verify X-Signature-256 header: "sha256=<hex>"
|
|
116
|
+
*/
|
|
94
117
|
verifySignature(payload, signature, secret) {
|
|
95
118
|
const expected = "sha256=" + crypto.createHmac("sha256", secret).update(payload).digest("hex");
|
|
96
119
|
if (!this.safeEqual(signature, expected)) {
|
|
@@ -99,8 +122,8 @@ var Webhooks = class {
|
|
|
99
122
|
return this.parsePayload(payload);
|
|
100
123
|
}
|
|
101
124
|
/**
|
|
102
|
-
|
|
103
|
-
|
|
125
|
+
* Verify Stripe-like header: "t=<unix>, v1=<hex>"
|
|
126
|
+
*/
|
|
104
127
|
verifyTimestampSignature(payload, header, secret, options) {
|
|
105
128
|
const maxSkew = options?.maxSkewSeconds ?? 300;
|
|
106
129
|
const parts = this.parseHeader(header);
|
|
@@ -119,8 +142,8 @@ var Webhooks = class {
|
|
|
119
142
|
return this.parsePayload(payload);
|
|
120
143
|
}
|
|
121
144
|
/**
|
|
122
|
-
|
|
123
|
-
|
|
145
|
+
* Auto-detect signature format and verify.
|
|
146
|
+
*/
|
|
124
147
|
constructEvent(payload, signature, secret) {
|
|
125
148
|
if (signature.startsWith("sha256=")) {
|
|
126
149
|
return this.verifySignature(payload, signature, secret);
|
|
@@ -154,8 +177,13 @@ var Webhooks = class {
|
|
|
154
177
|
// src/server/index.ts
|
|
155
178
|
var SK_PATTERN = /^sk_(live|sandbox|test_sandbox|test_live)_[A-Za-z0-9]{16,}$/;
|
|
156
179
|
var FlonkKYCServer = class {
|
|
180
|
+
static {
|
|
181
|
+
__name(this, "FlonkKYCServer");
|
|
182
|
+
}
|
|
183
|
+
static version = SDK_VERSION;
|
|
184
|
+
http;
|
|
185
|
+
webhooks = new Webhooks();
|
|
157
186
|
constructor(options) {
|
|
158
|
-
this.webhooks = new Webhooks();
|
|
159
187
|
if (!options.secretKey) throw new FlonkAuthenticationError("secretKey is required");
|
|
160
188
|
if (!SK_PATTERN.test(options.secretKey)) {
|
|
161
189
|
throw new FlonkAuthenticationError("Invalid secret key format. Expected: sk_live_*, sk_sandbox_*, sk_test_sandbox_*, sk_test_live_*");
|
|
@@ -163,9 +191,6 @@ var FlonkKYCServer = class {
|
|
|
163
191
|
const base = (options.apiBase || DEFAULT_API_BASE).replace(/\/$/, "");
|
|
164
192
|
this.http = new HttpClient(base, options.secretKey, options.timeout);
|
|
165
193
|
}
|
|
166
|
-
static {
|
|
167
|
-
this.version = SDK_VERSION;
|
|
168
|
-
}
|
|
169
194
|
async createSession(params) {
|
|
170
195
|
return this.http.post("/sessions", params ?? {});
|
|
171
196
|
}
|
package/dist/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/shared/constants.ts","../src/shared/errors.ts","../src/server/http-client.ts","../src/server/webhooks.ts","../src/server/index.ts"],"names":[],"mappings":"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","file":"server.js","sourcesContent":["export const SDK_VERSION = '1.6.0';\r\nexport const DEFAULT_WIDGET_URL = 'https://widget.flonk.id';\r\nexport const DEFAULT_API_BASE = 'https://api.flonk.id/v1';\r\n\r\nexport const WIDGET_EVENTS = {\r\n READY: 'KYC_WIDGET_READY',\r\n COMPLETE: 'KYC_COMPLETE',\r\n CANCEL: 'KYC_CANCEL',\r\n ERROR: 'KYC_ERROR',\r\n} as const;\r\n","export class FlonkError extends Error {\r\n constructor(\r\n message: string,\r\n public readonly code: string,\r\n public readonly statusCode?: number,\r\n ) {\r\n super(message);\r\n this.name = 'FlonkError';\r\n }\r\n}\r\n\r\nexport class FlonkAPIError extends FlonkError {\r\n constructor(\r\n message: string,\r\n statusCode: number,\r\n public readonly body?: unknown,\r\n ) {\r\n super(message, 'api_error', statusCode);\r\n this.name = 'FlonkAPIError';\r\n }\r\n}\r\n\r\nexport class FlonkAuthenticationError extends FlonkError {\r\n constructor(message = 'Invalid or missing secret key') {\r\n super(message, 'authentication_error', 401);\r\n this.name = 'FlonkAuthenticationError';\r\n }\r\n}\r\n\r\nexport class FlonkValidationError extends FlonkError {\r\n constructor(message: string) {\r\n super(message, 'validation_error', 400);\r\n this.name = 'FlonkValidationError';\r\n }\r\n}\r\n\r\nexport class FlonkWebhookSignatureError extends FlonkError {\r\n constructor(message = 'Invalid webhook signature') {\r\n super(message, 'webhook_signature_error');\r\n this.name = 'FlonkWebhookSignatureError';\r\n }\r\n}\r\n","import { SDK_VERSION } from '../shared/constants';\r\nimport { FlonkAPIError, FlonkAuthenticationError } from '../shared/errors';\r\n\r\nexport class HttpClient {\r\n constructor(\r\n private readonly baseUrl: string,\r\n private readonly secretKey: string,\r\n private readonly timeout = 30_000,\r\n ) {}\r\n\r\n async get<T>(path: string): Promise<T> {\r\n return this.request<T>('GET', path);\r\n }\r\n\r\n async post<T>(path: string, body?: unknown): Promise<T> {\r\n return this.request<T>('POST', path, body);\r\n }\r\n\r\n async patch<T>(path: string, body?: unknown): Promise<T> {\r\n return this.request<T>('PATCH', path, body);\r\n }\r\n\r\n private async request<T>(method: string, path: string, body?: unknown): Promise<T> {\r\n const controller = new AbortController();\r\n const timer = setTimeout(() => controller.abort(), this.timeout);\r\n\r\n try {\r\n const res = await fetch(`${this.baseUrl}${path}`, {\r\n method,\r\n headers: {\r\n 'Authorization': `Bearer ${this.secretKey}`,\r\n 'Content-Type': 'application/json',\r\n 'User-Agent': `flonk-kyc-node/${SDK_VERSION}`,\r\n },\r\n body: body ? JSON.stringify(body) : undefined,\r\n signal: controller.signal,\r\n });\r\n\r\n const json = await res.json().catch(() => null);\r\n\r\n if (!res.ok) {\r\n if (res.status === 401) throw new FlonkAuthenticationError();\r\n throw new FlonkAPIError(\r\n json?.message || `Request failed: ${res.status}`,\r\n res.status,\r\n json,\r\n );\r\n }\r\n\r\n return json as T;\r\n } catch (err) {\r\n if (err instanceof FlonkAPIError || err instanceof FlonkAuthenticationError) throw err;\r\n throw new FlonkAPIError((err as Error).message, 0);\r\n } finally {\r\n clearTimeout(timer);\r\n }\r\n }\r\n}\r\n","import * as crypto from 'crypto';\r\nimport { FlonkWebhookSignatureError } from '../shared/errors';\r\nimport type { WebhookEvent, WebhookVerifyOptions } from '../shared/types';\r\n\r\nexport class Webhooks {\r\n /**\r\n * Verify X-Signature-256 header: \"sha256=<hex>\"\r\n */\r\n verifySignature(payload: string, signature: string, secret: string): WebhookEvent {\r\n const expected =\r\n 'sha256=' + crypto.createHmac('sha256', secret).update(payload).digest('hex');\r\n\r\n if (!this.safeEqual(signature, expected)) {\r\n throw new FlonkWebhookSignatureError();\r\n }\r\n\r\n return this.parsePayload(payload);\r\n }\r\n\r\n /**\r\n * Verify Stripe-like header: \"t=<unix>, v1=<hex>\"\r\n */\r\n verifyTimestampSignature(\r\n payload: string,\r\n header: string,\r\n secret: string,\r\n options?: WebhookVerifyOptions,\r\n ): WebhookEvent {\r\n const maxSkew = options?.maxSkewSeconds ?? 300;\r\n const parts = this.parseHeader(header);\r\n const ts = Number(parts['t']);\r\n const v1 = parts['v1'];\r\n\r\n if (!ts || !v1) {\r\n throw new FlonkWebhookSignatureError('Missing timestamp or signature');\r\n }\r\n\r\n if (Math.abs(Math.floor(Date.now() / 1000) - ts) > maxSkew) {\r\n throw new FlonkWebhookSignatureError(`Timestamp skew exceeds ${maxSkew}s`);\r\n }\r\n\r\n const expected = crypto\r\n .createHmac('sha256', secret)\r\n .update(`${ts}.${payload}`)\r\n .digest('hex');\r\n\r\n if (!this.safeEqual(v1, expected)) {\r\n throw new FlonkWebhookSignatureError();\r\n }\r\n\r\n return this.parsePayload(payload);\r\n }\r\n\r\n /**\r\n * Auto-detect signature format and verify.\r\n */\r\n constructEvent(payload: string, signature: string, secret: string): WebhookEvent {\r\n if (signature.startsWith('sha256=')) {\r\n return this.verifySignature(payload, signature, secret);\r\n }\r\n if (signature.includes('t=') && signature.includes('v1=')) {\r\n return this.verifyTimestampSignature(payload, signature, secret);\r\n }\r\n throw new FlonkWebhookSignatureError('Unrecognized signature format');\r\n }\r\n\r\n private parsePayload(payload: string): WebhookEvent {\r\n try {\r\n return JSON.parse(payload) as WebhookEvent;\r\n } catch {\r\n throw new FlonkWebhookSignatureError('Malformed JSON payload');\r\n }\r\n }\r\n\r\n private parseHeader(header: string): Record<string, string> {\r\n const result: Record<string, string> = {};\r\n for (const part of header.split(',')) {\r\n const [k, v] = part.trim().split('=');\r\n if (k && v) result[k] = v;\r\n }\r\n return result;\r\n }\r\n\r\n private safeEqual(a: string, b: string): boolean {\r\n if (a.length !== b.length) return false;\r\n return crypto.timingSafeEqual(Buffer.from(a), Buffer.from(b));\r\n }\r\n}\r\n","import { SDK_VERSION, DEFAULT_API_BASE } from '../shared/constants';\r\nimport { FlonkAuthenticationError, FlonkValidationError } from '../shared/errors';\r\nimport type {\r\n FlonkKYCServerOptions,\r\n CreateSessionParams,\r\n Session,\r\n SessionDetails,\r\n UpdateSessionParams,\r\n} from '../shared/types';\r\nimport { HttpClient } from './http-client';\r\nimport { Webhooks } from './webhooks';\r\n\r\nconst SK_PATTERN = /^sk_(live|sandbox|test_sandbox|test_live)_[A-Za-z0-9]{16,}$/;\r\n\r\nexport class FlonkKYCServer {\r\n static readonly version = SDK_VERSION;\r\n\r\n private readonly http: HttpClient;\r\n public readonly webhooks = new Webhooks();\r\n\r\n constructor(options: FlonkKYCServerOptions) {\r\n if (!options.secretKey) throw new FlonkAuthenticationError('secretKey is required');\r\n if (!SK_PATTERN.test(options.secretKey)) {\r\n throw new FlonkAuthenticationError('Invalid secret key format. Expected: sk_live_*, sk_sandbox_*, sk_test_sandbox_*, sk_test_live_*');\r\n }\r\n\r\n const base = (options.apiBase || DEFAULT_API_BASE).replace(/\\/$/, '');\r\n this.http = new HttpClient(base, options.secretKey, options.timeout);\r\n }\r\n\r\n async createSession(params?: CreateSessionParams): Promise<Session> {\r\n return this.http.post<Session>('/sessions', params ?? {});\r\n }\r\n\r\n async getSession(sessionId: string): Promise<SessionDetails> {\r\n if (!sessionId) throw new FlonkValidationError('sessionId is required');\r\n return this.http.get<SessionDetails>(`/sessions/${sessionId}`);\r\n }\r\n\r\n async updateSession(sessionId: string, params: UpdateSessionParams): Promise<SessionDetails> {\r\n if (!sessionId) throw new FlonkValidationError('sessionId is required');\r\n return this.http.patch<SessionDetails>(`/sessions/${sessionId}`, params);\r\n }\r\n}\r\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/shared/constants.ts","../src/shared/errors.ts","../src/server/http-client.ts","../src/server/webhooks.ts","../src/server/index.ts"],"names":["SDK_VERSION","DEFAULT_API_BASE","FlonkError","Error","message","code","statusCode","name","FlonkAPIError","body","FlonkAuthenticationError","FlonkValidationError","FlonkWebhookSignatureError","HttpClient","baseUrl","secretKey","timeout","get","path","request","post","patch","method","controller","AbortController","timer","setTimeout","abort","res","fetch","headers","JSON","stringify","undefined","signal","json","catch","ok","status","err","clearTimeout","Webhooks","verifySignature","payload","signature","secret","expected","createHmac","update","digest","safeEqual","parsePayload","verifyTimestampSignature","header","options","maxSkew","maxSkewSeconds","parts","parseHeader","ts","Number","v1","Math","abs","floor","Date","now","constructEvent","startsWith","includes","parse","result","part","split","k","v","trim","a","b","length","timingSafeEqual","Buffer","from","SK_PATTERN","FlonkKYCServer","version","http","webhooks","test","base","apiBase","replace","createSession","params","getSession","sessionId","updateSession"],"mappings":";;;;;;AAAO,IAAMA,WAAAA,GAAc,OAAA;AAEpB,IAAMC,gBAAAA,GAAmB,yBAAA;;;ACFzB,IAAMC,UAAAA,GAAN,cAAyBC,KAAAA,CAAAA;EAAhC;;;;;EACE,WAAA,CACEC,OAAAA,EACgBC,MACAC,UAAAA,EAChB;AACA,IAAA,KAAA,CAAMF,OAAAA,CAAAA,EAAAA,IAAAA,CAHUC,IAAAA,GAAAA,IAAAA,EAAAA,KACAC,UAAAA,GAAAA,UAAAA;AAGhB,IAAA,IAAA,CAAKC,IAAAA,GAAO,YAAA;AACd,EAAA;AACF;AAEO,IAAMC,aAAAA,GAAN,cAA4BN,UAAAA,CAAAA;EAXnC;;;;EAYE,WAAA,CACEE,OAAAA,EACAE,YACgBG,IAAAA,EAChB;AACA,IAAA,KAAA,CAAML,OAAAA,EAAS,WAAA,EAAaE,UAAAA,CAAAA,EAAAA,KAFZG,IAAAA,GAAAA,IAAAA;AAGhB,IAAA,IAAA,CAAKF,IAAAA,GAAO,eAAA;AACd,EAAA;AACF;AAEO,IAAMG,wBAAAA,GAAN,cAAuCR,UAAAA,CAAAA;EAtB9C;;;AAuBE,EAAA,WAAA,CAAYE,UAAU,+BAAA,EAAiC;AACrD,IAAA,KAAA,CAAMA,OAAAA,EAAS,wBAAwB,GAAA,CAAA;AACvC,IAAA,IAAA,CAAKG,IAAAA,GAAO,0BAAA;AACd,EAAA;AACF;AAEO,IAAMI,oBAAAA,GAAN,cAAmCT,UAAAA,CAAAA;EA7B1C;;;AA8BE,EAAA,WAAA,CAAYE,OAAAA,EAAiB;AAC3B,IAAA,KAAA,CAAMA,OAAAA,EAAS,oBAAoB,GAAA,CAAA;AACnC,IAAA,IAAA,CAAKG,IAAAA,GAAO,sBAAA;AACd,EAAA;AACF;AAEO,IAAMK,0BAAAA,GAAN,cAAyCV,UAAAA,CAAAA;EApChD;;;AAqCE,EAAA,WAAA,CAAYE,UAAU,2BAAA,EAA6B;AACjD,IAAA,KAAA,CAAMA,SAAS,yBAAA,CAAA;AACf,IAAA,IAAA,CAAKG,IAAAA,GAAO,4BAAA;AACd,EAAA;AACF;;;ACtCO,IAAMM,aAAN,MAAMA;EAHb;;;;;;EAIE,WAAA,CACmBC,OAAAA,EACAC,SAAAA,EACAC,OAAAA,GAAU,GAAA,EAC3B;SAHiBF,OAAAA,GAAAA,OAAAA;SACAC,SAAAA,GAAAA,SAAAA;SACAC,OAAAA,GAAAA,OAAAA;AAChB,EAAA;AAEH,EAAA,MAAMC,IAAOC,IAAAA,EAA0B;AACrC,IAAA,OAAO,IAAA,CAAKC,OAAAA,CAAW,KAAA,EAAOD,IAAAA,CAAAA;AAChC,EAAA;EAEA,MAAME,IAAAA,CAAQF,MAAcT,IAAAA,EAA4B;AACtD,IAAA,OAAO,IAAA,CAAKU,OAAAA,CAAW,MAAA,EAAQD,IAAAA,EAAMT,IAAAA,CAAAA;AACvC,EAAA;EAEA,MAAMY,KAAAA,CAASH,MAAcT,IAAAA,EAA4B;AACvD,IAAA,OAAO,IAAA,CAAKU,OAAAA,CAAW,OAAA,EAASD,IAAAA,EAAMT,IAAAA,CAAAA;AACxC,EAAA;EAEA,MAAcU,OAAAA,CAAWG,MAAAA,EAAgBJ,IAAAA,EAAcT,IAAAA,EAA4B;AACjF,IAAA,MAAMc,UAAAA,GAAa,IAAIC,eAAAA,EAAAA;AACvB,IAAA,MAAMC,QAAQC,UAAAA,CAAW,MAAMH,WAAWI,KAAAA,EAAK,EAAI,KAAKX,OAAO,CAAA;AAE/D,IAAA,IAAI;AACF,MAAA,MAAMY,GAAAA,GAAM,MAAMC,KAAAA,CAAM,CAAA,EAAG,KAAKf,OAAO,CAAA,EAAGI,IAAAA,CAAAA,CAAAA,EAAQ;AAChDI,QAAAA,MAAAA;QACAQ,OAAAA,EAAS;UACP,eAAA,EAAiB,CAAA,OAAA,EAAU,KAAKf,SAAS,CAAA,CAAA;UACzC,cAAA,EAAgB,kBAAA;AAChB,UAAA,YAAA,EAAc,kBAAkBf,WAAAA,CAAAA;AAClC,SAAA;AACAS,QAAAA,IAAAA,EAAMA,IAAAA,GAAOsB,IAAAA,CAAKC,SAAAA,CAAUvB,IAAAA,CAAAA,GAAQwB,KAAAA,CAAAA;AACpCC,QAAAA,MAAAA,EAAQX,UAAAA,CAAWW;OACrB,CAAA;AAEA,MAAA,MAAMC,OAAO,MAAMP,GAAAA,CAAIO,MAAI,CAAGC,KAAAA,CAAM,MAAM,IAAA,CAAA;AAE1C,MAAA,IAAI,CAACR,IAAIS,EAAAA,EAAI;AACX,QAAA,IAAIT,GAAAA,CAAIU,MAAAA,KAAW,GAAA,EAAK,MAAM,IAAI5B,wBAAAA,EAAAA;AAClC,QAAA,MAAM,IAAIF,aAAAA,CACR2B,IAAAA,EAAM/B,OAAAA,IAAW,CAAA,gBAAA,EAAmBwB,IAAIU,MAAM,CAAA,CAAA,EAC9CV,GAAAA,CAAIU,MAAAA,EACJH,IAAAA,CAAAA;AAEJ,MAAA;AAEA,MAAA,OAAOA,IAAAA;AACT,IAAA,CAAA,CAAA,OAASI,GAAAA,EAAK;AACZ,MAAA,IAAIA,GAAAA,YAAe/B,aAAAA,IAAiB+B,GAAAA,YAAe7B,wBAAAA,EAA0B,MAAM6B,GAAAA;AACnF,MAAA,MAAM,IAAI/B,aAAAA,CAAe+B,GAAAA,CAAcnC,OAAAA,EAAS,CAAA,CAAA;IAClD,CAAA,SAAA;AACEoC,MAAAA,YAAAA,CAAaf,KAAAA,CAAAA;AACf,IAAA;AACF,EAAA;AACF,CAAA;ACrDO,IAAMgB,WAAN,MAAMA;EAJb;;;;;;EAQEC,eAAAA,CAAgBC,OAAAA,EAAiBC,WAAmBC,MAAAA,EAA8B;AAChF,IAAA,MAAMC,QAAAA,GACJ,SAAA,GAAmBC,MAAAA,CAAAA,UAAAA,CAAW,QAAA,EAAUF,MAAAA,EAAQG,MAAAA,CAAOL,OAAAA,CAAAA,CAASM,MAAAA,CAAO,KAAA,CAAA;AAEzE,IAAA,IAAI,CAAC,IAAA,CAAKC,SAAAA,CAAUN,SAAAA,EAAWE,QAAAA,CAAAA,EAAW;AACxC,MAAA,MAAM,IAAIlC,0BAAAA,EAAAA;AACZ,IAAA;AAEA,IAAA,OAAO,IAAA,CAAKuC,aAAaR,OAAAA,CAAAA;AAC3B,EAAA;;;;EAKAS,wBAAAA,CACET,OAAAA,EACAU,MAAAA,EACAR,MAAAA,EACAS,OAAAA,EACc;AACd,IAAA,MAAMC,OAAAA,GAAUD,SAASE,cAAAA,IAAkB,GAAA;AAC3C,IAAA,MAAMC,KAAAA,GAAQ,IAAA,CAAKC,WAAAA,CAAYL,MAAAA,CAAAA;AAC/B,IAAA,MAAMM,EAAAA,GAAKC,MAAAA,CAAOH,KAAAA,CAAM,GAAA,CAAI,CAAA;AAC5B,IAAA,MAAMI,EAAAA,GAAKJ,MAAM,IAAA,CAAA;AAEjB,IAAA,IAAI,CAACE,EAAAA,IAAM,CAACE,EAAAA,EAAI;AACd,MAAA,MAAM,IAAIjD,2BAA2B,gCAAA,CAAA;AACvC,IAAA;AAEA,IAAA,IAAIkD,IAAAA,CAAKC,GAAAA,CAAID,IAAAA,CAAKE,KAAAA,CAAMC,IAAAA,CAAKC,GAAAA,EAAG,GAAK,GAAA,CAAA,GAAQP,EAAAA,CAAAA,GAAMJ,OAAAA,EAAS;AAC1D,MAAA,MAAM,IAAI3C,0BAAAA,CAA2B,CAAA,uBAAA,EAA0B2C,OAAAA,CAAAA,CAAAA,CAAU,CAAA;AAC3E,IAAA;AAEA,IAAA,MAAMT,QAAAA,GACHC,MAAAA,CAAAA,UAAAA,CAAW,QAAA,EAAUF,MAAAA,CAAAA,CACrBG,MAAAA,CAAO,CAAA,EAAGW,EAAAA,CAAAA,CAAAA,EAAMhB,OAAAA,CAAAA,CAAS,CAAA,CACzBM,OAAO,KAAA,CAAA;AAEV,IAAA,IAAI,CAAC,IAAA,CAAKC,SAAAA,CAAUW,EAAAA,EAAIf,QAAAA,CAAAA,EAAW;AACjC,MAAA,MAAM,IAAIlC,0BAAAA,EAAAA;AACZ,IAAA;AAEA,IAAA,OAAO,IAAA,CAAKuC,aAAaR,OAAAA,CAAAA;AAC3B,EAAA;;;;EAKAwB,cAAAA,CAAexB,OAAAA,EAAiBC,WAAmBC,MAAAA,EAA8B;AAC/E,IAAA,IAAID,SAAAA,CAAUwB,UAAAA,CAAW,SAAA,CAAA,EAAY;AACnC,MAAA,OAAO,IAAA,CAAK1B,eAAAA,CAAgBC,OAAAA,EAASC,SAAAA,EAAWC,MAAAA,CAAAA;AAClD,IAAA;AACA,IAAA,IAAID,UAAUyB,QAAAA,CAAS,IAAA,KAASzB,SAAAA,CAAUyB,QAAAA,CAAS,KAAA,CAAA,EAAQ;AACzD,MAAA,OAAO,IAAA,CAAKjB,wBAAAA,CAAyBT,OAAAA,EAASC,SAAAA,EAAWC,MAAAA,CAAAA;AAC3D,IAAA;AACA,IAAA,MAAM,IAAIjC,2BAA2B,+BAAA,CAAA;AACvC,EAAA;AAEQuC,EAAAA,YAAAA,CAAaR,OAAAA,EAA+B;AAClD,IAAA,IAAI;AACF,MAAA,OAAOZ,IAAAA,CAAKuC,MAAM3B,OAAAA,CAAAA;IACpB,CAAA,CAAA,MAAQ;AACN,MAAA,MAAM,IAAI/B,2BAA2B,wBAAA,CAAA;AACvC,IAAA;AACF,EAAA;AAEQ8C,EAAAA,WAAAA,CAAYL,MAAAA,EAAwC;AAC1D,IAAA,MAAMkB,SAAiC,EAAC;AACxC,IAAA,KAAA,MAAWC,IAAAA,IAAQnB,MAAAA,CAAOoB,KAAAA,CAAM,GAAA,CAAA,EAAM;AACpC,MAAA,MAAM,CAACC,GAAGC,CAAAA,CAAAA,GAAKH,KAAKI,IAAAA,EAAI,CAAGH,MAAM,GAAA,CAAA;AACjC,MAAA,IAAIC,CAAAA,IAAKC,CAAAA,EAAGJ,MAAAA,CAAOG,CAAAA,CAAAA,GAAKC,CAAAA;AAC1B,IAAA;AACA,IAAA,OAAOJ,MAAAA;AACT,EAAA;AAEQrB,EAAAA,SAAAA,CAAU2B,GAAWC,CAAAA,EAAoB;AAC/C,IAAA,IAAID,CAAAA,CAAEE,MAAAA,KAAWD,CAAAA,CAAEC,MAAAA,EAAQ,OAAO,KAAA;AAClC,IAAA,OAAcC,MAAAA,CAAAA,eAAAA,CAAgBC,OAAOC,IAAAA,CAAKL,CAAAA,GAAII,MAAAA,CAAOC,IAAAA,CAAKJ,CAAAA,CAAAA,CAAAA;AAC5D,EAAA;AACF;;;AC3EA,IAAMK,UAAAA,GAAa,6DAAA;AAEZ,IAAMC,iBAAN,MAAMA;EAdb;;;AAeE,EAAA,OAAgBC,OAAAA,GAAUrF,WAAAA;AAETsF,EAAAA,IAAAA;AACDC,EAAAA,QAAAA,GAAW,IAAI9C,QAAAA,EAAAA;AAE/B,EAAA,WAAA,CAAYa,OAAAA,EAAgC;AAC1C,IAAA,IAAI,CAACA,OAAAA,CAAQvC,SAAAA,EAAW,MAAM,IAAIL,yBAAyB,uBAAA,CAAA;AAC3D,IAAA,IAAI,CAACyE,UAAAA,CAAWK,IAAAA,CAAKlC,OAAAA,CAAQvC,SAAS,CAAA,EAAG;AACvC,MAAA,MAAM,IAAIL,yBAAyB,iGAAA,CAAA;AACrC,IAAA;AAEA,IAAA,MAAM+E,QAAQnC,OAAAA,CAAQoC,OAAAA,IAAWzF,gBAAAA,EAAkB0F,OAAAA,CAAQ,OAAO,EAAA,CAAA;AAClE,IAAA,IAAA,CAAKL,OAAO,IAAIzE,UAAAA,CAAW4E,MAAMnC,OAAAA,CAAQvC,SAAAA,EAAWuC,QAAQtC,OAAO,CAAA;AACrE,EAAA;AAEA,EAAA,MAAM4E,cAAcC,MAAAA,EAAgD;AAClE,IAAA,OAAO,KAAKP,IAAAA,CAAKlE,IAAAA,CAAc,WAAA,EAAayE,MAAAA,IAAU,EAAC,CAAA;AACzD,EAAA;AAEA,EAAA,MAAMC,WAAWC,SAAAA,EAA4C;AAC3D,IAAA,IAAI,CAACA,SAAAA,EAAW,MAAM,IAAIpF,qBAAqB,uBAAA,CAAA;AAC/C,IAAA,OAAO,IAAA,CAAK2E,IAAAA,CAAKrE,GAAAA,CAAoB,CAAA,UAAA,EAAa8E,SAAAA,CAAAA,CAAW,CAAA;AAC/D,EAAA;EAEA,MAAMC,aAAAA,CAAcD,WAAmBF,MAAAA,EAAsD;AAC3F,IAAA,IAAI,CAACE,SAAAA,EAAW,MAAM,IAAIpF,qBAAqB,uBAAA,CAAA;AAC/C,IAAA,OAAO,KAAK2E,IAAAA,CAAKjE,KAAAA,CAAsB,CAAA,UAAA,EAAa0E,SAAAA,IAAaF,MAAAA,CAAAA;AACnE,EAAA;AACF","file":"server.js","sourcesContent":["export const SDK_VERSION = '1.6.0';\r\nexport const DEFAULT_WIDGET_URL = 'https://widget.flonk.id';\r\nexport const DEFAULT_API_BASE = 'https://api.flonk.id/v1';\r\n\r\nexport const WIDGET_EVENTS = {\r\n READY: 'KYC_WIDGET_READY',\r\n COMPLETE: 'KYC_COMPLETE',\r\n CANCEL: 'KYC_CANCEL',\r\n ERROR: 'KYC_ERROR',\r\n} as const;\r\n","export class FlonkError extends Error {\r\n constructor(\r\n message: string,\r\n public readonly code: string,\r\n public readonly statusCode?: number,\r\n ) {\r\n super(message);\r\n this.name = 'FlonkError';\r\n }\r\n}\r\n\r\nexport class FlonkAPIError extends FlonkError {\r\n constructor(\r\n message: string,\r\n statusCode: number,\r\n public readonly body?: unknown,\r\n ) {\r\n super(message, 'api_error', statusCode);\r\n this.name = 'FlonkAPIError';\r\n }\r\n}\r\n\r\nexport class FlonkAuthenticationError extends FlonkError {\r\n constructor(message = 'Invalid or missing secret key') {\r\n super(message, 'authentication_error', 401);\r\n this.name = 'FlonkAuthenticationError';\r\n }\r\n}\r\n\r\nexport class FlonkValidationError extends FlonkError {\r\n constructor(message: string) {\r\n super(message, 'validation_error', 400);\r\n this.name = 'FlonkValidationError';\r\n }\r\n}\r\n\r\nexport class FlonkWebhookSignatureError extends FlonkError {\r\n constructor(message = 'Invalid webhook signature') {\r\n super(message, 'webhook_signature_error');\r\n this.name = 'FlonkWebhookSignatureError';\r\n }\r\n}\r\n","import { SDK_VERSION } from '../shared/constants';\r\nimport { FlonkAPIError, FlonkAuthenticationError } from '../shared/errors';\r\n\r\nexport class HttpClient {\r\n constructor(\r\n private readonly baseUrl: string,\r\n private readonly secretKey: string,\r\n private readonly timeout = 30_000,\r\n ) {}\r\n\r\n async get<T>(path: string): Promise<T> {\r\n return this.request<T>('GET', path);\r\n }\r\n\r\n async post<T>(path: string, body?: unknown): Promise<T> {\r\n return this.request<T>('POST', path, body);\r\n }\r\n\r\n async patch<T>(path: string, body?: unknown): Promise<T> {\r\n return this.request<T>('PATCH', path, body);\r\n }\r\n\r\n private async request<T>(method: string, path: string, body?: unknown): Promise<T> {\r\n const controller = new AbortController();\r\n const timer = setTimeout(() => controller.abort(), this.timeout);\r\n\r\n try {\r\n const res = await fetch(`${this.baseUrl}${path}`, {\r\n method,\r\n headers: {\r\n 'Authorization': `Bearer ${this.secretKey}`,\r\n 'Content-Type': 'application/json',\r\n 'User-Agent': `flonk-kyc-node/${SDK_VERSION}`,\r\n },\r\n body: body ? JSON.stringify(body) : undefined,\r\n signal: controller.signal,\r\n });\r\n\r\n const json = await res.json().catch(() => null);\r\n\r\n if (!res.ok) {\r\n if (res.status === 401) throw new FlonkAuthenticationError();\r\n throw new FlonkAPIError(\r\n json?.message || `Request failed: ${res.status}`,\r\n res.status,\r\n json,\r\n );\r\n }\r\n\r\n return json as T;\r\n } catch (err) {\r\n if (err instanceof FlonkAPIError || err instanceof FlonkAuthenticationError) throw err;\r\n throw new FlonkAPIError((err as Error).message, 0);\r\n } finally {\r\n clearTimeout(timer);\r\n }\r\n }\r\n}\r\n","import * as crypto from 'crypto';\r\nimport { FlonkWebhookSignatureError } from '../shared/errors';\r\nimport type { WebhookEvent, WebhookVerifyOptions } from '../shared/types';\r\n\r\nexport class Webhooks {\r\n /**\r\n * Verify X-Signature-256 header: \"sha256=<hex>\"\r\n */\r\n verifySignature(payload: string, signature: string, secret: string): WebhookEvent {\r\n const expected =\r\n 'sha256=' + crypto.createHmac('sha256', secret).update(payload).digest('hex');\r\n\r\n if (!this.safeEqual(signature, expected)) {\r\n throw new FlonkWebhookSignatureError();\r\n }\r\n\r\n return this.parsePayload(payload);\r\n }\r\n\r\n /**\r\n * Verify Stripe-like header: \"t=<unix>, v1=<hex>\"\r\n */\r\n verifyTimestampSignature(\r\n payload: string,\r\n header: string,\r\n secret: string,\r\n options?: WebhookVerifyOptions,\r\n ): WebhookEvent {\r\n const maxSkew = options?.maxSkewSeconds ?? 300;\r\n const parts = this.parseHeader(header);\r\n const ts = Number(parts['t']);\r\n const v1 = parts['v1'];\r\n\r\n if (!ts || !v1) {\r\n throw new FlonkWebhookSignatureError('Missing timestamp or signature');\r\n }\r\n\r\n if (Math.abs(Math.floor(Date.now() / 1000) - ts) > maxSkew) {\r\n throw new FlonkWebhookSignatureError(`Timestamp skew exceeds ${maxSkew}s`);\r\n }\r\n\r\n const expected = crypto\r\n .createHmac('sha256', secret)\r\n .update(`${ts}.${payload}`)\r\n .digest('hex');\r\n\r\n if (!this.safeEqual(v1, expected)) {\r\n throw new FlonkWebhookSignatureError();\r\n }\r\n\r\n return this.parsePayload(payload);\r\n }\r\n\r\n /**\r\n * Auto-detect signature format and verify.\r\n */\r\n constructEvent(payload: string, signature: string, secret: string): WebhookEvent {\r\n if (signature.startsWith('sha256=')) {\r\n return this.verifySignature(payload, signature, secret);\r\n }\r\n if (signature.includes('t=') && signature.includes('v1=')) {\r\n return this.verifyTimestampSignature(payload, signature, secret);\r\n }\r\n throw new FlonkWebhookSignatureError('Unrecognized signature format');\r\n }\r\n\r\n private parsePayload(payload: string): WebhookEvent {\r\n try {\r\n return JSON.parse(payload) as WebhookEvent;\r\n } catch {\r\n throw new FlonkWebhookSignatureError('Malformed JSON payload');\r\n }\r\n }\r\n\r\n private parseHeader(header: string): Record<string, string> {\r\n const result: Record<string, string> = {};\r\n for (const part of header.split(',')) {\r\n const [k, v] = part.trim().split('=');\r\n if (k && v) result[k] = v;\r\n }\r\n return result;\r\n }\r\n\r\n private safeEqual(a: string, b: string): boolean {\r\n if (a.length !== b.length) return false;\r\n return crypto.timingSafeEqual(Buffer.from(a), Buffer.from(b));\r\n }\r\n}\r\n","import { SDK_VERSION, DEFAULT_API_BASE } from '../shared/constants';\r\nimport { FlonkAuthenticationError, FlonkValidationError } from '../shared/errors';\r\nimport type {\r\n FlonkKYCServerOptions,\r\n CreateSessionParams,\r\n Session,\r\n SessionDetails,\r\n UpdateSessionParams,\r\n} from '../shared/types';\r\nimport { HttpClient } from './http-client';\r\nimport { Webhooks } from './webhooks';\r\n\r\nconst SK_PATTERN = /^sk_(live|sandbox|test_sandbox|test_live)_[A-Za-z0-9]{16,}$/;\r\n\r\nexport class FlonkKYCServer {\r\n static readonly version = SDK_VERSION;\r\n\r\n private readonly http: HttpClient;\r\n public readonly webhooks = new Webhooks();\r\n\r\n constructor(options: FlonkKYCServerOptions) {\r\n if (!options.secretKey) throw new FlonkAuthenticationError('secretKey is required');\r\n if (!SK_PATTERN.test(options.secretKey)) {\r\n throw new FlonkAuthenticationError('Invalid secret key format. Expected: sk_live_*, sk_sandbox_*, sk_test_sandbox_*, sk_test_live_*');\r\n }\r\n\r\n const base = (options.apiBase || DEFAULT_API_BASE).replace(/\\/$/, '');\r\n this.http = new HttpClient(base, options.secretKey, options.timeout);\r\n }\r\n\r\n async createSession(params?: CreateSessionParams): Promise<Session> {\r\n return this.http.post<Session>('/sessions', params ?? {});\r\n }\r\n\r\n async getSession(sessionId: string): Promise<SessionDetails> {\r\n if (!sessionId) throw new FlonkValidationError('sessionId is required');\r\n return this.http.get<SessionDetails>(`/sessions/${sessionId}`);\r\n }\r\n\r\n async updateSession(sessionId: string, params: UpdateSessionParams): Promise<SessionDetails> {\r\n if (!sessionId) throw new FlonkValidationError('sessionId is required');\r\n return this.http.patch<SessionDetails>(`/sessions/${sessionId}`, params);\r\n }\r\n}\r\n"]}
|
package/package.json
CHANGED