@reevit/react 0.3.0 → 0.3.2

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
@@ -118,6 +118,8 @@ interface PaymentIntent {
118
118
  recommendedPsp: 'paystack' | 'hubtel' | 'flutterwave';
119
119
  /** Available payment methods for this intent */
120
120
  availableMethods: PaymentMethod[];
121
+ /** Reference provided or generated */
122
+ reference?: string;
121
123
  /** Connection ID (from Reevit backend) */
122
124
  connectionId?: string;
123
125
  /** Provider name (from backend) */
@@ -203,9 +205,10 @@ interface PaystackConfig {
203
205
  key: string;
204
206
  email: string;
205
207
  phone?: string;
206
- amount: number;
208
+ amount?: number;
207
209
  currency?: string;
208
210
  ref?: string;
211
+ access_code?: string;
209
212
  metadata?: Record<string, unknown>;
210
213
  channels?: string[];
211
214
  callback: (response: PaystackResponse) => void;
@@ -226,6 +229,7 @@ interface PaystackBridgeProps {
226
229
  amount: number;
227
230
  currency?: string;
228
231
  reference?: string;
232
+ accessCode?: string;
229
233
  metadata?: Record<string, unknown>;
230
234
  channels?: ('card' | 'bank' | 'ussd' | 'qr' | 'mobile_money' | 'bank_transfer')[];
231
235
  onSuccess: (result: PaymentResult) => void;
@@ -234,7 +238,7 @@ interface PaystackBridgeProps {
234
238
  autoStart?: boolean;
235
239
  }
236
240
  declare function loadPaystackScript(): Promise<void>;
237
- declare function PaystackBridge({ publicKey, email, phone, amount, currency, reference, metadata, channels, onSuccess, onError, onClose, autoStart, }: PaystackBridgeProps): react_jsx_runtime.JSX.Element;
241
+ declare function PaystackBridge({ publicKey, email, phone, amount, currency, reference, accessCode, metadata, channels, onSuccess, onError, onClose, autoStart, }: PaystackBridgeProps): react_jsx_runtime.JSX.Element;
238
242
 
239
243
  declare global {
240
244
  interface Window {
@@ -541,6 +545,7 @@ interface PaymentIntentResponse {
541
545
  fee_amount: number;
542
546
  fee_currency: string;
543
547
  net_amount: number;
548
+ reference?: string;
544
549
  }
545
550
  interface PaymentDetailResponse {
546
551
  id: string;
@@ -595,7 +600,14 @@ declare class ReevitAPIClient {
595
600
  error?: PaymentError;
596
601
  }>;
597
602
  /**
598
- * Confirms a payment after PSP callback
603
+ * Confirms a payment intent after PSP callback (public endpoint)
604
+ */
605
+ confirmPaymentIntent(paymentId: string, clientSecret: string): Promise<{
606
+ data?: PaymentDetailResponse;
607
+ error?: PaymentError;
608
+ }>;
609
+ /**
610
+ * Confirms a payment after PSP callback (authenticated endpoint)
599
611
  */
600
612
  confirmPayment(paymentId: string): Promise<{
601
613
  data?: PaymentDetailResponse;
package/dist/index.d.ts CHANGED
@@ -118,6 +118,8 @@ interface PaymentIntent {
118
118
  recommendedPsp: 'paystack' | 'hubtel' | 'flutterwave';
119
119
  /** Available payment methods for this intent */
120
120
  availableMethods: PaymentMethod[];
121
+ /** Reference provided or generated */
122
+ reference?: string;
121
123
  /** Connection ID (from Reevit backend) */
122
124
  connectionId?: string;
123
125
  /** Provider name (from backend) */
@@ -203,9 +205,10 @@ interface PaystackConfig {
203
205
  key: string;
204
206
  email: string;
205
207
  phone?: string;
206
- amount: number;
208
+ amount?: number;
207
209
  currency?: string;
208
210
  ref?: string;
211
+ access_code?: string;
209
212
  metadata?: Record<string, unknown>;
210
213
  channels?: string[];
211
214
  callback: (response: PaystackResponse) => void;
@@ -226,6 +229,7 @@ interface PaystackBridgeProps {
226
229
  amount: number;
227
230
  currency?: string;
228
231
  reference?: string;
232
+ accessCode?: string;
229
233
  metadata?: Record<string, unknown>;
230
234
  channels?: ('card' | 'bank' | 'ussd' | 'qr' | 'mobile_money' | 'bank_transfer')[];
231
235
  onSuccess: (result: PaymentResult) => void;
@@ -234,7 +238,7 @@ interface PaystackBridgeProps {
234
238
  autoStart?: boolean;
235
239
  }
236
240
  declare function loadPaystackScript(): Promise<void>;
237
- declare function PaystackBridge({ publicKey, email, phone, amount, currency, reference, metadata, channels, onSuccess, onError, onClose, autoStart, }: PaystackBridgeProps): react_jsx_runtime.JSX.Element;
241
+ declare function PaystackBridge({ publicKey, email, phone, amount, currency, reference, accessCode, metadata, channels, onSuccess, onError, onClose, autoStart, }: PaystackBridgeProps): react_jsx_runtime.JSX.Element;
238
242
 
239
243
  declare global {
240
244
  interface Window {
@@ -541,6 +545,7 @@ interface PaymentIntentResponse {
541
545
  fee_amount: number;
542
546
  fee_currency: string;
543
547
  net_amount: number;
548
+ reference?: string;
544
549
  }
545
550
  interface PaymentDetailResponse {
546
551
  id: string;
@@ -595,7 +600,14 @@ declare class ReevitAPIClient {
595
600
  error?: PaymentError;
596
601
  }>;
597
602
  /**
598
- * Confirms a payment after PSP callback
603
+ * Confirms a payment intent after PSP callback (public endpoint)
604
+ */
605
+ confirmPaymentIntent(paymentId: string, clientSecret: string): Promise<{
606
+ data?: PaymentDetailResponse;
607
+ error?: PaymentError;
608
+ }>;
609
+ /**
610
+ * Confirms a payment after PSP callback (authenticated endpoint)
599
611
  */
600
612
  confirmPayment(paymentId: string): Promise<{
601
613
  data?: PaymentDetailResponse;
package/dist/index.js CHANGED
@@ -190,7 +190,13 @@ var ReevitAPIClient = class {
190
190
  return this.request("GET", `/v1/payments/${paymentId}`);
191
191
  }
192
192
  /**
193
- * Confirms a payment after PSP callback
193
+ * Confirms a payment intent after PSP callback (public endpoint)
194
+ */
195
+ async confirmPaymentIntent(paymentId, clientSecret) {
196
+ return this.request("POST", `/v1/payments/${paymentId}/confirm-intent?client_secret=${clientSecret}`);
197
+ }
198
+ /**
199
+ * Confirms a payment after PSP callback (authenticated endpoint)
194
200
  */
195
201
  async confirmPayment(paymentId) {
196
202
  return this.request("POST", `/v1/payments/${paymentId}/confirm`);
@@ -238,7 +244,7 @@ function reevitReducer(state, action) {
238
244
  ...state,
239
245
  status: "ready",
240
246
  paymentIntent: action.payload,
241
- selectedMethod: action.payload.availableMethods?.length === 1 ? action.payload.availableMethods[0] : state.selectedMethod
247
+ selectedMethod: action.payload.availableMethods?.length === 1 ? action.payload.availableMethods[0] : null
242
248
  };
243
249
  case "INIT_ERROR":
244
250
  return { ...state, status: "failed", error: action.payload };
@@ -275,6 +281,8 @@ function mapToPaymentIntent(response, config) {
275
281
  status: response.status,
276
282
  recommendedPsp: mapProviderToPsp(response.provider),
277
283
  availableMethods: config.paymentMethods || ["card", "mobile_money"],
284
+ reference: response.reference || response.id,
285
+ // Use backend reference or fallback to ID
278
286
  connectionId: response.connection_id,
279
287
  provider: response.provider,
280
288
  feeAmount: response.fee_amount,
@@ -377,8 +385,10 @@ function useReevit(options) {
377
385
  if (!apiClient) {
378
386
  throw new Error("API client not initialized");
379
387
  }
380
- const { data, error } = await apiClient.confirmPayment(state.paymentIntent.id);
388
+ const clientSecret = state.paymentIntent.clientSecret;
389
+ const { data, error } = clientSecret ? await apiClient.confirmPaymentIntent(state.paymentIntent.id, clientSecret) : await apiClient.confirmPayment(state.paymentIntent.id);
381
390
  if (error) {
391
+ console.error("[useReevit] Confirmation error:", error);
382
392
  dispatch({ type: "PROCESS_ERROR", payload: error });
383
393
  onError?.(error);
384
394
  return;
@@ -392,8 +402,9 @@ function useReevit(options) {
392
402
  psp: state.paymentIntent.recommendedPsp,
393
403
  pspReference: paymentData.pspReference || data?.provider_ref_id || "",
394
404
  status: data?.status === "succeeded" ? "success" : "pending",
395
- metadata: paymentData
405
+ metadata: { ...paymentData, backend_status: data?.status }
396
406
  };
407
+ console.log("[useReevit] Process result:", result);
397
408
  if (result.status === "success") {
398
409
  dispatch({ type: "PROCESS_SUCCESS", payload: result });
399
410
  onSuccess?.(result);
@@ -694,6 +705,7 @@ function PaystackBridge({
694
705
  amount,
695
706
  currency = "GHS",
696
707
  reference,
708
+ accessCode,
697
709
  metadata,
698
710
  channels = ["card", "mobile_money"],
699
711
  onSuccess,
@@ -704,30 +716,38 @@ function PaystackBridge({
704
716
  const initialized = react.useRef(false);
705
717
  const startPayment = react.useCallback(async () => {
706
718
  try {
719
+ console.log("[PaystackBridge] Starting payment", {
720
+ hasPublicKey: !!publicKey,
721
+ email,
722
+ amount,
723
+ reference,
724
+ hasAccessCode: !!accessCode
725
+ });
707
726
  if (!publicKey) {
708
727
  throw new Error("Paystack public key is required but was empty");
709
728
  }
710
- if (!email) {
711
- throw new Error("Email is required for Paystack payments");
729
+ if (!email && !accessCode) {
730
+ throw new Error("Email is required for Paystack payments when no access code is provided");
712
731
  }
713
- if (!amount || amount <= 0) {
714
- throw new Error("Valid amount is required for Paystack payments");
732
+ if (!amount && !accessCode) {
733
+ throw new Error("Valid amount is required for Paystack payments when no access code is provided");
715
734
  }
716
735
  await loadPaystackScript();
717
736
  if (!window.PaystackPop) {
718
737
  throw new Error("Paystack script loaded but PaystackPop not available");
719
738
  }
720
- const handler = window.PaystackPop.setup({
739
+ const setupConfig = {
721
740
  key: publicKey,
722
741
  email,
723
742
  phone,
724
743
  amount,
725
- // Paystack expects amount in kobo/pesewas (smallest unit)
726
744
  currency,
727
745
  ref: reference,
746
+ access_code: accessCode,
728
747
  metadata,
729
748
  channels,
730
749
  callback: (response) => {
750
+ console.log("[PaystackBridge] Callback received", response);
731
751
  let usedMethod = "card";
732
752
  if (channels && channels.length === 1) {
733
753
  usedMethod = channels[0];
@@ -735,22 +755,31 @@ function PaystackBridge({
735
755
  usedMethod = "mobile_money";
736
756
  }
737
757
  const result = {
738
- paymentId: response.transaction,
758
+ paymentId: response.reference,
759
+ // Use the reference as paymentId because we set it to Reevit's UUID
739
760
  reference: response.reference,
740
761
  amount,
741
762
  currency,
742
763
  paymentMethod: usedMethod,
743
764
  psp: "paystack",
744
- pspReference: response.trans,
765
+ pspReference: response.transaction,
766
+ // Paystack's internal transaction ID
745
767
  status: response.status === "success" ? "success" : "pending",
746
- metadata: { trxref: response.trxref }
768
+ metadata: {
769
+ ...response,
770
+ trxref: response.trxref,
771
+ paystack_transaction_id: response.transaction,
772
+ paystack_trans: response.trans
773
+ }
747
774
  };
748
775
  onSuccess(result);
749
776
  },
750
777
  onClose: () => {
778
+ console.log("[PaystackBridge] Modal closed");
751
779
  onClose();
752
780
  }
753
- });
781
+ };
782
+ const handler = window.PaystackPop.setup(setupConfig);
754
783
  handler.openIframe();
755
784
  } catch (err) {
756
785
  const errorMessage = err instanceof Error ? err.message : "Failed to initialize Paystack";
@@ -762,7 +791,7 @@ function PaystackBridge({
762
791
  };
763
792
  onError(error);
764
793
  }
765
- }, [publicKey, email, amount, currency, reference, metadata, channels, onSuccess, onError, onClose]);
794
+ }, [publicKey, email, amount, currency, reference, accessCode, metadata, channels, onSuccess, onError, onClose]);
766
795
  react.useEffect(() => {
767
796
  if (autoStart && !initialized.current) {
768
797
  initialized.current = true;
@@ -865,10 +894,10 @@ function ReevitCheckout({
865
894
  }
866
895
  }, [isOpen, status, initialize, initialPaymentIntent]);
867
896
  react.useEffect(() => {
868
- if (isOpen && (selectedMethod === "card" || selectedMethod === "mobile_money") && !showPSPBridge) {
869
- if (selectedMethod === "card" && paymentIntent) {
897
+ if (isOpen && selectedMethod && paymentIntent && !showPSPBridge) {
898
+ if (selectedMethod === "card") {
870
899
  setShowPSPBridge(true);
871
- } else if (selectedMethod === "mobile_money" && paymentIntent && (momoData?.phone || phone)) {
900
+ } else if (selectedMethod === "mobile_money" && (momoData?.phone || phone)) {
872
901
  setShowPSPBridge(true);
873
902
  }
874
903
  }
@@ -932,10 +961,10 @@ function ReevitCheckout({
932
961
  formatAmount(amount, currency)
933
962
  ] }) : null;
934
963
  const renderContent = () => {
935
- if (status === "loading") {
964
+ if (status === "loading" || status === "processing") {
936
965
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "reevit-loading", children: [
937
966
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "reevit-spinner" }),
938
- /* @__PURE__ */ jsxRuntime.jsx("p", { children: "Preparing checkout..." })
967
+ /* @__PURE__ */ jsxRuntime.jsx("p", { children: status === "loading" ? "Preparing checkout..." : "Processing payment..." })
939
968
  ] });
940
969
  }
941
970
  if (status === "success" && result) {
@@ -967,6 +996,7 @@ function ReevitCheckout({
967
996
  amount: paymentIntent?.amount ?? amount,
968
997
  currency: paymentIntent?.currency ?? currency,
969
998
  reference,
999
+ accessCode: paymentIntent?.clientSecret,
970
1000
  metadata: {
971
1001
  ...metadata,
972
1002
  // Override with correct payment intent ID for webhook routing