@greenpay_prod/3ds-sdk 0.2.1-qa.0 → 0.3.0-qa.30
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.d.mts +32 -5
- package/dist/index.d.ts +32 -5
- package/dist/index.js +44 -12
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +41 -11
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -7,9 +7,20 @@ interface GreenPay3DSConfig {
|
|
|
7
7
|
}
|
|
8
8
|
interface OrderData {
|
|
9
9
|
cardData: {
|
|
10
|
+
/**
|
|
11
|
+
* Encrypted card/merchant/payment payload. With payload encryption (v2,
|
|
12
|
+
* every new merchant) it is a compact JWE (`RSA-OAEP-256` + `A256GCM`,
|
|
13
|
+
* `typ: "gp+v2"`) built with the session key of the order (`encryption`
|
|
14
|
+
* block of Create Order), sealing `orderId`, `nonce` and `ts`
|
|
15
|
+
* (milliseconds). It is accepted for 300 seconds after `ts`: build it
|
|
16
|
+
* right before starting the payment, and build a new one per attempt.
|
|
17
|
+
* The SDK sends it as is; it does not encrypt it.
|
|
18
|
+
*/
|
|
10
19
|
ed: string;
|
|
20
|
+
/** Order session identifier. */
|
|
11
21
|
session: string;
|
|
12
22
|
};
|
|
23
|
+
/** Order token (`token` from Create Order), sent as `session-token`. */
|
|
13
24
|
sessionToken: string;
|
|
14
25
|
terminalId?: string;
|
|
15
26
|
}
|
|
@@ -39,17 +50,33 @@ interface ThreeDSPaymentCallbacks {
|
|
|
39
50
|
onStatusChange?: (status: string) => void;
|
|
40
51
|
}
|
|
41
52
|
|
|
53
|
+
interface GreenPay3DSErrorDetails {
|
|
54
|
+
/** Greenpay error code, e.g. "ORCH_ENCRYPTION_01" (`result.error.reason`). */
|
|
55
|
+
reason?: string;
|
|
56
|
+
/** Status reported by Greenpay (`result.error.status`) or the HTTP status. */
|
|
57
|
+
status?: number;
|
|
58
|
+
}
|
|
42
59
|
declare class GreenPay3DSError extends Error {
|
|
43
60
|
code: string;
|
|
44
|
-
|
|
61
|
+
reason?: string;
|
|
62
|
+
status?: number;
|
|
63
|
+
constructor(message: string, code: string, details?: GreenPay3DSErrorDetails);
|
|
45
64
|
}
|
|
65
|
+
/**
|
|
66
|
+
* Greenpay codes for a rejected payload encryption (v2): 400 for a missing or
|
|
67
|
+
* invalid JWE (wrong kid, orderId or nonce of another session, `ts` outside
|
|
68
|
+
* 300 seconds), 503 when it could not be verified. Do not retry with the same
|
|
69
|
+
* `ed`: build a new JWE and start a new attempt.
|
|
70
|
+
*/
|
|
71
|
+
declare const ENCRYPTION_ERROR_REASONS: readonly string[];
|
|
72
|
+
declare const isEncryptionError: (error: unknown) => boolean;
|
|
46
73
|
declare class GreenPay3DS {
|
|
47
|
-
private teamId;
|
|
48
|
-
private appId;
|
|
49
|
-
private apiUrl?;
|
|
74
|
+
private readonly teamId;
|
|
75
|
+
private readonly appId;
|
|
76
|
+
private readonly apiUrl?;
|
|
50
77
|
constructor(config?: GreenPay3DSConfig);
|
|
51
78
|
authenticate(sessionId: string, callbacks?: ThreeDSCallbacks): Promise<void>;
|
|
52
79
|
processPayment(orderData: OrderData, callbacks?: ThreeDSPaymentCallbacks): Promise<ThreeDSResult>;
|
|
53
80
|
}
|
|
54
81
|
|
|
55
|
-
export { GreenPay3DS, type GreenPay3DSConfig, type GreenPay3DSEnvironment, GreenPay3DSError, type OrderData, type ThreeDSCallbacks, type ThreeDSPaymentCallbacks, type ThreeDSResult, type ThreeDSSession };
|
|
82
|
+
export { ENCRYPTION_ERROR_REASONS, GreenPay3DS, type GreenPay3DSConfig, type GreenPay3DSEnvironment, GreenPay3DSError, type GreenPay3DSErrorDetails, type OrderData, type ThreeDSCallbacks, type ThreeDSPaymentCallbacks, type ThreeDSResult, type ThreeDSSession, isEncryptionError };
|
package/dist/index.d.ts
CHANGED
|
@@ -7,9 +7,20 @@ interface GreenPay3DSConfig {
|
|
|
7
7
|
}
|
|
8
8
|
interface OrderData {
|
|
9
9
|
cardData: {
|
|
10
|
+
/**
|
|
11
|
+
* Encrypted card/merchant/payment payload. With payload encryption (v2,
|
|
12
|
+
* every new merchant) it is a compact JWE (`RSA-OAEP-256` + `A256GCM`,
|
|
13
|
+
* `typ: "gp+v2"`) built with the session key of the order (`encryption`
|
|
14
|
+
* block of Create Order), sealing `orderId`, `nonce` and `ts`
|
|
15
|
+
* (milliseconds). It is accepted for 300 seconds after `ts`: build it
|
|
16
|
+
* right before starting the payment, and build a new one per attempt.
|
|
17
|
+
* The SDK sends it as is; it does not encrypt it.
|
|
18
|
+
*/
|
|
10
19
|
ed: string;
|
|
20
|
+
/** Order session identifier. */
|
|
11
21
|
session: string;
|
|
12
22
|
};
|
|
23
|
+
/** Order token (`token` from Create Order), sent as `session-token`. */
|
|
13
24
|
sessionToken: string;
|
|
14
25
|
terminalId?: string;
|
|
15
26
|
}
|
|
@@ -39,17 +50,33 @@ interface ThreeDSPaymentCallbacks {
|
|
|
39
50
|
onStatusChange?: (status: string) => void;
|
|
40
51
|
}
|
|
41
52
|
|
|
53
|
+
interface GreenPay3DSErrorDetails {
|
|
54
|
+
/** Greenpay error code, e.g. "ORCH_ENCRYPTION_01" (`result.error.reason`). */
|
|
55
|
+
reason?: string;
|
|
56
|
+
/** Status reported by Greenpay (`result.error.status`) or the HTTP status. */
|
|
57
|
+
status?: number;
|
|
58
|
+
}
|
|
42
59
|
declare class GreenPay3DSError extends Error {
|
|
43
60
|
code: string;
|
|
44
|
-
|
|
61
|
+
reason?: string;
|
|
62
|
+
status?: number;
|
|
63
|
+
constructor(message: string, code: string, details?: GreenPay3DSErrorDetails);
|
|
45
64
|
}
|
|
65
|
+
/**
|
|
66
|
+
* Greenpay codes for a rejected payload encryption (v2): 400 for a missing or
|
|
67
|
+
* invalid JWE (wrong kid, orderId or nonce of another session, `ts` outside
|
|
68
|
+
* 300 seconds), 503 when it could not be verified. Do not retry with the same
|
|
69
|
+
* `ed`: build a new JWE and start a new attempt.
|
|
70
|
+
*/
|
|
71
|
+
declare const ENCRYPTION_ERROR_REASONS: readonly string[];
|
|
72
|
+
declare const isEncryptionError: (error: unknown) => boolean;
|
|
46
73
|
declare class GreenPay3DS {
|
|
47
|
-
private teamId;
|
|
48
|
-
private appId;
|
|
49
|
-
private apiUrl?;
|
|
74
|
+
private readonly teamId;
|
|
75
|
+
private readonly appId;
|
|
76
|
+
private readonly apiUrl?;
|
|
50
77
|
constructor(config?: GreenPay3DSConfig);
|
|
51
78
|
authenticate(sessionId: string, callbacks?: ThreeDSCallbacks): Promise<void>;
|
|
52
79
|
processPayment(orderData: OrderData, callbacks?: ThreeDSPaymentCallbacks): Promise<ThreeDSResult>;
|
|
53
80
|
}
|
|
54
81
|
|
|
55
|
-
export { GreenPay3DS, type GreenPay3DSConfig, type GreenPay3DSEnvironment, GreenPay3DSError, type OrderData, type ThreeDSCallbacks, type ThreeDSPaymentCallbacks, type ThreeDSResult, type ThreeDSSession };
|
|
82
|
+
export { ENCRYPTION_ERROR_REASONS, GreenPay3DS, type GreenPay3DSConfig, type GreenPay3DSEnvironment, GreenPay3DSError, type GreenPay3DSErrorDetails, type OrderData, type ThreeDSCallbacks, type ThreeDSPaymentCallbacks, type ThreeDSResult, type ThreeDSSession, isEncryptionError };
|
package/dist/index.js
CHANGED
|
@@ -30,12 +30,30 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
// src/index.ts
|
|
31
31
|
var index_exports = {};
|
|
32
32
|
__export(index_exports, {
|
|
33
|
+
ENCRYPTION_ERROR_REASONS: () => ENCRYPTION_ERROR_REASONS,
|
|
33
34
|
GreenPay3DS: () => GreenPay3DS,
|
|
34
|
-
GreenPay3DSError: () => GreenPay3DSError
|
|
35
|
+
GreenPay3DSError: () => GreenPay3DSError,
|
|
36
|
+
isEncryptionError: () => isEncryptionError
|
|
35
37
|
});
|
|
36
38
|
module.exports = __toCommonJS(index_exports);
|
|
37
39
|
|
|
38
40
|
// src/api.ts
|
|
41
|
+
var readJson = async (response) => {
|
|
42
|
+
try {
|
|
43
|
+
return await response.json();
|
|
44
|
+
} catch {
|
|
45
|
+
return {};
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
var errorMessage = (body, fallback) => body?.result?.error?.message || body?.message || fallback;
|
|
49
|
+
var errorDetails = (response, body) => {
|
|
50
|
+
const reason = body?.result?.error?.reason ?? body?.gp_error?.errorCode ?? void 0;
|
|
51
|
+
const status = body?.result?.error?.status ?? body?.result?.statusCode ?? (typeof body?.statusCode === "number" ? body.statusCode : void 0) ?? (response.ok ? void 0 : response.status);
|
|
52
|
+
return {
|
|
53
|
+
...typeof reason === "string" && reason !== "" && { reason },
|
|
54
|
+
...typeof status === "number" && { status }
|
|
55
|
+
};
|
|
56
|
+
};
|
|
39
57
|
async function createSession(apiUrl, cardData, sessionToken, terminalId) {
|
|
40
58
|
const requestBody = { cardData };
|
|
41
59
|
if (terminalId !== void 0 && terminalId !== "") {
|
|
@@ -49,11 +67,12 @@ async function createSession(apiUrl, cardData, sessionToken, terminalId) {
|
|
|
49
67
|
},
|
|
50
68
|
body: JSON.stringify(requestBody)
|
|
51
69
|
});
|
|
52
|
-
const json = await response
|
|
53
|
-
if (!response.ok || json
|
|
70
|
+
const json = await readJson(response);
|
|
71
|
+
if (!response.ok || json?.statusCode !== 200) {
|
|
54
72
|
throw new GreenPay3DSError(
|
|
55
|
-
json
|
|
56
|
-
"CREATE_SESSION_FAILED"
|
|
73
|
+
errorMessage(json, "Failed to create 3DS session"),
|
|
74
|
+
"CREATE_SESSION_FAILED",
|
|
75
|
+
errorDetails(response, json)
|
|
57
76
|
);
|
|
58
77
|
}
|
|
59
78
|
return json.data;
|
|
@@ -65,13 +84,17 @@ async function retrieveSession(apiUrl, sessionId, cardData, sessionToken) {
|
|
|
65
84
|
"Content-Type": "application/json",
|
|
66
85
|
"session-token": sessionToken
|
|
67
86
|
},
|
|
68
|
-
body: JSON.stringify({
|
|
87
|
+
body: JSON.stringify({
|
|
88
|
+
sessionId,
|
|
89
|
+
cardData: { session: cardData.session }
|
|
90
|
+
})
|
|
69
91
|
});
|
|
70
|
-
const body = await response
|
|
71
|
-
if (!response.ok || body
|
|
92
|
+
const body = await readJson(response);
|
|
93
|
+
if (!response.ok || body?.statusCode !== 200) {
|
|
72
94
|
throw new GreenPay3DSError(
|
|
73
|
-
body
|
|
74
|
-
"RETRIEVE_SESSION_FAILED"
|
|
95
|
+
errorMessage(body, "Failed to retrieve 3DS session"),
|
|
96
|
+
"RETRIEVE_SESSION_FAILED",
|
|
97
|
+
errorDetails(response, body)
|
|
75
98
|
);
|
|
76
99
|
}
|
|
77
100
|
return body;
|
|
@@ -93,12 +116,19 @@ var ENVIRONMENTS = {
|
|
|
93
116
|
|
|
94
117
|
// src/GreenPay3DS.ts
|
|
95
118
|
var GreenPay3DSError = class extends Error {
|
|
96
|
-
constructor(message, code) {
|
|
119
|
+
constructor(message, code, details = {}) {
|
|
97
120
|
super(message);
|
|
98
121
|
this.name = "GreenPay3DSError";
|
|
99
122
|
this.code = code;
|
|
123
|
+
if (details.reason !== void 0) this.reason = details.reason;
|
|
124
|
+
if (details.status !== void 0) this.status = details.status;
|
|
100
125
|
}
|
|
101
126
|
};
|
|
127
|
+
var ENCRYPTION_ERROR_REASONS = Object.freeze([
|
|
128
|
+
"ORCH_ENCRYPTION_01",
|
|
129
|
+
"ORCH_ENCRYPTION_02"
|
|
130
|
+
]);
|
|
131
|
+
var isEncryptionError = (error) => error instanceof GreenPay3DSError && error.reason !== void 0 && ENCRYPTION_ERROR_REASONS.includes(error.reason);
|
|
102
132
|
var GreenPay3DS = class {
|
|
103
133
|
constructor(config = {}) {
|
|
104
134
|
const defaults = config.environment !== void 0 ? ENVIRONMENTS[config.environment] : void 0;
|
|
@@ -196,7 +226,9 @@ var GreenPay3DS = class {
|
|
|
196
226
|
};
|
|
197
227
|
// Annotate the CommonJS export names for ESM import in node:
|
|
198
228
|
0 && (module.exports = {
|
|
229
|
+
ENCRYPTION_ERROR_REASONS,
|
|
199
230
|
GreenPay3DS,
|
|
200
|
-
GreenPay3DSError
|
|
231
|
+
GreenPay3DSError,
|
|
232
|
+
isEncryptionError
|
|
201
233
|
});
|
|
202
234
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/api.ts","../src/environments.ts","../src/GreenPay3DS.ts"],"sourcesContent":["export { GreenPay3DS, GreenPay3DSError } from './GreenPay3DS'\nexport type {\n GreenPay3DSConfig,\n GreenPay3DSEnvironment,\n ThreeDSCallbacks,\n ThreeDSPaymentCallbacks,\n OrderData,\n ThreeDSSession,\n ThreeDSResult,\n} from './types'\n","import type { ThreeDSSession, ThreeDSResult } from './types'\nimport { GreenPay3DSError } from './GreenPay3DS'\n\nexport async function createSession(\n apiUrl: string,\n cardData: { ed: string; session: string },\n sessionToken: string,\n terminalId?: string\n): Promise<ThreeDSSession> {\n const requestBody: Record<string, unknown> = { cardData }\n if (terminalId !== undefined && terminalId !== '') {\n requestBody.terminalId = terminalId\n }\n\n const response = await fetch(`${apiUrl}/3ds/create-session`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'session-token': sessionToken,\n },\n body: JSON.stringify(requestBody),\n })\n\n const json = await response.json()\n\n if (!response.ok || json.statusCode !== 200) {\n throw new GreenPay3DSError(\n json?.result?.error?.message ||\n json?.message ||\n 'Failed to create 3DS session',\n 'CREATE_SESSION_FAILED'\n )\n }\n\n return json.data\n}\n\nexport async function retrieveSession(\n apiUrl: string,\n sessionId: string,\n cardData: { ed: string; session: string },\n sessionToken: string\n): Promise<ThreeDSResult> {\n const response = await fetch(`${apiUrl}/3ds/retrieve-session`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'session-token': sessionToken,\n },\n body: JSON.stringify({ sessionId, cardData }),\n })\n\n const body = await response.json()\n\n if (!response.ok || body.statusCode !== 200) {\n throw new GreenPay3DSError(\n body?.result?.error?.message || body?.message || 'Failed to retrieve 3DS session',\n 'RETRIEVE_SESSION_FAILED'\n )\n }\n\n return body\n}\n","import type { GreenPay3DSEnvironment } from './types'\n\nexport interface EnvironmentConfig {\n teamId: string\n appId: string\n apiUrl: string\n}\n\nexport const ENVIRONMENTS: Record<GreenPay3DSEnvironment, EnvironmentConfig> = {\n prod: {\n teamId: 'team_115ea2493762',\n appId: 'app_86bb433bb19f',\n apiUrl: 'https://checkoutv2.greenpay.me',\n },\n sbx: {\n teamId: 'team_115ea2493762',\n appId: 'app_910ecf6fb931',\n apiUrl: 'https://checkoutv2.greenpaysbx.me',\n },\n}\n","import type {\n GreenPay3DSConfig,\n ThreeDSCallbacks,\n ThreeDSPaymentCallbacks,\n OrderData,\n ThreeDSResult,\n} from './types'\nimport { createSession, retrieveSession } from './api'\nimport { ENVIRONMENTS } from './environments'\n\nexport class GreenPay3DSError extends Error {\n code: string\n\n constructor(message: string, code: string) {\n super(message)\n this.name = 'GreenPay3DSError'\n this.code = code\n }\n}\n\nexport class GreenPay3DS {\n private teamId: string\n private appId: string\n private apiUrl?: string\n\n constructor(config: GreenPay3DSConfig = {}) {\n const defaults =\n config.environment !== undefined\n ? ENVIRONMENTS[config.environment]\n : undefined\n\n if (config.environment !== undefined && !defaults) {\n throw new GreenPay3DSError(\n `Unknown environment \"${config.environment}\" (expected \"prod\" or \"sbx\")`,\n 'INVALID_CONFIG'\n )\n }\n\n this.teamId = config.teamId ?? defaults?.teamId ?? ''\n this.appId = config.appId ?? defaults?.appId ?? ''\n this.apiUrl = config.apiUrl ?? defaults?.apiUrl\n\n if (!this.teamId || !this.appId) {\n throw new GreenPay3DSError(\n 'Set environment (\"prod\" or \"sbx\"), or pass teamId and appId explicitly',\n 'INVALID_CONFIG'\n )\n }\n }\n\n async authenticate(\n sessionId: string,\n callbacks?: ThreeDSCallbacks\n ): Promise<void> {\n if (!sessionId) {\n throw new GreenPay3DSError('sessionId is required', 'INVALID_SESSION')\n }\n\n callbacks?.onStatusChange?.('Loading 3DS authentication...')\n\n const { loadEvervault } = await import('@evervault/js')\n const ev = await loadEvervault(this.teamId, this.appId)\n\n callbacks?.onStatusChange?.('Initializing 3DS challenge...')\n\n return new Promise<void>((resolve, reject) => {\n const threeDSecure = ev.ui.threeDSecure(sessionId)\n\n threeDSecure.on('ready', () => {\n callbacks?.onReady?.()\n callbacks?.onStatusChange?.(\n 'Challenge ready. If frictionless it will complete automatically, otherwise complete the verification prompt.'\n )\n })\n\n threeDSecure.on('success', () => {\n callbacks?.onSuccess?.()\n callbacks?.onStatusChange?.('Authentication successful')\n resolve()\n })\n\n threeDSecure.on('failure', () => {\n const msg = '3DS authentication was rejected by the issuer'\n callbacks?.onFailure?.(msg)\n callbacks?.onStatusChange?.('Authentication failed')\n reject(new GreenPay3DSError(msg, 'AUTHENTICATION_FAILED'))\n })\n\n threeDSecure.on('error', (err: unknown) => {\n const msg = err instanceof Error ? err.message : String(err)\n callbacks?.onError?.(err instanceof Error ? err : msg)\n callbacks?.onStatusChange?.('Authentication error')\n reject(new GreenPay3DSError(msg, 'AUTHENTICATION_ERROR'))\n })\n\n threeDSecure.mount()\n })\n }\n\n async processPayment(\n orderData: OrderData,\n callbacks?: ThreeDSPaymentCallbacks\n ): Promise<ThreeDSResult> {\n if (!this.apiUrl) {\n throw new GreenPay3DSError(\n 'apiUrl is required in config for processPayment',\n 'INVALID_CONFIG'\n )\n }\n\n const { cardData, sessionToken, terminalId } = orderData\n if (!cardData?.ed || !cardData?.session || !sessionToken) {\n throw new GreenPay3DSError(\n 'cardData.ed, cardData.session, and sessionToken are required',\n 'INVALID_ORDER_DATA'\n )\n }\n\n callbacks?.onStatusChange?.('Creating 3DS session...')\n const session = await createSession(\n this.apiUrl,\n cardData,\n sessionToken,\n terminalId\n )\n\n callbacks?.onStatusChange?.('Starting 3DS authentication...')\n await this.authenticate(session.id, {\n onReady: callbacks?.onReady,\n onFailure: callbacks?.onFailure,\n onError: callbacks?.onError,\n onStatusChange: callbacks?.onStatusChange,\n })\n\n callbacks?.onStatusChange?.('Retrieving authentication result...')\n const result = await retrieveSession(\n this.apiUrl,\n session.id,\n cardData,\n sessionToken\n )\n\n callbacks?.onSuccess?.(result)\n callbacks?.onStatusChange?.('3DS authentication complete')\n return result\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/api.ts","../src/environments.ts","../src/GreenPay3DS.ts"],"sourcesContent":["export {\n GreenPay3DS,\n GreenPay3DSError,\n ENCRYPTION_ERROR_REASONS,\n isEncryptionError,\n type GreenPay3DSErrorDetails,\n} from './GreenPay3DS'\nexport type {\n GreenPay3DSConfig,\n GreenPay3DSEnvironment,\n ThreeDSCallbacks,\n ThreeDSPaymentCallbacks,\n OrderData,\n ThreeDSSession,\n ThreeDSResult,\n} from './types'\n","import type { ThreeDSSession, ThreeDSResult } from './types'\nimport { GreenPay3DSError, type GreenPay3DSErrorDetails } from './GreenPay3DS'\n\n// Greenpay answers /3ds/* errors with HTTP 200 and the code in\n// `result.error` ({ status, reason, message }); other failures (gateway,\n// auth) can come with a non-2xx status and a different body, or no JSON.\n\nconst readJson = async (response: Response): Promise<any> => {\n try {\n return await response.json()\n } catch {\n return {}\n }\n}\n\nconst errorMessage = (body: any, fallback: string): string =>\n body?.result?.error?.message || body?.message || fallback\n\nconst errorDetails = (\n response: Response,\n body: any\n): GreenPay3DSErrorDetails => {\n const reason =\n body?.result?.error?.reason ?? body?.gp_error?.errorCode ?? undefined\n const status =\n body?.result?.error?.status ??\n body?.result?.statusCode ??\n (typeof body?.statusCode === 'number' ? body.statusCode : undefined) ??\n (response.ok ? undefined : response.status)\n return {\n ...(typeof reason === 'string' && reason !== '' && { reason }),\n ...(typeof status === 'number' && { status }),\n }\n}\n\n/**\n * `cardData.ed` travels as received: with payload encryption (v2) it is the\n * JWE built by the merchant with the session key, sealing `orderId`, `nonce`\n * and `ts` (accepted for 300 seconds).\n */\nexport async function createSession(\n apiUrl: string,\n cardData: { ed: string; session: string },\n sessionToken: string,\n terminalId?: string\n): Promise<ThreeDSSession> {\n const requestBody: Record<string, unknown> = { cardData }\n if (terminalId !== undefined && terminalId !== '') {\n requestBody.terminalId = terminalId\n }\n\n const response = await fetch(`${apiUrl}/3ds/create-session`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'session-token': sessionToken,\n },\n body: JSON.stringify(requestBody),\n })\n\n const json = await readJson(response)\n\n if (!response.ok || json?.statusCode !== 200) {\n throw new GreenPay3DSError(\n errorMessage(json, 'Failed to create 3DS session'),\n 'CREATE_SESSION_FAILED',\n errorDetails(response, json)\n )\n }\n\n return json.data\n}\n\n/**\n * Greenpay only reads `cardData.session` here, so the JWE (`ed`) is not sent\n * a second time.\n */\nexport async function retrieveSession(\n apiUrl: string,\n sessionId: string,\n cardData: { ed?: string; session: string },\n sessionToken: string\n): Promise<ThreeDSResult> {\n const response = await fetch(`${apiUrl}/3ds/retrieve-session`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'session-token': sessionToken,\n },\n body: JSON.stringify({\n sessionId,\n cardData: { session: cardData.session },\n }),\n })\n\n const body = await readJson(response)\n\n if (!response.ok || body?.statusCode !== 200) {\n throw new GreenPay3DSError(\n errorMessage(body, 'Failed to retrieve 3DS session'),\n 'RETRIEVE_SESSION_FAILED',\n errorDetails(response, body)\n )\n }\n\n return body\n}\n","import type { GreenPay3DSEnvironment } from './types'\n\nexport interface EnvironmentConfig {\n teamId: string\n appId: string\n apiUrl: string\n}\n\nexport const ENVIRONMENTS: Record<GreenPay3DSEnvironment, EnvironmentConfig> = {\n prod: {\n teamId: 'team_115ea2493762',\n appId: 'app_86bb433bb19f',\n apiUrl: 'https://checkoutv2.greenpay.me',\n },\n sbx: {\n teamId: 'team_115ea2493762',\n appId: 'app_910ecf6fb931',\n apiUrl: 'https://checkoutv2.greenpaysbx.me',\n },\n}\n","import type {\n GreenPay3DSConfig,\n ThreeDSCallbacks,\n ThreeDSPaymentCallbacks,\n OrderData,\n ThreeDSResult,\n} from './types'\nimport { createSession, retrieveSession } from './api'\nimport { ENVIRONMENTS } from './environments'\n\nexport interface GreenPay3DSErrorDetails {\n /** Greenpay error code, e.g. \"ORCH_ENCRYPTION_01\" (`result.error.reason`). */\n reason?: string\n /** Status reported by Greenpay (`result.error.status`) or the HTTP status. */\n status?: number\n}\n\nexport class GreenPay3DSError extends Error {\n code: string\n reason?: string\n status?: number\n\n constructor(\n message: string,\n code: string,\n details: GreenPay3DSErrorDetails = {}\n ) {\n super(message)\n this.name = 'GreenPay3DSError'\n this.code = code\n if (details.reason !== undefined) this.reason = details.reason\n if (details.status !== undefined) this.status = details.status\n }\n}\n\n/**\n * Greenpay codes for a rejected payload encryption (v2): 400 for a missing or\n * invalid JWE (wrong kid, orderId or nonce of another session, `ts` outside\n * 300 seconds), 503 when it could not be verified. Do not retry with the same\n * `ed`: build a new JWE and start a new attempt.\n */\nexport const ENCRYPTION_ERROR_REASONS: readonly string[] = Object.freeze([\n 'ORCH_ENCRYPTION_01',\n 'ORCH_ENCRYPTION_02',\n])\n\nexport const isEncryptionError = (error: unknown): boolean =>\n error instanceof GreenPay3DSError &&\n error.reason !== undefined &&\n ENCRYPTION_ERROR_REASONS.includes(error.reason)\n\nexport class GreenPay3DS {\n private readonly teamId: string\n private readonly appId: string\n private readonly apiUrl?: string\n\n constructor(config: GreenPay3DSConfig = {}) {\n const defaults =\n config.environment !== undefined\n ? ENVIRONMENTS[config.environment]\n : undefined\n\n if (config.environment !== undefined && !defaults) {\n throw new GreenPay3DSError(\n `Unknown environment \"${config.environment}\" (expected \"prod\" or \"sbx\")`,\n 'INVALID_CONFIG'\n )\n }\n\n this.teamId = config.teamId ?? defaults?.teamId ?? ''\n this.appId = config.appId ?? defaults?.appId ?? ''\n this.apiUrl = config.apiUrl ?? defaults?.apiUrl\n\n if (!this.teamId || !this.appId) {\n throw new GreenPay3DSError(\n 'Set environment (\"prod\" or \"sbx\"), or pass teamId and appId explicitly',\n 'INVALID_CONFIG'\n )\n }\n }\n\n async authenticate(\n sessionId: string,\n callbacks?: ThreeDSCallbacks\n ): Promise<void> {\n if (!sessionId) {\n throw new GreenPay3DSError('sessionId is required', 'INVALID_SESSION')\n }\n\n callbacks?.onStatusChange?.('Loading 3DS authentication...')\n\n const { loadEvervault } = await import('@evervault/js')\n const ev = await loadEvervault(this.teamId, this.appId)\n\n callbacks?.onStatusChange?.('Initializing 3DS challenge...')\n\n return new Promise<void>((resolve, reject) => {\n const threeDSecure = ev.ui.threeDSecure(sessionId)\n\n threeDSecure.on('ready', () => {\n callbacks?.onReady?.()\n callbacks?.onStatusChange?.(\n 'Challenge ready. If frictionless it will complete automatically, otherwise complete the verification prompt.'\n )\n })\n\n threeDSecure.on('success', () => {\n callbacks?.onSuccess?.()\n callbacks?.onStatusChange?.('Authentication successful')\n resolve()\n })\n\n threeDSecure.on('failure', () => {\n const msg = '3DS authentication was rejected by the issuer'\n callbacks?.onFailure?.(msg)\n callbacks?.onStatusChange?.('Authentication failed')\n reject(new GreenPay3DSError(msg, 'AUTHENTICATION_FAILED'))\n })\n\n threeDSecure.on('error', (err: unknown) => {\n const msg = err instanceof Error ? err.message : String(err)\n callbacks?.onError?.(err instanceof Error ? err : msg)\n callbacks?.onStatusChange?.('Authentication error')\n reject(new GreenPay3DSError(msg, 'AUTHENTICATION_ERROR'))\n })\n\n threeDSecure.mount()\n })\n }\n\n async processPayment(\n orderData: OrderData,\n callbacks?: ThreeDSPaymentCallbacks\n ): Promise<ThreeDSResult> {\n if (!this.apiUrl) {\n throw new GreenPay3DSError(\n 'apiUrl is required in config for processPayment',\n 'INVALID_CONFIG'\n )\n }\n\n const { cardData, sessionToken, terminalId } = orderData\n if (!cardData?.ed || !cardData?.session || !sessionToken) {\n throw new GreenPay3DSError(\n 'cardData.ed, cardData.session, and sessionToken are required',\n 'INVALID_ORDER_DATA'\n )\n }\n\n callbacks?.onStatusChange?.('Creating 3DS session...')\n const session = await createSession(\n this.apiUrl,\n cardData,\n sessionToken,\n terminalId\n )\n\n callbacks?.onStatusChange?.('Starting 3DS authentication...')\n await this.authenticate(session.id, {\n onReady: callbacks?.onReady,\n onFailure: callbacks?.onFailure,\n onError: callbacks?.onError,\n onStatusChange: callbacks?.onStatusChange,\n })\n\n callbacks?.onStatusChange?.('Retrieving authentication result...')\n const result = await retrieveSession(\n this.apiUrl,\n session.id,\n cardData,\n sessionToken\n )\n\n callbacks?.onSuccess?.(result)\n callbacks?.onStatusChange?.('3DS authentication complete')\n return result\n }\n}\n"],"mappings":"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","names":[]}
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,20 @@
|
|
|
1
1
|
// src/api.ts
|
|
2
|
+
var readJson = async (response) => {
|
|
3
|
+
try {
|
|
4
|
+
return await response.json();
|
|
5
|
+
} catch {
|
|
6
|
+
return {};
|
|
7
|
+
}
|
|
8
|
+
};
|
|
9
|
+
var errorMessage = (body, fallback) => body?.result?.error?.message || body?.message || fallback;
|
|
10
|
+
var errorDetails = (response, body) => {
|
|
11
|
+
const reason = body?.result?.error?.reason ?? body?.gp_error?.errorCode ?? void 0;
|
|
12
|
+
const status = body?.result?.error?.status ?? body?.result?.statusCode ?? (typeof body?.statusCode === "number" ? body.statusCode : void 0) ?? (response.ok ? void 0 : response.status);
|
|
13
|
+
return {
|
|
14
|
+
...typeof reason === "string" && reason !== "" && { reason },
|
|
15
|
+
...typeof status === "number" && { status }
|
|
16
|
+
};
|
|
17
|
+
};
|
|
2
18
|
async function createSession(apiUrl, cardData, sessionToken, terminalId) {
|
|
3
19
|
const requestBody = { cardData };
|
|
4
20
|
if (terminalId !== void 0 && terminalId !== "") {
|
|
@@ -12,11 +28,12 @@ async function createSession(apiUrl, cardData, sessionToken, terminalId) {
|
|
|
12
28
|
},
|
|
13
29
|
body: JSON.stringify(requestBody)
|
|
14
30
|
});
|
|
15
|
-
const json = await response
|
|
16
|
-
if (!response.ok || json
|
|
31
|
+
const json = await readJson(response);
|
|
32
|
+
if (!response.ok || json?.statusCode !== 200) {
|
|
17
33
|
throw new GreenPay3DSError(
|
|
18
|
-
json
|
|
19
|
-
"CREATE_SESSION_FAILED"
|
|
34
|
+
errorMessage(json, "Failed to create 3DS session"),
|
|
35
|
+
"CREATE_SESSION_FAILED",
|
|
36
|
+
errorDetails(response, json)
|
|
20
37
|
);
|
|
21
38
|
}
|
|
22
39
|
return json.data;
|
|
@@ -28,13 +45,17 @@ async function retrieveSession(apiUrl, sessionId, cardData, sessionToken) {
|
|
|
28
45
|
"Content-Type": "application/json",
|
|
29
46
|
"session-token": sessionToken
|
|
30
47
|
},
|
|
31
|
-
body: JSON.stringify({
|
|
48
|
+
body: JSON.stringify({
|
|
49
|
+
sessionId,
|
|
50
|
+
cardData: { session: cardData.session }
|
|
51
|
+
})
|
|
32
52
|
});
|
|
33
|
-
const body = await response
|
|
34
|
-
if (!response.ok || body
|
|
53
|
+
const body = await readJson(response);
|
|
54
|
+
if (!response.ok || body?.statusCode !== 200) {
|
|
35
55
|
throw new GreenPay3DSError(
|
|
36
|
-
body
|
|
37
|
-
"RETRIEVE_SESSION_FAILED"
|
|
56
|
+
errorMessage(body, "Failed to retrieve 3DS session"),
|
|
57
|
+
"RETRIEVE_SESSION_FAILED",
|
|
58
|
+
errorDetails(response, body)
|
|
38
59
|
);
|
|
39
60
|
}
|
|
40
61
|
return body;
|
|
@@ -56,12 +77,19 @@ var ENVIRONMENTS = {
|
|
|
56
77
|
|
|
57
78
|
// src/GreenPay3DS.ts
|
|
58
79
|
var GreenPay3DSError = class extends Error {
|
|
59
|
-
constructor(message, code) {
|
|
80
|
+
constructor(message, code, details = {}) {
|
|
60
81
|
super(message);
|
|
61
82
|
this.name = "GreenPay3DSError";
|
|
62
83
|
this.code = code;
|
|
84
|
+
if (details.reason !== void 0) this.reason = details.reason;
|
|
85
|
+
if (details.status !== void 0) this.status = details.status;
|
|
63
86
|
}
|
|
64
87
|
};
|
|
88
|
+
var ENCRYPTION_ERROR_REASONS = Object.freeze([
|
|
89
|
+
"ORCH_ENCRYPTION_01",
|
|
90
|
+
"ORCH_ENCRYPTION_02"
|
|
91
|
+
]);
|
|
92
|
+
var isEncryptionError = (error) => error instanceof GreenPay3DSError && error.reason !== void 0 && ENCRYPTION_ERROR_REASONS.includes(error.reason);
|
|
65
93
|
var GreenPay3DS = class {
|
|
66
94
|
constructor(config = {}) {
|
|
67
95
|
const defaults = config.environment !== void 0 ? ENVIRONMENTS[config.environment] : void 0;
|
|
@@ -158,7 +186,9 @@ var GreenPay3DS = class {
|
|
|
158
186
|
}
|
|
159
187
|
};
|
|
160
188
|
export {
|
|
189
|
+
ENCRYPTION_ERROR_REASONS,
|
|
161
190
|
GreenPay3DS,
|
|
162
|
-
GreenPay3DSError
|
|
191
|
+
GreenPay3DSError,
|
|
192
|
+
isEncryptionError
|
|
163
193
|
};
|
|
164
194
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/api.ts","../src/environments.ts","../src/GreenPay3DS.ts"],"sourcesContent":["import type { ThreeDSSession, ThreeDSResult } from './types'\nimport { GreenPay3DSError } from './GreenPay3DS'\n\nexport async function createSession(\n apiUrl: string,\n cardData: { ed: string; session: string },\n sessionToken: string,\n terminalId?: string\n): Promise<ThreeDSSession> {\n const requestBody: Record<string, unknown> = { cardData }\n if (terminalId !== undefined && terminalId !== '') {\n requestBody.terminalId = terminalId\n }\n\n const response = await fetch(`${apiUrl}/3ds/create-session`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'session-token': sessionToken,\n },\n body: JSON.stringify(requestBody),\n })\n\n const json = await response.json()\n\n if (!response.ok || json.statusCode !== 200) {\n throw new GreenPay3DSError(\n json?.result?.error?.message ||\n json?.message ||\n 'Failed to create 3DS session',\n 'CREATE_SESSION_FAILED'\n )\n }\n\n return json.data\n}\n\nexport async function retrieveSession(\n apiUrl: string,\n sessionId: string,\n cardData: { ed: string; session: string },\n sessionToken: string\n): Promise<ThreeDSResult> {\n const response = await fetch(`${apiUrl}/3ds/retrieve-session`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'session-token': sessionToken,\n },\n body: JSON.stringify({ sessionId, cardData }),\n })\n\n const body = await response.json()\n\n if (!response.ok || body.statusCode !== 200) {\n throw new GreenPay3DSError(\n body?.result?.error?.message || body?.message || 'Failed to retrieve 3DS session',\n 'RETRIEVE_SESSION_FAILED'\n )\n }\n\n return body\n}\n","import type { GreenPay3DSEnvironment } from './types'\n\nexport interface EnvironmentConfig {\n teamId: string\n appId: string\n apiUrl: string\n}\n\nexport const ENVIRONMENTS: Record<GreenPay3DSEnvironment, EnvironmentConfig> = {\n prod: {\n teamId: 'team_115ea2493762',\n appId: 'app_86bb433bb19f',\n apiUrl: 'https://checkoutv2.greenpay.me',\n },\n sbx: {\n teamId: 'team_115ea2493762',\n appId: 'app_910ecf6fb931',\n apiUrl: 'https://checkoutv2.greenpaysbx.me',\n },\n}\n","import type {\n GreenPay3DSConfig,\n ThreeDSCallbacks,\n ThreeDSPaymentCallbacks,\n OrderData,\n ThreeDSResult,\n} from './types'\nimport { createSession, retrieveSession } from './api'\nimport { ENVIRONMENTS } from './environments'\n\nexport class GreenPay3DSError extends Error {\n code: string\n\n constructor(message: string, code: string) {\n super(message)\n this.name = 'GreenPay3DSError'\n this.code = code\n }\n}\n\nexport class GreenPay3DS {\n private teamId: string\n private appId: string\n private apiUrl?: string\n\n constructor(config: GreenPay3DSConfig = {}) {\n const defaults =\n config.environment !== undefined\n ? ENVIRONMENTS[config.environment]\n : undefined\n\n if (config.environment !== undefined && !defaults) {\n throw new GreenPay3DSError(\n `Unknown environment \"${config.environment}\" (expected \"prod\" or \"sbx\")`,\n 'INVALID_CONFIG'\n )\n }\n\n this.teamId = config.teamId ?? defaults?.teamId ?? ''\n this.appId = config.appId ?? defaults?.appId ?? ''\n this.apiUrl = config.apiUrl ?? defaults?.apiUrl\n\n if (!this.teamId || !this.appId) {\n throw new GreenPay3DSError(\n 'Set environment (\"prod\" or \"sbx\"), or pass teamId and appId explicitly',\n 'INVALID_CONFIG'\n )\n }\n }\n\n async authenticate(\n sessionId: string,\n callbacks?: ThreeDSCallbacks\n ): Promise<void> {\n if (!sessionId) {\n throw new GreenPay3DSError('sessionId is required', 'INVALID_SESSION')\n }\n\n callbacks?.onStatusChange?.('Loading 3DS authentication...')\n\n const { loadEvervault } = await import('@evervault/js')\n const ev = await loadEvervault(this.teamId, this.appId)\n\n callbacks?.onStatusChange?.('Initializing 3DS challenge...')\n\n return new Promise<void>((resolve, reject) => {\n const threeDSecure = ev.ui.threeDSecure(sessionId)\n\n threeDSecure.on('ready', () => {\n callbacks?.onReady?.()\n callbacks?.onStatusChange?.(\n 'Challenge ready. If frictionless it will complete automatically, otherwise complete the verification prompt.'\n )\n })\n\n threeDSecure.on('success', () => {\n callbacks?.onSuccess?.()\n callbacks?.onStatusChange?.('Authentication successful')\n resolve()\n })\n\n threeDSecure.on('failure', () => {\n const msg = '3DS authentication was rejected by the issuer'\n callbacks?.onFailure?.(msg)\n callbacks?.onStatusChange?.('Authentication failed')\n reject(new GreenPay3DSError(msg, 'AUTHENTICATION_FAILED'))\n })\n\n threeDSecure.on('error', (err: unknown) => {\n const msg = err instanceof Error ? err.message : String(err)\n callbacks?.onError?.(err instanceof Error ? err : msg)\n callbacks?.onStatusChange?.('Authentication error')\n reject(new GreenPay3DSError(msg, 'AUTHENTICATION_ERROR'))\n })\n\n threeDSecure.mount()\n })\n }\n\n async processPayment(\n orderData: OrderData,\n callbacks?: ThreeDSPaymentCallbacks\n ): Promise<ThreeDSResult> {\n if (!this.apiUrl) {\n throw new GreenPay3DSError(\n 'apiUrl is required in config for processPayment',\n 'INVALID_CONFIG'\n )\n }\n\n const { cardData, sessionToken, terminalId } = orderData\n if (!cardData?.ed || !cardData?.session || !sessionToken) {\n throw new GreenPay3DSError(\n 'cardData.ed, cardData.session, and sessionToken are required',\n 'INVALID_ORDER_DATA'\n )\n }\n\n callbacks?.onStatusChange?.('Creating 3DS session...')\n const session = await createSession(\n this.apiUrl,\n cardData,\n sessionToken,\n terminalId\n )\n\n callbacks?.onStatusChange?.('Starting 3DS authentication...')\n await this.authenticate(session.id, {\n onReady: callbacks?.onReady,\n onFailure: callbacks?.onFailure,\n onError: callbacks?.onError,\n onStatusChange: callbacks?.onStatusChange,\n })\n\n callbacks?.onStatusChange?.('Retrieving authentication result...')\n const result = await retrieveSession(\n this.apiUrl,\n session.id,\n cardData,\n sessionToken\n )\n\n callbacks?.onSuccess?.(result)\n callbacks?.onStatusChange?.('3DS authentication complete')\n return result\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/api.ts","../src/environments.ts","../src/GreenPay3DS.ts"],"sourcesContent":["import type { ThreeDSSession, ThreeDSResult } from './types'\nimport { GreenPay3DSError, type GreenPay3DSErrorDetails } from './GreenPay3DS'\n\n// Greenpay answers /3ds/* errors with HTTP 200 and the code in\n// `result.error` ({ status, reason, message }); other failures (gateway,\n// auth) can come with a non-2xx status and a different body, or no JSON.\n\nconst readJson = async (response: Response): Promise<any> => {\n try {\n return await response.json()\n } catch {\n return {}\n }\n}\n\nconst errorMessage = (body: any, fallback: string): string =>\n body?.result?.error?.message || body?.message || fallback\n\nconst errorDetails = (\n response: Response,\n body: any\n): GreenPay3DSErrorDetails => {\n const reason =\n body?.result?.error?.reason ?? body?.gp_error?.errorCode ?? undefined\n const status =\n body?.result?.error?.status ??\n body?.result?.statusCode ??\n (typeof body?.statusCode === 'number' ? body.statusCode : undefined) ??\n (response.ok ? undefined : response.status)\n return {\n ...(typeof reason === 'string' && reason !== '' && { reason }),\n ...(typeof status === 'number' && { status }),\n }\n}\n\n/**\n * `cardData.ed` travels as received: with payload encryption (v2) it is the\n * JWE built by the merchant with the session key, sealing `orderId`, `nonce`\n * and `ts` (accepted for 300 seconds).\n */\nexport async function createSession(\n apiUrl: string,\n cardData: { ed: string; session: string },\n sessionToken: string,\n terminalId?: string\n): Promise<ThreeDSSession> {\n const requestBody: Record<string, unknown> = { cardData }\n if (terminalId !== undefined && terminalId !== '') {\n requestBody.terminalId = terminalId\n }\n\n const response = await fetch(`${apiUrl}/3ds/create-session`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'session-token': sessionToken,\n },\n body: JSON.stringify(requestBody),\n })\n\n const json = await readJson(response)\n\n if (!response.ok || json?.statusCode !== 200) {\n throw new GreenPay3DSError(\n errorMessage(json, 'Failed to create 3DS session'),\n 'CREATE_SESSION_FAILED',\n errorDetails(response, json)\n )\n }\n\n return json.data\n}\n\n/**\n * Greenpay only reads `cardData.session` here, so the JWE (`ed`) is not sent\n * a second time.\n */\nexport async function retrieveSession(\n apiUrl: string,\n sessionId: string,\n cardData: { ed?: string; session: string },\n sessionToken: string\n): Promise<ThreeDSResult> {\n const response = await fetch(`${apiUrl}/3ds/retrieve-session`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'session-token': sessionToken,\n },\n body: JSON.stringify({\n sessionId,\n cardData: { session: cardData.session },\n }),\n })\n\n const body = await readJson(response)\n\n if (!response.ok || body?.statusCode !== 200) {\n throw new GreenPay3DSError(\n errorMessage(body, 'Failed to retrieve 3DS session'),\n 'RETRIEVE_SESSION_FAILED',\n errorDetails(response, body)\n )\n }\n\n return body\n}\n","import type { GreenPay3DSEnvironment } from './types'\n\nexport interface EnvironmentConfig {\n teamId: string\n appId: string\n apiUrl: string\n}\n\nexport const ENVIRONMENTS: Record<GreenPay3DSEnvironment, EnvironmentConfig> = {\n prod: {\n teamId: 'team_115ea2493762',\n appId: 'app_86bb433bb19f',\n apiUrl: 'https://checkoutv2.greenpay.me',\n },\n sbx: {\n teamId: 'team_115ea2493762',\n appId: 'app_910ecf6fb931',\n apiUrl: 'https://checkoutv2.greenpaysbx.me',\n },\n}\n","import type {\n GreenPay3DSConfig,\n ThreeDSCallbacks,\n ThreeDSPaymentCallbacks,\n OrderData,\n ThreeDSResult,\n} from './types'\nimport { createSession, retrieveSession } from './api'\nimport { ENVIRONMENTS } from './environments'\n\nexport interface GreenPay3DSErrorDetails {\n /** Greenpay error code, e.g. \"ORCH_ENCRYPTION_01\" (`result.error.reason`). */\n reason?: string\n /** Status reported by Greenpay (`result.error.status`) or the HTTP status. */\n status?: number\n}\n\nexport class GreenPay3DSError extends Error {\n code: string\n reason?: string\n status?: number\n\n constructor(\n message: string,\n code: string,\n details: GreenPay3DSErrorDetails = {}\n ) {\n super(message)\n this.name = 'GreenPay3DSError'\n this.code = code\n if (details.reason !== undefined) this.reason = details.reason\n if (details.status !== undefined) this.status = details.status\n }\n}\n\n/**\n * Greenpay codes for a rejected payload encryption (v2): 400 for a missing or\n * invalid JWE (wrong kid, orderId or nonce of another session, `ts` outside\n * 300 seconds), 503 when it could not be verified. Do not retry with the same\n * `ed`: build a new JWE and start a new attempt.\n */\nexport const ENCRYPTION_ERROR_REASONS: readonly string[] = Object.freeze([\n 'ORCH_ENCRYPTION_01',\n 'ORCH_ENCRYPTION_02',\n])\n\nexport const isEncryptionError = (error: unknown): boolean =>\n error instanceof GreenPay3DSError &&\n error.reason !== undefined &&\n ENCRYPTION_ERROR_REASONS.includes(error.reason)\n\nexport class GreenPay3DS {\n private readonly teamId: string\n private readonly appId: string\n private readonly apiUrl?: string\n\n constructor(config: GreenPay3DSConfig = {}) {\n const defaults =\n config.environment !== undefined\n ? ENVIRONMENTS[config.environment]\n : undefined\n\n if (config.environment !== undefined && !defaults) {\n throw new GreenPay3DSError(\n `Unknown environment \"${config.environment}\" (expected \"prod\" or \"sbx\")`,\n 'INVALID_CONFIG'\n )\n }\n\n this.teamId = config.teamId ?? defaults?.teamId ?? ''\n this.appId = config.appId ?? defaults?.appId ?? ''\n this.apiUrl = config.apiUrl ?? defaults?.apiUrl\n\n if (!this.teamId || !this.appId) {\n throw new GreenPay3DSError(\n 'Set environment (\"prod\" or \"sbx\"), or pass teamId and appId explicitly',\n 'INVALID_CONFIG'\n )\n }\n }\n\n async authenticate(\n sessionId: string,\n callbacks?: ThreeDSCallbacks\n ): Promise<void> {\n if (!sessionId) {\n throw new GreenPay3DSError('sessionId is required', 'INVALID_SESSION')\n }\n\n callbacks?.onStatusChange?.('Loading 3DS authentication...')\n\n const { loadEvervault } = await import('@evervault/js')\n const ev = await loadEvervault(this.teamId, this.appId)\n\n callbacks?.onStatusChange?.('Initializing 3DS challenge...')\n\n return new Promise<void>((resolve, reject) => {\n const threeDSecure = ev.ui.threeDSecure(sessionId)\n\n threeDSecure.on('ready', () => {\n callbacks?.onReady?.()\n callbacks?.onStatusChange?.(\n 'Challenge ready. If frictionless it will complete automatically, otherwise complete the verification prompt.'\n )\n })\n\n threeDSecure.on('success', () => {\n callbacks?.onSuccess?.()\n callbacks?.onStatusChange?.('Authentication successful')\n resolve()\n })\n\n threeDSecure.on('failure', () => {\n const msg = '3DS authentication was rejected by the issuer'\n callbacks?.onFailure?.(msg)\n callbacks?.onStatusChange?.('Authentication failed')\n reject(new GreenPay3DSError(msg, 'AUTHENTICATION_FAILED'))\n })\n\n threeDSecure.on('error', (err: unknown) => {\n const msg = err instanceof Error ? err.message : String(err)\n callbacks?.onError?.(err instanceof Error ? err : msg)\n callbacks?.onStatusChange?.('Authentication error')\n reject(new GreenPay3DSError(msg, 'AUTHENTICATION_ERROR'))\n })\n\n threeDSecure.mount()\n })\n }\n\n async processPayment(\n orderData: OrderData,\n callbacks?: ThreeDSPaymentCallbacks\n ): Promise<ThreeDSResult> {\n if (!this.apiUrl) {\n throw new GreenPay3DSError(\n 'apiUrl is required in config for processPayment',\n 'INVALID_CONFIG'\n )\n }\n\n const { cardData, sessionToken, terminalId } = orderData\n if (!cardData?.ed || !cardData?.session || !sessionToken) {\n throw new GreenPay3DSError(\n 'cardData.ed, cardData.session, and sessionToken are required',\n 'INVALID_ORDER_DATA'\n )\n }\n\n callbacks?.onStatusChange?.('Creating 3DS session...')\n const session = await createSession(\n this.apiUrl,\n cardData,\n sessionToken,\n terminalId\n )\n\n callbacks?.onStatusChange?.('Starting 3DS authentication...')\n await this.authenticate(session.id, {\n onReady: callbacks?.onReady,\n onFailure: callbacks?.onFailure,\n onError: callbacks?.onError,\n onStatusChange: callbacks?.onStatusChange,\n })\n\n callbacks?.onStatusChange?.('Retrieving authentication result...')\n const result = await retrieveSession(\n this.apiUrl,\n session.id,\n cardData,\n sessionToken\n )\n\n callbacks?.onSuccess?.(result)\n callbacks?.onStatusChange?.('3DS authentication complete')\n return result\n }\n}\n"],"mappings":"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","names":[]}
|