react-paysky-lightbox 0.1.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 +100 -0
- package/dist/index.cjs +244 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +91 -0
- package/dist/index.d.ts +91 -0
- package/dist/index.js +212 -0
- package/dist/index.js.map +1 -0
- package/package.json +50 -0
package/README.md
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# react-paysky-lightbox
|
|
2
|
+
|
|
3
|
+
React hook and button component for **PaySky OMNI Gateway Lightbox**.
|
|
4
|
+
|
|
5
|
+
The package only opens PaySky’s hosted checkout. Your **backend** must create the payment session (including `SecureHash`) and verify the result SecureHash before fulfilling orders.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install react-paysky-lightbox
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Peer dependencies: `react` and `react-dom` ≥ 18.
|
|
14
|
+
|
|
15
|
+
## Quick start — component
|
|
16
|
+
|
|
17
|
+
```tsx
|
|
18
|
+
import { PaySkyCheckout } from 'react-paysky-lightbox';
|
|
19
|
+
|
|
20
|
+
function Checkout() {
|
|
21
|
+
return (
|
|
22
|
+
<PaySkyCheckout
|
|
23
|
+
environment="sandbox"
|
|
24
|
+
session={{
|
|
25
|
+
mid: session.mid,
|
|
26
|
+
tid: session.tid,
|
|
27
|
+
amountTrxn: session.amountTrxn,
|
|
28
|
+
merchantReference: session.merchantReference,
|
|
29
|
+
trxDateTime: session.trxDateTime,
|
|
30
|
+
secureHash: session.secureHash,
|
|
31
|
+
}}
|
|
32
|
+
notifyUrl="https://api.yoursite.com/paysky/notify"
|
|
33
|
+
onSuccess={(data) => console.log('paid', data)}
|
|
34
|
+
onError={(err) => console.error(err)}
|
|
35
|
+
onCancel={() => console.log('cancelled')}
|
|
36
|
+
>
|
|
37
|
+
Pay now
|
|
38
|
+
</PaySkyCheckout>
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Quick start — hook
|
|
44
|
+
|
|
45
|
+
```tsx
|
|
46
|
+
import { usePaySky } from 'react-paysky-lightbox';
|
|
47
|
+
|
|
48
|
+
function CheckoutButton({ session }) {
|
|
49
|
+
const { openPayment, isLoading, error } = usePaySky();
|
|
50
|
+
|
|
51
|
+
return (
|
|
52
|
+
<button
|
|
53
|
+
disabled={isLoading}
|
|
54
|
+
onClick={() =>
|
|
55
|
+
void openPayment({
|
|
56
|
+
environment: 'production',
|
|
57
|
+
session,
|
|
58
|
+
onSuccess: (data) => {
|
|
59
|
+
/* still verify SecureHash on your backend */
|
|
60
|
+
},
|
|
61
|
+
})
|
|
62
|
+
}
|
|
63
|
+
>
|
|
64
|
+
{isLoading ? 'Opening…' : 'Pay'}
|
|
65
|
+
{error ? ` (${error.message})` : null}
|
|
66
|
+
</button>
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Backend responsibilities
|
|
72
|
+
|
|
73
|
+
1. Generate `SecureHash` with your merchant secret (never ship the secret to the browser).
|
|
74
|
+
2. Return session fields: `mid`, `tid`, `amountTrxn`, optional `merchantReference`, `trxDateTime`, `secureHash`.
|
|
75
|
+
3. On success (browser `notifyUrl` and/or PaySky server notification), **re-verify** response `SecureHash` before marking the order paid.
|
|
76
|
+
|
|
77
|
+
Amount is in the **smallest currency unit** (1 EGP = `100`).
|
|
78
|
+
|
|
79
|
+
## Environments
|
|
80
|
+
|
|
81
|
+
| `environment` | Script |
|
|
82
|
+
| --- | --- |
|
|
83
|
+
| `sandbox` (default) | `https://grey.paysky.io:9006/invchost/JS/LightBox.js` |
|
|
84
|
+
| `production` | `https://cube.paysky.io:6006/js/LightBox.js` |
|
|
85
|
+
|
|
86
|
+
Override with `scriptUrl` if PaySky gives you a different host.
|
|
87
|
+
|
|
88
|
+
## Optional notify
|
|
89
|
+
|
|
90
|
+
If you pass `notifyUrl`, the package `POST`s JSON after complete/error:
|
|
91
|
+
|
|
92
|
+
```json
|
|
93
|
+
{ "event": "complete", "data": { /* PaySky callback fields */ } }
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Cancel does not notify. Notify failures call `onNotifyError` and do not change payment success.
|
|
97
|
+
|
|
98
|
+
## License
|
|
99
|
+
|
|
100
|
+
MIT
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
PaySkyCheckout: () => PaySkyCheckout,
|
|
24
|
+
SCRIPT_URLS: () => SCRIPT_URLS,
|
|
25
|
+
closeLightbox: () => closeLightbox,
|
|
26
|
+
openLightbox: () => openLightbox,
|
|
27
|
+
resolveScriptUrl: () => resolveScriptUrl,
|
|
28
|
+
usePaySky: () => usePaySky
|
|
29
|
+
});
|
|
30
|
+
module.exports = __toCommonJS(index_exports);
|
|
31
|
+
|
|
32
|
+
// src/constants.ts
|
|
33
|
+
var SCRIPT_URLS = {
|
|
34
|
+
sandbox: "https://grey.paysky.io:9006/invchost/JS/LightBox.js",
|
|
35
|
+
production: "https://cube.paysky.io:6006/js/LightBox.js"
|
|
36
|
+
};
|
|
37
|
+
function resolveScriptUrl(environment = "sandbox", scriptUrl) {
|
|
38
|
+
return scriptUrl ?? SCRIPT_URLS[environment];
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// src/loadScript.ts
|
|
42
|
+
var loaders = /* @__PURE__ */ new Map();
|
|
43
|
+
function loadPaySkyScript(url) {
|
|
44
|
+
const existing = loaders.get(url);
|
|
45
|
+
if (existing) {
|
|
46
|
+
return existing;
|
|
47
|
+
}
|
|
48
|
+
const promise = new Promise((resolve, reject) => {
|
|
49
|
+
const script = document.createElement("script");
|
|
50
|
+
script.src = url;
|
|
51
|
+
script.async = true;
|
|
52
|
+
script.addEventListener("load", () => resolve(), { once: true });
|
|
53
|
+
script.addEventListener(
|
|
54
|
+
"error",
|
|
55
|
+
() => {
|
|
56
|
+
loaders.delete(url);
|
|
57
|
+
reject(new Error(`Failed to load PaySky Lightbox script: ${url}`));
|
|
58
|
+
},
|
|
59
|
+
{ once: true }
|
|
60
|
+
);
|
|
61
|
+
document.head.appendChild(script);
|
|
62
|
+
});
|
|
63
|
+
loaders.set(url, promise);
|
|
64
|
+
return promise;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// src/notify.ts
|
|
68
|
+
async function postNotify(notifyUrl, payload, headers) {
|
|
69
|
+
const response = await fetch(notifyUrl, {
|
|
70
|
+
method: "POST",
|
|
71
|
+
headers: {
|
|
72
|
+
"Content-Type": "application/json",
|
|
73
|
+
...headers
|
|
74
|
+
},
|
|
75
|
+
body: JSON.stringify(payload)
|
|
76
|
+
});
|
|
77
|
+
if (!response.ok) {
|
|
78
|
+
throw new Error(
|
|
79
|
+
`PaySky notify failed: ${response.status} ${response.statusText}`
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// src/checkout.ts
|
|
85
|
+
var openInProgress = false;
|
|
86
|
+
function assertSession(session) {
|
|
87
|
+
if (!session.mid?.trim()) {
|
|
88
|
+
throw new Error("PaySky session.mid is required");
|
|
89
|
+
}
|
|
90
|
+
if (!session.tid?.trim()) {
|
|
91
|
+
throw new Error("PaySky session.tid is required");
|
|
92
|
+
}
|
|
93
|
+
if (typeof session.amountTrxn !== "number" || !Number.isFinite(session.amountTrxn) || session.amountTrxn <= 0) {
|
|
94
|
+
throw new Error("PaySky session.amountTrxn must be a positive number");
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
function getCheckout() {
|
|
98
|
+
const checkout = window.Lightbox?.Checkout;
|
|
99
|
+
if (!checkout) {
|
|
100
|
+
throw new Error(
|
|
101
|
+
"PaySky Lightbox is not available on window.Lightbox after script load"
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
return checkout;
|
|
105
|
+
}
|
|
106
|
+
async function openLightbox(options) {
|
|
107
|
+
const {
|
|
108
|
+
session,
|
|
109
|
+
environment = "sandbox",
|
|
110
|
+
scriptUrl,
|
|
111
|
+
notifyUrl,
|
|
112
|
+
notifyHeaders,
|
|
113
|
+
onSuccess,
|
|
114
|
+
onError,
|
|
115
|
+
onCancel,
|
|
116
|
+
onNotifyError
|
|
117
|
+
} = options;
|
|
118
|
+
assertSession(session);
|
|
119
|
+
if (openInProgress) {
|
|
120
|
+
throw new Error("PaySky Lightbox is already open");
|
|
121
|
+
}
|
|
122
|
+
const url = resolveScriptUrl(environment, scriptUrl);
|
|
123
|
+
await loadPaySkyScript(url);
|
|
124
|
+
const checkout = getCheckout();
|
|
125
|
+
openInProgress = true;
|
|
126
|
+
const safeNotify = (event, data) => {
|
|
127
|
+
if (!notifyUrl) return;
|
|
128
|
+
void postNotify(notifyUrl, { event, data }, notifyHeaders).catch(
|
|
129
|
+
(error) => {
|
|
130
|
+
onNotifyError?.(error);
|
|
131
|
+
}
|
|
132
|
+
);
|
|
133
|
+
};
|
|
134
|
+
checkout.configure = {
|
|
135
|
+
MID: session.mid,
|
|
136
|
+
TID: session.tid,
|
|
137
|
+
AmountTrxn: session.amountTrxn,
|
|
138
|
+
...session.merchantReference != null ? { MerchantReference: session.merchantReference } : {},
|
|
139
|
+
...session.trxDateTime != null ? { TrxDateTime: session.trxDateTime } : {},
|
|
140
|
+
...session.secureHash != null ? { SecureHash: session.secureHash } : {},
|
|
141
|
+
completeCallback: (data) => {
|
|
142
|
+
openInProgress = false;
|
|
143
|
+
onSuccess?.(data);
|
|
144
|
+
safeNotify("complete", data);
|
|
145
|
+
},
|
|
146
|
+
errorCallback: (error) => {
|
|
147
|
+
openInProgress = false;
|
|
148
|
+
onError?.(error);
|
|
149
|
+
safeNotify("error", error);
|
|
150
|
+
},
|
|
151
|
+
cancelCallback: () => {
|
|
152
|
+
openInProgress = false;
|
|
153
|
+
onCancel?.();
|
|
154
|
+
}
|
|
155
|
+
};
|
|
156
|
+
checkout.showLightbox();
|
|
157
|
+
}
|
|
158
|
+
function closeLightbox() {
|
|
159
|
+
openInProgress = false;
|
|
160
|
+
window.Lightbox?.Checkout?.closeLightbox();
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// src/usePaySky.ts
|
|
164
|
+
var import_react = require("react");
|
|
165
|
+
function usePaySky() {
|
|
166
|
+
const [isOpen, setIsOpen] = (0, import_react.useState)(false);
|
|
167
|
+
const [isLoading, setIsLoading] = (0, import_react.useState)(false);
|
|
168
|
+
const [error, setError] = (0, import_react.useState)(null);
|
|
169
|
+
const closePayment = (0, import_react.useCallback)(() => {
|
|
170
|
+
closeLightbox();
|
|
171
|
+
setIsOpen(false);
|
|
172
|
+
}, []);
|
|
173
|
+
const openPayment = (0, import_react.useCallback)(async (options) => {
|
|
174
|
+
setIsLoading(true);
|
|
175
|
+
setError(null);
|
|
176
|
+
try {
|
|
177
|
+
await openLightbox({
|
|
178
|
+
...options,
|
|
179
|
+
onSuccess: (data) => {
|
|
180
|
+
setIsOpen(false);
|
|
181
|
+
options.onSuccess?.(data);
|
|
182
|
+
},
|
|
183
|
+
onError: (err) => {
|
|
184
|
+
setIsOpen(false);
|
|
185
|
+
options.onError?.(err);
|
|
186
|
+
},
|
|
187
|
+
onCancel: () => {
|
|
188
|
+
setIsOpen(false);
|
|
189
|
+
options.onCancel?.();
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
setIsOpen(true);
|
|
193
|
+
} catch (err) {
|
|
194
|
+
const next = err instanceof Error ? err : new Error("Failed to open PaySky Lightbox");
|
|
195
|
+
setError(next);
|
|
196
|
+
setIsOpen(false);
|
|
197
|
+
throw next;
|
|
198
|
+
} finally {
|
|
199
|
+
setIsLoading(false);
|
|
200
|
+
}
|
|
201
|
+
}, []);
|
|
202
|
+
return {
|
|
203
|
+
openPayment,
|
|
204
|
+
closePayment,
|
|
205
|
+
isOpen,
|
|
206
|
+
isLoading,
|
|
207
|
+
error
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// src/PaySkyCheckout.tsx
|
|
212
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
213
|
+
function PaySkyCheckout({
|
|
214
|
+
children = "Pay with PaySky",
|
|
215
|
+
className,
|
|
216
|
+
disabled,
|
|
217
|
+
...options
|
|
218
|
+
}) {
|
|
219
|
+
const { openPayment, isLoading, error } = usePaySky();
|
|
220
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
221
|
+
"button",
|
|
222
|
+
{
|
|
223
|
+
type: "button",
|
|
224
|
+
className,
|
|
225
|
+
disabled: disabled || isLoading,
|
|
226
|
+
"aria-busy": isLoading || void 0,
|
|
227
|
+
"data-error": error ? error.message : void 0,
|
|
228
|
+
onClick: () => {
|
|
229
|
+
void openPayment(options);
|
|
230
|
+
},
|
|
231
|
+
children
|
|
232
|
+
}
|
|
233
|
+
);
|
|
234
|
+
}
|
|
235
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
236
|
+
0 && (module.exports = {
|
|
237
|
+
PaySkyCheckout,
|
|
238
|
+
SCRIPT_URLS,
|
|
239
|
+
closeLightbox,
|
|
240
|
+
openLightbox,
|
|
241
|
+
resolveScriptUrl,
|
|
242
|
+
usePaySky
|
|
243
|
+
});
|
|
244
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/constants.ts","../src/loadScript.ts","../src/notify.ts","../src/checkout.ts","../src/usePaySky.ts","../src/PaySkyCheckout.tsx"],"sourcesContent":["export { SCRIPT_URLS, resolveScriptUrl } from './constants';\r\nexport { openLightbox, closeLightbox } from './checkout';\r\nexport { usePaySky } from './usePaySky';\r\nexport type { UsePaySkyResult } from './usePaySky';\r\nexport { PaySkyCheckout } from './PaySkyCheckout';\r\nexport type {\r\n PaySkyEnvironment,\r\n PaySkySession,\r\n PaySkyCompleteData,\r\n PaySkyErrorData,\r\n PaySkyNotifyEvent,\r\n PaySkyNotifyPayload,\r\n PaySkyOpenOptions,\r\n PaySkyCheckoutProps,\r\n} from './types';\r\n","import type { PaySkyEnvironment } from './types';\r\n\r\nexport const SCRIPT_URLS: Record<PaySkyEnvironment, string> = {\r\n sandbox: 'https://grey.paysky.io:9006/invchost/JS/LightBox.js',\r\n production: 'https://cube.paysky.io:6006/js/LightBox.js',\r\n};\r\n\r\nexport function resolveScriptUrl(\r\n environment: PaySkyEnvironment = 'sandbox',\r\n scriptUrl?: string,\r\n): string {\r\n return scriptUrl ?? SCRIPT_URLS[environment];\r\n}\r\n","const loaders = new Map<string, Promise<void>>();\r\n\r\nexport function loadPaySkyScript(url: string): Promise<void> {\r\n const existing = loaders.get(url);\r\n if (existing) {\r\n return existing;\r\n }\r\n\r\n const promise = new Promise<void>((resolve, reject) => {\r\n const script = document.createElement('script');\r\n script.src = url;\r\n script.async = true;\r\n\r\n script.addEventListener('load', () => resolve(), { once: true });\r\n script.addEventListener(\r\n 'error',\r\n () => {\r\n loaders.delete(url);\r\n reject(new Error(`Failed to load PaySky Lightbox script: ${url}`));\r\n },\r\n { once: true },\r\n );\r\n\r\n document.head.appendChild(script);\r\n });\r\n\r\n loaders.set(url, promise);\r\n return promise;\r\n}\r\n\r\n/** Test helper — clears cached loaders between tests. */\r\nexport function __resetPaySkyScriptLoaders(): void {\r\n loaders.clear();\r\n}\r\n","import type { PaySkyNotifyPayload } from './types';\r\n\r\nexport async function postNotify(\r\n notifyUrl: string,\r\n payload: PaySkyNotifyPayload,\r\n headers?: Record<string, string>,\r\n): Promise<void> {\r\n const response = await fetch(notifyUrl, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n ...headers,\r\n },\r\n body: JSON.stringify(payload),\r\n });\r\n\r\n if (!response.ok) {\r\n throw new Error(\r\n `PaySky notify failed: ${response.status} ${response.statusText}`,\r\n );\r\n }\r\n}\r\n","import { resolveScriptUrl } from './constants';\r\nimport { loadPaySkyScript } from './loadScript';\r\nimport { postNotify } from './notify';\r\nimport type {\r\n PaySkyCompleteData,\r\n PaySkyErrorData,\r\n PaySkyOpenOptions,\r\n PaySkySession,\r\n} from './types';\r\n\r\nlet openInProgress = false;\r\n\r\nfunction assertSession(session: PaySkySession): void {\r\n if (!session.mid?.trim()) {\r\n throw new Error('PaySky session.mid is required');\r\n }\r\n if (!session.tid?.trim()) {\r\n throw new Error('PaySky session.tid is required');\r\n }\r\n if (\r\n typeof session.amountTrxn !== 'number' ||\r\n !Number.isFinite(session.amountTrxn) ||\r\n session.amountTrxn <= 0\r\n ) {\r\n throw new Error('PaySky session.amountTrxn must be a positive number');\r\n }\r\n}\r\n\r\nfunction getCheckout() {\r\n const checkout = window.Lightbox?.Checkout;\r\n if (!checkout) {\r\n throw new Error(\r\n 'PaySky Lightbox is not available on window.Lightbox after script load',\r\n );\r\n }\r\n return checkout;\r\n}\r\n\r\nexport async function openLightbox(options: PaySkyOpenOptions): Promise<void> {\r\n const {\r\n session,\r\n environment = 'sandbox',\r\n scriptUrl,\r\n notifyUrl,\r\n notifyHeaders,\r\n onSuccess,\r\n onError,\r\n onCancel,\r\n onNotifyError,\r\n } = options;\r\n\r\n assertSession(session);\r\n\r\n if (openInProgress) {\r\n throw new Error('PaySky Lightbox is already open');\r\n }\r\n\r\n const url = resolveScriptUrl(environment, scriptUrl);\r\n await loadPaySkyScript(url);\r\n\r\n const checkout = getCheckout();\r\n\r\n openInProgress = true;\r\n\r\n const safeNotify = (\r\n event: 'complete' | 'error',\r\n data: PaySkyCompleteData | PaySkyErrorData,\r\n ) => {\r\n if (!notifyUrl) return;\r\n void postNotify(notifyUrl, { event, data }, notifyHeaders).catch(\r\n (error) => {\r\n onNotifyError?.(error);\r\n },\r\n );\r\n };\r\n\r\n checkout.configure = {\r\n MID: session.mid,\r\n TID: session.tid,\r\n AmountTrxn: session.amountTrxn,\r\n ...(session.merchantReference != null\r\n ? { MerchantReference: session.merchantReference }\r\n : {}),\r\n ...(session.trxDateTime != null ? { TrxDateTime: session.trxDateTime } : {}),\r\n ...(session.secureHash != null ? { SecureHash: session.secureHash } : {}),\r\n completeCallback: (data: PaySkyCompleteData) => {\r\n openInProgress = false;\r\n onSuccess?.(data);\r\n safeNotify('complete', data);\r\n },\r\n errorCallback: (error: PaySkyErrorData) => {\r\n openInProgress = false;\r\n onError?.(error);\r\n safeNotify('error', error);\r\n },\r\n cancelCallback: () => {\r\n openInProgress = false;\r\n onCancel?.();\r\n },\r\n };\r\n\r\n checkout.showLightbox();\r\n}\r\n\r\nexport function closeLightbox(): void {\r\n openInProgress = false;\r\n window.Lightbox?.Checkout?.closeLightbox();\r\n}\r\n\r\n/** Test helper */\r\nexport function __resetCheckoutOpenState(): void {\r\n openInProgress = false;\r\n}\r\n","import { useCallback, useState } from 'react';\r\nimport { closeLightbox, openLightbox } from './checkout';\r\nimport type { PaySkyOpenOptions } from './types';\r\n\r\nexport interface UsePaySkyResult {\r\n openPayment: (options: PaySkyOpenOptions) => Promise<void>;\r\n closePayment: () => void;\r\n isOpen: boolean;\r\n isLoading: boolean;\r\n error: Error | null;\r\n}\r\n\r\nexport function usePaySky(): UsePaySkyResult {\r\n const [isOpen, setIsOpen] = useState(false);\r\n const [isLoading, setIsLoading] = useState(false);\r\n const [error, setError] = useState<Error | null>(null);\r\n\r\n const closePayment = useCallback(() => {\r\n closeLightbox();\r\n setIsOpen(false);\r\n }, []);\r\n\r\n const openPayment = useCallback(async (options: PaySkyOpenOptions) => {\r\n setIsLoading(true);\r\n setError(null);\r\n\r\n try {\r\n await openLightbox({\r\n ...options,\r\n onSuccess: (data) => {\r\n setIsOpen(false);\r\n options.onSuccess?.(data);\r\n },\r\n onError: (err) => {\r\n setIsOpen(false);\r\n options.onError?.(err);\r\n },\r\n onCancel: () => {\r\n setIsOpen(false);\r\n options.onCancel?.();\r\n },\r\n });\r\n setIsOpen(true);\r\n } catch (err) {\r\n const next =\r\n err instanceof Error ? err : new Error('Failed to open PaySky Lightbox');\r\n setError(next);\r\n setIsOpen(false);\r\n throw next;\r\n } finally {\r\n setIsLoading(false);\r\n }\r\n }, []);\r\n\r\n return {\r\n openPayment,\r\n closePayment,\r\n isOpen,\r\n isLoading,\r\n error,\r\n };\r\n}\r\n","import type { PaySkyCheckoutProps } from './types';\r\nimport { usePaySky } from './usePaySky';\r\n\r\nexport function PaySkyCheckout({\r\n children = 'Pay with PaySky',\r\n className,\r\n disabled,\r\n ...options\r\n}: PaySkyCheckoutProps) {\r\n const { openPayment, isLoading, error } = usePaySky();\r\n\r\n return (\r\n <button\r\n type=\"button\"\r\n className={className}\r\n disabled={disabled || isLoading}\r\n aria-busy={isLoading || undefined}\r\n data-error={error ? error.message : undefined}\r\n onClick={() => {\r\n void openPayment(options);\r\n }}\r\n >\r\n {children}\r\n </button>\r\n );\r\n}\r\n"],"mappings":"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","names":[]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
|
|
4
|
+
type PaySkyEnvironment = 'sandbox' | 'production';
|
|
5
|
+
/** Payment session prepared by the merchant backend (includes SecureHash). */
|
|
6
|
+
interface PaySkySession {
|
|
7
|
+
mid: string;
|
|
8
|
+
tid: string;
|
|
9
|
+
/** Amount in smallest currency unit (e.g. 100 = 1 EGP). */
|
|
10
|
+
amountTrxn: number;
|
|
11
|
+
merchantReference?: string;
|
|
12
|
+
/** Format yyyyMMddHHmm — required when secureHash is sent. */
|
|
13
|
+
trxDateTime?: string;
|
|
14
|
+
secureHash?: string;
|
|
15
|
+
}
|
|
16
|
+
interface PaySkyCompleteData {
|
|
17
|
+
TxnDate: string;
|
|
18
|
+
SystemReference: string;
|
|
19
|
+
NetworkReference: string;
|
|
20
|
+
MerchantReference?: string;
|
|
21
|
+
Amount: string;
|
|
22
|
+
Currency: string;
|
|
23
|
+
PaidThrough: string;
|
|
24
|
+
PayerAccount: string;
|
|
25
|
+
PayerName?: string;
|
|
26
|
+
ProviderSchemeName?: string;
|
|
27
|
+
SecureHash: string;
|
|
28
|
+
}
|
|
29
|
+
interface PaySkyErrorData {
|
|
30
|
+
error: string;
|
|
31
|
+
DateTimeLocalTrxn: string;
|
|
32
|
+
MerchantReference?: string;
|
|
33
|
+
Amount?: string;
|
|
34
|
+
SecureHash: string;
|
|
35
|
+
}
|
|
36
|
+
type PaySkyNotifyEvent = 'complete' | 'error';
|
|
37
|
+
interface PaySkyNotifyPayload {
|
|
38
|
+
event: PaySkyNotifyEvent;
|
|
39
|
+
data: PaySkyCompleteData | PaySkyErrorData;
|
|
40
|
+
}
|
|
41
|
+
interface PaySkyOpenOptions {
|
|
42
|
+
session: PaySkySession;
|
|
43
|
+
environment?: PaySkyEnvironment;
|
|
44
|
+
/** Overrides the default sandbox/production script URL. */
|
|
45
|
+
scriptUrl?: string;
|
|
46
|
+
/** Optional merchant backend URL to POST callback payloads. */
|
|
47
|
+
notifyUrl?: string;
|
|
48
|
+
notifyHeaders?: Record<string, string>;
|
|
49
|
+
onSuccess?: (data: PaySkyCompleteData) => void;
|
|
50
|
+
onError?: (error: PaySkyErrorData) => void;
|
|
51
|
+
onCancel?: () => void;
|
|
52
|
+
onNotifyError?: (error: unknown) => void;
|
|
53
|
+
}
|
|
54
|
+
interface PaySkyCheckoutProps extends PaySkyOpenOptions {
|
|
55
|
+
children?: ReactNode;
|
|
56
|
+
className?: string;
|
|
57
|
+
disabled?: boolean;
|
|
58
|
+
}
|
|
59
|
+
/** Minimal typing for the global PaySky Lightbox script. */
|
|
60
|
+
interface PaySkyLightboxCheckout {
|
|
61
|
+
configure: Record<string, unknown>;
|
|
62
|
+
showLightbox: () => void;
|
|
63
|
+
closeLightbox: () => void;
|
|
64
|
+
}
|
|
65
|
+
interface PaySkyLightboxGlobal {
|
|
66
|
+
Checkout: PaySkyLightboxCheckout;
|
|
67
|
+
}
|
|
68
|
+
declare global {
|
|
69
|
+
interface Window {
|
|
70
|
+
Lightbox?: PaySkyLightboxGlobal;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
declare const SCRIPT_URLS: Record<PaySkyEnvironment, string>;
|
|
75
|
+
declare function resolveScriptUrl(environment?: PaySkyEnvironment, scriptUrl?: string): string;
|
|
76
|
+
|
|
77
|
+
declare function openLightbox(options: PaySkyOpenOptions): Promise<void>;
|
|
78
|
+
declare function closeLightbox(): void;
|
|
79
|
+
|
|
80
|
+
interface UsePaySkyResult {
|
|
81
|
+
openPayment: (options: PaySkyOpenOptions) => Promise<void>;
|
|
82
|
+
closePayment: () => void;
|
|
83
|
+
isOpen: boolean;
|
|
84
|
+
isLoading: boolean;
|
|
85
|
+
error: Error | null;
|
|
86
|
+
}
|
|
87
|
+
declare function usePaySky(): UsePaySkyResult;
|
|
88
|
+
|
|
89
|
+
declare function PaySkyCheckout({ children, className, disabled, ...options }: PaySkyCheckoutProps): react.JSX.Element;
|
|
90
|
+
|
|
91
|
+
export { PaySkyCheckout, type PaySkyCheckoutProps, type PaySkyCompleteData, type PaySkyEnvironment, type PaySkyErrorData, type PaySkyNotifyEvent, type PaySkyNotifyPayload, type PaySkyOpenOptions, type PaySkySession, SCRIPT_URLS, type UsePaySkyResult, closeLightbox, openLightbox, resolveScriptUrl, usePaySky };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
|
|
4
|
+
type PaySkyEnvironment = 'sandbox' | 'production';
|
|
5
|
+
/** Payment session prepared by the merchant backend (includes SecureHash). */
|
|
6
|
+
interface PaySkySession {
|
|
7
|
+
mid: string;
|
|
8
|
+
tid: string;
|
|
9
|
+
/** Amount in smallest currency unit (e.g. 100 = 1 EGP). */
|
|
10
|
+
amountTrxn: number;
|
|
11
|
+
merchantReference?: string;
|
|
12
|
+
/** Format yyyyMMddHHmm — required when secureHash is sent. */
|
|
13
|
+
trxDateTime?: string;
|
|
14
|
+
secureHash?: string;
|
|
15
|
+
}
|
|
16
|
+
interface PaySkyCompleteData {
|
|
17
|
+
TxnDate: string;
|
|
18
|
+
SystemReference: string;
|
|
19
|
+
NetworkReference: string;
|
|
20
|
+
MerchantReference?: string;
|
|
21
|
+
Amount: string;
|
|
22
|
+
Currency: string;
|
|
23
|
+
PaidThrough: string;
|
|
24
|
+
PayerAccount: string;
|
|
25
|
+
PayerName?: string;
|
|
26
|
+
ProviderSchemeName?: string;
|
|
27
|
+
SecureHash: string;
|
|
28
|
+
}
|
|
29
|
+
interface PaySkyErrorData {
|
|
30
|
+
error: string;
|
|
31
|
+
DateTimeLocalTrxn: string;
|
|
32
|
+
MerchantReference?: string;
|
|
33
|
+
Amount?: string;
|
|
34
|
+
SecureHash: string;
|
|
35
|
+
}
|
|
36
|
+
type PaySkyNotifyEvent = 'complete' | 'error';
|
|
37
|
+
interface PaySkyNotifyPayload {
|
|
38
|
+
event: PaySkyNotifyEvent;
|
|
39
|
+
data: PaySkyCompleteData | PaySkyErrorData;
|
|
40
|
+
}
|
|
41
|
+
interface PaySkyOpenOptions {
|
|
42
|
+
session: PaySkySession;
|
|
43
|
+
environment?: PaySkyEnvironment;
|
|
44
|
+
/** Overrides the default sandbox/production script URL. */
|
|
45
|
+
scriptUrl?: string;
|
|
46
|
+
/** Optional merchant backend URL to POST callback payloads. */
|
|
47
|
+
notifyUrl?: string;
|
|
48
|
+
notifyHeaders?: Record<string, string>;
|
|
49
|
+
onSuccess?: (data: PaySkyCompleteData) => void;
|
|
50
|
+
onError?: (error: PaySkyErrorData) => void;
|
|
51
|
+
onCancel?: () => void;
|
|
52
|
+
onNotifyError?: (error: unknown) => void;
|
|
53
|
+
}
|
|
54
|
+
interface PaySkyCheckoutProps extends PaySkyOpenOptions {
|
|
55
|
+
children?: ReactNode;
|
|
56
|
+
className?: string;
|
|
57
|
+
disabled?: boolean;
|
|
58
|
+
}
|
|
59
|
+
/** Minimal typing for the global PaySky Lightbox script. */
|
|
60
|
+
interface PaySkyLightboxCheckout {
|
|
61
|
+
configure: Record<string, unknown>;
|
|
62
|
+
showLightbox: () => void;
|
|
63
|
+
closeLightbox: () => void;
|
|
64
|
+
}
|
|
65
|
+
interface PaySkyLightboxGlobal {
|
|
66
|
+
Checkout: PaySkyLightboxCheckout;
|
|
67
|
+
}
|
|
68
|
+
declare global {
|
|
69
|
+
interface Window {
|
|
70
|
+
Lightbox?: PaySkyLightboxGlobal;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
declare const SCRIPT_URLS: Record<PaySkyEnvironment, string>;
|
|
75
|
+
declare function resolveScriptUrl(environment?: PaySkyEnvironment, scriptUrl?: string): string;
|
|
76
|
+
|
|
77
|
+
declare function openLightbox(options: PaySkyOpenOptions): Promise<void>;
|
|
78
|
+
declare function closeLightbox(): void;
|
|
79
|
+
|
|
80
|
+
interface UsePaySkyResult {
|
|
81
|
+
openPayment: (options: PaySkyOpenOptions) => Promise<void>;
|
|
82
|
+
closePayment: () => void;
|
|
83
|
+
isOpen: boolean;
|
|
84
|
+
isLoading: boolean;
|
|
85
|
+
error: Error | null;
|
|
86
|
+
}
|
|
87
|
+
declare function usePaySky(): UsePaySkyResult;
|
|
88
|
+
|
|
89
|
+
declare function PaySkyCheckout({ children, className, disabled, ...options }: PaySkyCheckoutProps): react.JSX.Element;
|
|
90
|
+
|
|
91
|
+
export { PaySkyCheckout, type PaySkyCheckoutProps, type PaySkyCompleteData, type PaySkyEnvironment, type PaySkyErrorData, type PaySkyNotifyEvent, type PaySkyNotifyPayload, type PaySkyOpenOptions, type PaySkySession, SCRIPT_URLS, type UsePaySkyResult, closeLightbox, openLightbox, resolveScriptUrl, usePaySky };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
// src/constants.ts
|
|
2
|
+
var SCRIPT_URLS = {
|
|
3
|
+
sandbox: "https://grey.paysky.io:9006/invchost/JS/LightBox.js",
|
|
4
|
+
production: "https://cube.paysky.io:6006/js/LightBox.js"
|
|
5
|
+
};
|
|
6
|
+
function resolveScriptUrl(environment = "sandbox", scriptUrl) {
|
|
7
|
+
return scriptUrl ?? SCRIPT_URLS[environment];
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// src/loadScript.ts
|
|
11
|
+
var loaders = /* @__PURE__ */ new Map();
|
|
12
|
+
function loadPaySkyScript(url) {
|
|
13
|
+
const existing = loaders.get(url);
|
|
14
|
+
if (existing) {
|
|
15
|
+
return existing;
|
|
16
|
+
}
|
|
17
|
+
const promise = new Promise((resolve, reject) => {
|
|
18
|
+
const script = document.createElement("script");
|
|
19
|
+
script.src = url;
|
|
20
|
+
script.async = true;
|
|
21
|
+
script.addEventListener("load", () => resolve(), { once: true });
|
|
22
|
+
script.addEventListener(
|
|
23
|
+
"error",
|
|
24
|
+
() => {
|
|
25
|
+
loaders.delete(url);
|
|
26
|
+
reject(new Error(`Failed to load PaySky Lightbox script: ${url}`));
|
|
27
|
+
},
|
|
28
|
+
{ once: true }
|
|
29
|
+
);
|
|
30
|
+
document.head.appendChild(script);
|
|
31
|
+
});
|
|
32
|
+
loaders.set(url, promise);
|
|
33
|
+
return promise;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// src/notify.ts
|
|
37
|
+
async function postNotify(notifyUrl, payload, headers) {
|
|
38
|
+
const response = await fetch(notifyUrl, {
|
|
39
|
+
method: "POST",
|
|
40
|
+
headers: {
|
|
41
|
+
"Content-Type": "application/json",
|
|
42
|
+
...headers
|
|
43
|
+
},
|
|
44
|
+
body: JSON.stringify(payload)
|
|
45
|
+
});
|
|
46
|
+
if (!response.ok) {
|
|
47
|
+
throw new Error(
|
|
48
|
+
`PaySky notify failed: ${response.status} ${response.statusText}`
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// src/checkout.ts
|
|
54
|
+
var openInProgress = false;
|
|
55
|
+
function assertSession(session) {
|
|
56
|
+
if (!session.mid?.trim()) {
|
|
57
|
+
throw new Error("PaySky session.mid is required");
|
|
58
|
+
}
|
|
59
|
+
if (!session.tid?.trim()) {
|
|
60
|
+
throw new Error("PaySky session.tid is required");
|
|
61
|
+
}
|
|
62
|
+
if (typeof session.amountTrxn !== "number" || !Number.isFinite(session.amountTrxn) || session.amountTrxn <= 0) {
|
|
63
|
+
throw new Error("PaySky session.amountTrxn must be a positive number");
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
function getCheckout() {
|
|
67
|
+
const checkout = window.Lightbox?.Checkout;
|
|
68
|
+
if (!checkout) {
|
|
69
|
+
throw new Error(
|
|
70
|
+
"PaySky Lightbox is not available on window.Lightbox after script load"
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
return checkout;
|
|
74
|
+
}
|
|
75
|
+
async function openLightbox(options) {
|
|
76
|
+
const {
|
|
77
|
+
session,
|
|
78
|
+
environment = "sandbox",
|
|
79
|
+
scriptUrl,
|
|
80
|
+
notifyUrl,
|
|
81
|
+
notifyHeaders,
|
|
82
|
+
onSuccess,
|
|
83
|
+
onError,
|
|
84
|
+
onCancel,
|
|
85
|
+
onNotifyError
|
|
86
|
+
} = options;
|
|
87
|
+
assertSession(session);
|
|
88
|
+
if (openInProgress) {
|
|
89
|
+
throw new Error("PaySky Lightbox is already open");
|
|
90
|
+
}
|
|
91
|
+
const url = resolveScriptUrl(environment, scriptUrl);
|
|
92
|
+
await loadPaySkyScript(url);
|
|
93
|
+
const checkout = getCheckout();
|
|
94
|
+
openInProgress = true;
|
|
95
|
+
const safeNotify = (event, data) => {
|
|
96
|
+
if (!notifyUrl) return;
|
|
97
|
+
void postNotify(notifyUrl, { event, data }, notifyHeaders).catch(
|
|
98
|
+
(error) => {
|
|
99
|
+
onNotifyError?.(error);
|
|
100
|
+
}
|
|
101
|
+
);
|
|
102
|
+
};
|
|
103
|
+
checkout.configure = {
|
|
104
|
+
MID: session.mid,
|
|
105
|
+
TID: session.tid,
|
|
106
|
+
AmountTrxn: session.amountTrxn,
|
|
107
|
+
...session.merchantReference != null ? { MerchantReference: session.merchantReference } : {},
|
|
108
|
+
...session.trxDateTime != null ? { TrxDateTime: session.trxDateTime } : {},
|
|
109
|
+
...session.secureHash != null ? { SecureHash: session.secureHash } : {},
|
|
110
|
+
completeCallback: (data) => {
|
|
111
|
+
openInProgress = false;
|
|
112
|
+
onSuccess?.(data);
|
|
113
|
+
safeNotify("complete", data);
|
|
114
|
+
},
|
|
115
|
+
errorCallback: (error) => {
|
|
116
|
+
openInProgress = false;
|
|
117
|
+
onError?.(error);
|
|
118
|
+
safeNotify("error", error);
|
|
119
|
+
},
|
|
120
|
+
cancelCallback: () => {
|
|
121
|
+
openInProgress = false;
|
|
122
|
+
onCancel?.();
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
checkout.showLightbox();
|
|
126
|
+
}
|
|
127
|
+
function closeLightbox() {
|
|
128
|
+
openInProgress = false;
|
|
129
|
+
window.Lightbox?.Checkout?.closeLightbox();
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// src/usePaySky.ts
|
|
133
|
+
import { useCallback, useState } from "react";
|
|
134
|
+
function usePaySky() {
|
|
135
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
136
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
137
|
+
const [error, setError] = useState(null);
|
|
138
|
+
const closePayment = useCallback(() => {
|
|
139
|
+
closeLightbox();
|
|
140
|
+
setIsOpen(false);
|
|
141
|
+
}, []);
|
|
142
|
+
const openPayment = useCallback(async (options) => {
|
|
143
|
+
setIsLoading(true);
|
|
144
|
+
setError(null);
|
|
145
|
+
try {
|
|
146
|
+
await openLightbox({
|
|
147
|
+
...options,
|
|
148
|
+
onSuccess: (data) => {
|
|
149
|
+
setIsOpen(false);
|
|
150
|
+
options.onSuccess?.(data);
|
|
151
|
+
},
|
|
152
|
+
onError: (err) => {
|
|
153
|
+
setIsOpen(false);
|
|
154
|
+
options.onError?.(err);
|
|
155
|
+
},
|
|
156
|
+
onCancel: () => {
|
|
157
|
+
setIsOpen(false);
|
|
158
|
+
options.onCancel?.();
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
setIsOpen(true);
|
|
162
|
+
} catch (err) {
|
|
163
|
+
const next = err instanceof Error ? err : new Error("Failed to open PaySky Lightbox");
|
|
164
|
+
setError(next);
|
|
165
|
+
setIsOpen(false);
|
|
166
|
+
throw next;
|
|
167
|
+
} finally {
|
|
168
|
+
setIsLoading(false);
|
|
169
|
+
}
|
|
170
|
+
}, []);
|
|
171
|
+
return {
|
|
172
|
+
openPayment,
|
|
173
|
+
closePayment,
|
|
174
|
+
isOpen,
|
|
175
|
+
isLoading,
|
|
176
|
+
error
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// src/PaySkyCheckout.tsx
|
|
181
|
+
import { jsx } from "react/jsx-runtime";
|
|
182
|
+
function PaySkyCheckout({
|
|
183
|
+
children = "Pay with PaySky",
|
|
184
|
+
className,
|
|
185
|
+
disabled,
|
|
186
|
+
...options
|
|
187
|
+
}) {
|
|
188
|
+
const { openPayment, isLoading, error } = usePaySky();
|
|
189
|
+
return /* @__PURE__ */ jsx(
|
|
190
|
+
"button",
|
|
191
|
+
{
|
|
192
|
+
type: "button",
|
|
193
|
+
className,
|
|
194
|
+
disabled: disabled || isLoading,
|
|
195
|
+
"aria-busy": isLoading || void 0,
|
|
196
|
+
"data-error": error ? error.message : void 0,
|
|
197
|
+
onClick: () => {
|
|
198
|
+
void openPayment(options);
|
|
199
|
+
},
|
|
200
|
+
children
|
|
201
|
+
}
|
|
202
|
+
);
|
|
203
|
+
}
|
|
204
|
+
export {
|
|
205
|
+
PaySkyCheckout,
|
|
206
|
+
SCRIPT_URLS,
|
|
207
|
+
closeLightbox,
|
|
208
|
+
openLightbox,
|
|
209
|
+
resolveScriptUrl,
|
|
210
|
+
usePaySky
|
|
211
|
+
};
|
|
212
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/constants.ts","../src/loadScript.ts","../src/notify.ts","../src/checkout.ts","../src/usePaySky.ts","../src/PaySkyCheckout.tsx"],"sourcesContent":["import type { PaySkyEnvironment } from './types';\r\n\r\nexport const SCRIPT_URLS: Record<PaySkyEnvironment, string> = {\r\n sandbox: 'https://grey.paysky.io:9006/invchost/JS/LightBox.js',\r\n production: 'https://cube.paysky.io:6006/js/LightBox.js',\r\n};\r\n\r\nexport function resolveScriptUrl(\r\n environment: PaySkyEnvironment = 'sandbox',\r\n scriptUrl?: string,\r\n): string {\r\n return scriptUrl ?? SCRIPT_URLS[environment];\r\n}\r\n","const loaders = new Map<string, Promise<void>>();\r\n\r\nexport function loadPaySkyScript(url: string): Promise<void> {\r\n const existing = loaders.get(url);\r\n if (existing) {\r\n return existing;\r\n }\r\n\r\n const promise = new Promise<void>((resolve, reject) => {\r\n const script = document.createElement('script');\r\n script.src = url;\r\n script.async = true;\r\n\r\n script.addEventListener('load', () => resolve(), { once: true });\r\n script.addEventListener(\r\n 'error',\r\n () => {\r\n loaders.delete(url);\r\n reject(new Error(`Failed to load PaySky Lightbox script: ${url}`));\r\n },\r\n { once: true },\r\n );\r\n\r\n document.head.appendChild(script);\r\n });\r\n\r\n loaders.set(url, promise);\r\n return promise;\r\n}\r\n\r\n/** Test helper — clears cached loaders between tests. */\r\nexport function __resetPaySkyScriptLoaders(): void {\r\n loaders.clear();\r\n}\r\n","import type { PaySkyNotifyPayload } from './types';\r\n\r\nexport async function postNotify(\r\n notifyUrl: string,\r\n payload: PaySkyNotifyPayload,\r\n headers?: Record<string, string>,\r\n): Promise<void> {\r\n const response = await fetch(notifyUrl, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n ...headers,\r\n },\r\n body: JSON.stringify(payload),\r\n });\r\n\r\n if (!response.ok) {\r\n throw new Error(\r\n `PaySky notify failed: ${response.status} ${response.statusText}`,\r\n );\r\n }\r\n}\r\n","import { resolveScriptUrl } from './constants';\r\nimport { loadPaySkyScript } from './loadScript';\r\nimport { postNotify } from './notify';\r\nimport type {\r\n PaySkyCompleteData,\r\n PaySkyErrorData,\r\n PaySkyOpenOptions,\r\n PaySkySession,\r\n} from './types';\r\n\r\nlet openInProgress = false;\r\n\r\nfunction assertSession(session: PaySkySession): void {\r\n if (!session.mid?.trim()) {\r\n throw new Error('PaySky session.mid is required');\r\n }\r\n if (!session.tid?.trim()) {\r\n throw new Error('PaySky session.tid is required');\r\n }\r\n if (\r\n typeof session.amountTrxn !== 'number' ||\r\n !Number.isFinite(session.amountTrxn) ||\r\n session.amountTrxn <= 0\r\n ) {\r\n throw new Error('PaySky session.amountTrxn must be a positive number');\r\n }\r\n}\r\n\r\nfunction getCheckout() {\r\n const checkout = window.Lightbox?.Checkout;\r\n if (!checkout) {\r\n throw new Error(\r\n 'PaySky Lightbox is not available on window.Lightbox after script load',\r\n );\r\n }\r\n return checkout;\r\n}\r\n\r\nexport async function openLightbox(options: PaySkyOpenOptions): Promise<void> {\r\n const {\r\n session,\r\n environment = 'sandbox',\r\n scriptUrl,\r\n notifyUrl,\r\n notifyHeaders,\r\n onSuccess,\r\n onError,\r\n onCancel,\r\n onNotifyError,\r\n } = options;\r\n\r\n assertSession(session);\r\n\r\n if (openInProgress) {\r\n throw new Error('PaySky Lightbox is already open');\r\n }\r\n\r\n const url = resolveScriptUrl(environment, scriptUrl);\r\n await loadPaySkyScript(url);\r\n\r\n const checkout = getCheckout();\r\n\r\n openInProgress = true;\r\n\r\n const safeNotify = (\r\n event: 'complete' | 'error',\r\n data: PaySkyCompleteData | PaySkyErrorData,\r\n ) => {\r\n if (!notifyUrl) return;\r\n void postNotify(notifyUrl, { event, data }, notifyHeaders).catch(\r\n (error) => {\r\n onNotifyError?.(error);\r\n },\r\n );\r\n };\r\n\r\n checkout.configure = {\r\n MID: session.mid,\r\n TID: session.tid,\r\n AmountTrxn: session.amountTrxn,\r\n ...(session.merchantReference != null\r\n ? { MerchantReference: session.merchantReference }\r\n : {}),\r\n ...(session.trxDateTime != null ? { TrxDateTime: session.trxDateTime } : {}),\r\n ...(session.secureHash != null ? { SecureHash: session.secureHash } : {}),\r\n completeCallback: (data: PaySkyCompleteData) => {\r\n openInProgress = false;\r\n onSuccess?.(data);\r\n safeNotify('complete', data);\r\n },\r\n errorCallback: (error: PaySkyErrorData) => {\r\n openInProgress = false;\r\n onError?.(error);\r\n safeNotify('error', error);\r\n },\r\n cancelCallback: () => {\r\n openInProgress = false;\r\n onCancel?.();\r\n },\r\n };\r\n\r\n checkout.showLightbox();\r\n}\r\n\r\nexport function closeLightbox(): void {\r\n openInProgress = false;\r\n window.Lightbox?.Checkout?.closeLightbox();\r\n}\r\n\r\n/** Test helper */\r\nexport function __resetCheckoutOpenState(): void {\r\n openInProgress = false;\r\n}\r\n","import { useCallback, useState } from 'react';\r\nimport { closeLightbox, openLightbox } from './checkout';\r\nimport type { PaySkyOpenOptions } from './types';\r\n\r\nexport interface UsePaySkyResult {\r\n openPayment: (options: PaySkyOpenOptions) => Promise<void>;\r\n closePayment: () => void;\r\n isOpen: boolean;\r\n isLoading: boolean;\r\n error: Error | null;\r\n}\r\n\r\nexport function usePaySky(): UsePaySkyResult {\r\n const [isOpen, setIsOpen] = useState(false);\r\n const [isLoading, setIsLoading] = useState(false);\r\n const [error, setError] = useState<Error | null>(null);\r\n\r\n const closePayment = useCallback(() => {\r\n closeLightbox();\r\n setIsOpen(false);\r\n }, []);\r\n\r\n const openPayment = useCallback(async (options: PaySkyOpenOptions) => {\r\n setIsLoading(true);\r\n setError(null);\r\n\r\n try {\r\n await openLightbox({\r\n ...options,\r\n onSuccess: (data) => {\r\n setIsOpen(false);\r\n options.onSuccess?.(data);\r\n },\r\n onError: (err) => {\r\n setIsOpen(false);\r\n options.onError?.(err);\r\n },\r\n onCancel: () => {\r\n setIsOpen(false);\r\n options.onCancel?.();\r\n },\r\n });\r\n setIsOpen(true);\r\n } catch (err) {\r\n const next =\r\n err instanceof Error ? err : new Error('Failed to open PaySky Lightbox');\r\n setError(next);\r\n setIsOpen(false);\r\n throw next;\r\n } finally {\r\n setIsLoading(false);\r\n }\r\n }, []);\r\n\r\n return {\r\n openPayment,\r\n closePayment,\r\n isOpen,\r\n isLoading,\r\n error,\r\n };\r\n}\r\n","import type { PaySkyCheckoutProps } from './types';\r\nimport { usePaySky } from './usePaySky';\r\n\r\nexport function PaySkyCheckout({\r\n children = 'Pay with PaySky',\r\n className,\r\n disabled,\r\n ...options\r\n}: PaySkyCheckoutProps) {\r\n const { openPayment, isLoading, error } = usePaySky();\r\n\r\n return (\r\n <button\r\n type=\"button\"\r\n className={className}\r\n disabled={disabled || isLoading}\r\n aria-busy={isLoading || undefined}\r\n data-error={error ? error.message : undefined}\r\n onClick={() => {\r\n void openPayment(options);\r\n }}\r\n >\r\n {children}\r\n </button>\r\n );\r\n}\r\n"],"mappings":"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","names":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "react-paysky-lightbox",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "React hook and component for PaySky OMNI Gateway Lightbox",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "./dist/index.cjs",
|
|
8
|
+
"module": "./dist/index.js",
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"import": "./dist/index.js",
|
|
14
|
+
"require": "./dist/index.cjs"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"files": [
|
|
18
|
+
"dist",
|
|
19
|
+
"README.md"
|
|
20
|
+
],
|
|
21
|
+
"sideEffects": false,
|
|
22
|
+
"scripts": {
|
|
23
|
+
"build": "tsup",
|
|
24
|
+
"test": "vitest run",
|
|
25
|
+
"test:watch": "vitest",
|
|
26
|
+
"typecheck": "tsc --noEmit"
|
|
27
|
+
},
|
|
28
|
+
"peerDependencies": {
|
|
29
|
+
"react": ">=18",
|
|
30
|
+
"react-dom": ">=18"
|
|
31
|
+
},
|
|
32
|
+
"devDependencies": {
|
|
33
|
+
"@testing-library/react": "^16.0.0",
|
|
34
|
+
"@types/react": "^18.3.0",
|
|
35
|
+
"@types/react-dom": "^18.3.0",
|
|
36
|
+
"jsdom": "^24.0.0",
|
|
37
|
+
"react": "^18.3.0",
|
|
38
|
+
"react-dom": "^18.3.0",
|
|
39
|
+
"tsup": "^8.0.0",
|
|
40
|
+
"typescript": "^5.5.0",
|
|
41
|
+
"vitest": "^2.0.0"
|
|
42
|
+
},
|
|
43
|
+
"keywords": [
|
|
44
|
+
"paysky",
|
|
45
|
+
"lightbox",
|
|
46
|
+
"react",
|
|
47
|
+
"payments",
|
|
48
|
+
"egypt"
|
|
49
|
+
]
|
|
50
|
+
}
|