@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 +15 -3
- package/dist/index.d.ts +15 -3
- package/dist/index.js +50 -20
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +50 -20
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
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
|
|
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
|
|
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] :
|
|
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
|
|
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
|
|
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
|
|
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.
|
|
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.
|
|
765
|
+
pspReference: response.transaction,
|
|
766
|
+
// Paystack's internal transaction ID
|
|
745
767
|
status: response.status === "success" ? "success" : "pending",
|
|
746
|
-
metadata: {
|
|
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 &&
|
|
869
|
-
if (selectedMethod === "card"
|
|
897
|
+
if (isOpen && selectedMethod && paymentIntent && !showPSPBridge) {
|
|
898
|
+
if (selectedMethod === "card") {
|
|
870
899
|
setShowPSPBridge(true);
|
|
871
|
-
} else if (selectedMethod === "mobile_money" &&
|
|
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
|