@reevit/react 0.2.8 → 0.3.0
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 +10 -2
- package/dist/index.d.ts +10 -2
- package/dist/index.js +85 -17
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +85 -17
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -23,6 +23,8 @@ interface ReevitCheckoutConfig {
|
|
|
23
23
|
metadata?: Record<string, unknown>;
|
|
24
24
|
/** Payment methods to display */
|
|
25
25
|
paymentMethods?: PaymentMethod[];
|
|
26
|
+
/** Optional existing payment intent to use instead of creating a new one */
|
|
27
|
+
initialPaymentIntent?: PaymentIntent;
|
|
26
28
|
}
|
|
27
29
|
interface ReevitCheckoutCallbacks {
|
|
28
30
|
/** Called when payment is successful */
|
|
@@ -39,6 +41,10 @@ interface ReevitCheckoutProps extends ReevitCheckoutConfig, ReevitCheckoutCallba
|
|
|
39
41
|
children?: React.ReactNode;
|
|
40
42
|
/** Whether to open automatically */
|
|
41
43
|
autoOpen?: boolean;
|
|
44
|
+
/** Controlled open state */
|
|
45
|
+
isOpen?: boolean;
|
|
46
|
+
/** Callback for open state changes */
|
|
47
|
+
onOpenChange?: (isOpen: boolean) => void;
|
|
42
48
|
/** Custom theme */
|
|
43
49
|
theme?: ReevitTheme;
|
|
44
50
|
/** Custom API base URL (for testing or self-hosted deployments) */
|
|
@@ -132,7 +138,7 @@ interface ReevitContextValue {
|
|
|
132
138
|
currency: string;
|
|
133
139
|
}
|
|
134
140
|
declare function useReevitContext(): ReevitContextValue;
|
|
135
|
-
declare function ReevitCheckout({ publicKey, amount, currency, email, phone, reference, metadata, paymentMethods, onSuccess, onError, onClose, onStateChange, children, autoOpen, theme, apiBaseUrl, }: ReevitCheckoutProps): react_jsx_runtime.JSX.Element;
|
|
141
|
+
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;
|
|
136
142
|
|
|
137
143
|
interface PaymentMethodSelectorProps {
|
|
138
144
|
methods: PaymentMethod[];
|
|
@@ -196,6 +202,7 @@ interface PaystackPopupInterface {
|
|
|
196
202
|
interface PaystackConfig {
|
|
197
203
|
key: string;
|
|
198
204
|
email: string;
|
|
205
|
+
phone?: string;
|
|
199
206
|
amount: number;
|
|
200
207
|
currency?: string;
|
|
201
208
|
ref?: string;
|
|
@@ -215,6 +222,7 @@ interface PaystackResponse {
|
|
|
215
222
|
interface PaystackBridgeProps {
|
|
216
223
|
publicKey: string;
|
|
217
224
|
email: string;
|
|
225
|
+
phone?: string;
|
|
218
226
|
amount: number;
|
|
219
227
|
currency?: string;
|
|
220
228
|
reference?: string;
|
|
@@ -226,7 +234,7 @@ interface PaystackBridgeProps {
|
|
|
226
234
|
autoStart?: boolean;
|
|
227
235
|
}
|
|
228
236
|
declare function loadPaystackScript(): Promise<void>;
|
|
229
|
-
declare function PaystackBridge({ publicKey, email, amount, currency, reference, metadata, channels, onSuccess, onError, onClose, autoStart, }: PaystackBridgeProps): react_jsx_runtime.JSX.Element;
|
|
237
|
+
declare function PaystackBridge({ publicKey, email, phone, amount, currency, reference, metadata, channels, onSuccess, onError, onClose, autoStart, }: PaystackBridgeProps): react_jsx_runtime.JSX.Element;
|
|
230
238
|
|
|
231
239
|
declare global {
|
|
232
240
|
interface Window {
|
package/dist/index.d.ts
CHANGED
|
@@ -23,6 +23,8 @@ interface ReevitCheckoutConfig {
|
|
|
23
23
|
metadata?: Record<string, unknown>;
|
|
24
24
|
/** Payment methods to display */
|
|
25
25
|
paymentMethods?: PaymentMethod[];
|
|
26
|
+
/** Optional existing payment intent to use instead of creating a new one */
|
|
27
|
+
initialPaymentIntent?: PaymentIntent;
|
|
26
28
|
}
|
|
27
29
|
interface ReevitCheckoutCallbacks {
|
|
28
30
|
/** Called when payment is successful */
|
|
@@ -39,6 +41,10 @@ interface ReevitCheckoutProps extends ReevitCheckoutConfig, ReevitCheckoutCallba
|
|
|
39
41
|
children?: React.ReactNode;
|
|
40
42
|
/** Whether to open automatically */
|
|
41
43
|
autoOpen?: boolean;
|
|
44
|
+
/** Controlled open state */
|
|
45
|
+
isOpen?: boolean;
|
|
46
|
+
/** Callback for open state changes */
|
|
47
|
+
onOpenChange?: (isOpen: boolean) => void;
|
|
42
48
|
/** Custom theme */
|
|
43
49
|
theme?: ReevitTheme;
|
|
44
50
|
/** Custom API base URL (for testing or self-hosted deployments) */
|
|
@@ -132,7 +138,7 @@ interface ReevitContextValue {
|
|
|
132
138
|
currency: string;
|
|
133
139
|
}
|
|
134
140
|
declare function useReevitContext(): ReevitContextValue;
|
|
135
|
-
declare function ReevitCheckout({ publicKey, amount, currency, email, phone, reference, metadata, paymentMethods, onSuccess, onError, onClose, onStateChange, children, autoOpen, theme, apiBaseUrl, }: ReevitCheckoutProps): react_jsx_runtime.JSX.Element;
|
|
141
|
+
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;
|
|
136
142
|
|
|
137
143
|
interface PaymentMethodSelectorProps {
|
|
138
144
|
methods: PaymentMethod[];
|
|
@@ -196,6 +202,7 @@ interface PaystackPopupInterface {
|
|
|
196
202
|
interface PaystackConfig {
|
|
197
203
|
key: string;
|
|
198
204
|
email: string;
|
|
205
|
+
phone?: string;
|
|
199
206
|
amount: number;
|
|
200
207
|
currency?: string;
|
|
201
208
|
ref?: string;
|
|
@@ -215,6 +222,7 @@ interface PaystackResponse {
|
|
|
215
222
|
interface PaystackBridgeProps {
|
|
216
223
|
publicKey: string;
|
|
217
224
|
email: string;
|
|
225
|
+
phone?: string;
|
|
218
226
|
amount: number;
|
|
219
227
|
currency?: string;
|
|
220
228
|
reference?: string;
|
|
@@ -226,7 +234,7 @@ interface PaystackBridgeProps {
|
|
|
226
234
|
autoStart?: boolean;
|
|
227
235
|
}
|
|
228
236
|
declare function loadPaystackScript(): Promise<void>;
|
|
229
|
-
declare function PaystackBridge({ publicKey, email, amount, currency, reference, metadata, channels, onSuccess, onError, onClose, autoStart, }: PaystackBridgeProps): react_jsx_runtime.JSX.Element;
|
|
237
|
+
declare function PaystackBridge({ publicKey, email, phone, amount, currency, reference, metadata, channels, onSuccess, onError, onClose, autoStart, }: PaystackBridgeProps): react_jsx_runtime.JSX.Element;
|
|
230
238
|
|
|
231
239
|
declare global {
|
|
232
240
|
interface Window {
|
package/dist/index.js
CHANGED
|
@@ -178,6 +178,7 @@ var ReevitAPIClient = class {
|
|
|
178
178
|
method: this.mapPaymentMethod(method),
|
|
179
179
|
country,
|
|
180
180
|
customer_id: config.email || config.metadata?.customerId,
|
|
181
|
+
phone: config.phone,
|
|
181
182
|
metadata
|
|
182
183
|
};
|
|
183
184
|
return this.request("POST", "/v1/payments/intents", request);
|
|
@@ -233,7 +234,12 @@ function reevitReducer(state, action) {
|
|
|
233
234
|
case "INIT_START":
|
|
234
235
|
return { ...state, status: "loading", error: null };
|
|
235
236
|
case "INIT_SUCCESS":
|
|
236
|
-
return {
|
|
237
|
+
return {
|
|
238
|
+
...state,
|
|
239
|
+
status: "ready",
|
|
240
|
+
paymentIntent: action.payload,
|
|
241
|
+
selectedMethod: action.payload.availableMethods?.length === 1 ? action.payload.availableMethods[0] : state.selectedMethod
|
|
242
|
+
};
|
|
237
243
|
case "INIT_ERROR":
|
|
238
244
|
return { ...state, status: "failed", error: action.payload };
|
|
239
245
|
case "SELECT_METHOD":
|
|
@@ -279,9 +285,22 @@ function mapToPaymentIntent(response, config) {
|
|
|
279
285
|
}
|
|
280
286
|
function useReevit(options) {
|
|
281
287
|
const { config, onSuccess, onError, onClose, onStateChange, apiBaseUrl } = options;
|
|
282
|
-
const [state, dispatch] = react.useReducer(reevitReducer,
|
|
288
|
+
const [state, dispatch] = react.useReducer(reevitReducer, {
|
|
289
|
+
...initialState,
|
|
290
|
+
status: config.initialPaymentIntent ? "ready" : "idle",
|
|
291
|
+
paymentIntent: config.initialPaymentIntent || null,
|
|
292
|
+
selectedMethod: config.initialPaymentIntent?.availableMethods?.length === 1 ? config.initialPaymentIntent.availableMethods[0] : null
|
|
293
|
+
});
|
|
283
294
|
const apiClientRef = react.useRef(null);
|
|
284
|
-
const initializingRef = react.useRef(
|
|
295
|
+
const initializingRef = react.useRef(!!config.initialPaymentIntent);
|
|
296
|
+
react.useEffect(() => {
|
|
297
|
+
if (config.initialPaymentIntent) {
|
|
298
|
+
if (!state.paymentIntent || state.paymentIntent.id !== config.initialPaymentIntent.id) {
|
|
299
|
+
dispatch({ type: "INIT_SUCCESS", payload: config.initialPaymentIntent });
|
|
300
|
+
initializingRef.current = true;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
}, [config.initialPaymentIntent, state.paymentIntent?.id]);
|
|
285
304
|
if (!apiClientRef.current) {
|
|
286
305
|
apiClientRef.current = new ReevitAPIClient({
|
|
287
306
|
publicKey: config.publicKey,
|
|
@@ -372,11 +391,16 @@ function useReevit(options) {
|
|
|
372
391
|
paymentMethod: state.selectedMethod,
|
|
373
392
|
psp: state.paymentIntent.recommendedPsp,
|
|
374
393
|
pspReference: paymentData.pspReference || data?.provider_ref_id || "",
|
|
375
|
-
status: "success",
|
|
394
|
+
status: data?.status === "succeeded" ? "success" : "pending",
|
|
376
395
|
metadata: paymentData
|
|
377
396
|
};
|
|
378
|
-
|
|
379
|
-
|
|
397
|
+
if (result.status === "success") {
|
|
398
|
+
dispatch({ type: "PROCESS_SUCCESS", payload: result });
|
|
399
|
+
onSuccess?.(result);
|
|
400
|
+
} else {
|
|
401
|
+
dispatch({ type: "PROCESS_SUCCESS", payload: result });
|
|
402
|
+
onSuccess?.(result);
|
|
403
|
+
}
|
|
380
404
|
} catch (err) {
|
|
381
405
|
const error = {
|
|
382
406
|
code: "PAYMENT_FAILED",
|
|
@@ -666,6 +690,7 @@ function loadPaystackScript() {
|
|
|
666
690
|
function PaystackBridge({
|
|
667
691
|
publicKey,
|
|
668
692
|
email,
|
|
693
|
+
phone,
|
|
669
694
|
amount,
|
|
670
695
|
currency = "GHS",
|
|
671
696
|
reference,
|
|
@@ -695,6 +720,7 @@ function PaystackBridge({
|
|
|
695
720
|
const handler = window.PaystackPop.setup({
|
|
696
721
|
key: publicKey,
|
|
697
722
|
email,
|
|
723
|
+
phone,
|
|
698
724
|
amount,
|
|
699
725
|
// Paystack expects amount in kobo/pesewas (smallest unit)
|
|
700
726
|
currency,
|
|
@@ -702,13 +728,18 @@ function PaystackBridge({
|
|
|
702
728
|
metadata,
|
|
703
729
|
channels,
|
|
704
730
|
callback: (response) => {
|
|
731
|
+
let usedMethod = "card";
|
|
732
|
+
if (channels && channels.length === 1) {
|
|
733
|
+
usedMethod = channels[0];
|
|
734
|
+
} else if (response.message?.toLowerCase().includes("mobile money")) {
|
|
735
|
+
usedMethod = "mobile_money";
|
|
736
|
+
}
|
|
705
737
|
const result = {
|
|
706
738
|
paymentId: response.transaction,
|
|
707
739
|
reference: response.reference,
|
|
708
740
|
amount,
|
|
709
741
|
currency,
|
|
710
|
-
paymentMethod:
|
|
711
|
-
// Paystack handles this internally
|
|
742
|
+
paymentMethod: usedMethod,
|
|
712
743
|
psp: "paystack",
|
|
713
744
|
pspReference: response.trans,
|
|
714
745
|
status: response.status === "success" ? "success" : "pending",
|
|
@@ -761,6 +792,7 @@ function ReevitCheckout({
|
|
|
761
792
|
reference,
|
|
762
793
|
metadata,
|
|
763
794
|
paymentMethods = ["card", "mobile_money"],
|
|
795
|
+
initialPaymentIntent,
|
|
764
796
|
// Callbacks
|
|
765
797
|
onSuccess,
|
|
766
798
|
onError,
|
|
@@ -769,10 +801,23 @@ function ReevitCheckout({
|
|
|
769
801
|
// UI
|
|
770
802
|
children,
|
|
771
803
|
autoOpen = false,
|
|
804
|
+
isOpen: controlledIsOpen,
|
|
805
|
+
onOpenChange,
|
|
772
806
|
theme,
|
|
773
807
|
apiBaseUrl
|
|
774
808
|
}) {
|
|
775
|
-
const [
|
|
809
|
+
const [internalIsOpen, setInternalIsOpen] = react.useState(autoOpen);
|
|
810
|
+
const isOpen = controlledIsOpen !== void 0 ? controlledIsOpen : internalIsOpen;
|
|
811
|
+
const setIsOpen = react.useCallback(
|
|
812
|
+
(value) => {
|
|
813
|
+
if (onOpenChange) {
|
|
814
|
+
onOpenChange(value);
|
|
815
|
+
} else {
|
|
816
|
+
setInternalIsOpen(value);
|
|
817
|
+
}
|
|
818
|
+
},
|
|
819
|
+
[onOpenChange]
|
|
820
|
+
);
|
|
776
821
|
const [showPSPBridge, setShowPSPBridge] = react.useState(false);
|
|
777
822
|
const [momoData, setMomoData] = react.useState(null);
|
|
778
823
|
const {
|
|
@@ -789,7 +834,17 @@ function ReevitCheckout({
|
|
|
789
834
|
isLoading,
|
|
790
835
|
isComplete
|
|
791
836
|
} = useReevit({
|
|
792
|
-
config: {
|
|
837
|
+
config: {
|
|
838
|
+
publicKey,
|
|
839
|
+
amount,
|
|
840
|
+
currency,
|
|
841
|
+
email,
|
|
842
|
+
phone,
|
|
843
|
+
reference,
|
|
844
|
+
metadata,
|
|
845
|
+
paymentMethods,
|
|
846
|
+
initialPaymentIntent
|
|
847
|
+
},
|
|
793
848
|
apiBaseUrl,
|
|
794
849
|
onSuccess: (result2) => {
|
|
795
850
|
onSuccess?.(result2);
|
|
@@ -805,21 +860,31 @@ function ReevitCheckout({
|
|
|
805
860
|
onStateChange
|
|
806
861
|
});
|
|
807
862
|
react.useEffect(() => {
|
|
808
|
-
if (isOpen && status === "idle") {
|
|
863
|
+
if (isOpen && status === "idle" && !initialPaymentIntent) {
|
|
809
864
|
initialize();
|
|
810
865
|
}
|
|
811
|
-
}, [isOpen, status, initialize]);
|
|
866
|
+
}, [isOpen, status, initialize, initialPaymentIntent]);
|
|
867
|
+
react.useEffect(() => {
|
|
868
|
+
if (isOpen && (selectedMethod === "card" || selectedMethod === "mobile_money") && !showPSPBridge) {
|
|
869
|
+
if (selectedMethod === "card" && paymentIntent) {
|
|
870
|
+
setShowPSPBridge(true);
|
|
871
|
+
} else if (selectedMethod === "mobile_money" && paymentIntent && (momoData?.phone || phone)) {
|
|
872
|
+
setShowPSPBridge(true);
|
|
873
|
+
}
|
|
874
|
+
}
|
|
875
|
+
}, [isOpen, selectedMethod, showPSPBridge, paymentIntent, momoData, phone]);
|
|
812
876
|
const handleOpen = react.useCallback(() => {
|
|
877
|
+
if (controlledIsOpen !== void 0) return;
|
|
813
878
|
setIsOpen(true);
|
|
814
879
|
setShowPSPBridge(false);
|
|
815
880
|
setMomoData(null);
|
|
816
|
-
}, []);
|
|
881
|
+
}, [controlledIsOpen, setIsOpen]);
|
|
817
882
|
const handleClose = react.useCallback(() => {
|
|
818
883
|
closeCheckout();
|
|
819
884
|
setIsOpen(false);
|
|
820
885
|
setShowPSPBridge(false);
|
|
821
886
|
setMomoData(null);
|
|
822
|
-
}, [closeCheckout]);
|
|
887
|
+
}, [closeCheckout, setIsOpen]);
|
|
823
888
|
const handleMethodSelect = react.useCallback(
|
|
824
889
|
(method) => {
|
|
825
890
|
selectMethod(method);
|
|
@@ -861,10 +926,11 @@ function ReevitCheckout({
|
|
|
861
926
|
setShowPSPBridge(false);
|
|
862
927
|
}, [reset]);
|
|
863
928
|
const themeStyles = theme ? createThemeVariables(theme) : {};
|
|
864
|
-
const
|
|
929
|
+
const isControlled = controlledIsOpen !== void 0;
|
|
930
|
+
const trigger = children ? /* @__PURE__ */ jsxRuntime.jsx("span", { onClick: isControlled ? void 0 : handleOpen, role: isControlled ? void 0 : "button", tabIndex: isControlled ? void 0 : 0, children }) : !isControlled ? /* @__PURE__ */ jsxRuntime.jsxs("button", { className: "reevit-trigger-btn", onClick: handleOpen, children: [
|
|
865
931
|
"Pay ",
|
|
866
932
|
formatAmount(amount, currency)
|
|
867
|
-
] });
|
|
933
|
+
] }) : null;
|
|
868
934
|
const renderContent = () => {
|
|
869
935
|
if (status === "loading") {
|
|
870
936
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "reevit-loading", children: [
|
|
@@ -897,6 +963,7 @@ function ReevitCheckout({
|
|
|
897
963
|
{
|
|
898
964
|
publicKey: pspKey,
|
|
899
965
|
email,
|
|
966
|
+
phone: momoData?.phone || phone,
|
|
900
967
|
amount: paymentIntent?.amount ?? amount,
|
|
901
968
|
currency: paymentIntent?.currency ?? currency,
|
|
902
969
|
reference,
|
|
@@ -905,7 +972,8 @@ function ReevitCheckout({
|
|
|
905
972
|
// Override with correct payment intent ID for webhook routing
|
|
906
973
|
// This ensures Paystack webhook includes the correct ID to find the payment
|
|
907
974
|
payment_id: paymentIntent?.id,
|
|
908
|
-
connection_id: paymentIntent?.connectionId ?? metadata?.connection_id
|
|
975
|
+
connection_id: paymentIntent?.connectionId ?? metadata?.connection_id,
|
|
976
|
+
customer_phone: momoData?.phone || phone
|
|
909
977
|
},
|
|
910
978
|
channels: selectedMethod === "mobile_money" ? ["mobile_money"] : ["card"],
|
|
911
979
|
onSuccess: handlePSPSuccess,
|