@reevit/react 0.4.5 → 0.4.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.d.mts CHANGED
@@ -117,6 +117,8 @@ interface ReevitTheme {
117
117
  darkMode?: boolean;
118
118
  /** Custom logo URL to display in checkout header */
119
119
  logoUrl?: string;
120
+ /** Company or organization name to display in checkout header */
121
+ companyName?: string;
120
122
  /** PSP selector background color */
121
123
  pspSelectorBgColor?: string;
122
124
  /** PSP selector text color */
@@ -308,9 +310,9 @@ interface HubtelBridgeProps {
308
310
  callbackUrl?: string;
309
311
  apiBaseUrl?: string;
310
312
  clientSecret?: string;
311
- /** Session token from server (recommended - credentials never exposed to client) */
313
+ /** Session token from server (triggers session fetch) */
312
314
  hubtelSessionToken?: string;
313
- /** Basic auth credential (legacy - credentials exposed to client, deprecated) */
315
+ /** Base64 basic auth credential (legacy - credentials exposed) */
314
316
  basicAuth?: string;
315
317
  preferredMethod?: PaymentMethod;
316
318
  onSuccess: (result: PaymentResult) => void;
@@ -318,7 +320,7 @@ interface HubtelBridgeProps {
318
320
  onClose: () => void;
319
321
  autoStart?: boolean;
320
322
  }
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;
323
+ declare function HubtelBridge({ paymentId, publicKey, merchantAccount, amount, currency, reference, email, phone, description, callbackUrl, apiBaseUrl, clientSecret, hubtelSessionToken, basicAuth, preferredMethod, onSuccess, onError, onClose, autoStart, }: HubtelBridgeProps): react_jsx_runtime.JSX.Element;
322
324
  /**
323
325
  * Opens Hubtel checkout modal directly
324
326
  * Uses the @hubteljs/checkout npm package
@@ -616,6 +618,8 @@ interface HubtelSessionResponse {
616
618
  token: string;
617
619
  /** Hubtel merchant account number */
618
620
  merchantAccount: string;
621
+ /** Base64 basic auth for Hubtel checkout (exposes credentials) */
622
+ basicAuth?: string;
619
623
  /** Token expiry time in seconds */
620
624
  expiresInSeconds: number;
621
625
  /** Unix timestamp when the token expires */
package/dist/index.d.ts CHANGED
@@ -117,6 +117,8 @@ interface ReevitTheme {
117
117
  darkMode?: boolean;
118
118
  /** Custom logo URL to display in checkout header */
119
119
  logoUrl?: string;
120
+ /** Company or organization name to display in checkout header */
121
+ companyName?: string;
120
122
  /** PSP selector background color */
121
123
  pspSelectorBgColor?: string;
122
124
  /** PSP selector text color */
@@ -308,9 +310,9 @@ interface HubtelBridgeProps {
308
310
  callbackUrl?: string;
309
311
  apiBaseUrl?: string;
310
312
  clientSecret?: string;
311
- /** Session token from server (recommended - credentials never exposed to client) */
313
+ /** Session token from server (triggers session fetch) */
312
314
  hubtelSessionToken?: string;
313
- /** Basic auth credential (legacy - credentials exposed to client, deprecated) */
315
+ /** Base64 basic auth credential (legacy - credentials exposed) */
314
316
  basicAuth?: string;
315
317
  preferredMethod?: PaymentMethod;
316
318
  onSuccess: (result: PaymentResult) => void;
@@ -318,7 +320,7 @@ interface HubtelBridgeProps {
318
320
  onClose: () => void;
319
321
  autoStart?: boolean;
320
322
  }
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;
323
+ declare function HubtelBridge({ paymentId, publicKey, merchantAccount, amount, currency, reference, email, phone, description, callbackUrl, apiBaseUrl, clientSecret, hubtelSessionToken, basicAuth, preferredMethod, onSuccess, onError, onClose, autoStart, }: HubtelBridgeProps): react_jsx_runtime.JSX.Element;
322
324
  /**
323
325
  * Opens Hubtel checkout modal directly
324
326
  * Uses the @hubteljs/checkout npm package
@@ -616,6 +618,8 @@ interface HubtelSessionResponse {
616
618
  token: string;
617
619
  /** Hubtel merchant account number */
618
620
  merchantAccount: string;
621
+ /** Base64 basic auth for Hubtel checkout (exposes credentials) */
622
+ basicAuth?: string;
619
623
  /** Token expiry time in seconds */
620
624
  expiresInSeconds: number;
621
625
  /** Unix timestamp when the token expires */
package/dist/index.js CHANGED
@@ -366,6 +366,36 @@ function mapAvailableProviders(providers) {
366
366
  };
367
367
  }).filter((provider) => provider.methods.length > 0);
368
368
  }
369
+ function normalizeBranding(branding) {
370
+ if (!branding) {
371
+ return {};
372
+ }
373
+ const raw = branding;
374
+ const theme = { ...raw };
375
+ const getString = (value) => typeof value === "string" ? value : void 0;
376
+ const getBoolean = (value) => typeof value === "boolean" ? value : void 0;
377
+ const setIf = (key, value) => {
378
+ if (value !== void 0) {
379
+ theme[key] = value;
380
+ }
381
+ };
382
+ setIf("logoUrl", getString(raw.logoUrl ?? raw.logo_url));
383
+ setIf("companyName", getString(raw.companyName ?? raw.company_name));
384
+ setIf("primaryColor", getString(raw.primaryColor ?? raw.primary_color));
385
+ setIf("primaryForegroundColor", getString(raw.primaryForegroundColor ?? raw.primary_foreground_color));
386
+ setIf("backgroundColor", getString(raw.backgroundColor ?? raw.background_color));
387
+ setIf("surfaceColor", getString(raw.surfaceColor ?? raw.surface_color));
388
+ setIf("textColor", getString(raw.textColor ?? raw.text_color));
389
+ setIf("mutedTextColor", getString(raw.mutedTextColor ?? raw.muted_text_color));
390
+ setIf("borderRadius", getString(raw.borderRadius ?? raw.border_radius));
391
+ setIf("fontFamily", getString(raw.fontFamily ?? raw.font_family));
392
+ setIf("darkMode", getBoolean(raw.darkMode ?? raw.dark_mode));
393
+ setIf("pspSelectorBgColor", getString(raw.pspSelectorBgColor ?? raw.psp_selector_bg_color));
394
+ setIf("pspSelectorTextColor", getString(raw.pspSelectorTextColor ?? raw.psp_selector_text_color));
395
+ setIf("pspSelectorBorderColor", getString(raw.pspSelectorBorderColor ?? raw.psp_selector_border_color));
396
+ setIf("pspSelectorUseBorder", getBoolean(raw.pspSelectorUseBorder ?? raw.psp_selector_use_border));
397
+ return theme;
398
+ }
369
399
  function mapToPaymentIntent(response, config) {
370
400
  return {
371
401
  id: response.id,
@@ -385,7 +415,7 @@ function mapToPaymentIntent(response, config) {
385
415
  netAmount: response.net_amount,
386
416
  metadata: config.metadata,
387
417
  availableProviders: mapAvailableProviders(response.available_psps),
388
- branding: response.branding
418
+ branding: normalizeBranding(response.branding)
389
419
  };
390
420
  }
391
421
  function useReevit(options) {
@@ -1089,7 +1119,9 @@ function HubtelBridge({
1089
1119
  publicKey,
1090
1120
  merchantAccount,
1091
1121
  amount,
1122
+ currency,
1092
1123
  reference,
1124
+ email,
1093
1125
  phone,
1094
1126
  description = "Payment",
1095
1127
  callbackUrl,
@@ -1104,7 +1136,6 @@ function HubtelBridge({
1104
1136
  autoStart = true
1105
1137
  }) {
1106
1138
  const initialized = react.useRef(false);
1107
- const checkoutRef = react.useRef(null);
1108
1139
  const [authValue, setAuthValue] = react.useState("");
1109
1140
  const [isLoading, setIsLoading] = react.useState(false);
1110
1141
  const [resolvedMerchantAccount, setResolvedMerchantAccount] = react.useState(merchantAccount);
@@ -1118,19 +1149,17 @@ function HubtelBridge({
1118
1149
  try {
1119
1150
  const client = createReevitClient({ publicKey, baseUrl: apiBaseUrl });
1120
1151
  const { data, error } = await client.createHubtelSession(paymentId, clientSecret);
1121
- if (error) {
1152
+ if (error || !data?.basicAuth) {
1122
1153
  onError({
1123
1154
  code: "SESSION_ERROR",
1124
- message: error.message || "Failed to create Hubtel session",
1155
+ message: error?.message || "Failed to create Hubtel session",
1125
1156
  recoverable: true
1126
1157
  });
1127
1158
  return;
1128
1159
  }
1129
- if (data) {
1130
- setAuthValue(data.token);
1131
- if (data.merchantAccount) {
1132
- setResolvedMerchantAccount(data.merchantAccount);
1133
- }
1160
+ setAuthValue(data.basicAuth);
1161
+ if (data.merchantAccount) {
1162
+ setResolvedMerchantAccount(data.merchantAccount);
1134
1163
  }
1135
1164
  } catch (err) {
1136
1165
  onError({
@@ -1154,13 +1183,13 @@ function HubtelBridge({
1154
1183
  }
1155
1184
  try {
1156
1185
  const checkout = new CheckoutSdk__default.default();
1157
- checkoutRef.current = checkout;
1158
1186
  const methodPreference = preferredMethod === "mobile_money" ? "momo" : preferredMethod === "card" ? "card" : void 0;
1159
1187
  const purchaseInfo = {
1160
1188
  amount: amount / 100,
1161
1189
  // Convert from minor to major units
1162
1190
  purchaseDescription: description,
1163
1191
  customerPhoneNumber: phone || "",
1192
+ ...email ? { customerEmail: email } : {},
1164
1193
  clientReference: reference || `hubtel_${Date.now()}`,
1165
1194
  ...methodPreference ? { paymentMethod: methodPreference } : {}
1166
1195
  };
@@ -1168,8 +1197,6 @@ function HubtelBridge({
1168
1197
  branding: "enabled",
1169
1198
  callbackUrl: callbackUrl || window.location.href,
1170
1199
  merchantAccount: typeof resolvedMerchantAccount === "string" ? parseInt(resolvedMerchantAccount, 10) : resolvedMerchantAccount,
1171
- // Use session token or basicAuth for authentication
1172
- // Session tokens are base64-encoded credentials fetched securely from the server
1173
1200
  basicAuth: authValue || "",
1174
1201
  ...methodPreference ? { paymentMethod: methodPreference } : {}
1175
1202
  };
@@ -1183,8 +1210,8 @@ function HubtelBridge({
1183
1210
  paymentId: data.transactionId || reference || "",
1184
1211
  reference: data.clientReference || reference || "",
1185
1212
  amount,
1186
- currency: "GHS",
1187
- paymentMethod: "mobile_money",
1213
+ currency: currency || "GHS",
1214
+ paymentMethod: preferredMethod || "mobile_money",
1188
1215
  psp: "hubtel",
1189
1216
  pspReference: data.transactionId || "",
1190
1217
  status: "success"
@@ -1215,7 +1242,21 @@ function HubtelBridge({
1215
1242
  };
1216
1243
  onError(error);
1217
1244
  }
1218
- }, [merchantAccount, amount, reference, phone, description, callbackUrl, authValue, isLoading, preferredMethod, onSuccess, onError, onClose]);
1245
+ }, [
1246
+ amount,
1247
+ reference,
1248
+ phone,
1249
+ description,
1250
+ callbackUrl,
1251
+ authValue,
1252
+ isLoading,
1253
+ preferredMethod,
1254
+ onSuccess,
1255
+ onError,
1256
+ onClose,
1257
+ resolvedMerchantAccount,
1258
+ currency
1259
+ ]);
1219
1260
  react.useEffect(() => {
1220
1261
  if (autoStart && !initialized.current && !isLoading && authValue) {
1221
1262
  initialized.current = true;
@@ -2173,6 +2214,7 @@ function ReevitCheckout({
2173
2214
  };
2174
2215
  }, [paymentIntent?.branding, theme]);
2175
2216
  const themeStyles = resolvedTheme ? createThemeVariables(resolvedTheme) : {};
2217
+ const brandName = resolvedTheme?.companyName;
2176
2218
  const themeMode = resolvedTheme?.darkMode;
2177
2219
  const dataTheme = react.useMemo(() => {
2178
2220
  if (typeof themeMode === "boolean") {
@@ -2249,7 +2291,7 @@ function ReevitCheckout({
2249
2291
  {
2250
2292
  paymentId: paymentIntent?.id || "",
2251
2293
  publicKey,
2252
- merchantAccount: pspKey,
2294
+ merchantAccount: paymentIntent?.pspCredentials?.merchantAccount || "",
2253
2295
  amount: paymentIntent?.amount ?? amount,
2254
2296
  currency: paymentIntent?.currency ?? currency,
2255
2297
  reference: paymentIntent?.reference || reference,
@@ -2415,7 +2457,17 @@ function ReevitCheckout({
2415
2457
  "aria-modal": "true",
2416
2458
  children: [
2417
2459
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "reevit-modal__header", children: [
2418
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "reevit-modal__branding", children: /* @__PURE__ */ jsxRuntime.jsx("img", { src: resolvedTheme?.logoUrl || "https://i.imgur.com/bzUR5Lm.png", alt: "Checkout", className: "reevit-modal__logo" }) }),
2460
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "reevit-modal__branding", children: [
2461
+ /* @__PURE__ */ jsxRuntime.jsx(
2462
+ "img",
2463
+ {
2464
+ src: resolvedTheme?.logoUrl || "https://i.imgur.com/bzUR5Lm.png",
2465
+ alt: brandName || "Reevit",
2466
+ className: "reevit-modal__logo"
2467
+ }
2468
+ ),
2469
+ brandName && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "reevit-modal__brand-name", children: brandName })
2470
+ ] }),
2419
2471
  /* @__PURE__ */ jsxRuntime.jsx("button", { className: "reevit-modal__close", onClick: handleClose, "aria-label": "Close", children: "\u2715" })
2420
2472
  ] }),
2421
2473
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "reevit-modal__amount", children: [