@starfish-codes/hellgate 3.9.0 → 3.10.0
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/3ds/typings.d.ts +1 -0
- package/dist/__tests__/card-handler.spec.d.ts +1 -0
- package/dist/__tests__/test-utils.d.ts +11 -0
- package/dist/card/card-handler.d.ts +24 -8
- package/dist/card/coordinator/__tests__/card-handler-coordinator.spec.d.ts +1 -0
- package/dist/card/coordinator/card-handler-coordinator.d.ts +34 -0
- package/dist/card/coordinator/index.d.ts +2 -0
- package/dist/card/coordinator/typings.d.ts +45 -0
- package/dist/card/typings.d.ts +30 -0
- package/dist/card/ui/elements/base-element.d.ts +3 -3
- package/dist/card/ui/elements/utils.d.ts +1 -2
- package/dist/card/ui/iframe/elements/base-element.d.ts +4 -2
- package/dist/card/ui/iframe/elements/card-expiration-month.d.ts +1 -0
- package/dist/card/ui/iframe/elements/text-element.d.ts +1 -0
- package/dist/card/ui/iframe/index.d.ts +1 -0
- package/dist/card/ui/iframe/utils.d.ts +1 -0
- package/dist/card/ui/typings.d.ts +8 -5
- package/dist/card/ui/utils.d.ts +3 -1
- package/dist/coordinator/coordinator.d.ts +38 -0
- package/dist/coordinator/iframe/constants.d.ts +1 -0
- package/dist/coordinator/iframe/iframe-coordinator.d.ts +33 -0
- package/dist/coordinator/iframe/iframe.d.ts +1 -0
- package/dist/coordinator/iframe/index.d.ts +2 -0
- package/dist/coordinator/index.d.ts +3 -0
- package/dist/coordinator/typings.d.ts +39 -0
- package/dist/hellgate-sdk.mjs +464 -1145
- package/dist/hellgate-sdk.umd.js +1 -1
- package/dist/hellgate.d.ts +5 -2
- package/dist/session/session.d.ts +1 -1
- package/dist/utils.d.ts +1 -0
- package/package.json +7 -6
package/dist/3ds/typings.d.ts
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,2 +1,13 @@
|
|
|
1
1
|
export declare function wait(milliseconds: number): Promise<void>;
|
|
2
2
|
export declare function fill(input: HTMLInputElement, value: string): void;
|
|
3
|
+
export declare const HELLGATE_BASE_URL: string;
|
|
4
|
+
type CreateHellgateSessionParams = {
|
|
5
|
+
bypass_identification?: boolean;
|
|
6
|
+
};
|
|
7
|
+
export declare function createHellgateSession(params: CreateHellgateSessionParams): Promise<{
|
|
8
|
+
session_id: string;
|
|
9
|
+
}>;
|
|
10
|
+
export declare function refreshHellgateSession(): Promise<{
|
|
11
|
+
session_id: string;
|
|
12
|
+
}>;
|
|
13
|
+
export {};
|
|
@@ -1,20 +1,35 @@
|
|
|
1
1
|
import { CompleteActionResult, HellgateSession } from '../session';
|
|
2
|
+
import { Coordinator } from '../coordinator';
|
|
2
3
|
import { CreateCardFieldsOptions, CreateCardFormOptions, PaymentAdditionalData, RefreshSecurityCodeSessionStateDTO, TokenizeCardSessionStateDTO, TokenizedData } from './typings';
|
|
3
4
|
import { CardElement, CardExpirationDateElement, CardNumberElement, CardVerificationCodeElement, TextElement } from './ui/elements';
|
|
5
|
+
import { CardElementBase } from './ui/elements/base-element';
|
|
4
6
|
import { CardExpirationMonthElement } from './ui/elements/card-expiration-month';
|
|
5
7
|
import { CardExpirationYearElement } from './ui/elements/card-expiration-year';
|
|
6
|
-
import { ChangeEvent, ElementBaseOptions } from './ui/typings';
|
|
7
|
-
export type FormFieldState = Omit<ChangeEvent
|
|
8
|
+
import { CardSchema, ChangeEvent, ElementBaseOptions } from './ui/typings';
|
|
9
|
+
export type FormFieldState = Omit<ChangeEvent['data'], 'type'>;
|
|
8
10
|
export type CardHandlerSessionInitState = TokenizeCardSessionStateDTO | RefreshSecurityCodeSessionStateDTO;
|
|
11
|
+
type FormField<T extends CardElementBase<any, any>> = {
|
|
12
|
+
element: T;
|
|
13
|
+
state: FormFieldState;
|
|
14
|
+
};
|
|
15
|
+
type ElementsMap = {
|
|
16
|
+
card: FormField<CardElement>;
|
|
17
|
+
cardNumber: FormField<CardNumberElement>;
|
|
18
|
+
cardExpirationDate: FormField<CardExpirationDateElement>;
|
|
19
|
+
cardExpirationMonth: FormField<CardExpirationMonthElement>;
|
|
20
|
+
cardExpirationYear: FormField<CardExpirationYearElement>;
|
|
21
|
+
cardVerificationCode: FormField<CardVerificationCodeElement>;
|
|
22
|
+
};
|
|
9
23
|
export declare class HellgateCardHandler {
|
|
10
24
|
session: HellgateSession<CardHandlerSessionInitState>;
|
|
25
|
+
private coordinator;
|
|
11
26
|
state: FormFieldState;
|
|
12
|
-
|
|
27
|
+
cardElements: Partial<ElementsMap>;
|
|
13
28
|
private textElements;
|
|
14
29
|
private stateChangeHandlers;
|
|
15
30
|
readonly cvcOnlyEnabled: boolean;
|
|
16
|
-
static init(session: HellgateSession<CardHandlerSessionInitState
|
|
17
|
-
constructor(session: HellgateSession<CardHandlerSessionInitState
|
|
31
|
+
static init(session: HellgateSession<CardHandlerSessionInitState>, coordinator: Coordinator): Promise<HellgateCardHandler>;
|
|
32
|
+
constructor(session: HellgateSession<CardHandlerSessionInitState>, coordinator: Coordinator);
|
|
18
33
|
createForm: (options?: CreateCardFormOptions) => CardElement;
|
|
19
34
|
createFormFields(options: CreateCardFieldsOptions<'separate'>): {
|
|
20
35
|
cardNumber: CardNumberElement;
|
|
@@ -35,13 +50,14 @@ export declare class HellgateCardHandler {
|
|
|
35
50
|
dispose: () => void;
|
|
36
51
|
process: (additionalData?: PaymentAdditionalData) => Promise<CompleteActionResult>;
|
|
37
52
|
private refreshSecurityCode;
|
|
38
|
-
private getFormValue;
|
|
39
53
|
private hasFormElements;
|
|
40
54
|
private disableFormElements;
|
|
41
|
-
private extractAdditionalData;
|
|
42
|
-
private encryptCardData;
|
|
43
55
|
private addElementStateListener;
|
|
44
56
|
updateFormState(): void;
|
|
45
57
|
private createFieldDefaultState;
|
|
58
|
+
private serializeAdditionalData;
|
|
59
|
+
private getSessionSchemes;
|
|
46
60
|
private getCardDataValidationError;
|
|
47
61
|
}
|
|
62
|
+
export declare function resolveSchemes(sessionSchemes: CardSchema[] | undefined, userSchemes: CardSchema[] | undefined): CardSchema[] | undefined;
|
|
63
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { CompleteActionResult, HellgateSession } from '../../session';
|
|
2
|
+
import { FormFieldState } from '../card-handler';
|
|
3
|
+
import { PaymentAdditionalDataDTO, TokenizedData } from '../typings';
|
|
4
|
+
type FormField<Value = string> = {
|
|
5
|
+
value?: Value;
|
|
6
|
+
state: FormFieldState;
|
|
7
|
+
};
|
|
8
|
+
type ElementsMap = {
|
|
9
|
+
card: FormField<{
|
|
10
|
+
number: string;
|
|
11
|
+
expiry_date: string;
|
|
12
|
+
cvc: string;
|
|
13
|
+
}>;
|
|
14
|
+
cardNumber: FormField;
|
|
15
|
+
cardExpirationDate: FormField;
|
|
16
|
+
cardExpirationMonth: FormField;
|
|
17
|
+
cardExpirationYear: FormField;
|
|
18
|
+
cardVerificationCode: FormField;
|
|
19
|
+
} & Record<string, FormField>;
|
|
20
|
+
export declare class CardHandlerCoordinator {
|
|
21
|
+
private session;
|
|
22
|
+
private cardElements;
|
|
23
|
+
constructor(session: HellgateSession);
|
|
24
|
+
tokenize: (additionalData: PaymentAdditionalDataDTO) => Promise<TokenizedData>;
|
|
25
|
+
process: (additionalData?: PaymentAdditionalDataDTO) => Promise<CompleteActionResult>;
|
|
26
|
+
refreshSecurityCode(): Promise<CompleteActionResult>;
|
|
27
|
+
onElementChange: (key: keyof ElementsMap | string, data: FormFieldState) => void;
|
|
28
|
+
dispose(): void;
|
|
29
|
+
private getFormValue;
|
|
30
|
+
private extractAdditionalData;
|
|
31
|
+
private encryptCardData;
|
|
32
|
+
private extractAdditionalDataStringValue;
|
|
33
|
+
}
|
|
34
|
+
export {};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { CompleteActionResult } from '../../session';
|
|
2
|
+
import { FormFieldState } from '../card-handler';
|
|
3
|
+
import { PaymentAdditionalDataDTO, TokenizedData } from '../typings';
|
|
4
|
+
import { ElementBaseOptions } from '../ui/typings';
|
|
5
|
+
export type CardHandlerToCoordinatorMessage = {
|
|
6
|
+
type: 'card:tokenize';
|
|
7
|
+
additionalData?: PaymentAdditionalDataDTO;
|
|
8
|
+
} | {
|
|
9
|
+
type: 'card:process';
|
|
10
|
+
additionalData?: PaymentAdditionalDataDTO;
|
|
11
|
+
} | {
|
|
12
|
+
type: 'card:refresh_security_code';
|
|
13
|
+
};
|
|
14
|
+
export type CoordinatorToCardHandlerMessage = {
|
|
15
|
+
type: 'card:tokenize:response';
|
|
16
|
+
success: boolean;
|
|
17
|
+
result: TokenizedData | null;
|
|
18
|
+
error?: string;
|
|
19
|
+
} | {
|
|
20
|
+
type: 'card:process:response';
|
|
21
|
+
success: boolean;
|
|
22
|
+
result: CompleteActionResult | null;
|
|
23
|
+
error?: string;
|
|
24
|
+
} | {
|
|
25
|
+
type: 'card:refresh_security_code:response';
|
|
26
|
+
success: boolean;
|
|
27
|
+
result: CompleteActionResult | null;
|
|
28
|
+
error?: string;
|
|
29
|
+
};
|
|
30
|
+
export type ElementToCoordinatorMessage = {
|
|
31
|
+
type: 'element:change';
|
|
32
|
+
data: {
|
|
33
|
+
element: string;
|
|
34
|
+
key: string;
|
|
35
|
+
state: FormFieldState;
|
|
36
|
+
};
|
|
37
|
+
};
|
|
38
|
+
export type CoordinatorToElementMessage = {
|
|
39
|
+
type: 'coordinator:element:update';
|
|
40
|
+
data: {
|
|
41
|
+
element: string;
|
|
42
|
+
key: string;
|
|
43
|
+
options: ElementBaseOptions;
|
|
44
|
+
};
|
|
45
|
+
};
|
package/dist/card/typings.d.ts
CHANGED
|
@@ -20,6 +20,9 @@ export type CreateCardFieldsOptions<T extends ExpiryDateElementType = 'combined'
|
|
|
20
20
|
expiryDate?: ElementBaseOptions;
|
|
21
21
|
});
|
|
22
22
|
export type AdditionalDataValue = string | TextElement;
|
|
23
|
+
export type AdditionalDataValueDTO = string | {
|
|
24
|
+
key: string;
|
|
25
|
+
};
|
|
23
26
|
export type PaymentAdditionalData<FieldValue = AdditionalDataValue> = {
|
|
24
27
|
cardholder_name?: FieldValue;
|
|
25
28
|
email?: FieldValue;
|
|
@@ -31,7 +34,21 @@ export type PaymentAdditionalData<FieldValue = AdditionalDataValue> = {
|
|
|
31
34
|
city?: FieldValue;
|
|
32
35
|
country?: FieldValue;
|
|
33
36
|
};
|
|
37
|
+
/**
|
|
38
|
+
* Token lifecycle intent. When `true` (the SDK default), the resulting PCI
|
|
39
|
+
* token is ephemeral and cleaned up after a short TTL. When `false`, the
|
|
40
|
+
* token is persistent. Use `false` only on cardholder consent.
|
|
41
|
+
*/
|
|
42
|
+
ephemeral?: boolean;
|
|
43
|
+
/**
|
|
44
|
+
* Optional ISO-8601 timestamp setting an explicit expiration for the
|
|
45
|
+
* resulting PCI token. When present it takes precedence over `ephemeral`
|
|
46
|
+
* (subject to a server-side cap). Use this for a "Save my card" UX where
|
|
47
|
+
* the merchant chooses the exact retention window after cardholder consent.
|
|
48
|
+
*/
|
|
49
|
+
expiration_date?: string;
|
|
34
50
|
};
|
|
51
|
+
export type PaymentAdditionalDataDTO = PaymentAdditionalData<AdditionalDataValueDTO>;
|
|
35
52
|
export type ElementsCardData = {
|
|
36
53
|
number: string | null;
|
|
37
54
|
expiration_month: number | null;
|
|
@@ -48,11 +65,13 @@ export type TokenizeCardActionDTO = {
|
|
|
48
65
|
action: 'tokenize_card';
|
|
49
66
|
result: TokenizedData;
|
|
50
67
|
};
|
|
68
|
+
export type HellgateCardScheme = 'visa' | 'mastercard' | 'americanexpress' | 'discover' | 'dinersclub' | 'jcb' | 'unionpay';
|
|
51
69
|
export type TokenizeCardConfig = {
|
|
52
70
|
provider: 'guardian';
|
|
53
71
|
api_key: string;
|
|
54
72
|
base_url: string;
|
|
55
73
|
jwk: JWK;
|
|
74
|
+
allowed_schemes?: HellgateCardScheme[];
|
|
56
75
|
};
|
|
57
76
|
export type TokenizeCardSessionStateDTO = {
|
|
58
77
|
next_action: 'tokenize_card';
|
|
@@ -65,6 +84,17 @@ export type CardTokenizeData = {
|
|
|
65
84
|
security_code: string;
|
|
66
85
|
cardholder_name?: string;
|
|
67
86
|
additional_data: PaymentAdditionalData<string>;
|
|
87
|
+
/**
|
|
88
|
+
* Optional token lifecycle intent decrypted by Guardian inside the JWE.
|
|
89
|
+
* `true` requests an ephemeral PCI token, `false` a persistent one. Absent
|
|
90
|
+
* preserves Guardian's pre-existing default behavior.
|
|
91
|
+
*/
|
|
92
|
+
ephemeral?: boolean;
|
|
93
|
+
/**
|
|
94
|
+
* Optional ISO-8601 expiration timestamp decrypted by Guardian inside the
|
|
95
|
+
* JWE. Wins over `ephemeral` server side.
|
|
96
|
+
*/
|
|
97
|
+
expiration_date?: string;
|
|
68
98
|
};
|
|
69
99
|
export type TokenizedCardMaskedData = {
|
|
70
100
|
account_number_last_four: string;
|
|
@@ -8,15 +8,15 @@ export declare abstract class CardElementBase<Value, IframeValue = string> {
|
|
|
8
8
|
protected abstract type: ElementType;
|
|
9
9
|
protected abstract extractValue: (rawValue: IframeValue | null) => Value | null;
|
|
10
10
|
protected abstract putValue: (rawValue: Value | null) => IframeValue | null;
|
|
11
|
-
|
|
11
|
+
key: string;
|
|
12
|
+
constructor(options: ElementBaseOptions<Value>);
|
|
12
13
|
mount(selector: string | Element): Promise<void>;
|
|
13
14
|
update: ({ ...data }: ElementBaseOptions<Value>) => Promise<void>;
|
|
14
15
|
clear: () => void;
|
|
15
16
|
focus: () => void;
|
|
16
17
|
blur: () => void;
|
|
17
18
|
unmount: () => void;
|
|
18
|
-
on<T extends EventType>(eventType: T, listener: (event: FindByType<Explicit<CardElementEvents
|
|
19
|
-
secureValue(key: string): Value | null;
|
|
19
|
+
on<T extends EventType>(eventType: T, listener: (event: FindByType<Explicit<CardElementEvents>, T>['data']) => void): Subscription;
|
|
20
20
|
private emitEvent;
|
|
21
21
|
private iframePostMessage;
|
|
22
22
|
}
|
|
@@ -15,6 +15,5 @@ type Elements = {
|
|
|
15
15
|
cardVerificationCode: CardVerificationCodeElement;
|
|
16
16
|
text: TextElement;
|
|
17
17
|
};
|
|
18
|
-
export declare function createElement<T extends keyof Elements>(type: T, options: ElementBaseOptions
|
|
19
|
-
export declare function uid(): string;
|
|
18
|
+
export declare function createElement<T extends keyof Elements>(type: T, options: ElementBaseOptions): Elements[T];
|
|
20
19
|
export {};
|
|
@@ -3,7 +3,6 @@ import { FactoryArg, InputMask, Masked } from 'imask';
|
|
|
3
3
|
import { BaseElement, CardElementEvents, ElementBaseOptions, ElementEventListener, ElementMetadata, ElementType, EventType, Subscription } from '../../typings';
|
|
4
4
|
export type PostMessageOptions = {
|
|
5
5
|
postMessageOrigin: string;
|
|
6
|
-
postMessageRoot: Window;
|
|
7
6
|
};
|
|
8
7
|
export declare abstract class IframeCardElementBase implements BaseElement<ElementBaseOptions, CardElementEvents<string>, string> {
|
|
9
8
|
protected rootNode: Element;
|
|
@@ -16,11 +15,13 @@ export declare abstract class IframeCardElementBase implements BaseElement<Eleme
|
|
|
16
15
|
protected abstract options: ElementBaseOptions;
|
|
17
16
|
protected abstract inputMaskOptions: FactoryArg;
|
|
18
17
|
protected inputMask?: InputMask<FactoryArg>;
|
|
19
|
-
|
|
18
|
+
protected id: string;
|
|
20
19
|
cardType?: CreditCardType;
|
|
21
20
|
value: null;
|
|
21
|
+
private channel;
|
|
22
22
|
constructor(rootNode: Element, postMessageOptions: PostMessageOptions);
|
|
23
23
|
mount(): Promise<void>;
|
|
24
|
+
protected onMount(): void;
|
|
24
25
|
unmount(): void;
|
|
25
26
|
focus(): void;
|
|
26
27
|
blur(): void;
|
|
@@ -29,6 +30,7 @@ export declare abstract class IframeCardElementBase implements BaseElement<Eleme
|
|
|
29
30
|
updateState(): void;
|
|
30
31
|
update(options: ElementBaseOptions): Promise<void>;
|
|
31
32
|
on<T extends EventType>(eventType: T, listener: ElementEventListener<CardElementEvents<string>, T>): Subscription;
|
|
33
|
+
protected get key(): string;
|
|
32
34
|
private emitEvent;
|
|
33
35
|
protected validate(masked: Masked): ElementMetadata;
|
|
34
36
|
protected renderHTML(): string;
|
|
@@ -21,4 +21,5 @@ export declare function generateElementId(type: ElementType): string;
|
|
|
21
21
|
export declare function mergeOptions(options1: ElementBaseOptions, options2: ElementBaseOptions): ElementBaseOptions;
|
|
22
22
|
export declare function mergeStyles(style1: ElementStyle, style2: ElementStyle): ElementStyle;
|
|
23
23
|
export declare function applyStyle(id: string, { fonts, ...styles }: ElementStyle): void;
|
|
24
|
+
export declare function uid(): string;
|
|
24
25
|
export {};
|
|
@@ -7,18 +7,21 @@ type EventType = 'ready' | 'change' | 'focus' | 'blur' | 'keydown';
|
|
|
7
7
|
export declare const EVENT_TYPES: EventType[];
|
|
8
8
|
type BaseEvent<T extends EventType, TData = unknown> = {
|
|
9
9
|
type: T;
|
|
10
|
+
id: string;
|
|
10
11
|
element: ElementType;
|
|
11
12
|
} & (TData extends object ? {
|
|
12
13
|
data: TData;
|
|
13
14
|
} : unknown);
|
|
14
|
-
type ReadyEvent = BaseEvent<'ready'
|
|
15
|
-
|
|
15
|
+
type ReadyEvent = BaseEvent<'ready', {
|
|
16
|
+
key: string;
|
|
17
|
+
}>;
|
|
18
|
+
type ChangeEvent<Value = never> = BaseEvent<'change', {
|
|
16
19
|
empty: boolean;
|
|
17
20
|
complete: boolean;
|
|
18
21
|
valid?: boolean;
|
|
19
22
|
error?: string;
|
|
20
23
|
errorCode?: CardValidationError;
|
|
21
|
-
value
|
|
24
|
+
value?: Value extends never ? never : Value | null;
|
|
22
25
|
}>;
|
|
23
26
|
type InputFocusEvent = BaseEvent<'focus'>;
|
|
24
27
|
type InputBlurEvent = BaseEvent<'blur'>;
|
|
@@ -26,11 +29,11 @@ type InputKeydownEvent = BaseEvent<'keydown', {
|
|
|
26
29
|
key: ListenableKey;
|
|
27
30
|
} & Pick<KeyboardEvent, 'altKey' | 'ctrlKey' | 'shiftKey' | 'metaKey'>>;
|
|
28
31
|
type BaseElementEvents = ReadyEvent | InputFocusEvent | InputBlurEvent | InputKeydownEvent;
|
|
29
|
-
type CardElementEvents<Value> = BaseElementEvents | ChangeEvent<Value>;
|
|
32
|
+
type CardElementEvents<Value = never> = BaseElementEvents | ChangeEvent<Value>;
|
|
30
33
|
/**
|
|
31
34
|
* Utility type that helps find a Union type based on a `type` property
|
|
32
35
|
*/
|
|
33
|
-
type FindByType<Union, Type extends
|
|
36
|
+
type FindByType<Union, Type extends string> = Union extends {
|
|
34
37
|
type: Type;
|
|
35
38
|
} ? Union : never;
|
|
36
39
|
type ElementEventListener<Events, Type extends EventType> = (event: FindByType<Events, Type>) => void;
|
package/dist/card/ui/utils.d.ts
CHANGED
|
@@ -1,2 +1,4 @@
|
|
|
1
|
-
import { TokenizedCardMaskedData } from '../typings';
|
|
1
|
+
import { HellgateCardScheme, TokenizedCardMaskedData } from '../typings';
|
|
2
|
+
import { CardSchema } from './typings';
|
|
3
|
+
export declare function mapHellgateSchemesToCardSchema(schemes: HellgateCardScheme[]): CardSchema[];
|
|
2
4
|
export declare function getMaskedCardNumber(data: TokenizedCardMaskedData): string;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { FindByType } from '../card/ui/typings';
|
|
2
|
+
import { CoordinatorToParentMessage, ParentToCoordinatorMessage } from './typings';
|
|
3
|
+
/**
|
|
4
|
+
* Coordinator lives on the parent (merchant) page.
|
|
5
|
+
*
|
|
6
|
+
* It creates a hidden iframe with `?type=coordinator` that hosts the
|
|
7
|
+
* IframeCoordinator. All sensitive card operations (data collection,
|
|
8
|
+
* encryption, API calls) happen inside that iframe — card data never
|
|
9
|
+
* crosses the iframe boundary back to the merchant page.
|
|
10
|
+
*
|
|
11
|
+
* Communication with the iframe uses window.postMessage, carrying only
|
|
12
|
+
* commands and validation state — never card data.
|
|
13
|
+
*/
|
|
14
|
+
export declare class Coordinator {
|
|
15
|
+
private iframe;
|
|
16
|
+
private iframeBaseUrl;
|
|
17
|
+
private messageHandler;
|
|
18
|
+
constructor();
|
|
19
|
+
/**
|
|
20
|
+
* Mount the coordinator iframe into the DOM and wait until it is
|
|
21
|
+
* fully initialised (receives `coordinator:ready` from the iframe with the session state).
|
|
22
|
+
*
|
|
23
|
+
* The iframe is hidden — it has no visual presence on the page.
|
|
24
|
+
* It serves purely as an isolated execution environment for secure
|
|
25
|
+
* card-data handling.
|
|
26
|
+
*/
|
|
27
|
+
init: (sessionId: string, baseUrl: string, abortCtrl?: AbortController) => Promise<void>;
|
|
28
|
+
/**
|
|
29
|
+
* Send a command to the coordinator iframe.
|
|
30
|
+
* Only commands and configuration — never card data.
|
|
31
|
+
*/
|
|
32
|
+
postMessage(message: ParentToCoordinatorMessage): void;
|
|
33
|
+
onMessage<T extends CoordinatorToParentMessage['type']>(type: T, callback: (message: FindByType<CoordinatorToParentMessage, T>) => void): void;
|
|
34
|
+
/**
|
|
35
|
+
* Clean up the coordinator iframe and all associated resources.
|
|
36
|
+
*/
|
|
37
|
+
dispose(): void;
|
|
38
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const COORDINATOR_IFRAME_CHANNEL_NAME = "coordinator-channel";
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* IframeCoordinator lives entirely within the iframe isolation layer.
|
|
3
|
+
*
|
|
4
|
+
* It coordinates all card form elements via the Channel Messaging API,
|
|
5
|
+
* combines and validates card data within the iframe, encrypts sensitive
|
|
6
|
+
* data, and makes direct API calls to the Hellgate backend.
|
|
7
|
+
*
|
|
8
|
+
* SECURITY: Card data NEVER crosses the iframe boundary.
|
|
9
|
+
* - Card form elements send raw values only to the coordinator (same origin, via MessagePort)
|
|
10
|
+
* - The coordinator encrypts data and communicates with the backend directly
|
|
11
|
+
* - Only validation state (empty, complete, valid) is sent to the parent via postMessage
|
|
12
|
+
*/
|
|
13
|
+
export declare class IframeCoordinator {
|
|
14
|
+
private parentOrigin;
|
|
15
|
+
private cardHandlerCoordinator;
|
|
16
|
+
private session;
|
|
17
|
+
private channel;
|
|
18
|
+
constructor(sessionId: string, apiBaseUrl: string, parentOrigin: string);
|
|
19
|
+
init: () => Promise<void>;
|
|
20
|
+
private setupChannelListener;
|
|
21
|
+
/**
|
|
22
|
+
* Listen for messages from the parent CardHandler.
|
|
23
|
+
* Only commands and configuration cross this boundary - never card data.
|
|
24
|
+
*/
|
|
25
|
+
private setupParentMessageListener;
|
|
26
|
+
private handleParentMessage;
|
|
27
|
+
/**
|
|
28
|
+
* Send a message to the parent CardHandler.
|
|
29
|
+
* Only validation state and results - never card data.
|
|
30
|
+
*/
|
|
31
|
+
private postMessageToParent;
|
|
32
|
+
dispose(): void;
|
|
33
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function initCoordinatorIframe(sessionId: string, apiBaseUrl: string, origin: string): void;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { CardHandlerToCoordinatorMessage, CoordinatorToCardHandlerMessage } from '../card/coordinator/typings';
|
|
2
|
+
import { SessionStateDTO } from '../session';
|
|
3
|
+
/**
|
|
4
|
+
* Message types sent FROM the parent CardHandler TO the coordinator iframe
|
|
5
|
+
* via window.postMessage (crosses iframe boundary)
|
|
6
|
+
*
|
|
7
|
+
* IMPORTANT: No card data flows through these messages.
|
|
8
|
+
* Only commands and configuration are sent.
|
|
9
|
+
*/
|
|
10
|
+
export type ParentToCoordinatorMessage = {
|
|
11
|
+
type: 'coordinator:init';
|
|
12
|
+
sessionId: string;
|
|
13
|
+
baseUrl: string;
|
|
14
|
+
} | {
|
|
15
|
+
type: 'coordinator:dispose';
|
|
16
|
+
} | CardHandlerToCoordinatorMessage;
|
|
17
|
+
/**
|
|
18
|
+
* Message types sent FROM the coordinator iframe TO the parent CardHandler
|
|
19
|
+
* via window.postMessage (crosses iframe boundary)
|
|
20
|
+
*
|
|
21
|
+
* IMPORTANT: No card data flows through these messages.
|
|
22
|
+
* Only validation state and tokenization results are sent.
|
|
23
|
+
*/
|
|
24
|
+
export type CoordinatorToParentMessage = {
|
|
25
|
+
type: 'coordinator:ready';
|
|
26
|
+
} | {
|
|
27
|
+
type: 'coordinator:error';
|
|
28
|
+
error: unknown;
|
|
29
|
+
} | {
|
|
30
|
+
type: 'coordinator:session_state_change';
|
|
31
|
+
state: SessionStateDTO;
|
|
32
|
+
} | CoordinatorToCardHandlerMessage;
|
|
33
|
+
export type CoordinatorFormState = {
|
|
34
|
+
empty: boolean;
|
|
35
|
+
complete: boolean;
|
|
36
|
+
valid: boolean;
|
|
37
|
+
error?: string;
|
|
38
|
+
errorCode?: string;
|
|
39
|
+
};
|