@reevit/react 0.4.3 → 0.4.5

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 CHANGED
@@ -8,8 +8,8 @@ type MobileMoneyNetwork = 'mtn' | 'vodafone' | 'airteltigo';
8
8
  /** Payment source type - indicates where the payment originated from */
9
9
  type PaymentSource = 'payment_link' | 'api' | 'subscription';
10
10
  interface ReevitCheckoutConfig {
11
- /** Your Reevit public key (pk_live_xxx or pk_test_xxx) */
12
- publicKey: string;
11
+ /** Your Reevit public key (required for API-created intents; omit for payment links) */
12
+ publicKey?: string;
13
13
  /** Amount in the smallest currency unit (e.g., pesewas for GHS) */
14
14
  amount: number;
15
15
  /** Currency code (e.g., 'GHS', 'NGN', 'USD') */
@@ -18,10 +18,16 @@ interface ReevitCheckoutConfig {
18
18
  email?: string;
19
19
  /** Customer phone number (required for mobile money) */
20
20
  phone?: string;
21
+ /** Customer name (optional, used for payment links) */
22
+ customerName?: string;
21
23
  /** Unique reference for this transaction */
22
24
  reference?: string;
23
25
  /** Additional metadata to attach to the payment */
24
26
  metadata?: Record<string, unknown>;
27
+ /** Custom fields for payment links (if applicable) */
28
+ customFields?: Record<string, unknown>;
29
+ /** Payment link code (for public checkout flows) */
30
+ paymentLinkCode?: string;
25
31
  /** Payment methods to display */
26
32
  paymentMethods?: PaymentMethod[];
27
33
  /** Optional existing payment intent to use instead of creating a new one */
@@ -182,7 +188,7 @@ interface ReevitContextValue {
182
188
  currency: string;
183
189
  }
184
190
  declare function useReevitContext(): ReevitContextValue;
185
- declare function ReevitCheckout({ publicKey, amount, currency, email, phone, reference, metadata, paymentMethods, initialPaymentIntent, onSuccess, onError, onClose, onStateChange, children, autoOpen, isOpen: controlledIsOpen, onOpenChange, theme, apiBaseUrl, }: ReevitCheckoutProps): react_jsx_runtime.JSX.Element;
191
+ declare function ReevitCheckout({ publicKey, amount, currency, email, phone, customerName, reference, metadata, customFields, paymentLinkCode, paymentMethods, initialPaymentIntent, onSuccess, onError, onClose, onStateChange, children, autoOpen, isOpen: controlledIsOpen, onOpenChange, theme, apiBaseUrl, }: ReevitCheckoutProps): react_jsx_runtime.JSX.Element;
186
192
 
187
193
  interface PaymentMethodSelectorProps {
188
194
  methods: PaymentMethod[];
@@ -291,7 +297,7 @@ declare function PaystackBridge({ publicKey, email, phone, amount, currency, ref
291
297
 
292
298
  interface HubtelBridgeProps {
293
299
  paymentId: string;
294
- publicKey: string;
300
+ publicKey?: string;
295
301
  merchantAccount: string | number;
296
302
  amount: number;
297
303
  currency?: string;
@@ -300,6 +306,8 @@ interface HubtelBridgeProps {
300
306
  phone?: string;
301
307
  description?: string;
302
308
  callbackUrl?: string;
309
+ apiBaseUrl?: string;
310
+ clientSecret?: string;
303
311
  /** Session token from server (recommended - credentials never exposed to client) */
304
312
  hubtelSessionToken?: string;
305
313
  /** Basic auth credential (legacy - credentials exposed to client, deprecated) */
@@ -310,7 +318,7 @@ interface HubtelBridgeProps {
310
318
  onClose: () => void;
311
319
  autoStart?: boolean;
312
320
  }
313
- declare function HubtelBridge({ paymentId, publicKey, merchantAccount, amount, reference, phone, description, callbackUrl, hubtelSessionToken, basicAuth, preferredMethod, onSuccess, onError, onClose, autoStart, }: HubtelBridgeProps): react_jsx_runtime.JSX.Element;
321
+ declare function HubtelBridge({ paymentId, publicKey, merchantAccount, amount, reference, phone, description, callbackUrl, apiBaseUrl, clientSecret, hubtelSessionToken, basicAuth, preferredMethod, onSuccess, onError, onClose, autoStart, }: HubtelBridgeProps): react_jsx_runtime.JSX.Element;
314
322
  /**
315
323
  * Opens Hubtel checkout modal directly
316
324
  * Uses the @hubteljs/checkout npm package
@@ -639,7 +647,7 @@ interface PaymentDetailResponse {
639
647
  }
640
648
  interface ReevitAPIClientConfig {
641
649
  /** Your Reevit public key */
642
- publicKey: string;
650
+ publicKey?: string;
643
651
  /** Base URL for the Reevit API (defaults to production) */
644
652
  baseUrl?: string;
645
653
  /** Request timeout in milliseconds */
@@ -660,7 +668,7 @@ declare class ReevitAPIClient {
660
668
  /**
661
669
  * Creates a payment intent
662
670
  */
663
- createPaymentIntent(config: ReevitCheckoutConfig, method: PaymentMethod, country?: string, options?: {
671
+ createPaymentIntent(config: ReevitCheckoutConfig, method?: PaymentMethod, country?: string, options?: {
664
672
  preferredProviders?: string[];
665
673
  allowedProviders?: string[];
666
674
  }): Promise<{
@@ -703,7 +711,7 @@ declare class ReevitAPIClient {
703
711
  * @param paymentId - The payment intent ID for Hubtel checkout
704
712
  * @returns Hubtel session with token, merchant account, and expiry information
705
713
  */
706
- createHubtelSession(paymentId: string): Promise<{
714
+ createHubtelSession(paymentId: string, clientSecret?: string): Promise<{
707
715
  data?: HubtelSessionResponse;
708
716
  error?: PaymentError;
709
717
  }>;
package/dist/index.d.ts CHANGED
@@ -8,8 +8,8 @@ type MobileMoneyNetwork = 'mtn' | 'vodafone' | 'airteltigo';
8
8
  /** Payment source type - indicates where the payment originated from */
9
9
  type PaymentSource = 'payment_link' | 'api' | 'subscription';
10
10
  interface ReevitCheckoutConfig {
11
- /** Your Reevit public key (pk_live_xxx or pk_test_xxx) */
12
- publicKey: string;
11
+ /** Your Reevit public key (required for API-created intents; omit for payment links) */
12
+ publicKey?: string;
13
13
  /** Amount in the smallest currency unit (e.g., pesewas for GHS) */
14
14
  amount: number;
15
15
  /** Currency code (e.g., 'GHS', 'NGN', 'USD') */
@@ -18,10 +18,16 @@ interface ReevitCheckoutConfig {
18
18
  email?: string;
19
19
  /** Customer phone number (required for mobile money) */
20
20
  phone?: string;
21
+ /** Customer name (optional, used for payment links) */
22
+ customerName?: string;
21
23
  /** Unique reference for this transaction */
22
24
  reference?: string;
23
25
  /** Additional metadata to attach to the payment */
24
26
  metadata?: Record<string, unknown>;
27
+ /** Custom fields for payment links (if applicable) */
28
+ customFields?: Record<string, unknown>;
29
+ /** Payment link code (for public checkout flows) */
30
+ paymentLinkCode?: string;
25
31
  /** Payment methods to display */
26
32
  paymentMethods?: PaymentMethod[];
27
33
  /** Optional existing payment intent to use instead of creating a new one */
@@ -182,7 +188,7 @@ interface ReevitContextValue {
182
188
  currency: string;
183
189
  }
184
190
  declare function useReevitContext(): ReevitContextValue;
185
- declare function ReevitCheckout({ publicKey, amount, currency, email, phone, reference, metadata, paymentMethods, initialPaymentIntent, onSuccess, onError, onClose, onStateChange, children, autoOpen, isOpen: controlledIsOpen, onOpenChange, theme, apiBaseUrl, }: ReevitCheckoutProps): react_jsx_runtime.JSX.Element;
191
+ declare function ReevitCheckout({ publicKey, amount, currency, email, phone, customerName, reference, metadata, customFields, paymentLinkCode, paymentMethods, initialPaymentIntent, onSuccess, onError, onClose, onStateChange, children, autoOpen, isOpen: controlledIsOpen, onOpenChange, theme, apiBaseUrl, }: ReevitCheckoutProps): react_jsx_runtime.JSX.Element;
186
192
 
187
193
  interface PaymentMethodSelectorProps {
188
194
  methods: PaymentMethod[];
@@ -291,7 +297,7 @@ declare function PaystackBridge({ publicKey, email, phone, amount, currency, ref
291
297
 
292
298
  interface HubtelBridgeProps {
293
299
  paymentId: string;
294
- publicKey: string;
300
+ publicKey?: string;
295
301
  merchantAccount: string | number;
296
302
  amount: number;
297
303
  currency?: string;
@@ -300,6 +306,8 @@ interface HubtelBridgeProps {
300
306
  phone?: string;
301
307
  description?: string;
302
308
  callbackUrl?: string;
309
+ apiBaseUrl?: string;
310
+ clientSecret?: string;
303
311
  /** Session token from server (recommended - credentials never exposed to client) */
304
312
  hubtelSessionToken?: string;
305
313
  /** Basic auth credential (legacy - credentials exposed to client, deprecated) */
@@ -310,7 +318,7 @@ interface HubtelBridgeProps {
310
318
  onClose: () => void;
311
319
  autoStart?: boolean;
312
320
  }
313
- declare function HubtelBridge({ paymentId, publicKey, merchantAccount, amount, reference, phone, description, callbackUrl, hubtelSessionToken, basicAuth, preferredMethod, onSuccess, onError, onClose, autoStart, }: HubtelBridgeProps): react_jsx_runtime.JSX.Element;
321
+ declare function HubtelBridge({ paymentId, publicKey, merchantAccount, amount, reference, phone, description, callbackUrl, apiBaseUrl, clientSecret, hubtelSessionToken, basicAuth, preferredMethod, onSuccess, onError, onClose, autoStart, }: HubtelBridgeProps): react_jsx_runtime.JSX.Element;
314
322
  /**
315
323
  * Opens Hubtel checkout modal directly
316
324
  * Uses the @hubteljs/checkout npm package
@@ -639,7 +647,7 @@ interface PaymentDetailResponse {
639
647
  }
640
648
  interface ReevitAPIClientConfig {
641
649
  /** Your Reevit public key */
642
- publicKey: string;
650
+ publicKey?: string;
643
651
  /** Base URL for the Reevit API (defaults to production) */
644
652
  baseUrl?: string;
645
653
  /** Request timeout in milliseconds */
@@ -660,7 +668,7 @@ declare class ReevitAPIClient {
660
668
  /**
661
669
  * Creates a payment intent
662
670
  */
663
- createPaymentIntent(config: ReevitCheckoutConfig, method: PaymentMethod, country?: string, options?: {
671
+ createPaymentIntent(config: ReevitCheckoutConfig, method?: PaymentMethod, country?: string, options?: {
664
672
  preferredProviders?: string[];
665
673
  allowedProviders?: string[];
666
674
  }): Promise<{
@@ -703,7 +711,7 @@ declare class ReevitAPIClient {
703
711
  * @param paymentId - The payment intent ID for Hubtel checkout
704
712
  * @returns Hubtel session with token, merchant account, and expiry information
705
713
  */
706
- createHubtelSession(paymentId: string): Promise<{
714
+ createHubtelSession(paymentId: string, clientSecret?: string): Promise<{
707
715
  data?: HubtelSessionResponse;
708
716
  error?: PaymentError;
709
717
  }>;
package/dist/index.js CHANGED
@@ -138,8 +138,8 @@ function createPaymentError(response, errorData) {
138
138
  }
139
139
  var ReevitAPIClient = class {
140
140
  constructor(config) {
141
- this.publicKey = config.publicKey;
142
- this.baseUrl = config.baseUrl || (isSandboxKey(config.publicKey) ? API_BASE_URL_SANDBOX : API_BASE_URL_PRODUCTION);
141
+ this.publicKey = config.publicKey || "";
142
+ this.baseUrl = config.baseUrl || (config.publicKey && isSandboxKey(config.publicKey) ? API_BASE_URL_SANDBOX : API_BASE_URL_PRODUCTION);
143
143
  this.timeout = config.timeout || DEFAULT_TIMEOUT;
144
144
  }
145
145
  /**
@@ -150,10 +150,12 @@ var ReevitAPIClient = class {
150
150
  const timeoutId = setTimeout(() => controller.abort(), this.timeout);
151
151
  const headers = {
152
152
  "Content-Type": "application/json",
153
- "X-Reevit-Key": this.publicKey,
154
153
  "X-Reevit-Client": "@reevit/react",
155
154
  "X-Reevit-Client-Version": "0.3.2"
156
155
  };
156
+ if (this.publicKey) {
157
+ headers["X-Reevit-Key"] = this.publicKey;
158
+ }
157
159
  if (method === "POST" || method === "PATCH" || method === "PUT") {
158
160
  headers["Idempotency-Key"] = `${Date.now()}-${Math.random().toString(36).substring(2, 15)}`;
159
161
  }
@@ -214,12 +216,14 @@ var ReevitAPIClient = class {
214
216
  const request = {
215
217
  amount: config.amount,
216
218
  currency: config.currency,
217
- method: this.mapPaymentMethod(method),
218
219
  country,
219
220
  customer_id: config.email || config.metadata?.customerId,
220
221
  phone: config.phone,
221
222
  metadata
222
223
  };
224
+ if (method) {
225
+ request.method = this.mapPaymentMethod(method);
226
+ }
223
227
  if (options?.preferredProviders?.length || options?.allowedProviders?.length) {
224
228
  request.policy = {
225
229
  prefer: options?.preferredProviders,
@@ -260,8 +264,9 @@ var ReevitAPIClient = class {
260
264
  * @param paymentId - The payment intent ID for Hubtel checkout
261
265
  * @returns Hubtel session with token, merchant account, and expiry information
262
266
  */
263
- async createHubtelSession(paymentId) {
264
- return this.request("POST", `/v1/payments/hubtel/sessions/${paymentId}`);
267
+ async createHubtelSession(paymentId, clientSecret) {
268
+ const query = clientSecret ? `?client_secret=${encodeURIComponent(clientSecret)}` : "";
269
+ return this.request("POST", `/v1/payments/hubtel/sessions/${paymentId}${query}`);
265
270
  }
266
271
  /**
267
272
  * Maps SDK payment method to backend format
@@ -291,6 +296,18 @@ var initialState = {
291
296
  error: null,
292
297
  result: null
293
298
  };
299
+ var DEFAULT_PUBLIC_API_BASE_URL = "https://api.reevit.io";
300
+ function buildPaymentLinkError(response, data) {
301
+ return {
302
+ code: data?.code || "payment_link_error",
303
+ message: data?.message || "Payment link request failed",
304
+ recoverable: true,
305
+ details: {
306
+ httpStatus: response.status,
307
+ ...data?.details || {}
308
+ }
309
+ };
310
+ }
294
311
  function reevitReducer(state, action) {
295
312
  switch (action.type) {
296
313
  case "INIT_START":
@@ -413,16 +430,50 @@ function useReevit(options) {
413
430
  }
414
431
  const reference = config.reference || generateReference();
415
432
  const country = detectCountryFromCurrency(config.currency);
416
- const paymentMethod = method || config.paymentMethods?.[0] || "card";
417
- const { data, error } = await apiClient.createPaymentIntent(
418
- { ...config, reference },
419
- paymentMethod,
420
- country,
421
- {
422
- preferredProviders: options2?.preferredProvider ? [options2.preferredProvider] : void 0,
423
- allowedProviders: options2?.allowedProviders
433
+ const defaultMethod = config.paymentMethods && config.paymentMethods.length === 1 ? config.paymentMethods[0] : void 0;
434
+ const paymentMethod = method ?? defaultMethod;
435
+ let data;
436
+ let error;
437
+ if (config.paymentLinkCode) {
438
+ const response = await fetch(
439
+ `${apiBaseUrl || DEFAULT_PUBLIC_API_BASE_URL}/v1/pay/${config.paymentLinkCode}/pay`,
440
+ {
441
+ method: "POST",
442
+ headers: {
443
+ "Content-Type": "application/json",
444
+ "Idempotency-Key": `${Date.now()}-${Math.random().toString(36).substring(2, 15)}`
445
+ },
446
+ body: JSON.stringify({
447
+ amount: config.amount,
448
+ email: config.email || "",
449
+ name: config.customerName || "",
450
+ phone: config.phone || "",
451
+ method: paymentMethod,
452
+ country,
453
+ provider: options2?.preferredProvider || options2?.allowedProviders?.[0],
454
+ custom_fields: config.customFields
455
+ })
456
+ }
457
+ );
458
+ const responseData = await response.json().catch(() => ({}));
459
+ if (!response.ok) {
460
+ error = buildPaymentLinkError(response, responseData);
461
+ } else {
462
+ data = responseData;
424
463
  }
425
- );
464
+ } else {
465
+ const result = await apiClient.createPaymentIntent(
466
+ { ...config, reference },
467
+ paymentMethod,
468
+ country,
469
+ {
470
+ preferredProviders: options2?.preferredProvider ? [options2.preferredProvider] : void 0,
471
+ allowedProviders: options2?.allowedProviders
472
+ }
473
+ );
474
+ data = result.data;
475
+ error = result.error;
476
+ }
426
477
  if (error) {
427
478
  dispatch({ type: "INIT_ERROR", payload: error });
428
479
  onError?.(error);
@@ -1042,6 +1093,8 @@ function HubtelBridge({
1042
1093
  phone,
1043
1094
  description = "Payment",
1044
1095
  callbackUrl,
1096
+ apiBaseUrl,
1097
+ clientSecret,
1045
1098
  hubtelSessionToken,
1046
1099
  basicAuth,
1047
1100
  preferredMethod,
@@ -1054,13 +1107,17 @@ function HubtelBridge({
1054
1107
  const checkoutRef = react.useRef(null);
1055
1108
  const [authValue, setAuthValue] = react.useState("");
1056
1109
  const [isLoading, setIsLoading] = react.useState(false);
1110
+ const [resolvedMerchantAccount, setResolvedMerchantAccount] = react.useState(merchantAccount);
1111
+ react.useEffect(() => {
1112
+ setResolvedMerchantAccount(merchantAccount);
1113
+ }, [merchantAccount]);
1057
1114
  react.useEffect(() => {
1058
1115
  const fetchAuth = async () => {
1059
1116
  if (hubtelSessionToken) {
1060
1117
  setIsLoading(true);
1061
1118
  try {
1062
- const client = createReevitClient({ publicKey });
1063
- const { data, error } = await client.createHubtelSession(paymentId);
1119
+ const client = createReevitClient({ publicKey, baseUrl: apiBaseUrl });
1120
+ const { data, error } = await client.createHubtelSession(paymentId, clientSecret);
1064
1121
  if (error) {
1065
1122
  onError({
1066
1123
  code: "SESSION_ERROR",
@@ -1071,6 +1128,9 @@ function HubtelBridge({
1071
1128
  }
1072
1129
  if (data) {
1073
1130
  setAuthValue(data.token);
1131
+ if (data.merchantAccount) {
1132
+ setResolvedMerchantAccount(data.merchantAccount);
1133
+ }
1074
1134
  }
1075
1135
  } catch (err) {
1076
1136
  onError({
@@ -1087,7 +1147,7 @@ function HubtelBridge({
1087
1147
  }
1088
1148
  };
1089
1149
  fetchAuth();
1090
- }, [paymentId, publicKey, hubtelSessionToken, basicAuth, onError]);
1150
+ }, [paymentId, publicKey, apiBaseUrl, clientSecret, hubtelSessionToken, basicAuth, onError]);
1091
1151
  const startPayment = react.useCallback(async () => {
1092
1152
  if (isLoading || !authValue) {
1093
1153
  return;
@@ -1107,7 +1167,7 @@ function HubtelBridge({
1107
1167
  const config = {
1108
1168
  branding: "enabled",
1109
1169
  callbackUrl: callbackUrl || window.location.href,
1110
- merchantAccount: typeof merchantAccount === "string" ? parseInt(merchantAccount, 10) : merchantAccount,
1170
+ merchantAccount: typeof resolvedMerchantAccount === "string" ? parseInt(resolvedMerchantAccount, 10) : resolvedMerchantAccount,
1111
1171
  // Use session token or basicAuth for authentication
1112
1172
  // Session tokens are base64-encoded credentials fetched securely from the server
1113
1173
  basicAuth: authValue || "",
@@ -1890,8 +1950,11 @@ function ReevitCheckout({
1890
1950
  currency,
1891
1951
  email = "",
1892
1952
  phone = "",
1953
+ customerName,
1893
1954
  reference,
1894
1955
  metadata,
1956
+ customFields,
1957
+ paymentLinkCode,
1895
1958
  paymentMethods = ["card", "mobile_money"],
1896
1959
  initialPaymentIntent,
1897
1960
  // Callbacks
@@ -1942,8 +2005,11 @@ function ReevitCheckout({
1942
2005
  currency,
1943
2006
  email,
1944
2007
  phone,
2008
+ customerName,
1945
2009
  reference,
1946
2010
  metadata,
2011
+ customFields,
2012
+ paymentLinkCode,
1947
2013
  paymentMethods,
1948
2014
  initialPaymentIntent
1949
2015
  },
@@ -2151,7 +2217,7 @@ function ReevitCheckout({
2151
2217
  const psp = selectedProvider || paymentIntent?.recommendedPsp || "paystack";
2152
2218
  const pspLower = psp.toLowerCase();
2153
2219
  if (showPSPBridge) {
2154
- const pspKey = paymentIntent?.pspPublicKey || publicKey;
2220
+ const pspKey = paymentIntent?.pspPublicKey || publicKey || "";
2155
2221
  const bridgeMetadata = {
2156
2222
  ...metadata,
2157
2223
  payment_id: paymentIntent?.id,
@@ -2191,6 +2257,8 @@ function ReevitCheckout({
2191
2257
  phone: momoData?.phone || phone,
2192
2258
  description: `Payment ${paymentIntent?.reference || reference || ""}`,
2193
2259
  hubtelSessionToken: paymentIntent?.id ? paymentIntent.id : void 0,
2260
+ clientSecret: paymentIntent?.clientSecret,
2261
+ apiBaseUrl,
2194
2262
  preferredMethod: selectedMethod || void 0,
2195
2263
  onSuccess: handlePSPSuccess,
2196
2264
  onError: (err) => handlePSPError(err),
@@ -2241,7 +2309,7 @@ function ReevitCheckout({
2241
2309
  currency: paymentIntent?.currency ?? currency,
2242
2310
  reference: paymentIntent?.reference || reference || `mpesa_${Date.now()}`,
2243
2311
  description: `Payment ${paymentIntent?.reference || reference || ""}`,
2244
- headers: { "x-reevit-public-key": publicKey },
2312
+ headers: { "x-reevit-public-key": publicKey || "" },
2245
2313
  onSuccess: handlePSPSuccess,
2246
2314
  onError: handlePSPError
2247
2315
  }
@@ -2334,7 +2402,7 @@ function ReevitCheckout({
2334
2402
  ] }) })
2335
2403
  ] });
2336
2404
  };
2337
- return /* @__PURE__ */ jsxRuntime.jsxs(ReevitContext.Provider, { value: { publicKey, amount, currency }, children: [
2405
+ return /* @__PURE__ */ jsxRuntime.jsxs(ReevitContext.Provider, { value: { publicKey: publicKey || "", amount, currency }, children: [
2338
2406
  trigger,
2339
2407
  isOpen && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "reevit-overlay", onClick: handleClose, children: /* @__PURE__ */ jsxRuntime.jsxs(
2340
2408
  "div",