@reevit/react 0.4.3 → 0.4.4

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
@@ -132,8 +132,8 @@ function createPaymentError(response, errorData) {
132
132
  }
133
133
  var ReevitAPIClient = class {
134
134
  constructor(config) {
135
- this.publicKey = config.publicKey;
136
- this.baseUrl = config.baseUrl || (isSandboxKey(config.publicKey) ? API_BASE_URL_SANDBOX : API_BASE_URL_PRODUCTION);
135
+ this.publicKey = config.publicKey || "";
136
+ this.baseUrl = config.baseUrl || (config.publicKey && isSandboxKey(config.publicKey) ? API_BASE_URL_SANDBOX : API_BASE_URL_PRODUCTION);
137
137
  this.timeout = config.timeout || DEFAULT_TIMEOUT;
138
138
  }
139
139
  /**
@@ -144,10 +144,12 @@ var ReevitAPIClient = class {
144
144
  const timeoutId = setTimeout(() => controller.abort(), this.timeout);
145
145
  const headers = {
146
146
  "Content-Type": "application/json",
147
- "X-Reevit-Key": this.publicKey,
148
147
  "X-Reevit-Client": "@reevit/react",
149
148
  "X-Reevit-Client-Version": "0.3.2"
150
149
  };
150
+ if (this.publicKey) {
151
+ headers["X-Reevit-Key"] = this.publicKey;
152
+ }
151
153
  if (method === "POST" || method === "PATCH" || method === "PUT") {
152
154
  headers["Idempotency-Key"] = `${Date.now()}-${Math.random().toString(36).substring(2, 15)}`;
153
155
  }
@@ -254,8 +256,9 @@ var ReevitAPIClient = class {
254
256
  * @param paymentId - The payment intent ID for Hubtel checkout
255
257
  * @returns Hubtel session with token, merchant account, and expiry information
256
258
  */
257
- async createHubtelSession(paymentId) {
258
- return this.request("POST", `/v1/payments/hubtel/sessions/${paymentId}`);
259
+ async createHubtelSession(paymentId, clientSecret) {
260
+ const query = clientSecret ? `?client_secret=${encodeURIComponent(clientSecret)}` : "";
261
+ return this.request("POST", `/v1/payments/hubtel/sessions/${paymentId}${query}`);
259
262
  }
260
263
  /**
261
264
  * Maps SDK payment method to backend format
@@ -285,6 +288,18 @@ var initialState = {
285
288
  error: null,
286
289
  result: null
287
290
  };
291
+ var DEFAULT_PUBLIC_API_BASE_URL = "https://api.reevit.io";
292
+ function buildPaymentLinkError(response, data) {
293
+ return {
294
+ code: data?.code || "payment_link_error",
295
+ message: data?.message || "Payment link request failed",
296
+ recoverable: true,
297
+ details: {
298
+ httpStatus: response.status,
299
+ ...data?.details || {}
300
+ }
301
+ };
302
+ }
288
303
  function reevitReducer(state, action) {
289
304
  switch (action.type) {
290
305
  case "INIT_START":
@@ -408,15 +423,48 @@ function useReevit(options) {
408
423
  const reference = config.reference || generateReference();
409
424
  const country = detectCountryFromCurrency(config.currency);
410
425
  const paymentMethod = method || config.paymentMethods?.[0] || "card";
411
- const { data, error } = await apiClient.createPaymentIntent(
412
- { ...config, reference },
413
- paymentMethod,
414
- country,
415
- {
416
- preferredProviders: options2?.preferredProvider ? [options2.preferredProvider] : void 0,
417
- allowedProviders: options2?.allowedProviders
426
+ let data;
427
+ let error;
428
+ if (config.paymentLinkCode) {
429
+ const response = await fetch(
430
+ `${apiBaseUrl || DEFAULT_PUBLIC_API_BASE_URL}/v1/pay/${config.paymentLinkCode}/pay`,
431
+ {
432
+ method: "POST",
433
+ headers: {
434
+ "Content-Type": "application/json",
435
+ "Idempotency-Key": `${Date.now()}-${Math.random().toString(36).substring(2, 15)}`
436
+ },
437
+ body: JSON.stringify({
438
+ amount: config.amount,
439
+ email: config.email || "",
440
+ name: config.customerName || "",
441
+ phone: config.phone || "",
442
+ method: paymentMethod,
443
+ country,
444
+ provider: options2?.preferredProvider || options2?.allowedProviders?.[0],
445
+ custom_fields: config.customFields
446
+ })
447
+ }
448
+ );
449
+ const responseData = await response.json().catch(() => ({}));
450
+ if (!response.ok) {
451
+ error = buildPaymentLinkError(response, responseData);
452
+ } else {
453
+ data = responseData;
418
454
  }
419
- );
455
+ } else {
456
+ const result = await apiClient.createPaymentIntent(
457
+ { ...config, reference },
458
+ paymentMethod,
459
+ country,
460
+ {
461
+ preferredProviders: options2?.preferredProvider ? [options2.preferredProvider] : void 0,
462
+ allowedProviders: options2?.allowedProviders
463
+ }
464
+ );
465
+ data = result.data;
466
+ error = result.error;
467
+ }
420
468
  if (error) {
421
469
  dispatch({ type: "INIT_ERROR", payload: error });
422
470
  onError?.(error);
@@ -1036,6 +1084,8 @@ function HubtelBridge({
1036
1084
  phone,
1037
1085
  description = "Payment",
1038
1086
  callbackUrl,
1087
+ apiBaseUrl,
1088
+ clientSecret,
1039
1089
  hubtelSessionToken,
1040
1090
  basicAuth,
1041
1091
  preferredMethod,
@@ -1048,13 +1098,17 @@ function HubtelBridge({
1048
1098
  const checkoutRef = useRef(null);
1049
1099
  const [authValue, setAuthValue] = useState("");
1050
1100
  const [isLoading, setIsLoading] = useState(false);
1101
+ const [resolvedMerchantAccount, setResolvedMerchantAccount] = useState(merchantAccount);
1102
+ useEffect(() => {
1103
+ setResolvedMerchantAccount(merchantAccount);
1104
+ }, [merchantAccount]);
1051
1105
  useEffect(() => {
1052
1106
  const fetchAuth = async () => {
1053
1107
  if (hubtelSessionToken) {
1054
1108
  setIsLoading(true);
1055
1109
  try {
1056
- const client = createReevitClient({ publicKey });
1057
- const { data, error } = await client.createHubtelSession(paymentId);
1110
+ const client = createReevitClient({ publicKey, baseUrl: apiBaseUrl });
1111
+ const { data, error } = await client.createHubtelSession(paymentId, clientSecret);
1058
1112
  if (error) {
1059
1113
  onError({
1060
1114
  code: "SESSION_ERROR",
@@ -1065,6 +1119,9 @@ function HubtelBridge({
1065
1119
  }
1066
1120
  if (data) {
1067
1121
  setAuthValue(data.token);
1122
+ if (data.merchantAccount) {
1123
+ setResolvedMerchantAccount(data.merchantAccount);
1124
+ }
1068
1125
  }
1069
1126
  } catch (err) {
1070
1127
  onError({
@@ -1081,7 +1138,7 @@ function HubtelBridge({
1081
1138
  }
1082
1139
  };
1083
1140
  fetchAuth();
1084
- }, [paymentId, publicKey, hubtelSessionToken, basicAuth, onError]);
1141
+ }, [paymentId, publicKey, apiBaseUrl, clientSecret, hubtelSessionToken, basicAuth, onError]);
1085
1142
  const startPayment = useCallback(async () => {
1086
1143
  if (isLoading || !authValue) {
1087
1144
  return;
@@ -1101,7 +1158,7 @@ function HubtelBridge({
1101
1158
  const config = {
1102
1159
  branding: "enabled",
1103
1160
  callbackUrl: callbackUrl || window.location.href,
1104
- merchantAccount: typeof merchantAccount === "string" ? parseInt(merchantAccount, 10) : merchantAccount,
1161
+ merchantAccount: typeof resolvedMerchantAccount === "string" ? parseInt(resolvedMerchantAccount, 10) : resolvedMerchantAccount,
1105
1162
  // Use session token or basicAuth for authentication
1106
1163
  // Session tokens are base64-encoded credentials fetched securely from the server
1107
1164
  basicAuth: authValue || "",
@@ -1884,8 +1941,11 @@ function ReevitCheckout({
1884
1941
  currency,
1885
1942
  email = "",
1886
1943
  phone = "",
1944
+ customerName,
1887
1945
  reference,
1888
1946
  metadata,
1947
+ customFields,
1948
+ paymentLinkCode,
1889
1949
  paymentMethods = ["card", "mobile_money"],
1890
1950
  initialPaymentIntent,
1891
1951
  // Callbacks
@@ -1936,8 +1996,11 @@ function ReevitCheckout({
1936
1996
  currency,
1937
1997
  email,
1938
1998
  phone,
1999
+ customerName,
1939
2000
  reference,
1940
2001
  metadata,
2002
+ customFields,
2003
+ paymentLinkCode,
1941
2004
  paymentMethods,
1942
2005
  initialPaymentIntent
1943
2006
  },
@@ -2145,7 +2208,7 @@ function ReevitCheckout({
2145
2208
  const psp = selectedProvider || paymentIntent?.recommendedPsp || "paystack";
2146
2209
  const pspLower = psp.toLowerCase();
2147
2210
  if (showPSPBridge) {
2148
- const pspKey = paymentIntent?.pspPublicKey || publicKey;
2211
+ const pspKey = paymentIntent?.pspPublicKey || publicKey || "";
2149
2212
  const bridgeMetadata = {
2150
2213
  ...metadata,
2151
2214
  payment_id: paymentIntent?.id,
@@ -2185,6 +2248,8 @@ function ReevitCheckout({
2185
2248
  phone: momoData?.phone || phone,
2186
2249
  description: `Payment ${paymentIntent?.reference || reference || ""}`,
2187
2250
  hubtelSessionToken: paymentIntent?.id ? paymentIntent.id : void 0,
2251
+ clientSecret: paymentIntent?.clientSecret,
2252
+ apiBaseUrl,
2188
2253
  preferredMethod: selectedMethod || void 0,
2189
2254
  onSuccess: handlePSPSuccess,
2190
2255
  onError: (err) => handlePSPError(err),
@@ -2235,7 +2300,7 @@ function ReevitCheckout({
2235
2300
  currency: paymentIntent?.currency ?? currency,
2236
2301
  reference: paymentIntent?.reference || reference || `mpesa_${Date.now()}`,
2237
2302
  description: `Payment ${paymentIntent?.reference || reference || ""}`,
2238
- headers: { "x-reevit-public-key": publicKey },
2303
+ headers: { "x-reevit-public-key": publicKey || "" },
2239
2304
  onSuccess: handlePSPSuccess,
2240
2305
  onError: handlePSPError
2241
2306
  }
@@ -2328,7 +2393,7 @@ function ReevitCheckout({
2328
2393
  ] }) })
2329
2394
  ] });
2330
2395
  };
2331
- return /* @__PURE__ */ jsxs(ReevitContext.Provider, { value: { publicKey, amount, currency }, children: [
2396
+ return /* @__PURE__ */ jsxs(ReevitContext.Provider, { value: { publicKey: publicKey || "", amount, currency }, children: [
2332
2397
  trigger,
2333
2398
  isOpen && /* @__PURE__ */ jsx("div", { className: "reevit-overlay", onClick: handleClose, children: /* @__PURE__ */ jsxs(
2334
2399
  "div",