xcel-paygate-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 (59) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +225 -0
  3. package/dist/api/client.d.ts +19 -0
  4. package/dist/api/client.d.ts.map +1 -0
  5. package/dist/api/client.js +215 -0
  6. package/dist/components/XcelPaymentFlow.d.ts +50 -0
  7. package/dist/components/XcelPaymentFlow.d.ts.map +1 -0
  8. package/dist/components/XcelPaymentFlow.js +125 -0
  9. package/dist/components/XcelPaymentScreen.d.ts +67 -0
  10. package/dist/components/XcelPaymentScreen.d.ts.map +1 -0
  11. package/dist/components/XcelPaymentScreen.js +356 -0
  12. package/dist/components/XcelPaymentWebView.d.ts +76 -0
  13. package/dist/components/XcelPaymentWebView.d.ts.map +1 -0
  14. package/dist/components/XcelPaymentWebView.js +413 -0
  15. package/dist/components/index.d.ts +12 -0
  16. package/dist/components/index.d.ts.map +1 -0
  17. package/dist/components/index.js +14 -0
  18. package/dist/context/XcelPayGateProvider.d.ts +56 -0
  19. package/dist/context/XcelPayGateProvider.d.ts.map +1 -0
  20. package/dist/context/XcelPayGateProvider.js +107 -0
  21. package/dist/hooks/use-payment-completion.d.ts +75 -0
  22. package/dist/hooks/use-payment-completion.d.ts.map +1 -0
  23. package/dist/hooks/use-payment-completion.js +181 -0
  24. package/dist/hooks/use-xcel-paygate.d.ts +96 -0
  25. package/dist/hooks/use-xcel-paygate.d.ts.map +1 -0
  26. package/dist/hooks/use-xcel-paygate.js +279 -0
  27. package/dist/index.d.ts +14 -0
  28. package/dist/index.d.ts.map +1 -0
  29. package/dist/index.js +65 -0
  30. package/dist/services/checkout.d.ts +32 -0
  31. package/dist/services/checkout.d.ts.map +1 -0
  32. package/dist/services/checkout.js +137 -0
  33. package/dist/services/xcel-wallet.d.ts +23 -0
  34. package/dist/services/xcel-wallet.d.ts.map +1 -0
  35. package/dist/services/xcel-wallet.js +107 -0
  36. package/dist/types/index.d.ts +373 -0
  37. package/dist/types/index.d.ts.map +1 -0
  38. package/dist/types/index.js +2 -0
  39. package/dist/utils/payment-completion.d.ts +87 -0
  40. package/dist/utils/payment-completion.d.ts.map +1 -0
  41. package/dist/utils/payment-completion.js +110 -0
  42. package/dist/utils/payment-helpers.d.ts +55 -0
  43. package/dist/utils/payment-helpers.d.ts.map +1 -0
  44. package/dist/utils/payment-helpers.js +261 -0
  45. package/package.json +51 -0
  46. package/src/api/client.ts +326 -0
  47. package/src/components/XcelPaymentFlow.tsx +154 -0
  48. package/src/components/XcelPaymentScreen.tsx +477 -0
  49. package/src/components/XcelPaymentWebView.tsx +533 -0
  50. package/src/components/index.ts +14 -0
  51. package/src/context/XcelPayGateProvider.tsx +98 -0
  52. package/src/hooks/use-payment-completion.ts +225 -0
  53. package/src/hooks/use-xcel-paygate.ts +363 -0
  54. package/src/index.ts +70 -0
  55. package/src/services/checkout.ts +165 -0
  56. package/src/services/xcel-wallet.ts +175 -0
  57. package/src/types/index.ts +407 -0
  58. package/src/utils/payment-completion.ts +144 -0
  59. package/src/utils/payment-helpers.ts +287 -0
