fairsure-checkout-sdk 1.0.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.
Files changed (40) hide show
  1. package/dist/components/CardPayment.d.ts +18 -0
  2. package/dist/components/CardPayment.js +302 -0
  3. package/dist/components/Checkout.d.ts +9 -0
  4. package/dist/components/Checkout.js +520 -0
  5. package/dist/components/OTPInput.d.ts +17 -0
  6. package/dist/components/OTPInput.js +132 -0
  7. package/dist/components/PaymentMethodSelector.d.ts +12 -0
  8. package/dist/components/PaymentMethodSelector.js +67 -0
  9. package/dist/components/PaystackCheckout.d.ts +13 -0
  10. package/dist/components/PaystackCheckout.js +385 -0
  11. package/dist/components/PurchaseModal.d.ts +17 -0
  12. package/dist/components/PurchaseModal.js +415 -0
  13. package/dist/components/TransferPayment.d.ts +16 -0
  14. package/dist/components/TransferPayment.js +311 -0
  15. package/dist/components/USSDPayment.d.ts +21 -0
  16. package/dist/components/USSDPayment.js +316 -0
  17. package/dist/components/usePaymentCheckout.d.ts +61 -0
  18. package/dist/components/usePaymentCheckout.js +398 -0
  19. package/dist/context/CheckoutProvider.d.ts +5 -0
  20. package/dist/context/CheckoutProvider.js +16 -0
  21. package/dist/hooks/useCheckout.d.ts +1 -0
  22. package/dist/hooks/useCheckout.js +8 -0
  23. package/dist/index.d.ts +2 -0
  24. package/dist/index.js +2 -0
  25. package/dist/types.d.ts +9 -0
  26. package/dist/types.js +1 -0
  27. package/fairsure-checkout-sdk-1.0.0.tgz +0 -0
  28. package/package.json +24 -0
  29. package/src/components/CardPayment.tsx +386 -0
  30. package/src/components/OTPInput.tsx +204 -0
  31. package/src/components/PaymentMethodSelector.tsx +99 -0
  32. package/src/components/PaystackCheckout.tsx +506 -0
  33. package/src/components/TransferPayment.tsx +372 -0
  34. package/src/components/USSDPayment.tsx +422 -0
  35. package/src/components/usePaymentCheckout.ts +441 -0
  36. package/src/context/CheckoutProvider.tsx +37 -0
  37. package/src/hooks/useCheckout.ts +11 -0
  38. package/src/index.ts +2 -0
  39. package/src/types.ts +9 -0
  40. package/tsconfig.json +22 -0
