@zezosoft/react-native-zezopay 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 (78) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +150 -0
  3. package/lib/module/ZezoPay/Payments/Providers/PaymentGateways.types.d.js +2 -0
  4. package/lib/module/ZezoPay/Payments/Providers/PaymentGateways.types.d.js.map +1 -0
  5. package/lib/module/ZezoPay/Payments/Providers/Razorpay/Razorpay.js +39 -0
  6. package/lib/module/ZezoPay/Payments/Providers/Razorpay/Razorpay.js.map +1 -0
  7. package/lib/module/ZezoPay/Payments/Providers/index.js +10 -0
  8. package/lib/module/ZezoPay/Payments/Providers/index.js.map +1 -0
  9. package/lib/module/ZezoPay/ZezoPay.js +176 -0
  10. package/lib/module/ZezoPay/ZezoPay.js.map +1 -0
  11. package/lib/module/ZezoPay/components/Header.js +97 -0
  12. package/lib/module/ZezoPay/components/Header.js.map +1 -0
  13. package/lib/module/ZezoPay/components/PayButton.js +143 -0
  14. package/lib/module/ZezoPay/components/PayButton.js.map +1 -0
  15. package/lib/module/ZezoPay/components/PaymentMethod.js +250 -0
  16. package/lib/module/ZezoPay/components/PaymentMethod.js.map +1 -0
  17. package/lib/module/ZezoPay/components/Summary.js +184 -0
  18. package/lib/module/ZezoPay/components/Summary.js.map +1 -0
  19. package/lib/module/ZezoPay/components/VoucherBox.js +124 -0
  20. package/lib/module/ZezoPay/components/VoucherBox.js.map +1 -0
  21. package/lib/module/ZezoPay/index.js +5 -0
  22. package/lib/module/ZezoPay/index.js.map +1 -0
  23. package/lib/module/ZezoPay/types/index.js +4 -0
  24. package/lib/module/ZezoPay/types/index.js.map +1 -0
  25. package/lib/module/ZezoPay/utils/hooks/useAsync.js +32 -0
  26. package/lib/module/ZezoPay/utils/hooks/useAsync.js.map +1 -0
  27. package/lib/module/ZezoPay/utils/hooks/useZezoPay.js +270 -0
  28. package/lib/module/ZezoPay/utils/hooks/useZezoPay.js.map +1 -0
  29. package/lib/module/ZezoPay/utils/index.js +15 -0
  30. package/lib/module/ZezoPay/utils/index.js.map +1 -0
  31. package/lib/module/index.js +4 -0
  32. package/lib/module/index.js.map +1 -0
  33. package/lib/module/package.json +1 -0
  34. package/lib/typescript/package.json +1 -0
  35. package/lib/typescript/src/ZezoPay/Payments/Providers/Razorpay/Razorpay.d.ts +7 -0
  36. package/lib/typescript/src/ZezoPay/Payments/Providers/Razorpay/Razorpay.d.ts.map +1 -0
  37. package/lib/typescript/src/ZezoPay/Payments/Providers/index.d.ts +7 -0
  38. package/lib/typescript/src/ZezoPay/Payments/Providers/index.d.ts.map +1 -0
  39. package/lib/typescript/src/ZezoPay/ZezoPay.d.ts +5 -0
  40. package/lib/typescript/src/ZezoPay/ZezoPay.d.ts.map +1 -0
  41. package/lib/typescript/src/ZezoPay/components/Header.d.ts +12 -0
  42. package/lib/typescript/src/ZezoPay/components/Header.d.ts.map +1 -0
  43. package/lib/typescript/src/ZezoPay/components/PayButton.d.ts +12 -0
  44. package/lib/typescript/src/ZezoPay/components/PayButton.d.ts.map +1 -0
  45. package/lib/typescript/src/ZezoPay/components/PaymentMethod.d.ts +12 -0
  46. package/lib/typescript/src/ZezoPay/components/PaymentMethod.d.ts.map +1 -0
  47. package/lib/typescript/src/ZezoPay/components/Summary.d.ts +7 -0
  48. package/lib/typescript/src/ZezoPay/components/Summary.d.ts.map +1 -0
  49. package/lib/typescript/src/ZezoPay/components/VoucherBox.d.ts +9 -0
  50. package/lib/typescript/src/ZezoPay/components/VoucherBox.d.ts.map +1 -0
  51. package/lib/typescript/src/ZezoPay/index.d.ts +3 -0
  52. package/lib/typescript/src/ZezoPay/index.d.ts.map +1 -0
  53. package/lib/typescript/src/ZezoPay/types/index.d.ts +65 -0
  54. package/lib/typescript/src/ZezoPay/types/index.d.ts.map +1 -0
  55. package/lib/typescript/src/ZezoPay/utils/hooks/useAsync.d.ts +6 -0
  56. package/lib/typescript/src/ZezoPay/utils/hooks/useAsync.d.ts.map +1 -0
  57. package/lib/typescript/src/ZezoPay/utils/hooks/useZezoPay.d.ts +46 -0
  58. package/lib/typescript/src/ZezoPay/utils/hooks/useZezoPay.d.ts.map +1 -0
  59. package/lib/typescript/src/ZezoPay/utils/index.d.ts +6 -0
  60. package/lib/typescript/src/ZezoPay/utils/index.d.ts.map +1 -0
  61. package/lib/typescript/src/index.d.ts +2 -0
  62. package/lib/typescript/src/index.d.ts.map +1 -0
  63. package/package.json +181 -0
  64. package/src/ZezoPay/Payments/Providers/PaymentGateways.types.d.ts +48 -0
  65. package/src/ZezoPay/Payments/Providers/Razorpay/Razorpay.ts +46 -0
  66. package/src/ZezoPay/Payments/Providers/index.ts +8 -0
  67. package/src/ZezoPay/ZezoPay.tsx +174 -0
  68. package/src/ZezoPay/components/Header.tsx +107 -0
  69. package/src/ZezoPay/components/PayButton.tsx +132 -0
  70. package/src/ZezoPay/components/PaymentMethod.tsx +259 -0
  71. package/src/ZezoPay/components/Summary.tsx +188 -0
  72. package/src/ZezoPay/components/VoucherBox.tsx +133 -0
  73. package/src/ZezoPay/index.ts +2 -0
  74. package/src/ZezoPay/types/index.ts +69 -0
  75. package/src/ZezoPay/utils/hooks/useAsync.ts +38 -0
  76. package/src/ZezoPay/utils/hooks/useZezoPay.ts +325 -0
  77. package/src/ZezoPay/utils/index.ts +16 -0
  78. package/src/index.tsx +1 -0
