@reevit/react 0.5.4 → 0.5.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +50 -11
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +50 -11
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -146,6 +146,18 @@ function createPaymentError(response, errorData) {
|
|
|
146
146
|
}
|
|
147
147
|
};
|
|
148
148
|
}
|
|
149
|
+
function generateIdempotencyKey(params) {
|
|
150
|
+
const sortedKeys = Object.keys(params).sort();
|
|
151
|
+
const stableString = sortedKeys.map((key) => `${key}:${JSON.stringify(params[key])}`).join("|");
|
|
152
|
+
let hash = 5381;
|
|
153
|
+
for (let i = 0; i < stableString.length; i++) {
|
|
154
|
+
hash = (hash << 5) + hash + stableString.charCodeAt(i);
|
|
155
|
+
hash = hash & hash;
|
|
156
|
+
}
|
|
157
|
+
const hashHex = (hash >>> 0).toString(16);
|
|
158
|
+
const timeBucket = Math.floor(Date.now() / (5 * 60 * 1e3));
|
|
159
|
+
return `reevit_${timeBucket}_${hashHex}`;
|
|
160
|
+
}
|
|
149
161
|
var ReevitAPIClient = class {
|
|
150
162
|
constructor(config) {
|
|
151
163
|
this.publicKey = config.publicKey || "";
|
|
@@ -154,8 +166,9 @@ var ReevitAPIClient = class {
|
|
|
154
166
|
}
|
|
155
167
|
/**
|
|
156
168
|
* Makes an authenticated API request
|
|
169
|
+
* @param idempotencyKey Optional deterministic idempotency key for the request
|
|
157
170
|
*/
|
|
158
|
-
async request(method, path, body) {
|
|
171
|
+
async request(method, path, body, idempotencyKey) {
|
|
159
172
|
const controller = new AbortController();
|
|
160
173
|
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
161
174
|
const headers = {
|
|
@@ -167,7 +180,7 @@ var ReevitAPIClient = class {
|
|
|
167
180
|
headers["X-Reevit-Key"] = this.publicKey;
|
|
168
181
|
}
|
|
169
182
|
if (method === "POST" || method === "PATCH" || method === "PUT") {
|
|
170
|
-
headers["Idempotency-Key"] = `${Date.now()}-${Math.random().toString(36).substring(2, 15)}
|
|
183
|
+
headers["Idempotency-Key"] = idempotencyKey || (body ? generateIdempotencyKey(body) : `${Date.now()}-${Math.random().toString(36).substring(2, 15)}`);
|
|
171
184
|
}
|
|
172
185
|
try {
|
|
173
186
|
const response = await fetch(`${this.baseUrl}${path}`, {
|
|
@@ -240,7 +253,16 @@ var ReevitAPIClient = class {
|
|
|
240
253
|
allowed_providers: options?.allowedProviders
|
|
241
254
|
};
|
|
242
255
|
}
|
|
243
|
-
|
|
256
|
+
const idempotencyKey = generateIdempotencyKey({
|
|
257
|
+
amount: config.amount,
|
|
258
|
+
currency: config.currency,
|
|
259
|
+
customer: config.email || config.metadata?.customerId || "",
|
|
260
|
+
reference: config.reference || "",
|
|
261
|
+
method: method || "",
|
|
262
|
+
provider: options?.preferredProviders?.[0] || options?.allowedProviders?.[0] || "",
|
|
263
|
+
publicKey: this.publicKey
|
|
264
|
+
});
|
|
265
|
+
return this.request("POST", "/v1/payments/intents", request, idempotencyKey);
|
|
244
266
|
}
|
|
245
267
|
/**
|
|
246
268
|
* Retrieves a payment intent by ID
|
|
@@ -482,13 +504,21 @@ function useReevit(options) {
|
|
|
482
504
|
let data;
|
|
483
505
|
let error;
|
|
484
506
|
if (config.paymentLinkCode) {
|
|
507
|
+
const idempotencyKey = generateIdempotencyKey({
|
|
508
|
+
paymentLinkCode: config.paymentLinkCode,
|
|
509
|
+
amount: config.amount,
|
|
510
|
+
email: config.email || "",
|
|
511
|
+
phone: config.phone || "",
|
|
512
|
+
method: paymentMethod || "",
|
|
513
|
+
provider: options2?.preferredProvider || options2?.allowedProviders?.[0] || ""
|
|
514
|
+
});
|
|
485
515
|
const response = await fetch(
|
|
486
516
|
`${apiBaseUrl || DEFAULT_PUBLIC_API_BASE_URL}/v1/pay/${config.paymentLinkCode}/pay`,
|
|
487
517
|
{
|
|
488
518
|
method: "POST",
|
|
489
519
|
headers: {
|
|
490
520
|
"Content-Type": "application/json",
|
|
491
|
-
"Idempotency-Key":
|
|
521
|
+
"Idempotency-Key": idempotencyKey
|
|
492
522
|
},
|
|
493
523
|
body: JSON.stringify({
|
|
494
524
|
amount: config.amount,
|
|
@@ -625,11 +655,20 @@ function useReevit(options) {
|
|
|
625
655
|
},
|
|
626
656
|
[onError]
|
|
627
657
|
);
|
|
628
|
-
const reset = useCallback(() => {
|
|
658
|
+
const reset = useCallback(async () => {
|
|
659
|
+
if (state.paymentIntent && state.status !== "success") {
|
|
660
|
+
try {
|
|
661
|
+
const apiClient = apiClientRef.current;
|
|
662
|
+
if (apiClient) {
|
|
663
|
+
await apiClient.cancelPaymentIntent(state.paymentIntent.id);
|
|
664
|
+
}
|
|
665
|
+
} catch {
|
|
666
|
+
}
|
|
667
|
+
}
|
|
629
668
|
initializingRef.current = false;
|
|
630
669
|
initRequestIdRef.current += 1;
|
|
631
670
|
dispatch({ type: "RESET" });
|
|
632
|
-
}, []);
|
|
671
|
+
}, [state.paymentIntent, state.status]);
|
|
633
672
|
const close = useCallback(async () => {
|
|
634
673
|
if (state.paymentIntent && state.status !== "success") {
|
|
635
674
|
try {
|
|
@@ -2252,10 +2291,10 @@ function ReevitCheckout({
|
|
|
2252
2291
|
[selectMethod]
|
|
2253
2292
|
);
|
|
2254
2293
|
const handleProviderSelect = useCallback(
|
|
2255
|
-
(provider) => {
|
|
2294
|
+
async (provider) => {
|
|
2256
2295
|
if (provider === selectedProvider) {
|
|
2257
2296
|
setSelectedProvider(null);
|
|
2258
|
-
reset();
|
|
2297
|
+
await reset();
|
|
2259
2298
|
setShowPSPBridge(false);
|
|
2260
2299
|
setMomoData(null);
|
|
2261
2300
|
return;
|
|
@@ -2263,7 +2302,7 @@ function ReevitCheckout({
|
|
|
2263
2302
|
const providerMethods = providerOptions.find((option) => option.provider === provider)?.methods || paymentMethods;
|
|
2264
2303
|
const methodForInit = selectedMethod && providerMethods.includes(selectedMethod) ? selectedMethod : providerMethods[0] || paymentMethods[0];
|
|
2265
2304
|
setSelectedProvider(provider);
|
|
2266
|
-
reset();
|
|
2305
|
+
await reset();
|
|
2267
2306
|
setShowPSPBridge(false);
|
|
2268
2307
|
setMomoData(null);
|
|
2269
2308
|
initialize(methodForInit, { preferredProvider: provider, allowedProviders: [provider] });
|
|
@@ -2305,8 +2344,8 @@ function ReevitCheckout({
|
|
|
2305
2344
|
const handlePSPClose = useCallback(() => {
|
|
2306
2345
|
setShowPSPBridge(false);
|
|
2307
2346
|
}, []);
|
|
2308
|
-
const handleBack = useCallback(() => {
|
|
2309
|
-
reset();
|
|
2347
|
+
const handleBack = useCallback(async () => {
|
|
2348
|
+
await reset();
|
|
2310
2349
|
setMomoData(null);
|
|
2311
2350
|
setShowPSPBridge(false);
|
|
2312
2351
|
}, [reset]);
|