@valuepay/react 2.0.0 → 2.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
CHANGED
|
@@ -161,6 +161,46 @@ https://yoursite.com/payment/verify?ref=VPS_TX_abc123&status=SUCCESS
|
|
|
161
161
|
|
|
162
162
|
Your server should then verify the transaction using the `ref` query parameter via the [ValuePay Verify API](https://developer.valuepayng.com/docs).
|
|
163
163
|
|
|
164
|
+
> **Important — Callback Precedence:** If you provide **any** callback (`onSuccess`, `onCallback`, `onCancelled`, `onClose`, or `onError`) alongside `redirectUrl`, the callbacks will take precedence and the redirect will **not** fire. `redirectUrl` is only used as a fallback when no callbacks are defined. This lets you safely set a `redirectUrl` as a backup while still handling events in-app when callbacks are present.
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
## `onSuccess` vs `onCallback`
|
|
169
|
+
|
|
170
|
+
These two callbacks serve different purposes — **use one or the other, not both**:
|
|
171
|
+
|
|
172
|
+
| Callback | Fires when | Use case |
|
|
173
|
+
|---|---|---|
|
|
174
|
+
| `onSuccess` | Payment succeeds (`SUCCESS` or `COMPLETED`) | You only care about successful payments |
|
|
175
|
+
| `onCallback` | **Every** payment event (success, failure, pending, etc.) | You want to handle all outcomes yourself |
|
|
176
|
+
|
|
177
|
+
```tsx
|
|
178
|
+
// Option A: Use onSuccess for success-only handling
|
|
179
|
+
<ValuePayButton
|
|
180
|
+
publicKey="KP_xxx"
|
|
181
|
+
amount={5000}
|
|
182
|
+
customer={customer}
|
|
183
|
+
onSuccess={(res) => console.log("Paid!", res)}
|
|
184
|
+
onCancelled={(res) => console.log("Cancelled", res)}
|
|
185
|
+
onClose={(res) => console.log("Closed", res)}
|
|
186
|
+
/>
|
|
187
|
+
|
|
188
|
+
// Option B: Use onCallback for all-events handling
|
|
189
|
+
<ValuePayButton
|
|
190
|
+
publicKey="KP_xxx"
|
|
191
|
+
amount={5000}
|
|
192
|
+
customer={customer}
|
|
193
|
+
onCallback={(res) => {
|
|
194
|
+
console.log("Event:", res.status, res);
|
|
195
|
+
// Handle SUCCESS, FAILED, PENDING, etc. yourself
|
|
196
|
+
}}
|
|
197
|
+
onCancelled={(res) => console.log("Cancelled", res)}
|
|
198
|
+
onClose={(res) => console.log("Closed", res)}
|
|
199
|
+
/>
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
> **Note:** `onCancelled`, `onClose`, and `onError` work alongside either choice — they handle separate events (user cancellation, modal close, SDK errors).
|
|
203
|
+
|
|
164
204
|
---
|
|
165
205
|
|
|
166
206
|
## API Reference
|
|
@@ -236,13 +276,13 @@ Extends `ValuePayConfig` with:
|
|
|
236
276
|
| `currency` | `string` | — | `"NGN"` | Currency code |
|
|
237
277
|
| `channels` | `PaymentChannel[]` | — | `["card","transfer","qrcode","ussd"]`| Enabled channels |
|
|
238
278
|
| `transactionRef` | `string` | — | Auto-generated | Custom transaction reference. `VPS_TX_` prefix auto-prepended if missing |
|
|
239
|
-
| `redirectUrl` | `string` | — | — |
|
|
279
|
+
| `redirectUrl` | `string` | — | — | Fallback redirect URL (only used when no callbacks are provided) |
|
|
240
280
|
| `metaData` | `Record<string, unknown>` | — | — | Custom metadata |
|
|
241
281
|
| `customization` | `{ title?, description?, logoUrl? }` | — | — | Checkout modal branding |
|
|
242
|
-
| `onSuccess` | `(response) => void` | — | — | Called on successful payment
|
|
282
|
+
| `onSuccess` | `(response) => void` | — | — | Called on successful payment. Use this **or** `onCallback` — not both |
|
|
243
283
|
| `onClose` | `(response) => void` | — | — | Called when modal is closed |
|
|
244
284
|
| `onCancelled` | `(response) => void` | — | — | Called when payment is cancelled |
|
|
245
|
-
| `onCallback` | `(response) => void` | — | — | Called on
|
|
285
|
+
| `onCallback` | `(response) => void` | — | — | Called on **every** payment event. Use this **or** `onSuccess` — not both |
|
|
246
286
|
| `onError` | `(error) => void` | — | — | Called on SDK errors |
|
|
247
287
|
| `scriptUrl` | `string` | — | Production CDN | Override ValuePay script URL |
|
|
248
288
|
|
|
@@ -5,6 +5,32 @@ var useScript = require('./useScript.js');
|
|
|
5
5
|
var helpers = require('../utils/helpers.js');
|
|
6
6
|
var constants = require('../utils/constants.js');
|
|
7
7
|
|
|
8
|
+
/**
|
|
9
|
+
* Checks whether any callback function is provided in the config,
|
|
10
|
+
* using case-insensitive detection to handle both SDK-style (onCallback)
|
|
11
|
+
* and raw checkout-style (oncallback) casing.
|
|
12
|
+
*/
|
|
13
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
14
|
+
function hasCallback(cfg, ...names) {
|
|
15
|
+
return names.some((name) => typeof cfg[name] === "function" || typeof cfg[name.toLowerCase()] === "function");
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Returns true if the config has ANY callback defined (case-insensitive).
|
|
19
|
+
* When true, callbacks take precedence and redirectUrl is ignored.
|
|
20
|
+
*/
|
|
21
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
22
|
+
function hasAnyCallback(cfg) {
|
|
23
|
+
return hasCallback(cfg, "onSuccess", "onCallback", "onCancelled", "onClose", "onError");
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Redirects the browser to the given URL with ref and status query params.
|
|
27
|
+
*/
|
|
28
|
+
function redirectTo(redirectUrl, ref, status) {
|
|
29
|
+
const url = new URL(redirectUrl);
|
|
30
|
+
url.searchParams.set("ref", ref);
|
|
31
|
+
url.searchParams.set("status", status);
|
|
32
|
+
window.location.href = url.toString();
|
|
33
|
+
}
|
|
8
34
|
const useValuePay = (config) => {
|
|
9
35
|
const scriptUrl = config.scriptUrl || constants.DEFAULT_SCRIPT_URL;
|
|
10
36
|
const isReady = useScript.useScript(scriptUrl);
|
|
@@ -23,24 +49,33 @@ const useValuePay = (config) => {
|
|
|
23
49
|
setIsProcessing(true);
|
|
24
50
|
const normalized = helpers.normalizeConfig(cfg, overrides);
|
|
25
51
|
const ref = normalized.transactionRef;
|
|
52
|
+
const useRedirect = !hasAnyCallback(cfg) && !!cfg.redirectUrl;
|
|
26
53
|
window.ValuepayCheckout({
|
|
27
54
|
...normalized,
|
|
28
55
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
56
|
+
onsuccess: (response) => {
|
|
57
|
+
var _a;
|
|
58
|
+
const res = helpers.normalizeResponse(response, ref, cfg);
|
|
59
|
+
setIsProcessing(false);
|
|
60
|
+
if (useRedirect) {
|
|
61
|
+
redirectTo(cfg.redirectUrl, res.ref, res.status);
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
if (res.status !== "SUCCESS" && res.status !== "COMPLETED") {
|
|
65
|
+
res.status = "SUCCESS";
|
|
66
|
+
}
|
|
67
|
+
(_a = cfg.onSuccess) === null || _a === void 0 ? void 0 : _a.call(cfg, res);
|
|
68
|
+
},
|
|
69
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
29
70
|
oncallback: (response) => {
|
|
30
|
-
var _a
|
|
71
|
+
var _a;
|
|
31
72
|
const res = helpers.normalizeResponse(response, ref, cfg);
|
|
32
73
|
setIsProcessing(false);
|
|
33
|
-
if (
|
|
34
|
-
|
|
35
|
-
url.searchParams.set("ref", res.ref);
|
|
36
|
-
url.searchParams.set("status", res.status);
|
|
37
|
-
window.location.href = url.toString();
|
|
74
|
+
if (useRedirect) {
|
|
75
|
+
redirectTo(cfg.redirectUrl, res.ref, res.status);
|
|
38
76
|
return;
|
|
39
77
|
}
|
|
40
78
|
(_a = cfg.onCallback) === null || _a === void 0 ? void 0 : _a.call(cfg, res);
|
|
41
|
-
if (res.status === "SUCCESS" || res.status === "COMPLETED") {
|
|
42
|
-
(_b = cfg.onSuccess) === null || _b === void 0 ? void 0 : _b.call(cfg, res);
|
|
43
|
-
}
|
|
44
79
|
},
|
|
45
80
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
46
81
|
onCancelled: (response) => {
|
|
@@ -48,11 +83,8 @@ const useValuePay = (config) => {
|
|
|
48
83
|
const res = helpers.normalizeResponse(response, ref, cfg);
|
|
49
84
|
res.status = "CANCELLED";
|
|
50
85
|
setIsProcessing(false);
|
|
51
|
-
if (
|
|
52
|
-
|
|
53
|
-
url.searchParams.set("ref", res.ref);
|
|
54
|
-
url.searchParams.set("status", "CANCELLED");
|
|
55
|
-
window.location.href = url.toString();
|
|
86
|
+
if (useRedirect) {
|
|
87
|
+
redirectTo(cfg.redirectUrl, res.ref, "CANCELLED");
|
|
56
88
|
return;
|
|
57
89
|
}
|
|
58
90
|
(_a = cfg.onCancelled) === null || _a === void 0 ? void 0 : _a.call(cfg, res);
|
|
@@ -70,11 +102,8 @@ const useValuePay = (config) => {
|
|
|
70
102
|
var _a;
|
|
71
103
|
const res = helpers.normalizeResponse(response, ref, cfg);
|
|
72
104
|
setIsProcessing(false);
|
|
73
|
-
if (
|
|
74
|
-
|
|
75
|
-
url.searchParams.set("ref", res.ref);
|
|
76
|
-
url.searchParams.set("status", "CLOSED");
|
|
77
|
-
window.location.href = url.toString();
|
|
105
|
+
if (useRedirect) {
|
|
106
|
+
redirectTo(cfg.redirectUrl, res.ref, "CLOSED");
|
|
78
107
|
return;
|
|
79
108
|
}
|
|
80
109
|
(_a = cfg.onClose) === null || _a === void 0 ? void 0 : _a.call(cfg, res);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useValuePay.js","sources":["../../../../src/hooks/useValuePay.ts"],"sourcesContent":["import { useCallback, useState, useRef } from \"react\";\nimport { useScript } from \"./useScript\";\nimport { normalizeConfig, normalizeResponse } from \"../utils/helpers\";\nimport { DEFAULT_SCRIPT_URL } from \"../utils/constants\";\nimport type { ValuePayConfig, UseValuePayReturn } from \"../types\";\n\nexport const useValuePay = (config: ValuePayConfig): UseValuePayReturn => {\n const scriptUrl = config.scriptUrl || DEFAULT_SCRIPT_URL;\n const isReady = useScript(scriptUrl);\n const [isProcessing, setIsProcessing] = useState(false);\n const configRef = useRef(config);\n configRef.current = config;\n\n const initialize = useCallback(\n (overrides?: Partial<ValuePayConfig>) => {\n const cfg = configRef.current;\n\n if (typeof window === \"undefined\" || !window.ValuepayCheckout) {\n cfg.onError?.(new Error(\"ValuePay script not loaded. Ensure the script URL is accessible.\"));\n return;\n }\n\n if (isProcessing) return;\n\n setIsProcessing(true);\n\n const normalized = normalizeConfig(cfg, overrides);\n const ref = normalized.transactionRef;\n\n window.ValuepayCheckout({\n ...normalized,\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n
|
|
1
|
+
{"version":3,"file":"useValuePay.js","sources":["../../../../src/hooks/useValuePay.ts"],"sourcesContent":["import { useCallback, useState, useRef } from \"react\";\r\nimport { useScript } from \"./useScript\";\r\nimport { normalizeConfig, normalizeResponse } from \"../utils/helpers\";\r\nimport { DEFAULT_SCRIPT_URL } from \"../utils/constants\";\r\nimport type { ValuePayConfig, UseValuePayReturn } from \"../types\";\r\n\r\n/**\r\n * Checks whether any callback function is provided in the config,\r\n * using case-insensitive detection to handle both SDK-style (onCallback)\r\n * and raw checkout-style (oncallback) casing.\r\n */\r\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\r\nfunction hasCallback(cfg: any, ...names: string[]): boolean {\r\n return names.some(\r\n (name) => typeof cfg[name] === \"function\" || typeof cfg[name.toLowerCase()] === \"function\",\r\n );\r\n}\r\n\r\n/**\r\n * Returns true if the config has ANY callback defined (case-insensitive).\r\n * When true, callbacks take precedence and redirectUrl is ignored.\r\n */\r\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\r\nfunction hasAnyCallback(cfg: any): boolean {\r\n return hasCallback(cfg, \"onSuccess\", \"onCallback\", \"onCancelled\", \"onClose\", \"onError\");\r\n}\r\n\r\n/**\r\n * Redirects the browser to the given URL with ref and status query params.\r\n */\r\nfunction redirectTo(redirectUrl: string, ref: string, status: string) {\r\n const url = new URL(redirectUrl);\r\n url.searchParams.set(\"ref\", ref);\r\n url.searchParams.set(\"status\", status);\r\n window.location.href = url.toString();\r\n}\r\n\r\nexport const useValuePay = (config: ValuePayConfig): UseValuePayReturn => {\r\n const scriptUrl = config.scriptUrl || DEFAULT_SCRIPT_URL;\r\n const isReady = useScript(scriptUrl);\r\n const [isProcessing, setIsProcessing] = useState(false);\r\n const configRef = useRef(config);\r\n configRef.current = config;\r\n\r\n const initialize = useCallback(\r\n (overrides?: Partial<ValuePayConfig>) => {\r\n const cfg = configRef.current;\r\n\r\n if (typeof window === \"undefined\" || !window.ValuepayCheckout) {\r\n cfg.onError?.(\r\n new Error(\"ValuePay script not loaded. Ensure the script URL is accessible.\"),\r\n );\r\n return;\r\n }\r\n\r\n if (isProcessing) return;\r\n\r\n setIsProcessing(true);\r\n\r\n const normalized = normalizeConfig(cfg, overrides);\r\n const ref = normalized.transactionRef;\r\n const useRedirect = !hasAnyCallback(cfg) && !!cfg.redirectUrl;\r\n\r\n window.ValuepayCheckout({\r\n ...normalized,\r\n\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n onsuccess: (response: any) => {\r\n const res = normalizeResponse(response, ref, cfg);\r\n setIsProcessing(false);\r\n\r\n if (useRedirect) {\r\n redirectTo(cfg.redirectUrl!, res.ref, res.status);\r\n return;\r\n }\r\n\r\n if (res.status !== \"SUCCESS\" && res.status !== \"COMPLETED\") {\r\n res.status = \"SUCCESS\";\r\n }\r\n cfg.onSuccess?.(res);\r\n },\r\n\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n oncallback: (response: any) => {\r\n const res = normalizeResponse(response, ref, cfg);\r\n setIsProcessing(false);\r\n\r\n if (useRedirect) {\r\n redirectTo(cfg.redirectUrl!, res.ref, res.status);\r\n return;\r\n }\r\n\r\n cfg.onCallback?.(res);\r\n },\r\n\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n onCancelled: (response: any) => {\r\n const res = normalizeResponse(response, ref, cfg);\r\n res.status = \"CANCELLED\";\r\n setIsProcessing(false);\r\n\r\n if (useRedirect) {\r\n redirectTo(cfg.redirectUrl!, res.ref, \"CANCELLED\");\r\n return;\r\n }\r\n\r\n cfg.onCancelled?.(res);\r\n },\r\n\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n onAborted: (response: any) => {\r\n const res = normalizeResponse(response, ref, cfg);\r\n res.status = \"CANCELLED\";\r\n setIsProcessing(false);\r\n cfg.onCancelled?.(res);\r\n },\r\n\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n onClosed: (response: any) => {\r\n const res = normalizeResponse(response, ref, cfg);\r\n setIsProcessing(false);\r\n\r\n if (useRedirect) {\r\n redirectTo(cfg.redirectUrl!, res.ref, \"CLOSED\");\r\n return;\r\n }\r\n\r\n cfg.onClose?.(res);\r\n },\r\n });\r\n },\r\n // eslint-disable-next-line react-hooks/exhaustive-deps\r\n [isReady, isProcessing],\r\n );\r\n\r\n return { initialize, isReady, isProcessing };\r\n};\r\n"],"names":["DEFAULT_SCRIPT_URL","useScript","useState","useRef","useCallback","normalizeConfig","normalizeResponse"],"mappings":"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"}
|
|
@@ -3,6 +3,32 @@ import { useScript } from './useScript.js';
|
|
|
3
3
|
import { normalizeConfig, normalizeResponse } from '../utils/helpers.js';
|
|
4
4
|
import { DEFAULT_SCRIPT_URL } from '../utils/constants.js';
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* Checks whether any callback function is provided in the config,
|
|
8
|
+
* using case-insensitive detection to handle both SDK-style (onCallback)
|
|
9
|
+
* and raw checkout-style (oncallback) casing.
|
|
10
|
+
*/
|
|
11
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
12
|
+
function hasCallback(cfg, ...names) {
|
|
13
|
+
return names.some((name) => typeof cfg[name] === "function" || typeof cfg[name.toLowerCase()] === "function");
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Returns true if the config has ANY callback defined (case-insensitive).
|
|
17
|
+
* When true, callbacks take precedence and redirectUrl is ignored.
|
|
18
|
+
*/
|
|
19
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
20
|
+
function hasAnyCallback(cfg) {
|
|
21
|
+
return hasCallback(cfg, "onSuccess", "onCallback", "onCancelled", "onClose", "onError");
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Redirects the browser to the given URL with ref and status query params.
|
|
25
|
+
*/
|
|
26
|
+
function redirectTo(redirectUrl, ref, status) {
|
|
27
|
+
const url = new URL(redirectUrl);
|
|
28
|
+
url.searchParams.set("ref", ref);
|
|
29
|
+
url.searchParams.set("status", status);
|
|
30
|
+
window.location.href = url.toString();
|
|
31
|
+
}
|
|
6
32
|
const useValuePay = (config) => {
|
|
7
33
|
const scriptUrl = config.scriptUrl || DEFAULT_SCRIPT_URL;
|
|
8
34
|
const isReady = useScript(scriptUrl);
|
|
@@ -21,24 +47,33 @@ const useValuePay = (config) => {
|
|
|
21
47
|
setIsProcessing(true);
|
|
22
48
|
const normalized = normalizeConfig(cfg, overrides);
|
|
23
49
|
const ref = normalized.transactionRef;
|
|
50
|
+
const useRedirect = !hasAnyCallback(cfg) && !!cfg.redirectUrl;
|
|
24
51
|
window.ValuepayCheckout({
|
|
25
52
|
...normalized,
|
|
26
53
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
54
|
+
onsuccess: (response) => {
|
|
55
|
+
var _a;
|
|
56
|
+
const res = normalizeResponse(response, ref, cfg);
|
|
57
|
+
setIsProcessing(false);
|
|
58
|
+
if (useRedirect) {
|
|
59
|
+
redirectTo(cfg.redirectUrl, res.ref, res.status);
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
if (res.status !== "SUCCESS" && res.status !== "COMPLETED") {
|
|
63
|
+
res.status = "SUCCESS";
|
|
64
|
+
}
|
|
65
|
+
(_a = cfg.onSuccess) === null || _a === void 0 ? void 0 : _a.call(cfg, res);
|
|
66
|
+
},
|
|
67
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
27
68
|
oncallback: (response) => {
|
|
28
|
-
var _a
|
|
69
|
+
var _a;
|
|
29
70
|
const res = normalizeResponse(response, ref, cfg);
|
|
30
71
|
setIsProcessing(false);
|
|
31
|
-
if (
|
|
32
|
-
|
|
33
|
-
url.searchParams.set("ref", res.ref);
|
|
34
|
-
url.searchParams.set("status", res.status);
|
|
35
|
-
window.location.href = url.toString();
|
|
72
|
+
if (useRedirect) {
|
|
73
|
+
redirectTo(cfg.redirectUrl, res.ref, res.status);
|
|
36
74
|
return;
|
|
37
75
|
}
|
|
38
76
|
(_a = cfg.onCallback) === null || _a === void 0 ? void 0 : _a.call(cfg, res);
|
|
39
|
-
if (res.status === "SUCCESS" || res.status === "COMPLETED") {
|
|
40
|
-
(_b = cfg.onSuccess) === null || _b === void 0 ? void 0 : _b.call(cfg, res);
|
|
41
|
-
}
|
|
42
77
|
},
|
|
43
78
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
44
79
|
onCancelled: (response) => {
|
|
@@ -46,11 +81,8 @@ const useValuePay = (config) => {
|
|
|
46
81
|
const res = normalizeResponse(response, ref, cfg);
|
|
47
82
|
res.status = "CANCELLED";
|
|
48
83
|
setIsProcessing(false);
|
|
49
|
-
if (
|
|
50
|
-
|
|
51
|
-
url.searchParams.set("ref", res.ref);
|
|
52
|
-
url.searchParams.set("status", "CANCELLED");
|
|
53
|
-
window.location.href = url.toString();
|
|
84
|
+
if (useRedirect) {
|
|
85
|
+
redirectTo(cfg.redirectUrl, res.ref, "CANCELLED");
|
|
54
86
|
return;
|
|
55
87
|
}
|
|
56
88
|
(_a = cfg.onCancelled) === null || _a === void 0 ? void 0 : _a.call(cfg, res);
|
|
@@ -68,11 +100,8 @@ const useValuePay = (config) => {
|
|
|
68
100
|
var _a;
|
|
69
101
|
const res = normalizeResponse(response, ref, cfg);
|
|
70
102
|
setIsProcessing(false);
|
|
71
|
-
if (
|
|
72
|
-
|
|
73
|
-
url.searchParams.set("ref", res.ref);
|
|
74
|
-
url.searchParams.set("status", "CLOSED");
|
|
75
|
-
window.location.href = url.toString();
|
|
103
|
+
if (useRedirect) {
|
|
104
|
+
redirectTo(cfg.redirectUrl, res.ref, "CLOSED");
|
|
76
105
|
return;
|
|
77
106
|
}
|
|
78
107
|
(_a = cfg.onClose) === null || _a === void 0 ? void 0 : _a.call(cfg, res);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useValuePay.js","sources":["../../../../src/hooks/useValuePay.ts"],"sourcesContent":["import { useCallback, useState, useRef } from \"react\";\nimport { useScript } from \"./useScript\";\nimport { normalizeConfig, normalizeResponse } from \"../utils/helpers\";\nimport { DEFAULT_SCRIPT_URL } from \"../utils/constants\";\nimport type { ValuePayConfig, UseValuePayReturn } from \"../types\";\n\nexport const useValuePay = (config: ValuePayConfig): UseValuePayReturn => {\n const scriptUrl = config.scriptUrl || DEFAULT_SCRIPT_URL;\n const isReady = useScript(scriptUrl);\n const [isProcessing, setIsProcessing] = useState(false);\n const configRef = useRef(config);\n configRef.current = config;\n\n const initialize = useCallback(\n (overrides?: Partial<ValuePayConfig>) => {\n const cfg = configRef.current;\n\n if (typeof window === \"undefined\" || !window.ValuepayCheckout) {\n cfg.onError?.(new Error(\"ValuePay script not loaded. Ensure the script URL is accessible.\"));\n return;\n }\n\n if (isProcessing) return;\n\n setIsProcessing(true);\n\n const normalized = normalizeConfig(cfg, overrides);\n const ref = normalized.transactionRef;\n\n window.ValuepayCheckout({\n ...normalized,\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n
|
|
1
|
+
{"version":3,"file":"useValuePay.js","sources":["../../../../src/hooks/useValuePay.ts"],"sourcesContent":["import { useCallback, useState, useRef } from \"react\";\r\nimport { useScript } from \"./useScript\";\r\nimport { normalizeConfig, normalizeResponse } from \"../utils/helpers\";\r\nimport { DEFAULT_SCRIPT_URL } from \"../utils/constants\";\r\nimport type { ValuePayConfig, UseValuePayReturn } from \"../types\";\r\n\r\n/**\r\n * Checks whether any callback function is provided in the config,\r\n * using case-insensitive detection to handle both SDK-style (onCallback)\r\n * and raw checkout-style (oncallback) casing.\r\n */\r\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\r\nfunction hasCallback(cfg: any, ...names: string[]): boolean {\r\n return names.some(\r\n (name) => typeof cfg[name] === \"function\" || typeof cfg[name.toLowerCase()] === \"function\",\r\n );\r\n}\r\n\r\n/**\r\n * Returns true if the config has ANY callback defined (case-insensitive).\r\n * When true, callbacks take precedence and redirectUrl is ignored.\r\n */\r\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\r\nfunction hasAnyCallback(cfg: any): boolean {\r\n return hasCallback(cfg, \"onSuccess\", \"onCallback\", \"onCancelled\", \"onClose\", \"onError\");\r\n}\r\n\r\n/**\r\n * Redirects the browser to the given URL with ref and status query params.\r\n */\r\nfunction redirectTo(redirectUrl: string, ref: string, status: string) {\r\n const url = new URL(redirectUrl);\r\n url.searchParams.set(\"ref\", ref);\r\n url.searchParams.set(\"status\", status);\r\n window.location.href = url.toString();\r\n}\r\n\r\nexport const useValuePay = (config: ValuePayConfig): UseValuePayReturn => {\r\n const scriptUrl = config.scriptUrl || DEFAULT_SCRIPT_URL;\r\n const isReady = useScript(scriptUrl);\r\n const [isProcessing, setIsProcessing] = useState(false);\r\n const configRef = useRef(config);\r\n configRef.current = config;\r\n\r\n const initialize = useCallback(\r\n (overrides?: Partial<ValuePayConfig>) => {\r\n const cfg = configRef.current;\r\n\r\n if (typeof window === \"undefined\" || !window.ValuepayCheckout) {\r\n cfg.onError?.(\r\n new Error(\"ValuePay script not loaded. Ensure the script URL is accessible.\"),\r\n );\r\n return;\r\n }\r\n\r\n if (isProcessing) return;\r\n\r\n setIsProcessing(true);\r\n\r\n const normalized = normalizeConfig(cfg, overrides);\r\n const ref = normalized.transactionRef;\r\n const useRedirect = !hasAnyCallback(cfg) && !!cfg.redirectUrl;\r\n\r\n window.ValuepayCheckout({\r\n ...normalized,\r\n\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n onsuccess: (response: any) => {\r\n const res = normalizeResponse(response, ref, cfg);\r\n setIsProcessing(false);\r\n\r\n if (useRedirect) {\r\n redirectTo(cfg.redirectUrl!, res.ref, res.status);\r\n return;\r\n }\r\n\r\n if (res.status !== \"SUCCESS\" && res.status !== \"COMPLETED\") {\r\n res.status = \"SUCCESS\";\r\n }\r\n cfg.onSuccess?.(res);\r\n },\r\n\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n oncallback: (response: any) => {\r\n const res = normalizeResponse(response, ref, cfg);\r\n setIsProcessing(false);\r\n\r\n if (useRedirect) {\r\n redirectTo(cfg.redirectUrl!, res.ref, res.status);\r\n return;\r\n }\r\n\r\n cfg.onCallback?.(res);\r\n },\r\n\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n onCancelled: (response: any) => {\r\n const res = normalizeResponse(response, ref, cfg);\r\n res.status = \"CANCELLED\";\r\n setIsProcessing(false);\r\n\r\n if (useRedirect) {\r\n redirectTo(cfg.redirectUrl!, res.ref, \"CANCELLED\");\r\n return;\r\n }\r\n\r\n cfg.onCancelled?.(res);\r\n },\r\n\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n onAborted: (response: any) => {\r\n const res = normalizeResponse(response, ref, cfg);\r\n res.status = \"CANCELLED\";\r\n setIsProcessing(false);\r\n cfg.onCancelled?.(res);\r\n },\r\n\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n onClosed: (response: any) => {\r\n const res = normalizeResponse(response, ref, cfg);\r\n setIsProcessing(false);\r\n\r\n if (useRedirect) {\r\n redirectTo(cfg.redirectUrl!, res.ref, \"CLOSED\");\r\n return;\r\n }\r\n\r\n cfg.onClose?.(res);\r\n },\r\n });\r\n },\r\n // eslint-disable-next-line react-hooks/exhaustive-deps\r\n [isReady, isProcessing],\r\n );\r\n\r\n return { initialize, isReady, isProcessing };\r\n};\r\n"],"names":[],"mappings":";;;;;AAMA;;;;AAIG;AACH;AACA,SAAS,WAAW,CAAC,GAAQ,EAAE,GAAG,KAAe,EAAA;AAC/C,IAAA,OAAO,KAAK,CAAC,IAAI,CACf,CAAC,IAAI,KAAK,OAAO,GAAG,CAAC,IAAI,CAAC,KAAK,UAAU,IAAI,OAAO,GAAG,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,KAAK,UAAU,CAC3F;AACH;AAEA;;;AAGG;AACH;AACA,SAAS,cAAc,CAAC,GAAQ,EAAA;AAC9B,IAAA,OAAO,WAAW,CAAC,GAAG,EAAE,WAAW,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,SAAS,CAAC;AACzF;AAEA;;AAEG;AACH,SAAS,UAAU,CAAC,WAAmB,EAAE,GAAW,EAAE,MAAc,EAAA;AAClE,IAAA,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,WAAW,CAAC;IAChC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC;IAChC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC;IACtC,MAAM,CAAC,QAAQ,CAAC,IAAI,GAAG,GAAG,CAAC,QAAQ,EAAE;AACvC;AAEO,MAAM,WAAW,GAAG,CAAC,MAAsB,KAAuB;AACvE,IAAA,MAAM,SAAS,GAAG,MAAM,CAAC,SAAS,IAAI,kBAAkB;AACxD,IAAA,MAAM,OAAO,GAAG,SAAS,CAAC,SAAS,CAAC;IACpC,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC;AACvD,IAAA,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC;AAChC,IAAA,SAAS,CAAC,OAAO,GAAG,MAAM;AAE1B,IAAA,MAAM,UAAU,GAAG,WAAW,CAC5B,CAAC,SAAmC,KAAI;;AACtC,QAAA,MAAM,GAAG,GAAG,SAAS,CAAC,OAAO;QAE7B,IAAI,OAAO,MAAM,KAAK,WAAW,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE;YAC7D,CAAA,EAAA,GAAA,GAAG,CAAC,OAAO,MAAA,IAAA,IAAA,EAAA,KAAA,MAAA,GAAA,MAAA,GAAA,EAAA,CAAA,IAAA,CAAA,GAAA,EACT,IAAI,KAAK,CAAC,kEAAkE,CAAC,CAC9E;YACD;QACF;AAEA,QAAA,IAAI,YAAY;YAAE;QAElB,eAAe,CAAC,IAAI,CAAC;QAErB,MAAM,UAAU,GAAG,eAAe,CAAC,GAAG,EAAE,SAAS,CAAC;AAClD,QAAA,MAAM,GAAG,GAAG,UAAU,CAAC,cAAc;AACrC,QAAA,MAAM,WAAW,GAAG,CAAC,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,WAAW;QAE7D,MAAM,CAAC,gBAAgB,CAAC;AACtB,YAAA,GAAG,UAAU;;AAGb,YAAA,SAAS,EAAE,CAAC,QAAa,KAAI;;gBAC3B,MAAM,GAAG,GAAG,iBAAiB,CAAC,QAAQ,EAAE,GAAG,EAAE,GAAG,CAAC;gBACjD,eAAe,CAAC,KAAK,CAAC;gBAEtB,IAAI,WAAW,EAAE;AACf,oBAAA,UAAU,CAAC,GAAG,CAAC,WAAY,EAAE,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,MAAM,CAAC;oBACjD;gBACF;AAEA,gBAAA,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS,IAAI,GAAG,CAAC,MAAM,KAAK,WAAW,EAAE;AAC1D,oBAAA,GAAG,CAAC,MAAM,GAAG,SAAS;gBACxB;AACA,gBAAA,CAAA,EAAA,GAAA,GAAG,CAAC,SAAS,MAAA,IAAA,IAAA,EAAA,KAAA,MAAA,GAAA,MAAA,GAAA,EAAA,CAAA,IAAA,CAAA,GAAA,EAAG,GAAG,CAAC;YACtB,CAAC;;AAGD,YAAA,UAAU,EAAE,CAAC,QAAa,KAAI;;gBAC5B,MAAM,GAAG,GAAG,iBAAiB,CAAC,QAAQ,EAAE,GAAG,EAAE,GAAG,CAAC;gBACjD,eAAe,CAAC,KAAK,CAAC;gBAEtB,IAAI,WAAW,EAAE;AACf,oBAAA,UAAU,CAAC,GAAG,CAAC,WAAY,EAAE,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,MAAM,CAAC;oBACjD;gBACF;AAEA,gBAAA,CAAA,EAAA,GAAA,GAAG,CAAC,UAAU,MAAA,IAAA,IAAA,EAAA,KAAA,MAAA,GAAA,MAAA,GAAA,EAAA,CAAA,IAAA,CAAA,GAAA,EAAG,GAAG,CAAC;YACvB,CAAC;;AAGD,YAAA,WAAW,EAAE,CAAC,QAAa,KAAI;;gBAC7B,MAAM,GAAG,GAAG,iBAAiB,CAAC,QAAQ,EAAE,GAAG,EAAE,GAAG,CAAC;AACjD,gBAAA,GAAG,CAAC,MAAM,GAAG,WAAW;gBACxB,eAAe,CAAC,KAAK,CAAC;gBAEtB,IAAI,WAAW,EAAE;oBACf,UAAU,CAAC,GAAG,CAAC,WAAY,EAAE,GAAG,CAAC,GAAG,EAAE,WAAW,CAAC;oBAClD;gBACF;AAEA,gBAAA,CAAA,EAAA,GAAA,GAAG,CAAC,WAAW,MAAA,IAAA,IAAA,EAAA,KAAA,MAAA,GAAA,MAAA,GAAA,EAAA,CAAA,IAAA,CAAA,GAAA,EAAG,GAAG,CAAC;YACxB,CAAC;;AAGD,YAAA,SAAS,EAAE,CAAC,QAAa,KAAI;;gBAC3B,MAAM,GAAG,GAAG,iBAAiB,CAAC,QAAQ,EAAE,GAAG,EAAE,GAAG,CAAC;AACjD,gBAAA,GAAG,CAAC,MAAM,GAAG,WAAW;gBACxB,eAAe,CAAC,KAAK,CAAC;AACtB,gBAAA,CAAA,EAAA,GAAA,GAAG,CAAC,WAAW,MAAA,IAAA,IAAA,EAAA,KAAA,MAAA,GAAA,MAAA,GAAA,EAAA,CAAA,IAAA,CAAA,GAAA,EAAG,GAAG,CAAC;YACxB,CAAC;;AAGD,YAAA,QAAQ,EAAE,CAAC,QAAa,KAAI;;gBAC1B,MAAM,GAAG,GAAG,iBAAiB,CAAC,QAAQ,EAAE,GAAG,EAAE,GAAG,CAAC;gBACjD,eAAe,CAAC,KAAK,CAAC;gBAEtB,IAAI,WAAW,EAAE;oBACf,UAAU,CAAC,GAAG,CAAC,WAAY,EAAE,GAAG,CAAC,GAAG,EAAE,QAAQ,CAAC;oBAC/C;gBACF;AAEA,gBAAA,CAAA,EAAA,GAAA,GAAG,CAAC,OAAO,MAAA,IAAA,IAAA,EAAA,KAAA,MAAA,GAAA,MAAA,GAAA,EAAA,CAAA,IAAA,CAAA,GAAA,EAAG,GAAG,CAAC;YACpB,CAAC;AACF,SAAA,CAAC;IACJ,CAAC;;AAED,IAAA,CAAC,OAAO,EAAE,YAAY,CAAC,CACxB;AAED,IAAA,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,YAAY,EAAE;AAC9C;;;;"}
|
|
@@ -32,13 +32,19 @@ export interface ValuePayConfig {
|
|
|
32
32
|
channels?: PaymentChannel[];
|
|
33
33
|
/** Optional custom transaction reference. The VPS_TX_ prefix is auto-prepended if missing. Auto-generated when omitted. */
|
|
34
34
|
transactionRef?: string;
|
|
35
|
+
/** Optional redirect URL after payment. Only used as a fallback when no callbacks (onSuccess, onCallback, onCancelled, onClose, onError) are provided. Callbacks always take precedence. */
|
|
35
36
|
redirectUrl?: string;
|
|
36
37
|
metaData?: Record<string, unknown>;
|
|
37
38
|
customization?: ValuePayCustomization;
|
|
39
|
+
/** Called on successful payment. Use this OR `onCallback` — not both. When provided, this is passed as `onsuccess` to the checkout and only fires for successful transactions. */
|
|
38
40
|
onSuccess?: (response: ValuePayResponse) => void;
|
|
41
|
+
/** Called when the user closes the checkout modal. */
|
|
39
42
|
onClose?: (response: ValuePayResponse) => void;
|
|
43
|
+
/** Called when the user explicitly cancels the payment. */
|
|
40
44
|
onCancelled?: (response: ValuePayResponse) => void;
|
|
45
|
+
/** General-purpose callback for ALL payment events (success, failure, etc.). Use this OR `onSuccess` — not both. When provided, this is passed as `oncallback` to the checkout and fires for every event. */
|
|
41
46
|
onCallback?: (response: ValuePayResponse) => void;
|
|
47
|
+
/** Called on SDK-level errors (script load failure, etc.). */
|
|
42
48
|
onError?: (error: Error) => void;
|
|
43
49
|
scriptUrl?: string;
|
|
44
50
|
}
|