@juspay-tech/hyperswitch-control-center-embed-core 1.1.1 → 1.2.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/README.md +152 -76
- package/dist/element.d.ts +9 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.esm.js +162 -57
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +163 -56
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/dist/index.umd.js +163 -56
- package/dist/index.umd.js.map +1 -1
- package/dist/payments.d.ts +8 -0
- package/dist/refunds.d.ts +8 -0
- package/dist/types.d.ts +2 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,114 +1,166 @@
|
|
|
1
1
|
# @juspay-tech/hyperswitch-control-center-embed-core
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/@juspay-tech/hyperswitch-control-center-embed-core)
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
The core JavaScript SDK for Hyperswitch Control Center embedded components. It lets you add Control Center functionality, such as connector configuration, payments and refunds, to your own website.
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
It:
|
|
9
|
-
|
|
10
|
-
- **Loads UI via an iframe** from the Hyperswitch Control Center
|
|
11
|
-
- **Requires a `fetchToken` function** that calls your backend to retrieve an embedded token
|
|
12
|
-
- **Optionally accepts `initConfig`** to customize the appearance of the embedded UI
|
|
7
|
+
This package contains the initialization logic for embedded components along with the related TypeScript types. It has no framework dependency. If you use React, see [`@juspay-tech/hyperswitch-control-center-embed-react`](https://www.npmjs.com/package/@juspay-tech/hyperswitch-control-center-embed-react).
|
|
13
8
|
|
|
14
9
|
## Installation
|
|
15
10
|
|
|
16
|
-
```
|
|
11
|
+
```sh
|
|
17
12
|
npm install @juspay-tech/hyperswitch-control-center-embed-core
|
|
18
13
|
```
|
|
19
14
|
|
|
20
15
|
or with `pnpm`:
|
|
21
16
|
|
|
22
|
-
```
|
|
17
|
+
```sh
|
|
23
18
|
pnpm add @juspay-tech/hyperswitch-control-center-embed-core
|
|
24
19
|
```
|
|
25
20
|
|
|
26
|
-
##
|
|
21
|
+
## Documentation
|
|
27
22
|
|
|
28
|
-
|
|
23
|
+
- [Integration Guide](https://docs.hyperswitch.io/explore-hyperswitch/account-management/beta-embeddable-components/integration-guide)
|
|
24
|
+
- [API reference](#api-reference)
|
|
29
25
|
|
|
30
|
-
|
|
31
|
-
import { loadHyperswitch } from '@juspay-tech/hyperswitch-control-center-embed-core';
|
|
32
|
-
```
|
|
26
|
+
## Usage
|
|
33
27
|
|
|
34
|
-
|
|
28
|
+
Embedded components authenticate with a short-lived embedded token. Your server requests the token from Hyperswitch with your API key, and the SDK retrieves it from your server through a `fetchToken` function that you provide. Your API key is never exposed to the browser.
|
|
35
29
|
|
|
36
|
-
|
|
37
|
-
const { loadHyperswitch } = require('@juspay-tech/hyperswitch-control-center-embed-core');
|
|
38
|
-
```
|
|
30
|
+
### Issue an embedded token on your server
|
|
39
31
|
|
|
40
|
-
|
|
32
|
+
Add an endpoint to your server that calls the Hyperswitch embedded token API and returns the token.
|
|
41
33
|
|
|
42
|
-
|
|
34
|
+
```js
|
|
35
|
+
// GET /api/get-embedded-token
|
|
36
|
+
app.get('/api/get-embedded-token', async (req, res) => {
|
|
37
|
+
const response = await fetch(`${process.env.HYPERSWITCH_API_URL}/embedded/token`, {
|
|
38
|
+
headers: {
|
|
39
|
+
'api-key': process.env.HYPERSWITCH_API_KEY,
|
|
40
|
+
'x-profile-id': process.env.HYPERSWITCH_PROFILE_ID,
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
43
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
fetchToken: async () => {
|
|
47
|
-
// Call your backend endpoint to get the embedded token
|
|
48
|
-
const response = await fetch('https://your-api.com/embedded/hyperswitch', {
|
|
49
|
-
method: 'GET',
|
|
50
|
-
headers: { 'Content-Type': 'application/json' }
|
|
51
|
-
});
|
|
52
|
-
const data = await response.json();
|
|
53
|
-
return data.token;
|
|
44
|
+
if (!response.ok) {
|
|
45
|
+
return res.status(502).json({ error: 'Unable to issue an embedded token.' });
|
|
54
46
|
}
|
|
47
|
+
|
|
48
|
+
const { token } = await response.json();
|
|
49
|
+
res.json({ token });
|
|
55
50
|
});
|
|
56
51
|
```
|
|
57
52
|
|
|
58
|
-
|
|
53
|
+
The token is scoped to the business profile passed in `x-profile-id`.
|
|
59
54
|
|
|
60
|
-
|
|
55
|
+
### `loadHyperswitch`
|
|
61
56
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
secondary: {
|
|
73
|
-
backgroundColor: '#f0f0f0',
|
|
74
|
-
textColor: '#333333',
|
|
75
|
-
hoverBackgroundColor: '#e0e0e0'
|
|
76
|
-
}
|
|
77
|
-
}
|
|
57
|
+
This synchronous function takes a function that retrieves the embedded token from your server, along with optional [appearance settings](#customizing-the-appearance). It returns a `Hyperswitch` instance.
|
|
58
|
+
|
|
59
|
+
```js
|
|
60
|
+
import { loadHyperswitch } from '@juspay-tech/hyperswitch-control-center-embed-core';
|
|
61
|
+
|
|
62
|
+
const fetchToken = async () => {
|
|
63
|
+
// Fetch the embedded token by making an API call to your server
|
|
64
|
+
const response = await fetch('/api/get-embedded-token');
|
|
65
|
+
const { token } = await response.json();
|
|
66
|
+
return token;
|
|
78
67
|
};
|
|
79
68
|
|
|
80
|
-
const hyperswitch = loadHyperswitch({
|
|
81
|
-
fetchToken: async () => { /* ... */ },
|
|
82
|
-
initConfig
|
|
83
|
-
});
|
|
69
|
+
const hyperswitch = loadHyperswitch({ fetchToken });
|
|
84
70
|
```
|
|
85
71
|
|
|
86
|
-
|
|
72
|
+
`fetchToken` is called when the instance is created, and again whenever the token expires.
|
|
87
73
|
|
|
88
|
-
|
|
74
|
+
The package also supports CommonJS:
|
|
89
75
|
|
|
90
|
-
|
|
76
|
+
```js
|
|
77
|
+
const { loadHyperswitch } = require('@juspay-tech/hyperswitch-control-center-embed-core');
|
|
78
|
+
```
|
|
91
79
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
80
|
+
### Creating and mounting a component
|
|
81
|
+
|
|
82
|
+
Create a component from the instance and mount it to an element on your page.
|
|
83
|
+
|
|
84
|
+
```html
|
|
85
|
+
<div id="hyperswitch-root"></div>
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
```js
|
|
89
|
+
const payments = hyperswitch.create('payments', {
|
|
90
|
+
url: 'https://app.hyperswitch.io',
|
|
95
91
|
});
|
|
92
|
+
|
|
93
|
+
payments.mount('#hyperswitch-root');
|
|
96
94
|
```
|
|
97
95
|
|
|
98
|
-
|
|
96
|
+
To remove a component, call `payments.destroy()`.
|
|
99
97
|
|
|
100
|
-
|
|
98
|
+
### Supported components
|
|
101
99
|
|
|
102
|
-
|
|
100
|
+
| Name | Description |
|
|
101
|
+
|------|-------------|
|
|
102
|
+
| `connectors` | Connector configuration |
|
|
103
|
+
| `payments` | Payments list and payment details |
|
|
104
|
+
| `refunds` | Refunds list and refund details |
|
|
103
105
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
+
Multiple components can be created from a single instance.
|
|
107
|
+
|
|
108
|
+
### Environments
|
|
109
|
+
|
|
110
|
+
The `url` option is the base URL of the Control Center that serves the components. The embedded token must be issued by the same environment.
|
|
111
|
+
|
|
112
|
+
| Environment | `url` | Token API base URL |
|
|
113
|
+
|-------------|-------|--------------------|
|
|
114
|
+
| Sandbox | `https://app.hyperswitch.io` | `https://app.hyperswitch.io/api` |
|
|
115
|
+
| Production | `https://live.hyperswitch.io` | `https://live.hyperswitch.io/api` |
|
|
116
|
+
|
|
117
|
+
### Customizing the appearance
|
|
118
|
+
|
|
119
|
+
Pass a theme configuration as `initConfig` to match the components to your brand.
|
|
120
|
+
|
|
121
|
+
```js
|
|
122
|
+
const hyperswitch = loadHyperswitch({
|
|
123
|
+
fetchToken,
|
|
124
|
+
initConfig: {
|
|
125
|
+
primaryColor: '#0066ff',
|
|
126
|
+
backgroundColor: '#ffffff',
|
|
127
|
+
buttons: {
|
|
128
|
+
primary: {
|
|
129
|
+
backgroundColor: '#0066ff',
|
|
130
|
+
textColor: '#ffffff',
|
|
131
|
+
hoverBackgroundColor: '#0052cc',
|
|
132
|
+
},
|
|
133
|
+
secondary: {
|
|
134
|
+
backgroundColor: '#f0f0f0',
|
|
135
|
+
textColor: '#333333',
|
|
136
|
+
hoverBackgroundColor: '#e0e0e0',
|
|
137
|
+
},
|
|
138
|
+
},
|
|
139
|
+
},
|
|
140
|
+
});
|
|
106
141
|
```
|
|
107
142
|
|
|
108
|
-
|
|
109
|
-
|
|
143
|
+
All fields in `initConfig` are optional. Omitted fields use the default Control Center theme. See [`MerchantTheme`](#merchanttheme) for the complete list.
|
|
144
|
+
|
|
145
|
+
### Modals
|
|
146
|
+
|
|
147
|
+
Modals opened inside a component are displayed over the full host page. While a modal is open, the SDK stretches the component's iframe across the window and locks page scrolling, and restores both when the modal closes.
|
|
148
|
+
|
|
149
|
+
To keep modals inside the component, set `fullPageModals` to `false`:
|
|
150
|
+
|
|
151
|
+
```js
|
|
152
|
+
const payments = hyperswitch.create('payments', {
|
|
153
|
+
url: 'https://app.hyperswitch.io',
|
|
154
|
+
fullPageModals: false,
|
|
155
|
+
});
|
|
110
156
|
```
|
|
111
157
|
|
|
158
|
+
Full-page modals rely on `position: fixed`. If an ancestor of the mount point has a CSS `transform`, `filter`, `perspective` or `contain`, or creates a stacking context below other page content, the modal can be clipped or covered. Set `fullPageModals` to `false` in that layout.
|
|
159
|
+
|
|
160
|
+
### Content Security Policy
|
|
161
|
+
|
|
162
|
+
If you have deployed a [Content Security Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP), include the Control Center origin in your `frame-src` directive.
|
|
163
|
+
|
|
112
164
|
## API reference
|
|
113
165
|
|
|
114
166
|
### `loadHyperswitch(options)`
|
|
@@ -117,8 +169,8 @@ Returns a `Hyperswitch` instance.
|
|
|
117
169
|
|
|
118
170
|
| Parameter | Type | Required | Description |
|
|
119
171
|
|-----------|------|----------|-------------|
|
|
120
|
-
| `fetchToken` | `() => Promise<string \| undefined>` | Yes | Async function that fetches the embedded token from your
|
|
121
|
-
| `initConfig` | `MerchantTheme` | No | Theme customization object |
|
|
172
|
+
| `fetchToken` | `() => Promise<string \| undefined>` | Yes | Async function that fetches the embedded token from your server |
|
|
173
|
+
| `initConfig` | [`MerchantTheme`](#merchanttheme) | No | Theme customization object |
|
|
122
174
|
|
|
123
175
|
### `MerchantTheme`
|
|
124
176
|
|
|
@@ -135,23 +187,47 @@ Returns a `Hyperswitch` instance.
|
|
|
135
187
|
| `buttons?.secondary?.textColor?` | `string` | Secondary button text color |
|
|
136
188
|
| `buttons?.secondary?.hoverBackgroundColor?` | `string` | Secondary button hover color |
|
|
137
189
|
|
|
138
|
-
### `
|
|
190
|
+
### `hyperswitch.create(name, options)`
|
|
139
191
|
|
|
140
192
|
Creates a component instance.
|
|
141
193
|
|
|
142
194
|
| Parameter | Type | Description |
|
|
143
195
|
|-----------|------|-------------|
|
|
144
|
-
| `name` | `
|
|
145
|
-
| `options
|
|
196
|
+
| `name` | `'connectors' \| 'payments' \| 'refunds'` | The component to create |
|
|
197
|
+
| `options` | [`ElementOptions`](#elementoptions) | Component options |
|
|
146
198
|
|
|
147
|
-
###
|
|
199
|
+
### `ElementOptions`
|
|
148
200
|
|
|
149
|
-
|
|
201
|
+
| Property | Type | Description |
|
|
202
|
+
|----------|------|-------------|
|
|
203
|
+
| `url` | `string` | Base URL of the Control Center that serves the component |
|
|
204
|
+
| `width?` | `string` | Width of the component container. Defaults to `100%` |
|
|
205
|
+
| `height?` | `string` | Initial height of the component container. The component resizes to fit its content |
|
|
206
|
+
| `className?` | `string` | Additional class names for the component container |
|
|
207
|
+
| `style?` | `Partial<CSSStyleDeclaration>` | Inline styles for the component container |
|
|
208
|
+
| `fullPageModals?` | `boolean` | Display modals over the full host page. Defaults to `true` |
|
|
209
|
+
| `onResize?` | `(dimensions: { width: number; height: number }) => void` | Called when the component is resized |
|
|
150
210
|
|
|
151
|
-
|
|
211
|
+
### `component.mount(target)`
|
|
152
212
|
|
|
153
|
-
|
|
213
|
+
Mounts the component to a DOM element. `target` is a CSS selector or an `HTMLElement`. Returns the component.
|
|
214
|
+
|
|
215
|
+
### `component.destroy()`
|
|
216
|
+
|
|
217
|
+
Removes the component from the page and cleans up its event listeners.
|
|
218
|
+
|
|
219
|
+
## TypeScript support
|
|
220
|
+
|
|
221
|
+
This package includes TypeScript declarations. The following types are exported:
|
|
222
|
+
|
|
223
|
+
```ts
|
|
224
|
+
import type {
|
|
225
|
+
HyperswitchInitOptions,
|
|
226
|
+
ElementOptions,
|
|
227
|
+
MerchantTheme,
|
|
228
|
+
} from '@juspay-tech/hyperswitch-control-center-embed-core';
|
|
229
|
+
```
|
|
154
230
|
|
|
155
231
|
## License
|
|
156
232
|
|
|
157
|
-
MIT
|
|
233
|
+
MIT
|
package/dist/element.d.ts
CHANGED
|
@@ -7,14 +7,23 @@ declare abstract class HyperswitchElement {
|
|
|
7
7
|
protected iframe: HTMLIFrameElement;
|
|
8
8
|
private boundMessageHandler;
|
|
9
9
|
readonly _internalId: string;
|
|
10
|
+
private isFullPage;
|
|
11
|
+
private previousBodyOverflow;
|
|
12
|
+
private showIframeTimer;
|
|
13
|
+
private iframeOrigin;
|
|
10
14
|
constructor(instance: Hyperswitch, options?: ElementOptions);
|
|
11
15
|
private setupElement;
|
|
12
16
|
private setupIframe;
|
|
13
17
|
private handleMessage;
|
|
18
|
+
private setFullPage;
|
|
19
|
+
private showIframe;
|
|
14
20
|
mount(domNode: string | HTMLElement): HyperswitchElement;
|
|
15
21
|
destroy(): void;
|
|
16
22
|
protected abstract getElementType(): string;
|
|
17
23
|
protected abstract getIframeSrc(): string;
|
|
18
24
|
getIframe(): HTMLIFrameElement;
|
|
25
|
+
acceptMessage(event: MessageEvent): boolean;
|
|
26
|
+
postMessageToIframe(message: Record<string, unknown>): void;
|
|
27
|
+
isFullPageModalEnabled(): boolean;
|
|
19
28
|
}
|
|
20
29
|
export { HyperswitchElement };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
export { loadHyperswitch, Hyperswitch } from './hyperswitch';
|
|
2
2
|
export { HyperswitchElement } from './element';
|
|
3
3
|
export { ConnectorConfigurationComponent } from './connector-configuration';
|
|
4
|
+
export { PaymentsComponent } from './payments';
|
|
5
|
+
export { RefundsComponent } from './refunds';
|
|
4
6
|
export type { HyperswitchInitOptions, ElementOptions } from './types';
|
|
5
7
|
export type { MerchantTheme } from './init-config';
|
|
6
8
|
export declare const VERSION = "1.0.0";
|
package/dist/index.esm.js
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
const isBrowser$1 = typeof window !== 'undefined';
|
|
2
2
|
class HyperswitchElement {
|
|
3
3
|
constructor(instance, options) {
|
|
4
|
+
this.isFullPage = false;
|
|
5
|
+
this.previousBodyOverflow = '';
|
|
6
|
+
this.showIframeTimer = null;
|
|
7
|
+
this.iframeOrigin = null;
|
|
4
8
|
this.instance = instance;
|
|
5
9
|
this.options = options || {};
|
|
6
10
|
this._internalId = `hyper-el-${Math.random().toString(36).substring(7)}`;
|
|
@@ -40,17 +44,31 @@ class HyperswitchElement {
|
|
|
40
44
|
this.element.appendChild(this.iframe);
|
|
41
45
|
}
|
|
42
46
|
handleMessage(event) {
|
|
43
|
-
var _a;
|
|
47
|
+
var _a, _b, _c, _d;
|
|
44
48
|
if (!isBrowser$1) {
|
|
45
49
|
return;
|
|
46
50
|
}
|
|
47
51
|
if (this.options.onMessage) {
|
|
48
52
|
this.options.onMessage(event.data);
|
|
49
53
|
}
|
|
50
|
-
if ((
|
|
54
|
+
if (!this.acceptMessage(event)) {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
if (this.isFullPageModalEnabled()) {
|
|
58
|
+
if (((_a = event.data) === null || _a === void 0 ? void 0 : _a.type) === 'EMBEDDED_MODAL_OPEN') {
|
|
59
|
+
this.setFullPage(true);
|
|
60
|
+
}
|
|
61
|
+
else if (((_b = event.data) === null || _b === void 0 ? void 0 : _b.type) === 'EMBEDDED_MODAL_CLOSE') {
|
|
62
|
+
this.setFullPage(false);
|
|
63
|
+
}
|
|
64
|
+
else if (((_c = event.data) === null || _c === void 0 ? void 0 : _c.type) === 'EMBEDDED_MODAL_VISIBLE') {
|
|
65
|
+
this.showIframe();
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
if (((_d = event.data) === null || _d === void 0 ? void 0 : _d.type) === 'EMBEDDED_COMPONENT_RESIZE') {
|
|
51
69
|
const newHeight = event.data.height;
|
|
52
70
|
const messageComponent = event.data.component || '';
|
|
53
|
-
if (messageComponent === this.getElementType() && typeof newHeight === 'number' && newHeight > 0) {
|
|
71
|
+
if (!this.isFullPage && messageComponent === this.getElementType() && typeof newHeight === 'number' && newHeight > 0) {
|
|
54
72
|
this.element.style.height = `${newHeight}px`;
|
|
55
73
|
if (this.options.onResize) {
|
|
56
74
|
this.options.onResize({
|
|
@@ -61,6 +79,49 @@ class HyperswitchElement {
|
|
|
61
79
|
}
|
|
62
80
|
}
|
|
63
81
|
}
|
|
82
|
+
setFullPage(isFullPage) {
|
|
83
|
+
if (isFullPage !== this.isFullPage) {
|
|
84
|
+
this.isFullPage = isFullPage;
|
|
85
|
+
this.iframe.style.visibility = 'hidden';
|
|
86
|
+
if (isFullPage) {
|
|
87
|
+
this.previousBodyOverflow = document.body.style.overflow;
|
|
88
|
+
document.body.style.overflow = 'hidden';
|
|
89
|
+
Object.assign(this.iframe.style, {
|
|
90
|
+
position: 'fixed',
|
|
91
|
+
top: '0',
|
|
92
|
+
left: '0',
|
|
93
|
+
width: '100vw',
|
|
94
|
+
height: '100vh',
|
|
95
|
+
zIndex: '2147483647'
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
document.body.style.overflow = this.previousBodyOverflow;
|
|
100
|
+
Object.assign(this.iframe.style, {
|
|
101
|
+
position: '',
|
|
102
|
+
top: '',
|
|
103
|
+
left: '',
|
|
104
|
+
width: '100%',
|
|
105
|
+
height: '100%',
|
|
106
|
+
zIndex: ''
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
if (this.showIframeTimer) {
|
|
110
|
+
clearTimeout(this.showIframeTimer);
|
|
111
|
+
}
|
|
112
|
+
this.showIframeTimer = setTimeout(() => this.showIframe(), 300);
|
|
113
|
+
}
|
|
114
|
+
this.postMessageToIframe({
|
|
115
|
+
type: isFullPage ? 'EMBEDDED_MODAL_OPENED' : 'EMBEDDED_MODAL_CLOSED'
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
showIframe() {
|
|
119
|
+
if (this.showIframeTimer) {
|
|
120
|
+
clearTimeout(this.showIframeTimer);
|
|
121
|
+
this.showIframeTimer = null;
|
|
122
|
+
}
|
|
123
|
+
this.iframe.style.visibility = '';
|
|
124
|
+
}
|
|
64
125
|
mount(domNode) {
|
|
65
126
|
if (!isBrowser$1) {
|
|
66
127
|
throw new Error('HyperswitchElement.mount can only be called in a browser environment');
|
|
@@ -78,6 +139,14 @@ class HyperswitchElement {
|
|
|
78
139
|
if (!isBrowser$1) {
|
|
79
140
|
return;
|
|
80
141
|
}
|
|
142
|
+
if (this.isFullPage) {
|
|
143
|
+
this.isFullPage = false;
|
|
144
|
+
document.body.style.overflow = this.previousBodyOverflow;
|
|
145
|
+
}
|
|
146
|
+
if (this.showIframeTimer) {
|
|
147
|
+
clearTimeout(this.showIframeTimer);
|
|
148
|
+
this.showIframeTimer = null;
|
|
149
|
+
}
|
|
81
150
|
if (this.boundMessageHandler) {
|
|
82
151
|
window.removeEventListener('message', this.boundMessageHandler);
|
|
83
152
|
}
|
|
@@ -88,6 +157,26 @@ class HyperswitchElement {
|
|
|
88
157
|
getIframe() {
|
|
89
158
|
return this.iframe;
|
|
90
159
|
}
|
|
160
|
+
acceptMessage(event) {
|
|
161
|
+
var _a;
|
|
162
|
+
if (event.source !== ((_a = this.iframe) === null || _a === void 0 ? void 0 : _a.contentWindow)) {
|
|
163
|
+
return false;
|
|
164
|
+
}
|
|
165
|
+
if (this.iframeOrigin === null && event.origin && event.origin !== 'null') {
|
|
166
|
+
this.iframeOrigin = event.origin;
|
|
167
|
+
}
|
|
168
|
+
return this.iframeOrigin === null || event.origin === this.iframeOrigin;
|
|
169
|
+
}
|
|
170
|
+
postMessageToIframe(message) {
|
|
171
|
+
var _a, _b;
|
|
172
|
+
if (this.iframeOrigin === null) {
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
(_b = (_a = this.iframe) === null || _a === void 0 ? void 0 : _a.contentWindow) === null || _b === void 0 ? void 0 : _b.postMessage(message, this.iframeOrigin);
|
|
176
|
+
}
|
|
177
|
+
isFullPageModalEnabled() {
|
|
178
|
+
return this.options.fullPageModals !== false;
|
|
179
|
+
}
|
|
91
180
|
}
|
|
92
181
|
|
|
93
182
|
class ConnectorConfigurationComponent extends HyperswitchElement {
|
|
@@ -103,6 +192,32 @@ class ConnectorConfigurationComponent extends HyperswitchElement {
|
|
|
103
192
|
}
|
|
104
193
|
}
|
|
105
194
|
|
|
195
|
+
class PaymentsComponent extends HyperswitchElement {
|
|
196
|
+
constructor(instance, options) {
|
|
197
|
+
super(instance, options);
|
|
198
|
+
}
|
|
199
|
+
getElementType() {
|
|
200
|
+
return 'payments';
|
|
201
|
+
}
|
|
202
|
+
getIframeSrc() {
|
|
203
|
+
const baseUrl = this.options.url || 'http://localhost:9000';
|
|
204
|
+
return `${baseUrl}/embedded/payments`;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
class RefundsComponent extends HyperswitchElement {
|
|
209
|
+
constructor(instance, options) {
|
|
210
|
+
super(instance, options);
|
|
211
|
+
}
|
|
212
|
+
getElementType() {
|
|
213
|
+
return 'refunds';
|
|
214
|
+
}
|
|
215
|
+
getIframeSrc() {
|
|
216
|
+
const baseUrl = this.options.url || 'http://localhost:9000';
|
|
217
|
+
return `${baseUrl}/embedded/refunds`;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
106
221
|
/**
|
|
107
222
|
* Build the init_config object that Control Center expects
|
|
108
223
|
* from the simple MerchantTheme contract.
|
|
@@ -188,17 +303,15 @@ class Hyperswitch {
|
|
|
188
303
|
}
|
|
189
304
|
window.addEventListener("message", async (event) => {
|
|
190
305
|
var _a, _b, _c;
|
|
306
|
+
const sourceElement = Array.from(this.activeElements.values()).find((element) => element.acceptMessage(event));
|
|
307
|
+
if (!sourceElement) {
|
|
308
|
+
return;
|
|
309
|
+
}
|
|
191
310
|
if (((_a = event.data) === null || _a === void 0 ? void 0 : _a.type) === "TOKEN_EXPIRED" && ((_b = event.data) === null || _b === void 0 ? void 0 : _b.value) === true) {
|
|
192
311
|
await this.refetchAndBroadcastToken();
|
|
193
312
|
}
|
|
194
313
|
else if (((_c = event.data) === null || _c === void 0 ? void 0 : _c.type) === "EMBEDDED_IFRAME_READY") {
|
|
195
|
-
|
|
196
|
-
this.activeElements.forEach((element) => {
|
|
197
|
-
const iframe = element.getIframe();
|
|
198
|
-
if ((iframe === null || iframe === void 0 ? void 0 : iframe.contentWindow) === event.source) {
|
|
199
|
-
this.onElementIframeLoaded(element);
|
|
200
|
-
}
|
|
201
|
-
});
|
|
314
|
+
this.onElementIframeLoaded(sourceElement);
|
|
202
315
|
}
|
|
203
316
|
});
|
|
204
317
|
}
|
|
@@ -212,14 +325,11 @@ class Hyperswitch {
|
|
|
212
325
|
if (newToken) {
|
|
213
326
|
this.token = newToken;
|
|
214
327
|
this.tokenError = null;
|
|
215
|
-
this.activeElements.forEach((element
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
token: this.token
|
|
221
|
-
}, '*');
|
|
222
|
-
}
|
|
328
|
+
this.activeElements.forEach((element) => {
|
|
329
|
+
element.postMessageToIframe({
|
|
330
|
+
type: 'AUTH_TOKEN',
|
|
331
|
+
token: this.token
|
|
332
|
+
});
|
|
223
333
|
});
|
|
224
334
|
}
|
|
225
335
|
else {
|
|
@@ -237,13 +347,10 @@ class Hyperswitch {
|
|
|
237
347
|
}
|
|
238
348
|
sendErrorToActiveElements(errorMessage) {
|
|
239
349
|
this.activeElements.forEach((element) => {
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
error: errorMessage
|
|
245
|
-
}, '*');
|
|
246
|
-
}
|
|
350
|
+
element.postMessageToIframe({
|
|
351
|
+
type: 'AUTH_ERROR',
|
|
352
|
+
error: errorMessage
|
|
353
|
+
});
|
|
247
354
|
});
|
|
248
355
|
}
|
|
249
356
|
create(type, options) {
|
|
@@ -252,6 +359,12 @@ class Hyperswitch {
|
|
|
252
359
|
case 'connectors':
|
|
253
360
|
element = new ConnectorConfigurationComponent(this, options);
|
|
254
361
|
break;
|
|
362
|
+
case 'payments':
|
|
363
|
+
element = new PaymentsComponent(this, options);
|
|
364
|
+
break;
|
|
365
|
+
case 'refunds':
|
|
366
|
+
element = new RefundsComponent(this, options);
|
|
367
|
+
break;
|
|
255
368
|
default:
|
|
256
369
|
throw new Error(`Unknown element type: ${type}`);
|
|
257
370
|
}
|
|
@@ -265,55 +378,47 @@ class Hyperswitch {
|
|
|
265
378
|
return;
|
|
266
379
|
}
|
|
267
380
|
setTimeout(() => {
|
|
381
|
+
var _a;
|
|
268
382
|
try {
|
|
269
|
-
const contentWindow = iframe.contentWindow;
|
|
270
|
-
if (!contentWindow) {
|
|
271
|
-
return;
|
|
272
|
-
}
|
|
273
383
|
if (this.tokenError) {
|
|
274
|
-
|
|
384
|
+
element.postMessageToIframe({
|
|
275
385
|
type: 'AUTH_ERROR',
|
|
276
386
|
error: this.tokenError
|
|
277
|
-
}
|
|
387
|
+
});
|
|
278
388
|
}
|
|
279
389
|
else if (this.token) {
|
|
280
|
-
|
|
390
|
+
element.postMessageToIframe({
|
|
281
391
|
type: 'AUTH_TOKEN',
|
|
282
392
|
token: this.token
|
|
283
|
-
}
|
|
393
|
+
});
|
|
284
394
|
}
|
|
285
395
|
else {
|
|
286
|
-
|
|
396
|
+
element.postMessageToIframe({
|
|
287
397
|
type: 'AUTH_ERROR',
|
|
288
398
|
error: 'No token available'
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
// Send init_config (if available) as a separate message
|
|
292
|
-
if (this.initConfig) {
|
|
293
|
-
contentWindow.postMessage({
|
|
294
|
-
type: 'INIT_CONFIG',
|
|
295
|
-
init_config: this.initConfig
|
|
296
|
-
}, '*');
|
|
399
|
+
});
|
|
297
400
|
}
|
|
401
|
+
// Always send init_config. If merchant doesn't provide it, send an empty object.
|
|
402
|
+
element.postMessageToIframe({
|
|
403
|
+
type: 'INIT_CONFIG',
|
|
404
|
+
init_config: (_a = this.initConfig) !== null && _a !== void 0 ? _a : {},
|
|
405
|
+
sdk_capabilities: { full_page_modal: element.isFullPageModalEnabled() }
|
|
406
|
+
});
|
|
298
407
|
}
|
|
299
408
|
catch (error) {
|
|
300
409
|
}
|
|
301
410
|
}, 100);
|
|
302
411
|
}).catch((error) => {
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
catch (_a) {
|
|
314
|
-
}
|
|
315
|
-
}, 100);
|
|
316
|
-
}
|
|
412
|
+
setTimeout(() => {
|
|
413
|
+
try {
|
|
414
|
+
element.postMessageToIframe({
|
|
415
|
+
type: 'AUTH_ERROR',
|
|
416
|
+
error: `Token initialization failed: ${error instanceof Error ? error.message : String(error)}`
|
|
417
|
+
});
|
|
418
|
+
}
|
|
419
|
+
catch (_a) {
|
|
420
|
+
}
|
|
421
|
+
}, 100);
|
|
317
422
|
});
|
|
318
423
|
}
|
|
319
424
|
}
|
|
@@ -323,5 +428,5 @@ function loadHyperswitch(options) {
|
|
|
323
428
|
|
|
324
429
|
const VERSION = '1.0.0';
|
|
325
430
|
|
|
326
|
-
export { ConnectorConfigurationComponent, Hyperswitch, HyperswitchElement, VERSION, loadHyperswitch };
|
|
431
|
+
export { ConnectorConfigurationComponent, Hyperswitch, HyperswitchElement, PaymentsComponent, RefundsComponent, VERSION, loadHyperswitch };
|
|
327
432
|
//# sourceMappingURL=index.esm.js.map
|