@@ -0,0 +1,325 @@
1
+ import { useCallback, useEffect, useMemo, useState } from 'react';
2
+ import { useAsync } from './useAsync';
3
+ import {
4
+ ZezoPayClient,
5
+ type ICheckoutResult,
6
+ type ISummaryItem,
7
+ type PaymentProvider,
8
+ type ZezoPayCallbacks,
9
+ type HandlePayment,
10
+ type IReadyPaymentProvider,
11
+ type ICheckoutPayload,
12
+ type BaseCheckoutInput,
13
+ } from '@zezosoft/zezopay-client';
14
+ import { Platform } from 'react-native';
15
+ import { Razorpay } from '../../Payments/Providers';
16
+
17
+ export const allowedProviders: PaymentProvider[] = ['razorpay'];
18
+
19
+ /**
20
+ * Parameters for the useZezoPay hook
21
+ * @interface UseZezoPayParams
22
+ */
23
+ interface UseZezoPayParams {
24
+ publicKey: string;
25
+ userInfo: { _id: string; name: string; email?: string; phone?: string };
26
+ subscriptionId?: string;
27
+ digitalProductId?: string;
28
+ summaryItems?: ISummaryItem[];
29
+ handlePayment?: HandlePayment;
30
+ callback?: ZezoPayCallbacks;
31
+ }
32
+
33
+ /**
34
+ * Custom hook to handle payments with ZezoPay SDK.
35
+ * Manages payment providers, summary items, and checkout process.
36
+ * @param params - Configuration for the ZezoPay client
37
+ * @returns Object with payment state and methods
38
+ */
39
+ export const useZezoPay = ({
40
+ publicKey,
41
+ userInfo,
42
+ subscriptionId,
43
+ digitalProductId,
44
+ summaryItems: initialItems = [],
45
+ handlePayment,
46
+ callback,
47
+ }: UseZezoPayParams) => {
48
+ // Input validation
49
+ if (!publicKey) throw new Error('publicKey is required');
50
+ if (!userInfo?._id || !userInfo?.name)
51
+ throw new Error('userInfo must include _id and name');
52
+
53
+ // SDK client
54
+ const zezopay = useMemo(
55
+ () =>
56
+ new ZezoPayClient({
57
+ publicKey,
58
+ platform: Platform.OS === 'ios' ? 'ios' : 'android',
59
+ }),
60
+ [publicKey]
61
+ );
62
+
63
+ // States
64
+ const [selectedPayment, setSelectedPayment] =
65
+ useState<PaymentProvider | null>(null);
66
+ const [summaryItems, setSummaryItems] =
67
+ useState<ISummaryItem[]>(initialItems);
68
+ const [voucherCode, setVoucherCode] = useState('');
69
+ const [isProcessing, setIsProcessing] = useState(false);
70
+ const [isSuccess, setIsSuccess] = useState(false);
71
+ const [error, setError] = useState('');
72
+
73
+ // Load payment providers
74
+ const {
75
+ result: providers,
76
+ loading,
77
+ error: providerError,
78
+ } = useAsync(async () => {
79
+ try {
80
+ const data = (await zezopay.payments.providers())?.data || [];
81
+ const filtered = data.filter((p: IReadyPaymentProvider) =>
82
+ allowedProviders.includes(p.provider as PaymentProvider)
83
+ );
84
+ if (!filtered.length) {
85
+ throw new Error('No supported payment providers available');
86
+ }
87
+ return filtered;
88
+ } catch (err) {
89
+ console.warn('Failed to load payment providers:', err);
90
+ throw new Error('Could not fetch payment providers');
91
+ }
92
+ }, [publicKey]);
93
+
94
+ // Auto-select first provider
95
+ useEffect(() => {
96
+ if (providers?.length && !selectedPayment) {
97
+ setSelectedPayment(providers[0]?.provider as PaymentProvider);
98
+ }
99
+ }, [providers, selectedPayment]);
100
+
101
+ // Total price calculation
102
+ const totalPrice = useMemo(() => {
103
+ if (!summaryItems.length) return 0;
104
+ return Number(
105
+ summaryItems
106
+ .reduce((sum, item) => {
107
+ let price = item.price || 0;
108
+ if (item.discount) {
109
+ if (typeof item.discount === 'number') {
110
+ price = (price * (100 - item.discount)) / 100;
111
+ } else if (item.discount.type === 'percentage') {
112
+ price = (price * (100 - item.discount.amount)) / 100;
113
+ } else if (item.discount.type === 'fixed') {
114
+ price = Math.max(0, price - item.discount.amount); // Prevent negative prices
115
+ }
116
+ }
117
+ return sum + price;
118
+ }, 0)
119
+ .toFixed(2)
120
+ );
121
+ }, [summaryItems]);
122
+
123
+ // Remove item from summary
124
+ const removeItem = useCallback((id: string | number) => {
125
+ setSummaryItems((prev) => prev.filter((item) => item.id !== id));
126
+ }, []);
127
+
128
+ // Default checkout handler
129
+ const defaultHandlePayment: HandlePayment = useCallback(
130
+ async ({
131
+ provider,
132
+ subscriptionId: subId,
133
+ digitalProductId: dpId,
134
+ userInfo: paymentUserInfo,
135
+ }) => {
136
+ if (!provider || !allowedProviders.includes(provider)) {
137
+ throw new Error(`Invalid payment provider: ${provider || 'none'}`);
138
+ }
139
+
140
+ // Common payload properties
141
+ const basePayload: BaseCheckoutInput = {
142
+ provider,
143
+ userId: paymentUserInfo._id,
144
+ metadata: { userInfo: paymentUserInfo },
145
+ ...(voucherCode && { coupon_code: voucherCode }), // Include coupon_code if provided
146
+ };
147
+
148
+ // Construct payload based on type
149
+ let payload: ICheckoutPayload;
150
+
151
+ if (subId) {
152
+ payload = {
153
+ ...basePayload,
154
+ type: 'subscription',
155
+ subscriptionId: subId,
156
+ };
157
+ } else if (dpId) {
158
+ payload = {
159
+ ...basePayload,
160
+ type: 'digital-product',
161
+ digitalProductId: dpId,
162
+ };
163
+ } else {
164
+ if (totalPrice <= 0) {
165
+ throw new Error(
166
+ 'Price must be greater than zero for normal payments'
167
+ );
168
+ }
169
+ payload = { ...basePayload, type: 'normal', price: totalPrice };
170
+ }
171
+
172
+ try {
173
+ const result = await zezopay.payments.checkout(payload);
174
+ if (result.status !== 200) {
175
+ throw new Error(`Checkout failed with status: ${result.status}`);
176
+ }
177
+ return result.data;
178
+ } catch (err) {
179
+ console.warn('Checkout error:', err);
180
+ throw new Error('Failed to initiate checkout');
181
+ }
182
+ },
183
+ [voucherCode, totalPrice, zezopay.payments]
184
+ );
185
+
186
+ const paymentFn = handlePayment || defaultHandlePayment;
187
+
188
+ // Payment handler
189
+ const paymentHandler = useCallback(
190
+ async (order: ICheckoutResult) => {
191
+ if (!selectedPayment) {
192
+ throw new Error('No payment provider selected');
193
+ }
194
+ if (!order?.orderId || !order?.price || !order?.currency) {
195
+ throw new Error(
196
+ 'Invalid order details: missing orderId, price, or currency'
197
+ );
198
+ }
199
+
200
+ try {
201
+ if (selectedPayment === 'razorpay') {
202
+ const razorpay = new Razorpay();
203
+ await razorpay.open({
204
+ amount: order.price * 100,
205
+ currency: order.currency,
206
+ order_id: order.orderId,
207
+ publicKey: order.publicKey || publicKey, // Fallback to publicKey
208
+ handler(response) {
209
+ if (response.razorpay_payment_id) {
210
+ callback?.onSuccess?.({
211
+ status: 'success',
212
+ order_id: response.razorpay_order_id,
213
+ signature: response.razorpay_signature,
214
+ payment_id: response.razorpay_payment_id,
215
+ });
216
+ setIsSuccess(true);
217
+ setError('');
218
+ } else {
219
+ const err = new Error('Payment failed: No payment ID received');
220
+ setError(err.message);
221
+ callback?.onFailure?.(err);
222
+ }
223
+ },
224
+ OnError(err) {
225
+ const errorMessage =
226
+ err?.description ||
227
+ err?.message ||
228
+ err?.details?.error?.description ||
229
+ 'Payment failed unexpectedly';
230
+
231
+ setError(errorMessage);
232
+ callback?.onError?.(err);
233
+ callback?.onFailure?.(err);
234
+ },
235
+ prefill: {
236
+ user_email: userInfo.email,
237
+ user_name: userInfo.name,
238
+ user_phone: userInfo.phone,
239
+ },
240
+ });
241
+ } else {
242
+ throw new Error(`Unsupported payment provider: ${selectedPayment}`);
243
+ }
244
+ } catch (err) {
245
+ console.warn('Payment handler error:', err);
246
+ throw err;
247
+ }
248
+ },
249
+ [selectedPayment, userInfo, callback, publicKey]
250
+ );
251
+
252
+ // Handle pay now
253
+ const handlePayNow = useCallback(async () => {
254
+ if (isProcessing) return; // Prevent multiple submissions
255
+ if (!selectedPayment) {
256
+ setError('Please select a payment provider');
257
+ return;
258
+ }
259
+ if (!summaryItems.length) {
260
+ setError('Cart is empty. Add items to proceed.');
261
+ return;
262
+ }
263
+ if (totalPrice <= 0) {
264
+ setError('Total price must be greater than zero');
265
+ return;
266
+ }
267
+
268
+ setError('');
269
+ setIsProcessing(true); // ✅ Set processing to true at the start
270
+
271
+ try {
272
+ const order = await paymentFn({
273
+ provider: selectedPayment,
274
+ subscriptionId,
275
+ digitalProductId,
276
+ userInfo,
277
+ });
278
+
279
+ if (!order) {
280
+ const err = new Error('No order data returned from checkout');
281
+ setError(err.message);
282
+ callback?.onFailure?.(err);
283
+ return;
284
+ }
285
+
286
+ await paymentHandler(order);
287
+ } catch (err: any) {
288
+ const errorMessage = err.message || 'Payment failed unexpectedly';
289
+ setError(errorMessage);
290
+ callback?.onFailure?.(err);
291
+ console.warn('Payment error:', err);
292
+ } finally {
293
+ setIsProcessing(false); // ✅ Reset processing state
294
+ }
295
+ }, [
296
+ isProcessing,
297
+ selectedPayment,
298
+ summaryItems,
299
+ totalPrice,
300
+ paymentFn,
301
+ subscriptionId,
302
+ digitalProductId,
303
+ userInfo,
304
+ paymentHandler,
305
+ callback,
306
+ ]);
307
+
308
+ return {
309
+ selectedPayment,
310
+ setSelectedPayment,
311
+ summaryItems,
312
+ setSummaryItems,
313
+ totalPrice,
314
+ voucherCode,
315
+ setVoucherCode,
316
+ isProcessing,
317
+ isSuccess,
318
+ error,
319
+ providers: providers || [],
320
+ loading,
321
+ providerError,
322
+ removeItem,
323
+ handlePayNow,
324
+ };
325
+ };
@@ -0,0 +1,16 @@
1
+ export function formatCurrency({
2
+ amount,
3
+ currency = 'INR',
4
+ minimumFractionDigits = 2,
5
+ }: {
6
+ amount: number;
7
+ currency?: string;
8
+ minimumFractionDigits?: number;
9
+ }): string {
10
+ return new Intl.NumberFormat('en-IN', {
11
+ style: 'currency',
12
+ currency,
13
+ minimumFractionDigits,
14
+ maximumFractionDigits: 2,
15
+ }).format(amount);
16
+ }
package/src/index.tsx ADDED
@@ -0,0 +1 @@
1
+ export * from './ZezoPay';