@@ -0,0 +1,61 @@
1
+ export declare function usePaymentCheckout(amount: number, requestId: string, customerEmail: string, customerName: string, customerPhone: string, onSuccess?: (reference: string) => void): {
2
+ selectedMethod: string;
3
+ cardNumber: string;
4
+ expiryDate: string;
5
+ cvv: string;
6
+ selectedBank: {
7
+ name: string;
8
+ code: string;
9
+ } | null;
10
+ showBankDropdown: boolean;
11
+ pin: string;
12
+ message: string;
13
+ otp: string;
14
+ copied: boolean;
15
+ showPin: boolean;
16
+ showOtp: boolean;
17
+ cardcontinue: boolean;
18
+ loading: boolean;
19
+ ussdBanks: never[];
20
+ transferDetail: {
21
+ accountName: string;
22
+ accountNumber: string;
23
+ bankName: string;
24
+ amount: number;
25
+ validityPeriodMins: number;
26
+ transactionReference: string;
27
+ };
28
+ cardDetails: {
29
+ transactionRef: string;
30
+ paymentId: string;
31
+ };
32
+ timeLeft: number;
33
+ ussdBankResponse: {
34
+ ussdString: string;
35
+ codeRef: string;
36
+ amount: string;
37
+ };
38
+ setSelectedMethod: import("react").Dispatch<import("react").SetStateAction<string>>;
39
+ setCardNumber: import("react").Dispatch<import("react").SetStateAction<string>>;
40
+ setExpiryDate: import("react").Dispatch<import("react").SetStateAction<string>>;
41
+ setCvv: import("react").Dispatch<import("react").SetStateAction<string>>;
42
+ setSelectedBank: import("react").Dispatch<import("react").SetStateAction<{
43
+ name: string;
44
+ code: string;
45
+ } | null>>;
46
+ setShowBankDropdown: import("react").Dispatch<import("react").SetStateAction<boolean>>;
47
+ setPin: import("react").Dispatch<import("react").SetStateAction<string>>;
48
+ setOtp: import("react").Dispatch<import("react").SetStateAction<string>>;
49
+ setcardcontinue: import("react").Dispatch<import("react").SetStateAction<boolean>>;
50
+ setShowOtp: import("react").Dispatch<import("react").SetStateAction<boolean>>;
51
+ formatTime: (seconds: number) => string;
52
+ formatAmount: (value: number) => string;
53
+ formatCardNumber: (value: string) => string;
54
+ formatExpiry: (value: string) => string;
55
+ handleCopy: (text: string) => Promise<void>;
56
+ handleCardPayment: () => Promise<any>;
57
+ verifyTransfer: () => Promise<any>;
58
+ verifyCardPayment: () => Promise<any>;
59
+ resetForm: () => void;
60
+ verifyUssd: () => Promise<void>;
61
+ };
@@ -0,0 +1,398 @@
1
+ import axios from "axios";
2
+ import * as Clipboard from "expo-clipboard";
3
+ import { useEffect, useState } from "react";
4
+ import { Dimensions, Platform } from "react-native";
5
+ const { width, height } = Dimensions.get("window");
6
+ export function usePaymentCheckout(amount, requestId, customerEmail, customerName, customerPhone, onSuccess) {
7
+ const [selectedMethod, setSelectedMethod] = useState("card");
8
+ const [cardNumber, setCardNumber] = useState("");
9
+ const [expiryDate, setExpiryDate] = useState("");
10
+ const [cvv, setCvv] = useState("");
11
+ const [selectedBank, setSelectedBank] = useState(null);
12
+ const [showBankDropdown, setShowBankDropdown] = useState(false);
13
+ const [pin, setPin] = useState("");
14
+ const [otp, setOtp] = useState("");
15
+ const [message, setMessage] = useState("");
16
+ const [copied, setCopied] = useState(false);
17
+ const [showPin, setShowPin] = useState(false);
18
+ const [showOtp, setShowOtp] = useState(false);
19
+ const [cardcontinue, setcardcontinue] = useState(false);
20
+ const [loading, setLoading] = useState(false);
21
+ const [ussdBanks, setUssdBanks] = useState([]);
22
+ const [ussdBankResponse, setUssdBankResponse] = useState({
23
+ ussdString: "",
24
+ codeRef: "",
25
+ amount: "",
26
+ });
27
+ const [transferDetail, setTransferDetail] = useState({
28
+ accountName: "",
29
+ accountNumber: "",
30
+ bankName: "",
31
+ amount: 0,
32
+ validityPeriodMins: 0,
33
+ transactionReference: "",
34
+ });
35
+ const [cardDetails, setCardDetails] = useState({
36
+ transactionRef: "",
37
+ paymentId: "",
38
+ });
39
+ const [timeLeft, setTimeLeft] = useState(0);
40
+ // Timer logic
41
+ useEffect(() => {
42
+ if (transferDetail.validityPeriodMins > 0) {
43
+ setTimeLeft(transferDetail.validityPeriodMins * 60);
44
+ }
45
+ }, [transferDetail.validityPeriodMins]);
46
+ useEffect(() => {
47
+ if (timeLeft <= 0)
48
+ return;
49
+ const timer = setInterval(() => {
50
+ setTimeLeft((prev) => {
51
+ if (prev <= 1) {
52
+ clearInterval(timer);
53
+ return 0;
54
+ }
55
+ return prev - 1;
56
+ });
57
+ }, 1000);
58
+ return () => clearInterval(timer);
59
+ }, [timeLeft]);
60
+ // Fetch transfer details or USSD banks based on selected method
61
+ useEffect(() => {
62
+ if (selectedMethod === "transfer" || selectedMethod === "card") {
63
+ fetchTransferDetails();
64
+ }
65
+ else if (selectedMethod === "ussd") {
66
+ getBanks();
67
+ }
68
+ }, [selectedMethod]);
69
+ const fetchTransferDetails = async () => {
70
+ var _a;
71
+ setLoading(true);
72
+ try {
73
+ const payload = {
74
+ amount,
75
+ accountName: "Fairsure",
76
+ isBill: true,
77
+ requestId,
78
+ };
79
+ const res = await axios.post("https://api.fairsurepayment.com.ng/api/pub/generate-account", payload, {
80
+ headers: {
81
+ Accept: "application/json",
82
+ "Content-Type": "application/json",
83
+ publickey: "LIVE_7AXSCCY8R3HABAN14QP7",
84
+ "User-Agent": "PostmanRuntime/7.51.0",
85
+ },
86
+ });
87
+ setTransferDetail((_a = res === null || res === void 0 ? void 0 : res.data) === null || _a === void 0 ? void 0 : _a.data);
88
+ }
89
+ catch (error) {
90
+ console.log("FETCH ERROR:", error);
91
+ }
92
+ finally {
93
+ setLoading(false);
94
+ }
95
+ };
96
+ const generateUssdCode = async () => {
97
+ var _a;
98
+ setLoading(true);
99
+ const payload = {
100
+ amount,
101
+ requestId,
102
+ bankCode: selectedBank === null || selectedBank === void 0 ? void 0 : selectedBank.code,
103
+ };
104
+ try {
105
+ const res = await axios.post("https://api.fairsurepayment.com.ng/api/pub/generate-ussd", payload, {
106
+ headers: {
107
+ Accept: "application/json",
108
+ "Content-Type": "application/json",
109
+ publickey: "LIVE_7AXSCCY8R3HABAN14QP7",
110
+ "User-Agent": "PostmanRuntime/7.51.0",
111
+ },
112
+ });
113
+ setUssdBankResponse((_a = res === null || res === void 0 ? void 0 : res.data) === null || _a === void 0 ? void 0 : _a.data);
114
+ }
115
+ catch (error) {
116
+ console.log("FETCH ERROR:", error);
117
+ }
118
+ finally {
119
+ setLoading(false);
120
+ }
121
+ };
122
+ const verifyUssd = async () => {
123
+ try {
124
+ setLoading(true);
125
+ const payload = {
126
+ codeReference: ussdBankResponse === null || ussdBankResponse === void 0 ? void 0 : ussdBankResponse.codeRef,
127
+ amount: ussdBankResponse === null || ussdBankResponse === void 0 ? void 0 : ussdBankResponse.amount,
128
+ };
129
+ const res = await axios.post("https://api.fairsurepayment.com.ng/api/pub/ussd-status", payload, {
130
+ headers: {
131
+ Accept: "application/json",
132
+ "Content-Type": "application/json",
133
+ publickey: "LIVE_7AXSCCY8R3HABAN14QP7",
134
+ "User-Agent": "PostmanRuntime/7.51.0",
135
+ },
136
+ });
137
+ onSuccess === null || onSuccess === void 0 ? void 0 : onSuccess(cardDetails.transactionRef);
138
+ setLoading(false);
139
+ }
140
+ catch (error) {
141
+ console.log("FETCH ERROR:", error);
142
+ }
143
+ finally {
144
+ setLoading(false);
145
+ }
146
+ };
147
+ useEffect(() => {
148
+ if (selectedBank) {
149
+ generateUssdCode();
150
+ }
151
+ }, [selectedBank]);
152
+ const getBanks = async () => {
153
+ var _a;
154
+ setLoading(true);
155
+ try {
156
+ setLoading(true);
157
+ const res = await axios.get("https://api.fairsurepayment.com.ng/api/pub/list-ussd-banks", {
158
+ timeout: 15000,
159
+ headers: {
160
+ Accept: "application/json",
161
+ "Content-Type": "application/json",
162
+ publickey: "LIVE_7AXSCCY8R3HABAN14QP7",
163
+ "User-Agent": "PostmanRuntime/7.36.0",
164
+ },
165
+ });
166
+ const banks = res.data.data.map((bank) => ({
167
+ name: bank.BankName,
168
+ code: bank.BankCode,
169
+ }));
170
+ setLoading(false);
171
+ setUssdBanks(banks);
172
+ }
173
+ catch (error) {
174
+ console.log("Failed to fetch banks", (_a = error.response) === null || _a === void 0 ? void 0 : _a.data);
175
+ }
176
+ finally {
177
+ setLoading(false);
178
+ }
179
+ };
180
+ const handleCopy = async (text) => {
181
+ await Clipboard.setStringAsync(text);
182
+ setCopied(true);
183
+ setTimeout(() => setCopied(false), 2000);
184
+ };
185
+ const formatTime = (seconds) => {
186
+ const m = Math.floor(seconds / 60);
187
+ const s = seconds % 60;
188
+ return `${m.toString().padStart(2, "0")}:${s.toString().padStart(2, "0")}`;
189
+ };
190
+ const formatAmount = (value) => {
191
+ return value.toLocaleString("en-NG", {
192
+ minimumFractionDigits: 2,
193
+ maximumFractionDigits: 2,
194
+ });
195
+ };
196
+ const formatCardNumber = (value) => {
197
+ const v = value.replace(/\s+/g, "").replace(/[^0-9]/gi, "");
198
+ const matches = v.match(/\d{4,16}/g);
199
+ const match = (matches && matches[0]) || "";
200
+ const parts = [];
201
+ for (let i = 0; i < match.length; i += 4) {
202
+ parts.push(match.substring(i, i + 4));
203
+ }
204
+ return parts.length ? parts.join(" ") : value;
205
+ };
206
+ const formatExpiry = (value) => {
207
+ const v = value.replace(/\s+/g, "").replace(/[^0-9]/gi, "");
208
+ if (v.length >= 2) {
209
+ return v.slice(0, 2) + "/" + v.slice(2, 4);
210
+ }
211
+ return v;
212
+ };
213
+ const completeCard = async (data) => {
214
+ var _a, _b, _c;
215
+ setLoading(true);
216
+ try {
217
+ const payload = {
218
+ customerId: customerEmail,
219
+ amount: String(amount),
220
+ transactionRef: requestId,
221
+ currency: "NGN",
222
+ callbackUrl: "https://yourcallbackurl.com",
223
+ isBill: "true",
224
+ data: data,
225
+ deviceInformation: {
226
+ deviceChannel: "MOBILE",
227
+ userAgentBrowserValue: `ReactNative/${Platform.OS}`,
228
+ httpBrowserLanguage: "en-NG",
229
+ httpBrowserJavaEnabled: false,
230
+ httpBrowserJavaScriptEnabled: true,
231
+ httpBrowserColorDepth: 32,
232
+ httpBrowserScreenHeight: Math.round(height),
233
+ httpBrowserScreenWidth: Math.round(width),
234
+ httpBrowserTimeDifference: `${-new Date().getTimezoneOffset()}`,
235
+ },
236
+ };
237
+ const res = await axios.post("https://api.fairsurepayment.com.ng/api/pub/card-payment", payload, {
238
+ headers: {
239
+ Accept: "application/json",
240
+ "Content-Type": "application/json",
241
+ publickey: "LIVE_7AXSCCY8R3HABAN14QP7",
242
+ "User-Agent": "PostmanRuntime/7.51.0",
243
+ },
244
+ });
245
+ setLoading(false);
246
+ return res.data;
247
+ }
248
+ catch (error) {
249
+ setLoading(false);
250
+ if (axios.isAxiosError(error)) {
251
+ console.log("STATUS:", (_a = error.response) === null || _a === void 0 ? void 0 : _a.status);
252
+ console.log("DATA:", (_b = error.response) === null || _b === void 0 ? void 0 : _b.data);
253
+ console.log("HEADERS:", (_c = error.response) === null || _c === void 0 ? void 0 : _c.headers);
254
+ }
255
+ else {
256
+ console.log("UNKNOWN ERROR:", error);
257
+ }
258
+ }
259
+ };
260
+ const handleCardPayment = async () => {
261
+ var _a, _b;
262
+ setLoading(true);
263
+ try {
264
+ const payload = {
265
+ pan: cardNumber.replace(/\s/g, ""),
266
+ expiryDate: expiryDate.replace("/", ""),
267
+ cvv,
268
+ pin,
269
+ };
270
+ const res = await axios.post("https://api.fairsurepayment.com.ng/api/pub/encrypt-test", payload, {
271
+ timeout: 15000,
272
+ headers: {
273
+ Accept: "application/json",
274
+ "Content-Type": "application/json",
275
+ publickey: "LIVE_7AXSCCY8R3HABAN14QP7",
276
+ "User-Agent": "PostmanRuntime/7.51.0",
277
+ },
278
+ });
279
+ const data = await completeCard((_a = res === null || res === void 0 ? void 0 : res.data) === null || _a === void 0 ? void 0 : _a.data);
280
+ setMessage((_b = data === null || data === void 0 ? void 0 : data.data) === null || _b === void 0 ? void 0 : _b.message);
281
+ setCardDetails(data === null || data === void 0 ? void 0 : data.data);
282
+ setOtp("");
283
+ setPin("");
284
+ setShowOtp(true);
285
+ return data;
286
+ }
287
+ catch (error) {
288
+ console.log(error);
289
+ }
290
+ finally {
291
+ setLoading(false);
292
+ }
293
+ };
294
+ const verifyCardPayment = async () => {
295
+ setLoading(true);
296
+ try {
297
+ const payload = {
298
+ transactionId: cardDetails === null || cardDetails === void 0 ? void 0 : cardDetails.transactionRef,
299
+ paymentId: cardDetails === null || cardDetails === void 0 ? void 0 : cardDetails.paymentId,
300
+ // eciFlag: "07",
301
+ otp: otp,
302
+ customerName,
303
+ customerPhone,
304
+ customerEmail,
305
+ };
306
+ const res = await axios.post("https://api.fairsurepayment.com.ng/api/pub/submit-otp", payload, {
307
+ headers: {
308
+ Accept: "application/json",
309
+ "Content-Type": "application/json",
310
+ publickey: "LIVE_7AXSCCY8R3HABAN14QP7",
311
+ "User-Agent": "PostmanRuntime/7.36.0",
312
+ },
313
+ });
314
+ onSuccess === null || onSuccess === void 0 ? void 0 : onSuccess(transferDetail.transactionReference);
315
+ setLoading(false);
316
+ return res === null || res === void 0 ? void 0 : res.data;
317
+ }
318
+ catch (error) {
319
+ setLoading(false);
320
+ console.log("ERROR", error);
321
+ }
322
+ };
323
+ const verifyTransfer = async () => {
324
+ var _a;
325
+ setLoading(true);
326
+ try {
327
+ const res = await axios.get(`https://api.fairsurepayment.com.ng/api/pub/transfer-status?transactionReference=${transferDetail === null || transferDetail === void 0 ? void 0 : transferDetail.transactionReference}`, {
328
+ timeout: 15000,
329
+ headers: {
330
+ Accept: "application/json",
331
+ "Content-Type": "application/json",
332
+ publickey: "LIVE_7AXSCCY8R3HABAN14QP7",
333
+ "User-Agent": "PostmanRuntime/7.36.0",
334
+ },
335
+ });
336
+ onSuccess === null || onSuccess === void 0 ? void 0 : onSuccess(transferDetail.transactionReference);
337
+ return res === null || res === void 0 ? void 0 : res.data;
338
+ }
339
+ catch (error) {
340
+ console.log("Failed to Verify transfer", (_a = error.response) === null || _a === void 0 ? void 0 : _a.data);
341
+ }
342
+ finally {
343
+ setLoading(false);
344
+ }
345
+ };
346
+ const resetForm = () => {
347
+ setCardNumber("");
348
+ setExpiryDate("");
349
+ setCvv("");
350
+ setSelectedBank(null);
351
+ setcardcontinue(false);
352
+ setSelectedMethod("card");
353
+ };
354
+ return {
355
+ // State
356
+ selectedMethod,
357
+ cardNumber,
358
+ expiryDate,
359
+ cvv,
360
+ selectedBank,
361
+ showBankDropdown,
362
+ pin,
363
+ message,
364
+ otp,
365
+ copied,
366
+ showPin,
367
+ showOtp,
368
+ cardcontinue,
369
+ loading,
370
+ ussdBanks,
371
+ transferDetail,
372
+ cardDetails,
373
+ timeLeft,
374
+ ussdBankResponse,
375
+ // Setters
376
+ setSelectedMethod,
377
+ setCardNumber,
378
+ setExpiryDate,
379
+ setCvv,
380
+ setSelectedBank,
381
+ setShowBankDropdown,
382
+ setPin,
383
+ setOtp,
384
+ setcardcontinue,
385
+ setShowOtp,
386
+ // Utilities
387
+ formatTime,
388
+ formatAmount,
389
+ formatCardNumber,
390
+ formatExpiry,
391
+ handleCopy,
392
+ handleCardPayment,
393
+ verifyTransfer,
394
+ verifyCardPayment,
395
+ resetForm,
396
+ verifyUssd,
397
+ };
398
+ }
@@ -0,0 +1,5 @@
1
+ import React from "react";
2
+ export declare function CheckoutProvider({ children }: {
3
+ children: React.ReactNode;
4
+ }): React.JSX.Element;
5
+ export declare const useCheckoutContext: () => any;
@@ -0,0 +1,16 @@
1
+ import React, { createContext, useContext, useState } from "react";
2
+ import Checkout from "../components/PaystackCheckout";
3
+ const CheckoutContext = createContext(null);
4
+ export function CheckoutProvider({ children }) {
5
+ const [config, setConfig] = useState(null);
6
+ const openCheckout = (options) => {
7
+ setConfig(options);
8
+ };
9
+ const closeCheckout = () => setConfig(null);
10
+ return (<CheckoutContext.Provider value={{ openCheckout }}>
11
+ {children}
12
+
13
+ {config && (<Checkout amount={config.amount} merchantName={config.merchantName} onSuccess={config.onSuccess} onClose={closeCheckout} requestId={config.requestId} customerEmail={config.customerEmail} customerName={config.customerName} customerPhone={config.customerPhone}/>)}
14
+ </CheckoutContext.Provider>);
15
+ }
16
+ export const useCheckoutContext = () => useContext(CheckoutContext);
@@ -0,0 +1 @@
1
+ export declare function useCheckout(): any;
@@ -0,0 +1,8 @@
1
+ import { useCheckoutContext } from "../context/CheckoutProvider";
2
+ export function useCheckout() {
3
+ const ctx = useCheckoutContext();
4
+ if (!ctx) {
5
+ throw new Error("usePaystackCheckout must be used inside CheckoutProvider");
6
+ }
7
+ return ctx;
8
+ }
@@ -0,0 +1,2 @@
1
+ export { CheckoutProvider } from "./context/CheckoutProvider";
2
+ export { useCheckout } from "./hooks/useCheckout";
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ export { CheckoutProvider } from "./context/CheckoutProvider";
2
+ export { useCheckout } from "./hooks/useCheckout";
@@ -0,0 +1,9 @@
1
+ export interface CheckoutConfig {
2
+ amount: number;
3
+ merchantName?: string;
4
+ onSuccess?: (reference: string) => void;
5
+ requestId: string;
6
+ customerEmail: string;
7
+ customerName: string;
8
+ customerPhone: string;
9
+ }
package/dist/types.js ADDED
@@ -0,0 +1 @@
1
+ export {};
Binary file
package/package.json ADDED
@@ -0,0 +1,24 @@
1
+ {
2
+ "name": "fairsure-checkout-sdk",
3
+ "version": "1.0.0",
4
+ "main": "dist/index.js",
5
+ "types": "dist/index.d.ts",
6
+ "peerDependencies": {
7
+ "expo": "*",
8
+ "react": "*",
9
+ "react-native": "*"
10
+ },
11
+ "scripts": {
12
+ "build": "tsc",
13
+ "pack": "npm pack"
14
+ },
15
+ "dependencies": {
16
+ "@expo/vector-icons": "^15.0.3",
17
+ "axios": "^1.13.4",
18
+ "expo-clipboard": "^8.0.8"
19
+ },
20
+ "devDependencies": {
21
+ "@types/react": "^19.2.10",
22
+ "typescript": "^5.9.3"
23
+ }
24
+ }