@reevit/react 0.5.5 → 0.5.7

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.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
- return this.request("POST", "/v1/payments/intents", request);
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": `${Date.now()}-${Math.random().toString(36).substring(2, 15)}`
521
+ "Idempotency-Key": idempotencyKey
492
522
  },
493
523
  body: JSON.stringify({
494
524
  amount: config.amount,
@@ -2264,7 +2294,6 @@ function ReevitCheckout({
2264
2294
  async (provider) => {
2265
2295
  if (provider === selectedProvider) {
2266
2296
  setSelectedProvider(null);
2267
- await reset();
2268
2297
  setShowPSPBridge(false);
2269
2298
  setMomoData(null);
2270
2299
  return;
@@ -2272,12 +2301,13 @@ function ReevitCheckout({
2272
2301
  const providerMethods = providerOptions.find((option) => option.provider === provider)?.methods || paymentMethods;
2273
2302
  const methodForInit = selectedMethod && providerMethods.includes(selectedMethod) ? selectedMethod : providerMethods[0] || paymentMethods[0];
2274
2303
  setSelectedProvider(provider);
2275
- await reset();
2276
2304
  setShowPSPBridge(false);
2277
2305
  setMomoData(null);
2278
- initialize(methodForInit, { preferredProvider: provider, allowedProviders: [provider] });
2306
+ if (methodForInit) {
2307
+ selectMethod(methodForInit);
2308
+ }
2279
2309
  },
2280
- [initialize, paymentMethods, providerOptions, reset, selectedMethod, selectedProvider]
2310
+ [paymentMethods, providerOptions, selectMethod, selectedMethod, selectedProvider]
2281
2311
  );
2282
2312
  const handleContinue = useCallback(() => {
2283
2313
  if (!selectedMethod) return;