@reevit/core 0.1.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Reevit
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,56 @@
1
+ # @reevit/core
2
+
3
+ The foundation for all Reevit payment SDKs. It provides the shared API client, state machine logic, type definitions, and utility functions used by the React, Vue, and Svelte SDKs.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @reevit/core
9
+ ```
10
+
11
+ ## Features
12
+
13
+ - **ReevitAPIClient**: A lightweight, promise-based client for interacting with the Reevit backend.
14
+ - **State Machine**: Framework-agnostic logic for managing checkout flows.
15
+ - **Utilities**: Amount formatting, phone validation, network detection, and more.
16
+ - **Types**: Comprehensive TypeScript definitions for the entire Reevit ecosystem.
17
+ - **Styles**: Shared CSS for the "Unified Payment Widget" appearance.
18
+
19
+ ## Usage (Low-level API)
20
+
21
+ If you're building a custom integration or another framework SDK, you can use the core components directly.
22
+
23
+ ### Interacting with the API
24
+
25
+ ```typescript
26
+ import { ReevitAPIClient } from '@reevit/core';
27
+
28
+ const client = new ReevitAPIClient({
29
+ publicKey: 'pk_test_xxx',
30
+ });
31
+
32
+ // Create a payment intent
33
+ const { data, error } = await client.createPaymentIntent({
34
+ amount: 5000,
35
+ currency: 'GHS',
36
+ email: 'customer@example.com',
37
+ }, 'card');
38
+
39
+ if (data) {
40
+ console.log('Intent created:', data.id);
41
+ }
42
+ ```
43
+
44
+ ### Using Utilities
45
+
46
+ ```typescript
47
+ import { formatAmount, validatePhone, detectNetwork } from '@reevit/core';
48
+
49
+ console.log(formatAmount(10000, 'GHS')); // "GH₵ 100.00"
50
+ console.log(validatePhone('0241234567')); // true
51
+ console.log(detectNetwork('0241234567')); // "mtn"
52
+ ```
53
+
54
+ ## License
55
+
56
+ MIT © Reevit
@@ -0,0 +1,332 @@
1
+ /**
2
+ * Reevit Core Types
3
+ * Shared type definitions for all Reevit SDKs
4
+ */
5
+ type PaymentMethod = 'card' | 'mobile_money' | 'bank_transfer';
6
+ type MobileMoneyNetwork = 'mtn' | 'vodafone' | 'airteltigo';
7
+ type PSPType = 'paystack' | 'hubtel' | 'flutterwave' | 'stripe' | 'monnify' | 'mpesa';
8
+ interface ReevitCheckoutConfig {
9
+ /** Your Reevit public key (pk_live_xxx or pk_test_xxx) */
10
+ publicKey: string;
11
+ /** Amount in the smallest currency unit (e.g., pesewas for GHS) */
12
+ amount: number;
13
+ /** Currency code (e.g., 'GHS', 'NGN', 'USD') */
14
+ currency: string;
15
+ /** Customer email address */
16
+ email?: string;
17
+ /** Customer phone number (required for mobile money) */
18
+ phone?: string;
19
+ /** Unique reference for this transaction */
20
+ reference?: string;
21
+ /** Additional metadata to attach to the payment */
22
+ metadata?: Record<string, unknown>;
23
+ /** Payment methods to display */
24
+ paymentMethods?: PaymentMethod[];
25
+ }
26
+ interface ReevitCheckoutCallbacks {
27
+ /** Called when payment is successful */
28
+ onSuccess?: (result: PaymentResult) => void;
29
+ /** Called when payment fails */
30
+ onError?: (error: PaymentError) => void;
31
+ /** Called when user closes the checkout */
32
+ onClose?: () => void;
33
+ /** Called when checkout state changes */
34
+ onStateChange?: (state: CheckoutState) => void;
35
+ }
36
+ type CheckoutState = 'idle' | 'loading' | 'ready' | 'method_selected' | 'processing' | 'success' | 'failed' | 'closed';
37
+ interface PaymentResult {
38
+ /** Unique payment ID from Reevit */
39
+ paymentId: string;
40
+ /** Reference provided or generated */
41
+ reference: string;
42
+ /** Amount paid in smallest currency unit */
43
+ amount: number;
44
+ /** Currency code */
45
+ currency: string;
46
+ /** Payment method used */
47
+ paymentMethod: PaymentMethod;
48
+ /** PSP that processed the payment */
49
+ psp: string;
50
+ /** PSP's transaction reference */
51
+ pspReference: string;
52
+ /** Payment status */
53
+ status: 'success' | 'pending';
54
+ /** Any additional data from the PSP */
55
+ metadata?: Record<string, unknown>;
56
+ }
57
+ interface PaymentError {
58
+ /** Error code */
59
+ code: string;
60
+ /** Human-readable error message */
61
+ message: string;
62
+ /** Whether the error is recoverable (user can retry) */
63
+ recoverable?: boolean;
64
+ /** Original error from PSP if available */
65
+ originalError?: unknown;
66
+ /** Additional error details */
67
+ details?: Record<string, unknown>;
68
+ }
69
+ interface ReevitTheme {
70
+ /** Primary brand color */
71
+ primaryColor?: string;
72
+ /** Background color */
73
+ backgroundColor?: string;
74
+ /** Text color */
75
+ textColor?: string;
76
+ /** Border radius for inputs and buttons */
77
+ borderRadius?: string;
78
+ /** Font family to use */
79
+ fontFamily?: string;
80
+ /** Whether to use dark mode */
81
+ darkMode?: boolean;
82
+ }
83
+ interface PSPConfig {
84
+ id: string;
85
+ name: string;
86
+ supportedMethods: PaymentMethod[];
87
+ supportedCurrencies: string[];
88
+ }
89
+ interface MobileMoneyFormData {
90
+ phone: string;
91
+ network: MobileMoneyNetwork;
92
+ }
93
+ interface CardFormData {
94
+ /** Token from PSP's hosted fields */
95
+ token: string;
96
+ /** Last 4 digits for display */
97
+ last4?: string;
98
+ /** Card brand (visa, mastercard, etc.) */
99
+ brand?: string;
100
+ }
101
+ interface PaymentIntent {
102
+ /** Unique payment intent ID */
103
+ id: string;
104
+ /** Client secret for authenticating client-side operations */
105
+ clientSecret: string;
106
+ /** Amount in smallest currency unit */
107
+ amount: number;
108
+ /** Currency code */
109
+ currency: string;
110
+ /** Payment status */
111
+ status: 'pending' | 'processing' | 'succeeded' | 'failed' | 'cancelled';
112
+ /** Recommended PSP based on routing rules */
113
+ recommendedPsp: PSPType;
114
+ /** Available payment methods for this intent */
115
+ availableMethods: PaymentMethod[];
116
+ /** Connection ID (from Reevit backend) */
117
+ connectionId?: string;
118
+ /** Provider name (from backend) */
119
+ provider?: string;
120
+ /** Fee amount charged by PSP */
121
+ feeAmount?: number;
122
+ /** Fee currency */
123
+ feeCurrency?: string;
124
+ /** Net amount after fees */
125
+ netAmount?: number;
126
+ /** Additional metadata */
127
+ metadata?: Record<string, unknown>;
128
+ }
129
+
130
+ /**
131
+ * Reevit API Client
132
+ *
133
+ * Handles communication with the Reevit backend for payment operations.
134
+ */
135
+
136
+ interface CreatePaymentIntentRequest {
137
+ amount: number;
138
+ currency: string;
139
+ method: string;
140
+ country: string;
141
+ customer_id?: string;
142
+ metadata?: Record<string, unknown>;
143
+ description?: string;
144
+ policy?: {
145
+ prefer?: string[];
146
+ max_amount?: number;
147
+ blocked_bins?: string[];
148
+ allowed_bins?: string[];
149
+ velocity_max_per_minute?: number;
150
+ };
151
+ }
152
+ interface PaymentIntentResponse {
153
+ id: string;
154
+ connection_id: string;
155
+ provider: string;
156
+ status: string;
157
+ client_secret: string;
158
+ amount: number;
159
+ currency: string;
160
+ fee_amount: number;
161
+ fee_currency: string;
162
+ net_amount: number;
163
+ }
164
+ interface ConfirmPaymentRequest {
165
+ provider_ref_id: string;
166
+ provider_data?: Record<string, unknown>;
167
+ }
168
+ interface PaymentDetailResponse {
169
+ id: string;
170
+ connection_id: string;
171
+ provider: string;
172
+ method: string;
173
+ status: string;
174
+ amount: number;
175
+ currency: string;
176
+ fee_amount: number;
177
+ fee_currency: string;
178
+ net_amount: number;
179
+ customer_id?: string;
180
+ client_secret: string;
181
+ provider_ref_id?: string;
182
+ metadata?: Record<string, unknown>;
183
+ created_at: string;
184
+ updated_at: string;
185
+ }
186
+ interface APIErrorResponse {
187
+ code: string;
188
+ message: string;
189
+ details?: Record<string, string>;
190
+ }
191
+ interface ReevitAPIClientConfig {
192
+ /** Your Reevit public key */
193
+ publicKey: string;
194
+ /** Base URL for the Reevit API (defaults to production) */
195
+ baseUrl?: string;
196
+ /** Request timeout in milliseconds */
197
+ timeout?: number;
198
+ }
199
+ /**
200
+ * Reevit API Client
201
+ */
202
+ declare class ReevitAPIClient {
203
+ private readonly publicKey;
204
+ private readonly baseUrl;
205
+ private readonly timeout;
206
+ constructor(config: ReevitAPIClientConfig);
207
+ /**
208
+ * Makes an authenticated API request
209
+ */
210
+ private request;
211
+ /**
212
+ * Creates a payment intent
213
+ */
214
+ createPaymentIntent(config: ReevitCheckoutConfig, method: PaymentMethod, country?: string): Promise<{
215
+ data?: PaymentIntentResponse;
216
+ error?: PaymentError;
217
+ }>;
218
+ /**
219
+ * Retrieves a payment intent by ID
220
+ */
221
+ getPaymentIntent(paymentId: string): Promise<{
222
+ data?: PaymentDetailResponse;
223
+ error?: PaymentError;
224
+ }>;
225
+ /**
226
+ * Confirms a payment after PSP callback
227
+ */
228
+ confirmPayment(paymentId: string): Promise<{
229
+ data?: PaymentDetailResponse;
230
+ error?: PaymentError;
231
+ }>;
232
+ /**
233
+ * Cancels a payment intent
234
+ */
235
+ cancelPaymentIntent(paymentId: string): Promise<{
236
+ data?: PaymentDetailResponse;
237
+ error?: PaymentError;
238
+ }>;
239
+ /**
240
+ * Maps SDK payment method to backend format
241
+ */
242
+ private mapPaymentMethod;
243
+ }
244
+ /**
245
+ * Creates a new Reevit API client instance
246
+ */
247
+ declare function createReevitClient(config: ReevitAPIClientConfig): ReevitAPIClient;
248
+
249
+ /**
250
+ * Utility Functions
251
+ * Shared utilities for Reevit SDKs
252
+ */
253
+
254
+ /**
255
+ * Formats an amount from smallest currency unit to display format
256
+ */
257
+ declare function formatAmount(amount: number, currency: string): string;
258
+ /**
259
+ * Generates a unique payment reference
260
+ */
261
+ declare function generateReference(prefix?: string): string;
262
+ /**
263
+ * Validates a phone number for mobile money
264
+ */
265
+ declare function validatePhone(phone: string, country?: string): boolean;
266
+ /**
267
+ * Formats a phone number for display
268
+ */
269
+ declare function formatPhone(phone: string, country?: string): string;
270
+ /**
271
+ * Detects mobile money network from phone number (Ghana)
272
+ */
273
+ declare function detectNetwork(phone: string): MobileMoneyNetwork | null;
274
+ /**
275
+ * Creates CSS custom property variables from theme
276
+ */
277
+ declare function createThemeVariables(theme: ReevitTheme): Record<string, string>;
278
+ /**
279
+ * Simple class name concatenation utility
280
+ */
281
+ declare function cn(...classes: (string | boolean | undefined | null)[]): string;
282
+ /**
283
+ * Detects country code from currency
284
+ */
285
+ declare function detectCountryFromCurrency(currency: string): string;
286
+
287
+ /**
288
+ * Reevit State Machine
289
+ * Shared state management logic for all SDKs
290
+ */
291
+
292
+ interface ReevitState {
293
+ status: CheckoutState;
294
+ paymentIntent: PaymentIntent | null;
295
+ selectedMethod: PaymentMethod | null;
296
+ error: PaymentError | null;
297
+ result: PaymentResult | null;
298
+ }
299
+ type ReevitAction = {
300
+ type: 'INIT_START';
301
+ } | {
302
+ type: 'INIT_SUCCESS';
303
+ payload: PaymentIntent;
304
+ } | {
305
+ type: 'INIT_ERROR';
306
+ payload: PaymentError;
307
+ } | {
308
+ type: 'SELECT_METHOD';
309
+ payload: PaymentMethod;
310
+ } | {
311
+ type: 'PROCESS_START';
312
+ } | {
313
+ type: 'PROCESS_SUCCESS';
314
+ payload: PaymentResult;
315
+ } | {
316
+ type: 'PROCESS_ERROR';
317
+ payload: PaymentError;
318
+ } | {
319
+ type: 'RESET';
320
+ } | {
321
+ type: 'CLOSE';
322
+ };
323
+ /**
324
+ * Creates the initial state for the checkout
325
+ */
326
+ declare function createInitialState(): ReevitState;
327
+ /**
328
+ * State reducer for checkout flow
329
+ */
330
+ declare function reevitReducer(state: ReevitState, action: ReevitAction): ReevitState;
331
+
332
+ export { type APIErrorResponse, type CardFormData, type CheckoutState, type ConfirmPaymentRequest, type CreatePaymentIntentRequest, type MobileMoneyFormData, type MobileMoneyNetwork, type PSPConfig, type PSPType, type PaymentDetailResponse, type PaymentError, type PaymentIntent, type PaymentIntentResponse, type PaymentMethod, type PaymentResult, ReevitAPIClient, type ReevitAPIClientConfig, type ReevitAction, type ReevitCheckoutCallbacks, type ReevitCheckoutConfig, type ReevitState, type ReevitTheme, cn, createInitialState, createReevitClient, createThemeVariables, detectCountryFromCurrency, detectNetwork, formatAmount, formatPhone, generateReference, reevitReducer, validatePhone };