@@ -0,0 +1,67 @@
1
+ /**
2
+ * XcelPaymentScreen - Complete Payment UI Component
3
+ *
4
+ * Drop-in payment screen with full UI and logic.
5
+ * Just import and use - handles everything!
6
+ *
7
+ * @example
8
+ * ```tsx
9
+ * import { XcelPaymentScreen } from '@xcelapp/paygate-sdk';
10
+ *
11
+ * export default function PaymentPage() {
12
+ * return (
13
+ * <XcelPaymentScreen
14
+ * config={{
15
+ * merchantId: 'your-merchant-id',
16
+ * publicKey: 'your-public-key',
17
+ * }}
18
+ * onPaymentComplete={(result) => {
19
+ * console.log('Payment complete:', result);
20
+ * }}
21
+ * />
22
+ * );
23
+ * }
24
+ * ```
25
+ */
26
+ import React from 'react';
27
+ import { ViewStyle, TextStyle } from 'react-native';
28
+ import type { XcelPayGateConfig, PaymentRequest, TransactionData } from '../types';
29
+ export interface XcelPaymentScreenProps {
30
+ /** SDK Configuration */
31
+ config?: XcelPayGateConfig;
32
+ /** Optional: Custom styles */
33
+ styles?: {
34
+ container?: ViewStyle;
35
+ button?: ViewStyle;
36
+ buttonText?: TextStyle;
37
+ input?: ViewStyle;
38
+ [key: string]: ViewStyle | TextStyle | undefined;
39
+ };
40
+ /** Optional: Pre-filled form values */
41
+ defaultValues?: {
42
+ amount?: string;
43
+ email?: string;
44
+ phone?: string;
45
+ description?: string;
46
+ };
47
+ /** Optional: Customize payment request */
48
+ paymentConfig?: Partial<Omit<PaymentRequest, 'amount' | 'currency'>>;
49
+ /** Called when payment link is generated */
50
+ onPaymentLinkGenerated?: (paymentLink: string, paymentCode: string) => void;
51
+ /** Called when payment is complete (success/fail) */
52
+ onPaymentComplete?: (transaction: TransactionData) => void;
53
+ /** Called on error */
54
+ onError?: (error: Error) => void;
55
+ /** Show status check button */
56
+ showStatusButton?: boolean;
57
+ /** Enable auto-polling */
58
+ enablePolling?: boolean;
59
+ /** Custom button text */
60
+ buttonText?: string;
61
+ /** Currency (default: XAF) */
62
+ currency?: string;
63
+ /** Hide form, only show button */
64
+ minimalMode?: boolean;
65
+ }
66
+ export declare function XcelPaymentScreen({ config, styles: customStyles, defaultValues, paymentConfig, onPaymentLinkGenerated, onPaymentComplete, onError, showStatusButton, enablePolling, buttonText, currency, minimalMode, }: XcelPaymentScreenProps): React.JSX.Element;
67
+ //# sourceMappingURL=XcelPaymentScreen.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"XcelPaymentScreen.d.ts","sourceRoot":"","sources":["../../src/components/XcelPaymentScreen.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,KAAmB,MAAM,OAAO,CAAC;AACxC,OAAO,EASL,SAAS,EACT,SAAS,EACV,MAAM,cAAc,CAAC;AAEtB,OAAO,KAAK,EAAE,iBAAiB,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAEnF,MAAM,WAAW,sBAAsB;IACrC,wBAAwB;IACxB,MAAM,CAAC,EAAE,iBAAiB,CAAC;IAE3B,8BAA8B;IAC9B,MAAM,CAAC,EAAE;QACP,SAAS,CAAC,EAAE,SAAS,CAAC;QACtB,MAAM,CAAC,EAAE,SAAS,CAAC;QACnB,UAAU,CAAC,EAAE,SAAS,CAAC;QACvB,KAAK,CAAC,EAAE,SAAS,CAAC;QAClB,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;KAClD,CAAC;IAEF,uCAAuC;IACvC,aAAa,CAAC,EAAE;QACd,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,CAAC;IAEF,0CAA0C;IAC1C,aAAa,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,cAAc,EAAE,QAAQ,GAAG,UAAU,CAAC,CAAC,CAAC;IAErE,4CAA4C;IAC5C,sBAAsB,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;IAE5E,qDAAqD;IACrD,iBAAiB,CAAC,EAAE,CAAC,WAAW,EAAE,eAAe,KAAK,IAAI,CAAC;IAE3D,sBAAsB;IACtB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IAEjC,+BAA+B;IAC/B,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAE3B,0BAA0B;IAC1B,aAAa,CAAC,EAAE,OAAO,CAAC;IAExB,yBAAyB;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB,8BAA8B;IAC9B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB,kCAAkC;IAClC,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,wBAAgB,iBAAiB,CAAC,EAChC,MAAM,EACN,MAAM,EAAE,YAAiB,EACzB,aAAkB,EAClB,aAAkB,EAClB,sBAAsB,EACtB,iBAAiB,EACjB,OAAO,EACP,gBAAuB,EACvB,aAAqB,EACrB,UAAoC,EACpC,QAAgB,EAChB,WAAmB,GACpB,EAAE,sBAAsB,qBAiPxB"}
@@ -0,0 +1,356 @@
1
+ "use strict";
2
+ /**
3
+ * XcelPaymentScreen - Complete Payment UI Component
4
+ *
5
+ * Drop-in payment screen with full UI and logic.
6
+ * Just import and use - handles everything!
7
+ *
8
+ * @example
9
+ * ```tsx
10
+ * import { XcelPaymentScreen } from '@xcelapp/paygate-sdk';
11
+ *
12
+ * export default function PaymentPage() {
13
+ * return (
14
+ * <XcelPaymentScreen
15
+ * config={{
16
+ * merchantId: 'your-merchant-id',
17
+ * publicKey: 'your-public-key',
18
+ * }}
19
+ * onPaymentComplete={(result) => {
20
+ * console.log('Payment complete:', result);
21
+ * }}
22
+ * />
23
+ * );
24
+ * }
25
+ * ```
26
+ */
27
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
28
+ if (k2 === undefined) k2 = k;
29
+ var desc = Object.getOwnPropertyDescriptor(m, k);
30
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
31
+ desc = { enumerable: true, get: function() { return m[k]; } };
32
+ }
33
+ Object.defineProperty(o, k2, desc);
34
+ }) : (function(o, m, k, k2) {
35
+ if (k2 === undefined) k2 = k;
36
+ o[k2] = m[k];
37
+ }));
38
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
39
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
40
+ }) : function(o, v) {
41
+ o["default"] = v;
42
+ });
43
+ var __importStar = (this && this.__importStar) || (function () {
44
+ var ownKeys = function(o) {
45
+ ownKeys = Object.getOwnPropertyNames || function (o) {
46
+ var ar = [];
47
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
48
+ return ar;
49
+ };
50
+ return ownKeys(o);
51
+ };
52
+ return function (mod) {
53
+ if (mod && mod.__esModule) return mod;
54
+ var result = {};
55
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
56
+ __setModuleDefault(result, mod);
57
+ return result;
58
+ };
59
+ })();
60
+ Object.defineProperty(exports, "__esModule", { value: true });
61
+ exports.XcelPaymentScreen = XcelPaymentScreen;
62
+ const react_1 = __importStar(require("react"));
63
+ const react_native_1 = require("react-native");
64
+ const use_xcel_paygate_1 = require("../hooks/use-xcel-paygate");
65
+ function XcelPaymentScreen({ config, styles: customStyles = {}, defaultValues = {}, paymentConfig = {}, onPaymentLinkGenerated, onPaymentComplete, onError, showStatusButton = true, enablePolling = false, buttonText = 'Generate Payment Link', currency = 'XAF', minimalMode = false, }) {
66
+ // Form state
67
+ const [amount, setAmount] = (0, react_1.useState)(defaultValues.amount || '1000');
68
+ const [email, setEmail] = (0, react_1.useState)(defaultValues.email || '');
69
+ const [phone, setPhone] = (0, react_1.useState)(defaultValues.phone || '');
70
+ const [description, setDescription] = (0, react_1.useState)(defaultValues.description || '');
71
+ // SDK Hook
72
+ const { initiatePayment, checkStatus, loading, error, paymentLink, paymentCode, transaction, } = (0, use_xcel_paygate_1.useCheckout)(config || undefined);
73
+ // Optional polling - only if enabled
74
+ const pollingEnabled = enablePolling && !!paymentCode;
75
+ const pollingResult = pollingEnabled
76
+ ? (0, use_xcel_paygate_1.usePaymentPolling)(config || null, paymentCode, {
77
+ enabled: true,
78
+ maxAttempts: 24,
79
+ intervalMs: 5000,
80
+ })
81
+ : { result: null, isPolling: false };
82
+ const { result, isPolling } = pollingResult;
83
+ // Handle payment initiation
84
+ const handlePay = async () => {
85
+ try {
86
+ const response = await initiatePayment({
87
+ amount,
88
+ currency,
89
+ client_transaction_id: `TXN-${Date.now()}`,
90
+ customer_email: email,
91
+ customer_phone: phone,
92
+ description: description,
93
+ channel: 'WEB',
94
+ redirect_url: 'https://business.xcelapp.com/#/auth',
95
+ ...paymentConfig,
96
+ });
97
+ const link = response.data.payment_link;
98
+ const code = response.data.payment_code;
99
+ console.log('✓ Payment Link Generated:', link);
100
+ console.log('✓ Payment Code:', code);
101
+ onPaymentLinkGenerated === null || onPaymentLinkGenerated === void 0 ? void 0 : onPaymentLinkGenerated(link, code);
102
+ }
103
+ catch (err) {
104
+ const errorObj = err instanceof Error ? err : new Error('Payment failed');
105
+ console.error('Payment Error:', errorObj);
106
+ onError === null || onError === void 0 ? void 0 : onError(errorObj);
107
+ react_native_1.Alert.alert('Error', errorObj.message);
108
+ }
109
+ };
110
+ // Handle status check
111
+ const handleCheckStatus = async () => {
112
+ if (!paymentCode) {
113
+ react_native_1.Alert.alert('Error', 'No payment code available');
114
+ return;
115
+ }
116
+ try {
117
+ const txn = await checkStatus();
118
+ react_native_1.Alert.alert('Payment Status', `Status: ${txn.status}\nAmount: ${txn.amount} ${txn.currency}`);
119
+ if (onPaymentComplete && (txn.status === 'SUCCESS' || txn.status === 'FAILED')) {
120
+ onPaymentComplete(txn);
121
+ }
122
+ }
123
+ catch (err) {
124
+ const errorObj = err instanceof Error ? err : new Error('Status check failed');
125
+ onError === null || onError === void 0 ? void 0 : onError(errorObj);
126
+ react_native_1.Alert.alert('Error', errorObj.message);
127
+ }
128
+ };
129
+ // Handle polling result - result is PaymentResult, not TransactionData
130
+ // We don't call onPaymentComplete here since it expects TransactionData
131
+ // User should use check status manually if using polling
132
+ // Minimal mode - just show payment link if available
133
+ if (minimalMode && paymentLink) {
134
+ return (<react_native_1.View style={[styles.container, customStyles.container]}>
135
+ <react_native_1.Text style={styles.title}>Payment Link Ready</react_native_1.Text>
136
+ <react_native_1.Text style={styles.paymentLink}>{paymentLink}</react_native_1.Text>
137
+ <react_native_1.Text style={styles.label}>Payment Code: {paymentCode}</react_native_1.Text>
138
+ {showStatusButton && (<react_native_1.Pressable style={[styles.secondaryButton, customStyles.button]} onPress={handleCheckStatus}>
139
+ <react_native_1.Text style={[styles.secondaryButtonText, customStyles.buttonText]}>
140
+ Check Status
141
+ </react_native_1.Text>
142
+ </react_native_1.Pressable>)}
143
+ </react_native_1.View>);
144
+ }
145
+ return (<react_native_1.ScrollView style={[styles.container, customStyles.container]}>
146
+ <react_native_1.View style={styles.content}>
147
+ <react_native_1.Text style={styles.title}>XCEL PayGate</react_native_1.Text>
148
+ <react_native_1.Text style={styles.subtitle}>Secure Payment Processing</react_native_1.Text>
149
+
150
+ {/* Payment Form */}
151
+ {!minimalMode && (<react_native_1.View style={styles.section}>
152
+ <react_native_1.Text style={styles.sectionTitle}>Payment Details</react_native_1.Text>
153
+
154
+ <react_native_1.Text style={styles.label}>Amount ({currency})</react_native_1.Text>
155
+ <react_native_1.TextInput style={[styles.input, customStyles.input]} value={amount} onChangeText={setAmount} placeholder="1000" keyboardType="decimal-pad"/>
156
+
157
+ <react_native_1.Text style={styles.label}>Customer Email (Optional)</react_native_1.Text>
158
+ <react_native_1.TextInput style={[styles.input, customStyles.input]} value={email} onChangeText={setEmail} placeholder="customer@example.com" keyboardType="email-address" autoCapitalize="none"/>
159
+
160
+ <react_native_1.Text style={styles.label}>Customer Phone (Optional)</react_native_1.Text>
161
+ <react_native_1.TextInput style={[styles.input, customStyles.input]} value={phone} onChangeText={setPhone} placeholder="237233429972" keyboardType="phone-pad"/>
162
+
163
+ <react_native_1.Text style={styles.label}>Description (Optional)</react_native_1.Text>
164
+ <react_native_1.TextInput style={[styles.input, customStyles.input]} value={description} onChangeText={setDescription} placeholder="Payment description"/>
165
+ </react_native_1.View>)}
166
+
167
+ {/* Generate Payment Button */}
168
+ <react_native_1.Pressable style={[
169
+ styles.button,
170
+ customStyles.button,
171
+ loading && styles.buttonDisabled,
172
+ ]} onPress={handlePay} disabled={loading}>
173
+ {loading ? (<react_native_1.ActivityIndicator color="#fff"/>) : (<react_native_1.Text style={[styles.buttonText, customStyles.buttonText]}>
174
+ {buttonText}
175
+ </react_native_1.Text>)}
176
+ </react_native_1.Pressable>
177
+
178
+ {/* Payment Result Section */}
179
+ {paymentCode && (<react_native_1.View style={styles.resultSection}>
180
+ <react_native_1.Text style={styles.resultTitle}>✓ Payment Created</react_native_1.Text>
181
+
182
+ <react_native_1.View style={styles.resultRow}>
183
+ <react_native_1.Text style={styles.resultLabel}>Payment Code:</react_native_1.Text>
184
+ <react_native_1.Text style={styles.resultValue}>{paymentCode}</react_native_1.Text>
185
+ </react_native_1.View>
186
+
187
+ {paymentLink && (<react_native_1.View style={styles.resultRow}>
188
+ <react_native_1.Text style={styles.resultLabel}>Payment Link:</react_native_1.Text>
189
+ <react_native_1.Text style={[styles.resultValue, styles.linkText]} numberOfLines={1}>
190
+ {paymentLink}
191
+ </react_native_1.Text>
192
+ </react_native_1.View>)}
193
+
194
+ {transaction && (<>
195
+ <react_native_1.View style={styles.resultRow}>
196
+ <react_native_1.Text style={styles.resultLabel}>Status:</react_native_1.Text>
197
+ <react_native_1.Text style={[styles.resultValue, styles.statusText]}>
198
+ {transaction.status}
199
+ </react_native_1.Text>
200
+ </react_native_1.View>
201
+
202
+ <react_native_1.View style={styles.resultRow}>
203
+ <react_native_1.Text style={styles.resultLabel}>Transaction ID:</react_native_1.Text>
204
+ <react_native_1.Text style={styles.resultValue}>
205
+ {transaction.transaction_id}
206
+ </react_native_1.Text>
207
+ </react_native_1.View>
208
+ </>)}
209
+
210
+ {isPolling && (<react_native_1.Text style={styles.pollingText}>Checking payment status...</react_native_1.Text>)}
211
+
212
+ {/* Manual Status Check */}
213
+ {showStatusButton && (<react_native_1.Pressable style={[styles.secondaryButton, customStyles.button]} onPress={handleCheckStatus}>
214
+ <react_native_1.Text style={[styles.secondaryButtonText, customStyles.buttonText]}>
215
+ Check Status Manually
216
+ </react_native_1.Text>
217
+ </react_native_1.Pressable>)}
218
+ </react_native_1.View>)}
219
+
220
+ {/* Error Display */}
221
+ {error && (<react_native_1.View style={styles.errorBox}>
222
+ <react_native_1.Text style={styles.errorText}>⚠️ {error.message}</react_native_1.Text>
223
+ </react_native_1.View>)}
224
+ </react_native_1.View>
225
+ </react_native_1.ScrollView>);
226
+ }
227
+ const styles = react_native_1.StyleSheet.create({
228
+ container: {
229
+ flex: 1,
230
+ backgroundColor: '#fff',
231
+ },
232
+ content: {
233
+ padding: 20,
234
+ },
235
+ title: {
236
+ fontSize: 24,
237
+ fontWeight: 'bold',
238
+ marginBottom: 8,
239
+ textAlign: 'center',
240
+ color: '#000',
241
+ },
242
+ subtitle: {
243
+ fontSize: 16,
244
+ marginBottom: 24,
245
+ textAlign: 'center',
246
+ color: '#666',
247
+ },
248
+ section: {
249
+ marginBottom: 24,
250
+ padding: 16,
251
+ borderRadius: 8,
252
+ backgroundColor: '#f5f5f5',
253
+ },
254
+ sectionTitle: {
255
+ fontSize: 18,
256
+ fontWeight: '600',
257
+ marginBottom: 16,
258
+ color: '#000',
259
+ },
260
+ label: {
261
+ marginBottom: 8,
262
+ fontWeight: '600',
263
+ color: '#333',
264
+ },
265
+ input: {
266
+ backgroundColor: '#fff',
267
+ borderWidth: 1,
268
+ borderColor: '#ddd',
269
+ borderRadius: 8,
270
+ padding: 12,
271
+ marginBottom: 16,
272
+ fontSize: 16,
273
+ },
274
+ button: {
275
+ backgroundColor: '#007AFF',
276
+ padding: 16,
277
+ borderRadius: 8,
278
+ alignItems: 'center',
279
+ marginBottom: 16,
280
+ },
281
+ buttonDisabled: {
282
+ opacity: 0.6,
283
+ },
284
+ buttonText: {
285
+ color: '#fff',
286
+ fontSize: 16,
287
+ fontWeight: '600',
288
+ },
289
+ secondaryButton: {
290
+ backgroundColor: '#f0f0f0',
291
+ padding: 12,
292
+ borderRadius: 8,
293
+ alignItems: 'center',
294
+ marginTop: 8,
295
+ },
296
+ secondaryButtonText: {
297
+ color: '#007AFF',
298
+ fontSize: 14,
299
+ fontWeight: '600',
300
+ },
301
+ resultSection: {
302
+ padding: 16,
303
+ borderRadius: 8,
304
+ backgroundColor: '#e8f5e9',
305
+ marginBottom: 16,
306
+ },
307
+ resultTitle: {
308
+ fontSize: 18,
309
+ fontWeight: 'bold',
310
+ marginBottom: 16,
311
+ color: '#2e7d32',
312
+ },
313
+ resultRow: {
314
+ marginBottom: 12,
315
+ },
316
+ resultLabel: {
317
+ fontWeight: '600',
318
+ marginBottom: 4,
319
+ color: '#333',
320
+ },
321
+ resultValue: {
322
+ fontSize: 14,
323
+ color: '#000',
324
+ },
325
+ linkText: {
326
+ fontSize: 12,
327
+ color: '#007AFF',
328
+ },
329
+ statusText: {
330
+ fontWeight: 'bold',
331
+ fontSize: 16,
332
+ },
333
+ pollingText: {
334
+ marginTop: 12,
335
+ fontStyle: 'italic',
336
+ color: '#666',
337
+ },
338
+ errorBox: {
339
+ backgroundColor: '#ffebee',
340
+ padding: 16,
341
+ borderRadius: 8,
342
+ marginBottom: 16,
343
+ },
344
+ errorText: {
345
+ color: '#c62828',
346
+ fontWeight: '500',
347
+ },
348
+ paymentLink: {
349
+ fontSize: 12,
350
+ color: '#007AFF',
351
+ marginBottom: 16,
352
+ padding: 12,
353
+ backgroundColor: '#f5f5f5',
354
+ borderRadius: 8,
355
+ },
356
+ });
@@ -0,0 +1,76 @@
1
+ /**
2
+ * XcelPaymentWebView - WebView Payment Handler Component
3
+ *
4
+ * Handles payment flow in a WebView with automatic status detection.
5
+ * Drop this component in your navigation stack and it handles everything!
6
+ *
7
+ * @example
8
+ * ```tsx
9
+ * import { XcelPaymentWebView } from '@xcelapp/paygate-sdk';
10
+ *
11
+ * export default function PaymentWebViewScreen({ route }) {
12
+ * const { paymentLink, paymentCode } = route.params;
13
+ *
14
+ * return (
15
+ * <XcelPaymentWebView
16
+ * paymentLink={paymentLink}
17
+ * paymentCode={paymentCode}
18
+ * onSuccess={(result) => {
19
+ * console.log('Payment successful!', result);
20
+ * navigation.navigate('Receipt', { result });
21
+ * }}
22
+ * onFailure={(result) => {
23
+ * console.log('Payment failed', result);
24
+ * navigation.goBack();
25
+ * }}
26
+ * />
27
+ * );
28
+ * }
29
+ * ```
30
+ */
31
+ import React from 'react';
32
+ import { ViewStyle, TextStyle } from 'react-native';
33
+ export interface PaymentResult {
34
+ status: 'SUCCESS' | 'FAILED' | 'PENDING';
35
+ paymentCode?: string;
36
+ transactionId?: string;
37
+ url?: string;
38
+ bodyText?: string;
39
+ }
40
+ export interface XcelPaymentWebViewProps {
41
+ /** Payment link URL */
42
+ paymentLink: string;
43
+ /** Payment code for tracking */
44
+ paymentCode?: string;
45
+ /** Additional payment details */
46
+ amount?: string;
47
+ currency?: string;
48
+ description?: string;
49
+ /** Called when payment succeeds */
50
+ onSuccess?: (result: PaymentResult) => void;
51
+ /** Called when payment fails */
52
+ onFailure?: (result: PaymentResult) => void;
53
+ /** Called when payment is pending */
54
+ onPending?: (result: PaymentResult) => void;
55
+ /** Called when user closes/cancels */
56
+ onCancel?: () => void;
57
+ /** Custom header component */
58
+ renderHeader?: () => React.ReactNode;
59
+ /** Custom loading component */
60
+ renderLoading?: () => React.ReactNode;
61
+ /** Custom styles */
62
+ styles?: {
63
+ container?: ViewStyle;
64
+ header?: ViewStyle;
65
+ backButton?: ViewStyle;
66
+ backButtonText?: TextStyle;
67
+ webview?: ViewStyle;
68
+ [key: string]: ViewStyle | TextStyle | undefined;
69
+ };
70
+ /** Success detection timeout (ms) */
71
+ successTimeout?: number;
72
+ /** Show back button */
73
+ showBackButton?: boolean;
74
+ }
75
+ export declare function XcelPaymentWebView({ paymentLink, paymentCode, amount, currency, description, onSuccess, onFailure, onPending, onCancel, renderHeader, renderLoading, styles: customStyles, successTimeout, showBackButton, }: XcelPaymentWebViewProps): React.JSX.Element;
76
+ //# sourceMappingURL=XcelPaymentWebView.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"XcelPaymentWebView.d.ts","sourceRoot":"","sources":["../../src/components/XcelPaymentWebView.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,OAAO,KAAmD,MAAM,OAAO,CAAC;AACxE,OAAO,EAML,SAAS,EACT,SAAS,EACV,MAAM,cAAc,CAAC;AAEtB,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,SAAS,GAAG,QAAQ,GAAG,SAAS,CAAC;IACzC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,uBAAuB;IACtC,uBAAuB;IACvB,WAAW,EAAE,MAAM,CAAC;IAEpB,gCAAgC;IAChC,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,iCAAiC;IACjC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,mCAAmC;IACnC,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,IAAI,CAAC;IAE5C,gCAAgC;IAChC,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,IAAI,CAAC;IAE5C,qCAAqC;IACrC,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,IAAI,CAAC;IAE5C,sCAAsC;IACtC,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IAEtB,8BAA8B;IAC9B,YAAY,CAAC,EAAE,MAAM,KAAK,CAAC,SAAS,CAAC;IAErC,+BAA+B;IAC/B,aAAa,CAAC,EAAE,MAAM,KAAK,CAAC,SAAS,CAAC;IAEtC,oBAAoB;IACpB,MAAM,CAAC,EAAE;QACP,SAAS,CAAC,EAAE,SAAS,CAAC;QACtB,MAAM,CAAC,EAAE,SAAS,CAAC;QACnB,UAAU,CAAC,EAAE,SAAS,CAAC;QACvB,cAAc,CAAC,EAAE,SAAS,CAAC;QAC3B,OAAO,CAAC,EAAE,SAAS,CAAC;QACpB,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;KAClD,CAAC;IAEF,qCAAqC;IACrC,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB,uBAAuB;IACvB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,wBAAgB,kBAAkB,CAAC,EACjC,WAAW,EACX,WAAW,EACX,MAAM,EACN,QAAQ,EACR,WAAW,EACX,SAAS,EACT,SAAS,EACT,SAAS,EACT,QAAQ,EACR,YAAY,EACZ,aAAa,EACb,MAAM,EAAE,YAAiB,EACzB,cAAsB,EACtB,cAAqB,GACtB,EAAE,uBAAuB,qBA4VzB"}