@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.d.mts
CHANGED
|
@@ -264,7 +264,7 @@ declare function useReevit(options: UseReevitOptions): {
|
|
|
264
264
|
processPayment: (paymentData: Record<string, unknown>) => Promise<void>;
|
|
265
265
|
handlePspSuccess: (pspData: Record<string, unknown>) => Promise<void>;
|
|
266
266
|
handlePspError: (error: PaymentError) => void;
|
|
267
|
-
reset: () => void
|
|
267
|
+
reset: () => Promise<void>;
|
|
268
268
|
close: () => Promise<void>;
|
|
269
269
|
isLoading: boolean;
|
|
270
270
|
isReady: boolean;
|
|
@@ -697,6 +697,7 @@ declare class ReevitAPIClient {
|
|
|
697
697
|
constructor(config: ReevitAPIClientConfig);
|
|
698
698
|
/**
|
|
699
699
|
* Makes an authenticated API request
|
|
700
|
+
* @param idempotencyKey Optional deterministic idempotency key for the request
|
|
700
701
|
*/
|
|
701
702
|
private request;
|
|
702
703
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -264,7 +264,7 @@ declare function useReevit(options: UseReevitOptions): {
|
|
|
264
264
|
processPayment: (paymentData: Record<string, unknown>) => Promise<void>;
|
|
265
265
|
handlePspSuccess: (pspData: Record<string, unknown>) => Promise<void>;
|
|
266
266
|
handlePspError: (error: PaymentError) => void;
|
|
267
|
-
reset: () => void
|
|
267
|
+
reset: () => Promise<void>;
|
|
268
268
|
close: () => Promise<void>;
|
|
269
269
|
isLoading: boolean;
|
|
270
270
|
isReady: boolean;
|
|
@@ -697,6 +697,7 @@ declare class ReevitAPIClient {
|
|
|
697
697
|
constructor(config: ReevitAPIClientConfig);
|
|
698
698
|
/**
|
|
699
699
|
* Makes an authenticated API request
|
|
700
|
+
* @param idempotencyKey Optional deterministic idempotency key for the request
|
|
700
701
|
*/
|
|
701
702
|
private request;
|
|
702
703
|
/**
|
package/dist/index.js
CHANGED
|
@@ -152,6 +152,18 @@ function createPaymentError(response, errorData) {
|
|
|
152
152
|
}
|
|
153
153
|
};
|
|
154
154
|
}
|
|
155
|
+
function generateIdempotencyKey(params) {
|
|
156
|
+
const sortedKeys = Object.keys(params).sort();
|
|
157
|
+
const stableString = sortedKeys.map((key) => `${key}:${JSON.stringify(params[key])}`).join("|");
|
|
158
|
+
let hash = 5381;
|
|
159
|
+
for (let i = 0; i < stableString.length; i++) {
|
|
160
|
+
hash = (hash << 5) + hash + stableString.charCodeAt(i);
|
|
161
|
+
hash = hash & hash;
|
|
162
|
+
}
|
|
163
|
+
const hashHex = (hash >>> 0).toString(16);
|
|
164
|
+
const timeBucket = Math.floor(Date.now() / (5 * 60 * 1e3));
|
|
165
|
+
return `reevit_${timeBucket}_${hashHex}`;
|
|
166
|
+
}
|
|
155
167
|
var ReevitAPIClient = class {
|
|
156
168
|
constructor(config) {
|
|
157
169
|
this.publicKey = config.publicKey || "";
|
|
@@ -160,8 +172,9 @@ var ReevitAPIClient = class {
|
|
|
160
172
|
}
|
|
161
173
|
/**
|
|
162
174
|
* Makes an authenticated API request
|
|
175
|
+
* @param idempotencyKey Optional deterministic idempotency key for the request
|
|
163
176
|
*/
|
|
164
|
-
async request(method, path, body) {
|
|
177
|
+
async request(method, path, body, idempotencyKey) {
|
|
165
178
|
const controller = new AbortController();
|
|
166
179
|
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
167
180
|
const headers = {
|
|
@@ -173,7 +186,7 @@ var ReevitAPIClient = class {
|
|
|
173
186
|
headers["X-Reevit-Key"] = this.publicKey;
|
|
174
187
|
}
|
|
175
188
|
if (method === "POST" || method === "PATCH" || method === "PUT") {
|
|
176
|
-
headers["Idempotency-Key"] = `${Date.now()}-${Math.random().toString(36).substring(2, 15)}
|
|
189
|
+
headers["Idempotency-Key"] = idempotencyKey || (body ? generateIdempotencyKey(body) : `${Date.now()}-${Math.random().toString(36).substring(2, 15)}`);
|
|
177
190
|
}
|
|
178
191
|
try {
|
|
179
192
|
const response = await fetch(`${this.baseUrl}${path}`, {
|
|
@@ -246,7 +259,16 @@ var ReevitAPIClient = class {
|
|
|
246
259
|
allowed_providers: options?.allowedProviders
|
|
247
260
|
};
|
|
248
261
|
}
|
|
249
|
-
|
|
262
|
+
const idempotencyKey = generateIdempotencyKey({
|
|
263
|
+
amount: config.amount,
|
|
264
|
+
currency: config.currency,
|
|
265
|
+
customer: config.email || config.metadata?.customerId || "",
|
|
266
|
+
reference: config.reference || "",
|
|
267
|
+
method: method || "",
|
|
268
|
+
provider: options?.preferredProviders?.[0] || options?.allowedProviders?.[0] || "",
|
|
269
|
+
publicKey: this.publicKey
|
|
270
|
+
});
|
|
271
|
+
return this.request("POST", "/v1/payments/intents", request, idempotencyKey);
|
|
250
272
|
}
|
|
251
273
|
/**
|
|
252
274
|
* Retrieves a payment intent by ID
|
|
@@ -488,13 +510,21 @@ function useReevit(options) {
|
|
|
488
510
|
let data;
|
|
489
511
|
let error;
|
|
490
512
|
if (config.paymentLinkCode) {
|
|
513
|
+
const idempotencyKey = generateIdempotencyKey({
|
|
514
|
+
paymentLinkCode: config.paymentLinkCode,
|
|
515
|
+
amount: config.amount,
|
|
516
|
+
email: config.email || "",
|
|
517
|
+
phone: config.phone || "",
|
|
518
|
+
method: paymentMethod || "",
|
|
519
|
+
provider: options2?.preferredProvider || options2?.allowedProviders?.[0] || ""
|
|
520
|
+
});
|
|
491
521
|
const response = await fetch(
|
|
492
522
|
`${apiBaseUrl || DEFAULT_PUBLIC_API_BASE_URL}/v1/pay/${config.paymentLinkCode}/pay`,
|
|
493
523
|
{
|
|
494
524
|
method: "POST",
|
|
495
525
|
headers: {
|
|
496
526
|
"Content-Type": "application/json",
|
|
497
|
-
"Idempotency-Key":
|
|
527
|
+
"Idempotency-Key": idempotencyKey
|
|
498
528
|
},
|
|
499
529
|
body: JSON.stringify({
|
|
500
530
|
amount: config.amount,
|
|
@@ -631,11 +661,20 @@ function useReevit(options) {
|
|
|
631
661
|
},
|
|
632
662
|
[onError]
|
|
633
663
|
);
|
|
634
|
-
const reset = react.useCallback(() => {
|
|
664
|
+
const reset = react.useCallback(async () => {
|
|
665
|
+
if (state.paymentIntent && state.status !== "success") {
|
|
666
|
+
try {
|
|
667
|
+
const apiClient = apiClientRef.current;
|
|
668
|
+
if (apiClient) {
|
|
669
|
+
await apiClient.cancelPaymentIntent(state.paymentIntent.id);
|
|
670
|
+
}
|
|
671
|
+
} catch {
|
|
672
|
+
}
|
|
673
|
+
}
|
|
635
674
|
initializingRef.current = false;
|
|
636
675
|
initRequestIdRef.current += 1;
|
|
637
676
|
dispatch({ type: "RESET" });
|
|
638
|
-
}, []);
|
|
677
|
+
}, [state.paymentIntent, state.status]);
|
|
639
678
|
const close = react.useCallback(async () => {
|
|
640
679
|
if (state.paymentIntent && state.status !== "success") {
|
|
641
680
|
try {
|
|
@@ -2258,10 +2297,10 @@ function ReevitCheckout({
|
|
|
2258
2297
|
[selectMethod]
|
|
2259
2298
|
);
|
|
2260
2299
|
const handleProviderSelect = react.useCallback(
|
|
2261
|
-
(provider) => {
|
|
2300
|
+
async (provider) => {
|
|
2262
2301
|
if (provider === selectedProvider) {
|
|
2263
2302
|
setSelectedProvider(null);
|
|
2264
|
-
reset();
|
|
2303
|
+
await reset();
|
|
2265
2304
|
setShowPSPBridge(false);
|
|
2266
2305
|
setMomoData(null);
|
|
2267
2306
|
return;
|
|
@@ -2269,7 +2308,7 @@ function ReevitCheckout({
|
|
|
2269
2308
|
const providerMethods = providerOptions.find((option) => option.provider === provider)?.methods || paymentMethods;
|
|
2270
2309
|
const methodForInit = selectedMethod && providerMethods.includes(selectedMethod) ? selectedMethod : providerMethods[0] || paymentMethods[0];
|
|
2271
2310
|
setSelectedProvider(provider);
|
|
2272
|
-
reset();
|
|
2311
|
+
await reset();
|
|
2273
2312
|
setShowPSPBridge(false);
|
|
2274
2313
|
setMomoData(null);
|
|
2275
2314
|
initialize(methodForInit, { preferredProvider: provider, allowedProviders: [provider] });
|
|
@@ -2311,8 +2350,8 @@ function ReevitCheckout({
|
|
|
2311
2350
|
const handlePSPClose = react.useCallback(() => {
|
|
2312
2351
|
setShowPSPBridge(false);
|
|
2313
2352
|
}, []);
|
|
2314
|
-
const handleBack = react.useCallback(() => {
|
|
2315
|
-
reset();
|
|
2353
|
+
const handleBack = react.useCallback(async () => {
|
|
2354
|
+
await reset();
|
|
2316
2355
|
setMomoData(null);
|
|
2317
2356
|
setShowPSPBridge(false);
|
|
2318
2357
|
}, [reset]);
|