@reevit/core 0.2.4 → 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 CHANGED
@@ -22,6 +22,8 @@ interface ReevitCheckoutConfig {
22
22
  metadata?: Record<string, unknown>;
23
23
  /** Payment methods to display */
24
24
  paymentMethods?: PaymentMethod[];
25
+ /** Pre-created payment intent to use */
26
+ initialPaymentIntent?: PaymentIntent | any;
25
27
  }
26
28
  interface ReevitCheckoutCallbacks {
27
29
  /** Called when payment is successful */
@@ -103,6 +105,8 @@ interface PaymentIntent {
103
105
  id: string;
104
106
  /** Client secret for authenticating client-side operations */
105
107
  clientSecret: string;
108
+ /** PSP public key if available */
109
+ pspPublicKey?: string;
106
110
  /** Amount in smallest currency unit */
107
111
  amount: number;
108
112
  /** Currency code */
@@ -113,6 +117,8 @@ interface PaymentIntent {
113
117
  recommendedPsp: PSPType;
114
118
  /** Available payment methods for this intent */
115
119
  availableMethods: PaymentMethod[];
120
+ /** Reference provided or generated */
121
+ reference?: string;
116
122
  /** Connection ID (from Reevit backend) */
117
123
  connectionId?: string;
118
124
  /** Provider name (from backend) */
@@ -155,11 +161,13 @@ interface PaymentIntentResponse {
155
161
  provider: string;
156
162
  status: string;
157
163
  client_secret: string;
164
+ psp_public_key: string;
158
165
  amount: number;
159
166
  currency: string;
160
167
  fee_amount: number;
161
168
  fee_currency: string;
162
169
  net_amount: number;
170
+ reference?: string;
163
171
  }
164
172
  interface ConfirmPaymentRequest {
165
173
  provider_ref_id: string;
@@ -229,6 +237,13 @@ declare class ReevitAPIClient {
229
237
  data?: PaymentDetailResponse;
230
238
  error?: PaymentError;
231
239
  }>;
240
+ /**
241
+ * Confirms a payment intent using client secret (public endpoint)
242
+ */
243
+ confirmPaymentIntent(paymentId: string, clientSecret: string): Promise<{
244
+ data?: PaymentDetailResponse;
245
+ error?: PaymentError;
246
+ }>;
232
247
  /**
233
248
  * Cancels a payment intent
234
249
  */
package/dist/index.d.ts CHANGED
@@ -22,6 +22,8 @@ interface ReevitCheckoutConfig {
22
22
  metadata?: Record<string, unknown>;
23
23
  /** Payment methods to display */
24
24
  paymentMethods?: PaymentMethod[];
25
+ /** Pre-created payment intent to use */
26
+ initialPaymentIntent?: PaymentIntent | any;
25
27
  }
26
28
  interface ReevitCheckoutCallbacks {
27
29
  /** Called when payment is successful */
@@ -103,6 +105,8 @@ interface PaymentIntent {
103
105
  id: string;
104
106
  /** Client secret for authenticating client-side operations */
105
107
  clientSecret: string;
108
+ /** PSP public key if available */
109
+ pspPublicKey?: string;
106
110
  /** Amount in smallest currency unit */
107
111
  amount: number;
108
112
  /** Currency code */
@@ -113,6 +117,8 @@ interface PaymentIntent {
113
117
  recommendedPsp: PSPType;
114
118
  /** Available payment methods for this intent */
115
119
  availableMethods: PaymentMethod[];
120
+ /** Reference provided or generated */
121
+ reference?: string;
116
122
  /** Connection ID (from Reevit backend) */
117
123
  connectionId?: string;
118
124
  /** Provider name (from backend) */
@@ -155,11 +161,13 @@ interface PaymentIntentResponse {
155
161
  provider: string;
156
162
  status: string;
157
163
  client_secret: string;
164
+ psp_public_key: string;
158
165
  amount: number;
159
166
  currency: string;
160
167
  fee_amount: number;
161
168
  fee_currency: string;
162
169
  net_amount: number;
170
+ reference?: string;
163
171
  }
164
172
  interface ConfirmPaymentRequest {
165
173
  provider_ref_id: string;
@@ -229,6 +237,13 @@ declare class ReevitAPIClient {
229
237
  data?: PaymentDetailResponse;
230
238
  error?: PaymentError;
231
239
  }>;
240
+ /**
241
+ * Confirms a payment intent using client secret (public endpoint)
242
+ */
243
+ confirmPaymentIntent(paymentId: string, clientSecret: string): Promise<{
244
+ data?: PaymentDetailResponse;
245
+ error?: PaymentError;
246
+ }>;
232
247
  /**
233
248
  * Cancels a payment intent
234
249
  */
package/dist/index.js CHANGED
@@ -68,7 +68,7 @@ var ReevitAPIClient = class {
68
68
  "Content-Type": "application/json",
69
69
  "X-Reevit-Key": this.publicKey,
70
70
  "X-Reevit-Client": "@reevit/core",
71
- "X-Reevit-Client-Version": "0.2.3"
71
+ "X-Reevit-Client-Version": "0.3.2"
72
72
  };
73
73
  if (method === "POST" || method === "PATCH" || method === "PUT") {
74
74
  headers["Idempotency-Key"] = `${Date.now()}-${Math.random().toString(36).substring(2, 15)}`;
@@ -120,13 +120,20 @@ var ReevitAPIClient = class {
120
120
  * Creates a payment intent
121
121
  */
122
122
  async createPaymentIntent(config, method, country = "GH") {
123
+ const metadata = { ...config.metadata };
124
+ if (config.email) {
125
+ metadata.customer_email = config.email;
126
+ }
127
+ if (config.phone) {
128
+ metadata.customer_phone = config.phone;
129
+ }
123
130
  const request = {
124
131
  amount: config.amount,
125
132
  currency: config.currency,
126
133
  method: this.mapPaymentMethod(method),
127
134
  country,
128
- customer_id: config.metadata?.customerId,
129
- metadata: config.metadata
135
+ customer_id: config.email || config.metadata?.customerId,
136
+ metadata
130
137
  };
131
138
  return this.request("POST", "/v1/payments/intents", request);
132
139
  }
@@ -142,6 +149,12 @@ var ReevitAPIClient = class {
142
149
  async confirmPayment(paymentId) {
143
150
  return this.request("POST", `/v1/payments/${paymentId}/confirm`);
144
151
  }
152
+ /**
153
+ * Confirms a payment intent using client secret (public endpoint)
154
+ */
155
+ async confirmPaymentIntent(paymentId, clientSecret) {
156
+ return this.request("POST", `/v1/payments/${paymentId}/confirm-intent?client_secret=${clientSecret}`);
157
+ }
145
158
  /**
146
159
  * Cancels a payment intent
147
160
  */
@@ -294,7 +307,12 @@ function reevitReducer(state, action) {
294
307
  case "INIT_START":
295
308
  return { ...state, status: "loading", error: null };
296
309
  case "INIT_SUCCESS":
297
- return { ...state, status: "ready", paymentIntent: action.payload };
310
+ return {
311
+ ...state,
312
+ status: "ready",
313
+ paymentIntent: action.payload,
314
+ selectedMethod: action.payload.availableMethods?.length === 1 ? action.payload.availableMethods[0] : null
315
+ };
298
316
  case "INIT_ERROR":
299
317
  return { ...state, status: "failed", error: action.payload };
300
318
  case "SELECT_METHOD":
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/api/client.ts","../src/utils.ts","../src/state.ts"],"sourcesContent":["/**\n * @reevit/core\n * Shared utilities and API client for Reevit payment SDKs\n */\n\n// API Client\nexport {\n ReevitAPIClient,\n createReevitClient,\n type ReevitAPIClientConfig,\n type CreatePaymentIntentRequest,\n type PaymentIntentResponse,\n type PaymentDetailResponse,\n type ConfirmPaymentRequest,\n type APIErrorResponse,\n} from './api/client';\n\n// Types\nexport type {\n PaymentMethod,\n MobileMoneyNetwork,\n ReevitCheckoutConfig,\n ReevitCheckoutCallbacks,\n CheckoutState,\n PaymentResult,\n PaymentError,\n ReevitTheme,\n MobileMoneyFormData,\n CardFormData,\n PaymentIntent,\n PSPConfig,\n PSPType,\n} from './types';\n\n// Utilities\nexport {\n formatAmount,\n generateReference,\n validatePhone,\n formatPhone,\n detectNetwork,\n detectCountryFromCurrency,\n createThemeVariables,\n cn,\n} from './utils';\n\n// State machine helpers\nexport {\n createInitialState,\n reevitReducer,\n type ReevitState,\n type ReevitAction,\n} from './state';\n","/**\n * Reevit API Client\n * \n * Handles communication with the Reevit backend for payment operations.\n */\n\nimport type { PaymentMethod, ReevitCheckoutConfig, PaymentError } from '../types';\n\n// API Response Types (matching backend handlers_payments.go)\nexport interface CreatePaymentIntentRequest {\n amount: number;\n currency: string;\n method: string;\n country: string;\n customer_id?: string;\n metadata?: Record<string, unknown>;\n description?: string;\n policy?: {\n prefer?: string[];\n max_amount?: number;\n blocked_bins?: string[];\n allowed_bins?: string[];\n velocity_max_per_minute?: number;\n };\n}\n\nexport interface PaymentIntentResponse {\n id: string;\n connection_id: string;\n provider: string;\n status: string;\n client_secret: string;\n amount: number;\n currency: string;\n fee_amount: number;\n fee_currency: string;\n net_amount: number;\n}\n\nexport interface ConfirmPaymentRequest {\n provider_ref_id: string;\n provider_data?: Record<string, unknown>;\n}\n\nexport interface PaymentDetailResponse {\n id: string;\n connection_id: string;\n provider: string;\n method: string;\n status: string;\n amount: number;\n currency: string;\n fee_amount: number;\n fee_currency: string;\n net_amount: number;\n customer_id?: string;\n client_secret: string;\n provider_ref_id?: string;\n metadata?: Record<string, unknown>;\n created_at: string;\n updated_at: string;\n}\n\nexport interface APIErrorResponse {\n code: string;\n message: string;\n details?: Record<string, string>;\n}\n\n// API Client configuration\nexport interface ReevitAPIClientConfig {\n /** Your Reevit public key */\n publicKey: string;\n /** Base URL for the Reevit API (defaults to production) */\n baseUrl?: string;\n /** Request timeout in milliseconds */\n timeout?: number;\n}\n\n// Default API base URLs\nconst API_BASE_URL_PRODUCTION = 'https://api.reevit.io';\nconst API_BASE_URL_SANDBOX = 'https://sandbox-api.reevit.io';\nconst DEFAULT_TIMEOUT = 30000; // 30 seconds\n\n/**\n * Determines if a public key is for sandbox mode\n */\nexport function isSandboxKey(publicKey: string): boolean {\n return publicKey.startsWith('pk_test_') ||\n publicKey.startsWith('pk_sandbox_') ||\n publicKey.startsWith('pfk_test_') ||\n publicKey.startsWith('pfk_sandbox_');\n}\n\n/**\n * Creates a PaymentError from an API error response\n */\nfunction createPaymentError(response: Response, errorData: APIErrorResponse): PaymentError {\n return {\n code: errorData.code || 'api_error',\n message: errorData.message || 'An unexpected error occurred',\n details: {\n httpStatus: response.status,\n ...errorData.details,\n },\n };\n}\n\n/**\n * Reevit API Client\n */\nexport class ReevitAPIClient {\n private readonly publicKey: string;\n private readonly baseUrl: string;\n private readonly timeout: number;\n\n constructor(config: ReevitAPIClientConfig) {\n this.publicKey = config.publicKey;\n this.baseUrl = config.baseUrl || (isSandboxKey(config.publicKey)\n ? API_BASE_URL_SANDBOX\n : API_BASE_URL_PRODUCTION);\n this.timeout = config.timeout || DEFAULT_TIMEOUT;\n }\n\n /**\n * Makes an authenticated API request\n */\n private async request<T>(\n method: string,\n path: string,\n body?: unknown\n ): Promise<{ data?: T; error?: PaymentError }> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n // Generate headers with idempotency key for mutating requests\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'X-Reevit-Key': this.publicKey,\n 'X-Reevit-Client': '@reevit/core',\n 'X-Reevit-Client-Version': '0.2.3',\n };\n\n if (method === 'POST' || method === 'PATCH' || method === 'PUT') {\n headers['Idempotency-Key'] = `${Date.now()}-${Math.random().toString(36).substring(2, 15)}`;\n }\n\n try {\n const response = await fetch(`${this.baseUrl}${path}`, {\n method,\n headers,\n body: body ? JSON.stringify(body) : undefined,\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n const responseData = await response.json().catch(() => ({}));\n\n if (!response.ok) {\n return {\n error: createPaymentError(response, responseData as APIErrorResponse),\n };\n }\n\n return { data: responseData as T };\n } catch (err) {\n clearTimeout(timeoutId);\n\n if (err instanceof Error) {\n if (err.name === 'AbortError') {\n return {\n error: {\n code: 'request_timeout',\n message: 'The request timed out. Please try again.',\n },\n };\n }\n\n if (err.message.includes('Failed to fetch') || err.message.includes('NetworkError')) {\n return {\n error: {\n code: 'network_error',\n message: 'Unable to connect to Reevit. Please check your internet connection.',\n },\n };\n }\n }\n\n return {\n error: {\n code: 'unknown_error',\n message: 'An unexpected error occurred. Please try again.',\n },\n };\n }\n }\n\n /**\n * Creates a payment intent\n */\n async createPaymentIntent(\n config: ReevitCheckoutConfig,\n method: PaymentMethod,\n country: string = 'GH'\n ): Promise<{ data?: PaymentIntentResponse; error?: PaymentError }> {\n const request: CreatePaymentIntentRequest = {\n amount: config.amount,\n currency: config.currency,\n method: this.mapPaymentMethod(method),\n country,\n customer_id: config.metadata?.customerId as string | undefined,\n metadata: config.metadata,\n };\n\n return this.request<PaymentIntentResponse>('POST', '/v1/payments/intents', request);\n }\n\n /**\n * Retrieves a payment intent by ID\n */\n async getPaymentIntent(paymentId: string): Promise<{ data?: PaymentDetailResponse; error?: PaymentError }> {\n return this.request<PaymentDetailResponse>('GET', `/v1/payments/${paymentId}`);\n }\n\n /**\n * Confirms a payment after PSP callback\n */\n async confirmPayment(paymentId: string): Promise<{ data?: PaymentDetailResponse; error?: PaymentError }> {\n return this.request<PaymentDetailResponse>('POST', `/v1/payments/${paymentId}/confirm`);\n }\n\n /**\n * Cancels a payment intent\n */\n async cancelPaymentIntent(paymentId: string): Promise<{ data?: PaymentDetailResponse; error?: PaymentError }> {\n return this.request<PaymentDetailResponse>('POST', `/v1/payments/${paymentId}/cancel`);\n }\n\n /**\n * Maps SDK payment method to backend format\n */\n private mapPaymentMethod(method: PaymentMethod): string {\n switch (method) {\n case 'card':\n return 'card';\n case 'mobile_money':\n return 'mobile_money';\n case 'bank_transfer':\n return 'bank_transfer';\n default:\n return method;\n }\n }\n}\n\n/**\n * Creates a new Reevit API client instance\n */\nexport function createReevitClient(config: ReevitAPIClientConfig): ReevitAPIClient {\n return new ReevitAPIClient(config);\n}\n","/**\n * Utility Functions\n * Shared utilities for Reevit SDKs\n */\n\nimport type { MobileMoneyNetwork, ReevitTheme } from './types';\n\n/**\n * Formats an amount from smallest currency unit to display format\n */\nexport function formatAmount(amount: number, currency: string): string {\n const majorUnit = amount / 100;\n\n const currencyFormats: Record<string, { locale: string; minimumFractionDigits: number }> = {\n GHS: { locale: 'en-GH', minimumFractionDigits: 2 },\n NGN: { locale: 'en-NG', minimumFractionDigits: 2 },\n KES: { locale: 'en-KE', minimumFractionDigits: 2 },\n USD: { locale: 'en-US', minimumFractionDigits: 2 },\n EUR: { locale: 'de-DE', minimumFractionDigits: 2 },\n GBP: { locale: 'en-GB', minimumFractionDigits: 2 },\n };\n\n const format = currencyFormats[currency.toUpperCase()] || { locale: 'en-US', minimumFractionDigits: 2 };\n\n try {\n return new Intl.NumberFormat(format.locale, {\n style: 'currency',\n currency: currency.toUpperCase(),\n minimumFractionDigits: format.minimumFractionDigits,\n }).format(majorUnit);\n } catch {\n // Fallback for unsupported currencies\n return `${currency} ${majorUnit.toFixed(2)}`;\n }\n}\n\n/**\n * Generates a unique payment reference\n */\nexport function generateReference(prefix: string = 'reevit'): string {\n const timestamp = Date.now().toString(36);\n const random = Math.random().toString(36).substring(2, 8);\n return `${prefix}_${timestamp}_${random}`;\n}\n\n/**\n * Validates a phone number for mobile money\n */\nexport function validatePhone(phone: string, country: string = 'GH'): boolean {\n // Remove non-digit characters\n const digits = phone.replace(/\\D/g, '');\n\n const patterns: Record<string, RegExp> = {\n GH: /^(?:233|0)?[235][0-9]{8}$/, // Ghana\n NG: /^(?:234|0)?[789][01][0-9]{8}$/, // Nigeria\n KE: /^(?:254|0)?[17][0-9]{8}$/, // Kenya\n };\n\n const pattern = patterns[country.toUpperCase()];\n if (!pattern) return digits.length >= 10;\n\n return pattern.test(digits);\n}\n\n/**\n * Formats a phone number for display\n */\nexport function formatPhone(phone: string, country: string = 'GH'): string {\n const digits = phone.replace(/\\D/g, '');\n\n if (country === 'GH') {\n // Format as 0XX XXX XXXX\n if (digits.startsWith('233') && digits.length === 12) {\n const local = '0' + digits.slice(3);\n return `${local.slice(0, 3)} ${local.slice(3, 6)} ${local.slice(6)}`;\n }\n if (digits.length === 10 && digits.startsWith('0')) {\n return `${digits.slice(0, 3)} ${digits.slice(3, 6)} ${digits.slice(6)}`;\n }\n }\n\n return phone;\n}\n\n/**\n * Detects mobile money network from phone number (Ghana)\n */\nexport function detectNetwork(phone: string): MobileMoneyNetwork | null {\n const digits = phone.replace(/\\D/g, '');\n\n // Get the network prefix (first 3 digits after country code or 0)\n let prefix: string;\n if (digits.startsWith('233')) {\n prefix = digits.slice(3, 5);\n } else if (digits.startsWith('0')) {\n prefix = digits.slice(1, 3);\n } else {\n prefix = digits.slice(0, 2);\n }\n\n // Ghana network prefixes\n const mtnPrefixes = ['24', '25', '53', '54', '55', '59'];\n const vodafonePrefixes = ['20', '50'];\n const airteltigoPrefixes = ['26', '27', '56', '57'];\n\n if (mtnPrefixes.includes(prefix)) return 'mtn';\n if (vodafonePrefixes.includes(prefix)) return 'vodafone';\n if (airteltigoPrefixes.includes(prefix)) return 'airteltigo';\n\n return null;\n}\n\n/**\n * Creates CSS custom property variables from theme\n */\nexport function createThemeVariables(theme: ReevitTheme): Record<string, string> {\n const variables: Record<string, string> = {};\n\n if (theme.primaryColor) {\n variables['--reevit-primary'] = theme.primaryColor;\n }\n if (theme.backgroundColor) {\n variables['--reevit-bg'] = theme.backgroundColor;\n }\n if (theme.textColor) {\n variables['--reevit-text'] = theme.textColor;\n }\n if (theme.borderRadius) {\n variables['--reevit-radius'] = theme.borderRadius;\n }\n if (theme.fontFamily) {\n variables['--reevit-font'] = theme.fontFamily;\n }\n\n return variables;\n}\n\n/**\n * Simple class name concatenation utility\n */\nexport function cn(...classes: (string | boolean | undefined | null)[]): string {\n return classes.filter(Boolean).join(' ');\n}\n\n/**\n * Detects country code from currency\n */\nexport function detectCountryFromCurrency(currency: string): string {\n const currencyToCountry: Record<string, string> = {\n GHS: 'GH',\n NGN: 'NG',\n KES: 'KE',\n UGX: 'UG',\n TZS: 'TZ',\n ZAR: 'ZA',\n XOF: 'CI',\n XAF: 'CM',\n USD: 'US',\n EUR: 'DE',\n GBP: 'GB',\n };\n\n return currencyToCountry[currency.toUpperCase()] || 'GH';\n}\n","/**\n * Reevit State Machine\n * Shared state management logic for all SDKs\n */\n\nimport type { CheckoutState, PaymentIntent, PaymentMethod, PaymentResult, PaymentError } from './types';\n\n// State shape\nexport interface ReevitState {\n status: CheckoutState;\n paymentIntent: PaymentIntent | null;\n selectedMethod: PaymentMethod | null;\n error: PaymentError | null;\n result: PaymentResult | null;\n}\n\n// Actions\nexport type ReevitAction =\n | { type: 'INIT_START' }\n | { type: 'INIT_SUCCESS'; payload: PaymentIntent }\n | { type: 'INIT_ERROR'; payload: PaymentError }\n | { type: 'SELECT_METHOD'; payload: PaymentMethod }\n | { type: 'PROCESS_START' }\n | { type: 'PROCESS_SUCCESS'; payload: PaymentResult }\n | { type: 'PROCESS_ERROR'; payload: PaymentError }\n | { type: 'RESET' }\n | { type: 'CLOSE' };\n\n/**\n * Creates the initial state for the checkout\n */\nexport function createInitialState(): ReevitState {\n return {\n status: 'idle',\n paymentIntent: null,\n selectedMethod: null,\n error: null,\n result: null,\n };\n}\n\n/**\n * State reducer for checkout flow\n */\nexport function reevitReducer(state: ReevitState, action: ReevitAction): ReevitState {\n switch (action.type) {\n case 'INIT_START':\n return { ...state, status: 'loading', error: null };\n case 'INIT_SUCCESS':\n return { ...state, status: 'ready', paymentIntent: action.payload };\n case 'INIT_ERROR':\n return { ...state, status: 'failed', error: action.payload };\n case 'SELECT_METHOD':\n return { ...state, status: 'method_selected', selectedMethod: action.payload };\n case 'PROCESS_START':\n return { ...state, status: 'processing', error: null };\n case 'PROCESS_SUCCESS':\n return { ...state, status: 'success', result: action.payload };\n case 'PROCESS_ERROR':\n return { ...state, status: 'failed', error: action.payload };\n case 'RESET':\n return { ...createInitialState(), status: 'ready', paymentIntent: state.paymentIntent };\n case 'CLOSE':\n return { ...state, status: 'closed' };\n default:\n return state;\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/index.ts","../src/api/client.ts","../src/utils.ts","../src/state.ts"],"sourcesContent":["/**\n * @reevit/core\n * Shared utilities and API client for Reevit payment SDKs\n */\n\n// API Client\nexport {\n ReevitAPIClient,\n createReevitClient,\n type ReevitAPIClientConfig,\n type CreatePaymentIntentRequest,\n type PaymentIntentResponse,\n type PaymentDetailResponse,\n type ConfirmPaymentRequest,\n type APIErrorResponse,\n} from './api/client';\n\n// Types\nexport type {\n PaymentMethod,\n MobileMoneyNetwork,\n ReevitCheckoutConfig,\n ReevitCheckoutCallbacks,\n CheckoutState,\n PaymentResult,\n PaymentError,\n ReevitTheme,\n MobileMoneyFormData,\n CardFormData,\n PaymentIntent,\n PSPConfig,\n PSPType,\n} from './types';\n\n// Utilities\nexport {\n formatAmount,\n generateReference,\n validatePhone,\n formatPhone,\n detectNetwork,\n detectCountryFromCurrency,\n createThemeVariables,\n cn,\n} from './utils';\n\n// State machine helpers\nexport {\n createInitialState,\n reevitReducer,\n type ReevitState,\n type ReevitAction,\n} from './state';\n","/**\n * Reevit API Client\n * \n * Handles communication with the Reevit backend for payment operations.\n */\n\nimport type { PaymentMethod, ReevitCheckoutConfig, PaymentError } from '../types';\n\n// API Response Types (matching backend handlers_payments.go)\nexport interface CreatePaymentIntentRequest {\n amount: number;\n currency: string;\n method: string;\n country: string;\n customer_id?: string;\n metadata?: Record<string, unknown>;\n description?: string;\n policy?: {\n prefer?: string[];\n max_amount?: number;\n blocked_bins?: string[];\n allowed_bins?: string[];\n velocity_max_per_minute?: number;\n };\n}\n\nexport interface PaymentIntentResponse {\n id: string;\n connection_id: string;\n provider: string;\n status: string;\n client_secret: string;\n psp_public_key: string;\n amount: number;\n currency: string;\n fee_amount: number;\n fee_currency: string;\n net_amount: number;\n reference?: string;\n}\n\nexport interface ConfirmPaymentRequest {\n provider_ref_id: string;\n provider_data?: Record<string, unknown>;\n}\n\nexport interface PaymentDetailResponse {\n id: string;\n connection_id: string;\n provider: string;\n method: string;\n status: string;\n amount: number;\n currency: string;\n fee_amount: number;\n fee_currency: string;\n net_amount: number;\n customer_id?: string;\n client_secret: string;\n provider_ref_id?: string;\n metadata?: Record<string, unknown>;\n created_at: string;\n updated_at: string;\n}\n\nexport interface APIErrorResponse {\n code: string;\n message: string;\n details?: Record<string, string>;\n}\n\n// API Client configuration\nexport interface ReevitAPIClientConfig {\n /** Your Reevit public key */\n publicKey: string;\n /** Base URL for the Reevit API (defaults to production) */\n baseUrl?: string;\n /** Request timeout in milliseconds */\n timeout?: number;\n}\n\n// Default API base URLs\nconst API_BASE_URL_PRODUCTION = 'https://api.reevit.io';\nconst API_BASE_URL_SANDBOX = 'https://sandbox-api.reevit.io';\nconst DEFAULT_TIMEOUT = 30000; // 30 seconds\n\n/**\n * Determines if a public key is for sandbox mode\n */\nexport function isSandboxKey(publicKey: string): boolean {\n return publicKey.startsWith('pk_test_') ||\n publicKey.startsWith('pk_sandbox_') ||\n publicKey.startsWith('pfk_test_') ||\n publicKey.startsWith('pfk_sandbox_');\n}\n\n/**\n * Creates a PaymentError from an API error response\n */\nfunction createPaymentError(response: Response, errorData: APIErrorResponse): PaymentError {\n return {\n code: errorData.code || 'api_error',\n message: errorData.message || 'An unexpected error occurred',\n details: {\n httpStatus: response.status,\n ...errorData.details,\n },\n };\n}\n\n/**\n * Reevit API Client\n */\nexport class ReevitAPIClient {\n private readonly publicKey: string;\n private readonly baseUrl: string;\n private readonly timeout: number;\n\n constructor(config: ReevitAPIClientConfig) {\n this.publicKey = config.publicKey;\n this.baseUrl = config.baseUrl || (isSandboxKey(config.publicKey)\n ? API_BASE_URL_SANDBOX\n : API_BASE_URL_PRODUCTION);\n this.timeout = config.timeout || DEFAULT_TIMEOUT;\n }\n\n /**\n * Makes an authenticated API request\n */\n private async request<T>(\n method: string,\n path: string,\n body?: unknown\n ): Promise<{ data?: T; error?: PaymentError }> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n // Generate headers with idempotency key for mutating requests\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'X-Reevit-Key': this.publicKey,\n 'X-Reevit-Client': '@reevit/core',\n 'X-Reevit-Client-Version': '0.3.2',\n };\n\n if (method === 'POST' || method === 'PATCH' || method === 'PUT') {\n headers['Idempotency-Key'] = `${Date.now()}-${Math.random().toString(36).substring(2, 15)}`;\n }\n\n try {\n const response = await fetch(`${this.baseUrl}${path}`, {\n method,\n headers,\n body: body ? JSON.stringify(body) : undefined,\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n const responseData = await response.json().catch(() => ({}));\n\n if (!response.ok) {\n return {\n error: createPaymentError(response, responseData as APIErrorResponse),\n };\n }\n\n return { data: responseData as T };\n } catch (err) {\n clearTimeout(timeoutId);\n\n if (err instanceof Error) {\n if (err.name === 'AbortError') {\n return {\n error: {\n code: 'request_timeout',\n message: 'The request timed out. Please try again.',\n },\n };\n }\n\n if (err.message.includes('Failed to fetch') || err.message.includes('NetworkError')) {\n return {\n error: {\n code: 'network_error',\n message: 'Unable to connect to Reevit. Please check your internet connection.',\n },\n };\n }\n }\n\n return {\n error: {\n code: 'unknown_error',\n message: 'An unexpected error occurred. Please try again.',\n },\n };\n }\n }\n\n /**\n * Creates a payment intent\n */\n async createPaymentIntent(\n config: ReevitCheckoutConfig,\n method: PaymentMethod,\n country: string = 'GH'\n ): Promise<{ data?: PaymentIntentResponse; error?: PaymentError }> {\n // Build metadata with customer_email for PSP providers that require it\n const metadata: Record<string, unknown> = { ...config.metadata };\n if (config.email) {\n metadata.customer_email = config.email;\n }\n if (config.phone) {\n metadata.customer_phone = config.phone;\n }\n\n const request: CreatePaymentIntentRequest = {\n amount: config.amount,\n currency: config.currency,\n method: this.mapPaymentMethod(method),\n country,\n customer_id: config.email || (config.metadata?.customerId as string | undefined),\n metadata,\n };\n\n return this.request<PaymentIntentResponse>('POST', '/v1/payments/intents', request);\n }\n\n /**\n * Retrieves a payment intent by ID\n */\n async getPaymentIntent(paymentId: string): Promise<{ data?: PaymentDetailResponse; error?: PaymentError }> {\n return this.request<PaymentDetailResponse>('GET', `/v1/payments/${paymentId}`);\n }\n\n /**\n * Confirms a payment after PSP callback\n */\n async confirmPayment(paymentId: string): Promise<{ data?: PaymentDetailResponse; error?: PaymentError }> {\n return this.request<PaymentDetailResponse>('POST', `/v1/payments/${paymentId}/confirm`);\n }\n\n /**\n * Confirms a payment intent using client secret (public endpoint)\n */\n async confirmPaymentIntent(paymentId: string, clientSecret: string): Promise<{ data?: PaymentDetailResponse; error?: PaymentError }> {\n return this.request<PaymentDetailResponse>('POST', `/v1/payments/${paymentId}/confirm-intent?client_secret=${clientSecret}`);\n }\n\n /**\n * Cancels a payment intent\n */\n async cancelPaymentIntent(paymentId: string): Promise<{ data?: PaymentDetailResponse; error?: PaymentError }> {\n return this.request<PaymentDetailResponse>('POST', `/v1/payments/${paymentId}/cancel`);\n }\n\n /**\n * Maps SDK payment method to backend format\n */\n private mapPaymentMethod(method: PaymentMethod): string {\n switch (method) {\n case 'card':\n return 'card';\n case 'mobile_money':\n return 'mobile_money';\n case 'bank_transfer':\n return 'bank_transfer';\n default:\n return method;\n }\n }\n}\n\n/**\n * Creates a new Reevit API client instance\n */\nexport function createReevitClient(config: ReevitAPIClientConfig): ReevitAPIClient {\n return new ReevitAPIClient(config);\n}\n","/**\n * Utility Functions\n * Shared utilities for Reevit SDKs\n */\n\nimport type { MobileMoneyNetwork, ReevitTheme } from './types';\n\n/**\n * Formats an amount from smallest currency unit to display format\n */\nexport function formatAmount(amount: number, currency: string): string {\n const majorUnit = amount / 100;\n\n const currencyFormats: Record<string, { locale: string; minimumFractionDigits: number }> = {\n GHS: { locale: 'en-GH', minimumFractionDigits: 2 },\n NGN: { locale: 'en-NG', minimumFractionDigits: 2 },\n KES: { locale: 'en-KE', minimumFractionDigits: 2 },\n USD: { locale: 'en-US', minimumFractionDigits: 2 },\n EUR: { locale: 'de-DE', minimumFractionDigits: 2 },\n GBP: { locale: 'en-GB', minimumFractionDigits: 2 },\n };\n\n const format = currencyFormats[currency.toUpperCase()] || { locale: 'en-US', minimumFractionDigits: 2 };\n\n try {\n return new Intl.NumberFormat(format.locale, {\n style: 'currency',\n currency: currency.toUpperCase(),\n minimumFractionDigits: format.minimumFractionDigits,\n }).format(majorUnit);\n } catch {\n // Fallback for unsupported currencies\n return `${currency} ${majorUnit.toFixed(2)}`;\n }\n}\n\n/**\n * Generates a unique payment reference\n */\nexport function generateReference(prefix: string = 'reevit'): string {\n const timestamp = Date.now().toString(36);\n const random = Math.random().toString(36).substring(2, 8);\n return `${prefix}_${timestamp}_${random}`;\n}\n\n/**\n * Validates a phone number for mobile money\n */\nexport function validatePhone(phone: string, country: string = 'GH'): boolean {\n // Remove non-digit characters\n const digits = phone.replace(/\\D/g, '');\n\n const patterns: Record<string, RegExp> = {\n GH: /^(?:233|0)?[235][0-9]{8}$/, // Ghana\n NG: /^(?:234|0)?[789][01][0-9]{8}$/, // Nigeria\n KE: /^(?:254|0)?[17][0-9]{8}$/, // Kenya\n };\n\n const pattern = patterns[country.toUpperCase()];\n if (!pattern) return digits.length >= 10;\n\n return pattern.test(digits);\n}\n\n/**\n * Formats a phone number for display\n */\nexport function formatPhone(phone: string, country: string = 'GH'): string {\n const digits = phone.replace(/\\D/g, '');\n\n if (country === 'GH') {\n // Format as 0XX XXX XXXX\n if (digits.startsWith('233') && digits.length === 12) {\n const local = '0' + digits.slice(3);\n return `${local.slice(0, 3)} ${local.slice(3, 6)} ${local.slice(6)}`;\n }\n if (digits.length === 10 && digits.startsWith('0')) {\n return `${digits.slice(0, 3)} ${digits.slice(3, 6)} ${digits.slice(6)}`;\n }\n }\n\n return phone;\n}\n\n/**\n * Detects mobile money network from phone number (Ghana)\n */\nexport function detectNetwork(phone: string): MobileMoneyNetwork | null {\n const digits = phone.replace(/\\D/g, '');\n\n // Get the network prefix (first 3 digits after country code or 0)\n let prefix: string;\n if (digits.startsWith('233')) {\n prefix = digits.slice(3, 5);\n } else if (digits.startsWith('0')) {\n prefix = digits.slice(1, 3);\n } else {\n prefix = digits.slice(0, 2);\n }\n\n // Ghana network prefixes\n const mtnPrefixes = ['24', '25', '53', '54', '55', '59'];\n const vodafonePrefixes = ['20', '50'];\n const airteltigoPrefixes = ['26', '27', '56', '57'];\n\n if (mtnPrefixes.includes(prefix)) return 'mtn';\n if (vodafonePrefixes.includes(prefix)) return 'vodafone';\n if (airteltigoPrefixes.includes(prefix)) return 'airteltigo';\n\n return null;\n}\n\n/**\n * Creates CSS custom property variables from theme\n */\nexport function createThemeVariables(theme: ReevitTheme): Record<string, string> {\n const variables: Record<string, string> = {};\n\n if (theme.primaryColor) {\n variables['--reevit-primary'] = theme.primaryColor;\n }\n if (theme.backgroundColor) {\n variables['--reevit-bg'] = theme.backgroundColor;\n }\n if (theme.textColor) {\n variables['--reevit-text'] = theme.textColor;\n }\n if (theme.borderRadius) {\n variables['--reevit-radius'] = theme.borderRadius;\n }\n if (theme.fontFamily) {\n variables['--reevit-font'] = theme.fontFamily;\n }\n\n return variables;\n}\n\n/**\n * Simple class name concatenation utility\n */\nexport function cn(...classes: (string | boolean | undefined | null)[]): string {\n return classes.filter(Boolean).join(' ');\n}\n\n/**\n * Detects country code from currency\n */\nexport function detectCountryFromCurrency(currency: string): string {\n const currencyToCountry: Record<string, string> = {\n GHS: 'GH',\n NGN: 'NG',\n KES: 'KE',\n UGX: 'UG',\n TZS: 'TZ',\n ZAR: 'ZA',\n XOF: 'CI',\n XAF: 'CM',\n USD: 'US',\n EUR: 'DE',\n GBP: 'GB',\n };\n\n return currencyToCountry[currency.toUpperCase()] || 'GH';\n}\n","/**\n * Reevit State Machine\n * Shared state management logic for all SDKs\n */\n\nimport type { CheckoutState, PaymentIntent, PaymentMethod, PaymentResult, PaymentError } from './types';\n\n// State shape\nexport interface ReevitState {\n status: CheckoutState;\n paymentIntent: PaymentIntent | null;\n selectedMethod: PaymentMethod | null;\n error: PaymentError | null;\n result: PaymentResult | null;\n}\n\n// Actions\nexport type ReevitAction =\n | { type: 'INIT_START' }\n | { type: 'INIT_SUCCESS'; payload: PaymentIntent }\n | { type: 'INIT_ERROR'; payload: PaymentError }\n | { type: 'SELECT_METHOD'; payload: PaymentMethod }\n | { type: 'PROCESS_START' }\n | { type: 'PROCESS_SUCCESS'; payload: PaymentResult }\n | { type: 'PROCESS_ERROR'; payload: PaymentError }\n | { type: 'RESET' }\n | { type: 'CLOSE' };\n\n/**\n * Creates the initial state for the checkout\n */\nexport function createInitialState(): ReevitState {\n return {\n status: 'idle',\n paymentIntent: null,\n selectedMethod: null,\n error: null,\n result: null,\n };\n}\n\n/**\n * State reducer for checkout flow\n */\nexport function reevitReducer(state: ReevitState, action: ReevitAction): ReevitState {\n switch (action.type) {\n case 'INIT_START':\n return { ...state, status: 'loading', error: null };\n case 'INIT_SUCCESS':\n return {\n ...state,\n status: 'ready',\n paymentIntent: action.payload,\n selectedMethod:\n action.payload.availableMethods?.length === 1 ? action.payload.availableMethods[0] : null,\n };\n case 'INIT_ERROR':\n return { ...state, status: 'failed', error: action.payload };\n case 'SELECT_METHOD':\n return { ...state, status: 'method_selected', selectedMethod: action.payload };\n case 'PROCESS_START':\n return { ...state, status: 'processing', error: null };\n case 'PROCESS_SUCCESS':\n return { ...state, status: 'success', result: action.payload };\n case 'PROCESS_ERROR':\n return { ...state, status: 'failed', error: action.payload };\n case 'RESET':\n return { ...createInitialState(), status: 'ready', paymentIntent: state.paymentIntent };\n case 'CLOSE':\n return { ...state, status: 'closed' };\n default:\n return state;\n }\n}\n"],"mappings":"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","names":[]}
package/dist/index.mjs CHANGED
@@ -31,7 +31,7 @@ var ReevitAPIClient = class {
31
31
  "Content-Type": "application/json",
32
32
  "X-Reevit-Key": this.publicKey,
33
33
  "X-Reevit-Client": "@reevit/core",
34
- "X-Reevit-Client-Version": "0.2.3"
34
+ "X-Reevit-Client-Version": "0.3.2"
35
35
  };
36
36
  if (method === "POST" || method === "PATCH" || method === "PUT") {
37
37
  headers["Idempotency-Key"] = `${Date.now()}-${Math.random().toString(36).substring(2, 15)}`;
@@ -83,13 +83,20 @@ var ReevitAPIClient = class {
83
83
  * Creates a payment intent
84
84
  */
85
85
  async createPaymentIntent(config, method, country = "GH") {
86
+ const metadata = { ...config.metadata };
87
+ if (config.email) {
88
+ metadata.customer_email = config.email;
89
+ }
90
+ if (config.phone) {
91
+ metadata.customer_phone = config.phone;
92
+ }
86
93
  const request = {
87
94
  amount: config.amount,
88
95
  currency: config.currency,
89
96
  method: this.mapPaymentMethod(method),
90
97
  country,
91
- customer_id: config.metadata?.customerId,
92
- metadata: config.metadata
98
+ customer_id: config.email || config.metadata?.customerId,
99
+ metadata
93
100
  };
94
101
  return this.request("POST", "/v1/payments/intents", request);
95
102
  }
@@ -105,6 +112,12 @@ var ReevitAPIClient = class {
105
112
  async confirmPayment(paymentId) {
106
113
  return this.request("POST", `/v1/payments/${paymentId}/confirm`);
107
114
  }
115
+ /**
116
+ * Confirms a payment intent using client secret (public endpoint)
117
+ */
118
+ async confirmPaymentIntent(paymentId, clientSecret) {
119
+ return this.request("POST", `/v1/payments/${paymentId}/confirm-intent?client_secret=${clientSecret}`);
120
+ }
108
121
  /**
109
122
  * Cancels a payment intent
110
123
  */
@@ -257,7 +270,12 @@ function reevitReducer(state, action) {
257
270
  case "INIT_START":
258
271
  return { ...state, status: "loading", error: null };
259
272
  case "INIT_SUCCESS":
260
- return { ...state, status: "ready", paymentIntent: action.payload };
273
+ return {
274
+ ...state,
275
+ status: "ready",
276
+ paymentIntent: action.payload,
277
+ selectedMethod: action.payload.availableMethods?.length === 1 ? action.payload.availableMethods[0] : null
278
+ };
261
279
  case "INIT_ERROR":
262
280
  return { ...state, status: "failed", error: action.payload };
263
281
  case "SELECT_METHOD":
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/api/client.ts","../src/utils.ts","../src/state.ts"],"sourcesContent":["/**\n * Reevit API Client\n * \n * Handles communication with the Reevit backend for payment operations.\n */\n\nimport type { PaymentMethod, ReevitCheckoutConfig, PaymentError } from '../types';\n\n// API Response Types (matching backend handlers_payments.go)\nexport interface CreatePaymentIntentRequest {\n amount: number;\n currency: string;\n method: string;\n country: string;\n customer_id?: string;\n metadata?: Record<string, unknown>;\n description?: string;\n policy?: {\n prefer?: string[];\n max_amount?: number;\n blocked_bins?: string[];\n allowed_bins?: string[];\n velocity_max_per_minute?: number;\n };\n}\n\nexport interface PaymentIntentResponse {\n id: string;\n connection_id: string;\n provider: string;\n status: string;\n client_secret: string;\n amount: number;\n currency: string;\n fee_amount: number;\n fee_currency: string;\n net_amount: number;\n}\n\nexport interface ConfirmPaymentRequest {\n provider_ref_id: string;\n provider_data?: Record<string, unknown>;\n}\n\nexport interface PaymentDetailResponse {\n id: string;\n connection_id: string;\n provider: string;\n method: string;\n status: string;\n amount: number;\n currency: string;\n fee_amount: number;\n fee_currency: string;\n net_amount: number;\n customer_id?: string;\n client_secret: string;\n provider_ref_id?: string;\n metadata?: Record<string, unknown>;\n created_at: string;\n updated_at: string;\n}\n\nexport interface APIErrorResponse {\n code: string;\n message: string;\n details?: Record<string, string>;\n}\n\n// API Client configuration\nexport interface ReevitAPIClientConfig {\n /** Your Reevit public key */\n publicKey: string;\n /** Base URL for the Reevit API (defaults to production) */\n baseUrl?: string;\n /** Request timeout in milliseconds */\n timeout?: number;\n}\n\n// Default API base URLs\nconst API_BASE_URL_PRODUCTION = 'https://api.reevit.io';\nconst API_BASE_URL_SANDBOX = 'https://sandbox-api.reevit.io';\nconst DEFAULT_TIMEOUT = 30000; // 30 seconds\n\n/**\n * Determines if a public key is for sandbox mode\n */\nexport function isSandboxKey(publicKey: string): boolean {\n return publicKey.startsWith('pk_test_') ||\n publicKey.startsWith('pk_sandbox_') ||\n publicKey.startsWith('pfk_test_') ||\n publicKey.startsWith('pfk_sandbox_');\n}\n\n/**\n * Creates a PaymentError from an API error response\n */\nfunction createPaymentError(response: Response, errorData: APIErrorResponse): PaymentError {\n return {\n code: errorData.code || 'api_error',\n message: errorData.message || 'An unexpected error occurred',\n details: {\n httpStatus: response.status,\n ...errorData.details,\n },\n };\n}\n\n/**\n * Reevit API Client\n */\nexport class ReevitAPIClient {\n private readonly publicKey: string;\n private readonly baseUrl: string;\n private readonly timeout: number;\n\n constructor(config: ReevitAPIClientConfig) {\n this.publicKey = config.publicKey;\n this.baseUrl = config.baseUrl || (isSandboxKey(config.publicKey)\n ? API_BASE_URL_SANDBOX\n : API_BASE_URL_PRODUCTION);\n this.timeout = config.timeout || DEFAULT_TIMEOUT;\n }\n\n /**\n * Makes an authenticated API request\n */\n private async request<T>(\n method: string,\n path: string,\n body?: unknown\n ): Promise<{ data?: T; error?: PaymentError }> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n // Generate headers with idempotency key for mutating requests\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'X-Reevit-Key': this.publicKey,\n 'X-Reevit-Client': '@reevit/core',\n 'X-Reevit-Client-Version': '0.2.3',\n };\n\n if (method === 'POST' || method === 'PATCH' || method === 'PUT') {\n headers['Idempotency-Key'] = `${Date.now()}-${Math.random().toString(36).substring(2, 15)}`;\n }\n\n try {\n const response = await fetch(`${this.baseUrl}${path}`, {\n method,\n headers,\n body: body ? JSON.stringify(body) : undefined,\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n const responseData = await response.json().catch(() => ({}));\n\n if (!response.ok) {\n return {\n error: createPaymentError(response, responseData as APIErrorResponse),\n };\n }\n\n return { data: responseData as T };\n } catch (err) {\n clearTimeout(timeoutId);\n\n if (err instanceof Error) {\n if (err.name === 'AbortError') {\n return {\n error: {\n code: 'request_timeout',\n message: 'The request timed out. Please try again.',\n },\n };\n }\n\n if (err.message.includes('Failed to fetch') || err.message.includes('NetworkError')) {\n return {\n error: {\n code: 'network_error',\n message: 'Unable to connect to Reevit. Please check your internet connection.',\n },\n };\n }\n }\n\n return {\n error: {\n code: 'unknown_error',\n message: 'An unexpected error occurred. Please try again.',\n },\n };\n }\n }\n\n /**\n * Creates a payment intent\n */\n async createPaymentIntent(\n config: ReevitCheckoutConfig,\n method: PaymentMethod,\n country: string = 'GH'\n ): Promise<{ data?: PaymentIntentResponse; error?: PaymentError }> {\n const request: CreatePaymentIntentRequest = {\n amount: config.amount,\n currency: config.currency,\n method: this.mapPaymentMethod(method),\n country,\n customer_id: config.metadata?.customerId as string | undefined,\n metadata: config.metadata,\n };\n\n return this.request<PaymentIntentResponse>('POST', '/v1/payments/intents', request);\n }\n\n /**\n * Retrieves a payment intent by ID\n */\n async getPaymentIntent(paymentId: string): Promise<{ data?: PaymentDetailResponse; error?: PaymentError }> {\n return this.request<PaymentDetailResponse>('GET', `/v1/payments/${paymentId}`);\n }\n\n /**\n * Confirms a payment after PSP callback\n */\n async confirmPayment(paymentId: string): Promise<{ data?: PaymentDetailResponse; error?: PaymentError }> {\n return this.request<PaymentDetailResponse>('POST', `/v1/payments/${paymentId}/confirm`);\n }\n\n /**\n * Cancels a payment intent\n */\n async cancelPaymentIntent(paymentId: string): Promise<{ data?: PaymentDetailResponse; error?: PaymentError }> {\n return this.request<PaymentDetailResponse>('POST', `/v1/payments/${paymentId}/cancel`);\n }\n\n /**\n * Maps SDK payment method to backend format\n */\n private mapPaymentMethod(method: PaymentMethod): string {\n switch (method) {\n case 'card':\n return 'card';\n case 'mobile_money':\n return 'mobile_money';\n case 'bank_transfer':\n return 'bank_transfer';\n default:\n return method;\n }\n }\n}\n\n/**\n * Creates a new Reevit API client instance\n */\nexport function createReevitClient(config: ReevitAPIClientConfig): ReevitAPIClient {\n return new ReevitAPIClient(config);\n}\n","/**\n * Utility Functions\n * Shared utilities for Reevit SDKs\n */\n\nimport type { MobileMoneyNetwork, ReevitTheme } from './types';\n\n/**\n * Formats an amount from smallest currency unit to display format\n */\nexport function formatAmount(amount: number, currency: string): string {\n const majorUnit = amount / 100;\n\n const currencyFormats: Record<string, { locale: string; minimumFractionDigits: number }> = {\n GHS: { locale: 'en-GH', minimumFractionDigits: 2 },\n NGN: { locale: 'en-NG', minimumFractionDigits: 2 },\n KES: { locale: 'en-KE', minimumFractionDigits: 2 },\n USD: { locale: 'en-US', minimumFractionDigits: 2 },\n EUR: { locale: 'de-DE', minimumFractionDigits: 2 },\n GBP: { locale: 'en-GB', minimumFractionDigits: 2 },\n };\n\n const format = currencyFormats[currency.toUpperCase()] || { locale: 'en-US', minimumFractionDigits: 2 };\n\n try {\n return new Intl.NumberFormat(format.locale, {\n style: 'currency',\n currency: currency.toUpperCase(),\n minimumFractionDigits: format.minimumFractionDigits,\n }).format(majorUnit);\n } catch {\n // Fallback for unsupported currencies\n return `${currency} ${majorUnit.toFixed(2)}`;\n }\n}\n\n/**\n * Generates a unique payment reference\n */\nexport function generateReference(prefix: string = 'reevit'): string {\n const timestamp = Date.now().toString(36);\n const random = Math.random().toString(36).substring(2, 8);\n return `${prefix}_${timestamp}_${random}`;\n}\n\n/**\n * Validates a phone number for mobile money\n */\nexport function validatePhone(phone: string, country: string = 'GH'): boolean {\n // Remove non-digit characters\n const digits = phone.replace(/\\D/g, '');\n\n const patterns: Record<string, RegExp> = {\n GH: /^(?:233|0)?[235][0-9]{8}$/, // Ghana\n NG: /^(?:234|0)?[789][01][0-9]{8}$/, // Nigeria\n KE: /^(?:254|0)?[17][0-9]{8}$/, // Kenya\n };\n\n const pattern = patterns[country.toUpperCase()];\n if (!pattern) return digits.length >= 10;\n\n return pattern.test(digits);\n}\n\n/**\n * Formats a phone number for display\n */\nexport function formatPhone(phone: string, country: string = 'GH'): string {\n const digits = phone.replace(/\\D/g, '');\n\n if (country === 'GH') {\n // Format as 0XX XXX XXXX\n if (digits.startsWith('233') && digits.length === 12) {\n const local = '0' + digits.slice(3);\n return `${local.slice(0, 3)} ${local.slice(3, 6)} ${local.slice(6)}`;\n }\n if (digits.length === 10 && digits.startsWith('0')) {\n return `${digits.slice(0, 3)} ${digits.slice(3, 6)} ${digits.slice(6)}`;\n }\n }\n\n return phone;\n}\n\n/**\n * Detects mobile money network from phone number (Ghana)\n */\nexport function detectNetwork(phone: string): MobileMoneyNetwork | null {\n const digits = phone.replace(/\\D/g, '');\n\n // Get the network prefix (first 3 digits after country code or 0)\n let prefix: string;\n if (digits.startsWith('233')) {\n prefix = digits.slice(3, 5);\n } else if (digits.startsWith('0')) {\n prefix = digits.slice(1, 3);\n } else {\n prefix = digits.slice(0, 2);\n }\n\n // Ghana network prefixes\n const mtnPrefixes = ['24', '25', '53', '54', '55', '59'];\n const vodafonePrefixes = ['20', '50'];\n const airteltigoPrefixes = ['26', '27', '56', '57'];\n\n if (mtnPrefixes.includes(prefix)) return 'mtn';\n if (vodafonePrefixes.includes(prefix)) return 'vodafone';\n if (airteltigoPrefixes.includes(prefix)) return 'airteltigo';\n\n return null;\n}\n\n/**\n * Creates CSS custom property variables from theme\n */\nexport function createThemeVariables(theme: ReevitTheme): Record<string, string> {\n const variables: Record<string, string> = {};\n\n if (theme.primaryColor) {\n variables['--reevit-primary'] = theme.primaryColor;\n }\n if (theme.backgroundColor) {\n variables['--reevit-bg'] = theme.backgroundColor;\n }\n if (theme.textColor) {\n variables['--reevit-text'] = theme.textColor;\n }\n if (theme.borderRadius) {\n variables['--reevit-radius'] = theme.borderRadius;\n }\n if (theme.fontFamily) {\n variables['--reevit-font'] = theme.fontFamily;\n }\n\n return variables;\n}\n\n/**\n * Simple class name concatenation utility\n */\nexport function cn(...classes: (string | boolean | undefined | null)[]): string {\n return classes.filter(Boolean).join(' ');\n}\n\n/**\n * Detects country code from currency\n */\nexport function detectCountryFromCurrency(currency: string): string {\n const currencyToCountry: Record<string, string> = {\n GHS: 'GH',\n NGN: 'NG',\n KES: 'KE',\n UGX: 'UG',\n TZS: 'TZ',\n ZAR: 'ZA',\n XOF: 'CI',\n XAF: 'CM',\n USD: 'US',\n EUR: 'DE',\n GBP: 'GB',\n };\n\n return currencyToCountry[currency.toUpperCase()] || 'GH';\n}\n","/**\n * Reevit State Machine\n * Shared state management logic for all SDKs\n */\n\nimport type { CheckoutState, PaymentIntent, PaymentMethod, PaymentResult, PaymentError } from './types';\n\n// State shape\nexport interface ReevitState {\n status: CheckoutState;\n paymentIntent: PaymentIntent | null;\n selectedMethod: PaymentMethod | null;\n error: PaymentError | null;\n result: PaymentResult | null;\n}\n\n// Actions\nexport type ReevitAction =\n | { type: 'INIT_START' }\n | { type: 'INIT_SUCCESS'; payload: PaymentIntent }\n | { type: 'INIT_ERROR'; payload: PaymentError }\n | { type: 'SELECT_METHOD'; payload: PaymentMethod }\n | { type: 'PROCESS_START' }\n | { type: 'PROCESS_SUCCESS'; payload: PaymentResult }\n | { type: 'PROCESS_ERROR'; payload: PaymentError }\n | { type: 'RESET' }\n | { type: 'CLOSE' };\n\n/**\n * Creates the initial state for the checkout\n */\nexport function createInitialState(): ReevitState {\n return {\n status: 'idle',\n paymentIntent: null,\n selectedMethod: null,\n error: null,\n result: null,\n };\n}\n\n/**\n * State reducer for checkout flow\n */\nexport function reevitReducer(state: ReevitState, action: ReevitAction): ReevitState {\n switch (action.type) {\n case 'INIT_START':\n return { ...state, status: 'loading', error: null };\n case 'INIT_SUCCESS':\n return { ...state, status: 'ready', paymentIntent: action.payload };\n case 'INIT_ERROR':\n return { ...state, status: 'failed', error: action.payload };\n case 'SELECT_METHOD':\n return { ...state, status: 'method_selected', selectedMethod: action.payload };\n case 'PROCESS_START':\n return { ...state, status: 'processing', error: null };\n case 'PROCESS_SUCCESS':\n return { ...state, status: 'success', result: action.payload };\n case 'PROCESS_ERROR':\n return { ...state, status: 'failed', error: action.payload };\n case 'RESET':\n return { ...createInitialState(), status: 'ready', paymentIntent: state.paymentIntent };\n case 'CLOSE':\n return { ...state, status: 'closed' };\n default:\n return state;\n }\n}\n"],"mappings":";AAgFA,IAAM,0BAA0B;AAChC,IAAM,uBAAuB;AAC7B,IAAM,kBAAkB;AAKjB,SAAS,aAAa,WAA4B;AACvD,SAAO,UAAU,WAAW,UAAU,KACpC,UAAU,WAAW,aAAa,KAClC,UAAU,WAAW,WAAW,KAChC,UAAU,WAAW,cAAc;AACvC;AAKA,SAAS,mBAAmB,UAAoB,WAA2C;AACzF,SAAO;AAAA,IACL,MAAM,UAAU,QAAQ;AAAA,IACxB,SAAS,UAAU,WAAW;AAAA,IAC9B,SAAS;AAAA,MACP,YAAY,SAAS;AAAA,MACrB,GAAG,UAAU;AAAA,IACf;AAAA,EACF;AACF;AAKO,IAAM,kBAAN,MAAsB;AAAA,EAK3B,YAAY,QAA+B;AACzC,SAAK,YAAY,OAAO;AACxB,SAAK,UAAU,OAAO,YAAY,aAAa,OAAO,SAAS,IAC3D,uBACA;AACJ,SAAK,UAAU,OAAO,WAAW;AAAA,EACnC;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,QACZ,QACA,MACA,MAC6C;AAC7C,UAAM,aAAa,IAAI,gBAAgB;AACvC,UAAM,YAAY,WAAW,MAAM,WAAW,MAAM,GAAG,KAAK,OAAO;AAGnE,UAAM,UAAkC;AAAA,MACtC,gBAAgB;AAAA,MAChB,gBAAgB,KAAK;AAAA,MACrB,mBAAmB;AAAA,MACnB,2BAA2B;AAAA,IAC7B;AAEA,QAAI,WAAW,UAAU,WAAW,WAAW,WAAW,OAAO;AAC/D,cAAQ,iBAAiB,IAAI,GAAG,KAAK,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,UAAU,GAAG,EAAE,CAAC;AAAA,IAC3F;AAEA,QAAI;AACF,YAAM,WAAW,MAAM,MAAM,GAAG,KAAK,OAAO,GAAG,IAAI,IAAI;AAAA,QACrD;AAAA,QACA;AAAA,QACA,MAAM,OAAO,KAAK,UAAU,IAAI,IAAI;AAAA,QACpC,QAAQ,WAAW;AAAA,MACrB,CAAC;AAED,mBAAa,SAAS;AAEtB,YAAM,eAAe,MAAM,SAAS,KAAK,EAAE,MAAM,OAAO,CAAC,EAAE;AAE3D,UAAI,CAAC,SAAS,IAAI;AAChB,eAAO;AAAA,UACL,OAAO,mBAAmB,UAAU,YAAgC;AAAA,QACtE;AAAA,MACF;AAEA,aAAO,EAAE,MAAM,aAAkB;AAAA,IACnC,SAAS,KAAK;AACZ,mBAAa,SAAS;AAEtB,UAAI,eAAe,OAAO;AACxB,YAAI,IAAI,SAAS,cAAc;AAC7B,iBAAO;AAAA,YACL,OAAO;AAAA,cACL,MAAM;AAAA,cACN,SAAS;AAAA,YACX;AAAA,UACF;AAAA,QACF;AAEA,YAAI,IAAI,QAAQ,SAAS,iBAAiB,KAAK,IAAI,QAAQ,SAAS,cAAc,GAAG;AACnF,iBAAO;AAAA,YACL,OAAO;AAAA,cACL,MAAM;AAAA,cACN,SAAS;AAAA,YACX;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAEA,aAAO;AAAA,QACL,OAAO;AAAA,UACL,MAAM;AAAA,UACN,SAAS;AAAA,QACX;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,oBACJ,QACA,QACA,UAAkB,MAC+C;AACjE,UAAM,UAAsC;AAAA,MAC1C,QAAQ,OAAO;AAAA,MACf,UAAU,OAAO;AAAA,MACjB,QAAQ,KAAK,iBAAiB,MAAM;AAAA,MACpC;AAAA,MACA,aAAa,OAAO,UAAU;AAAA,MAC9B,UAAU,OAAO;AAAA,IACnB;AAEA,WAAO,KAAK,QAA+B,QAAQ,wBAAwB,OAAO;AAAA,EACpF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,iBAAiB,WAAoF;AACzG,WAAO,KAAK,QAA+B,OAAO,gBAAgB,SAAS,EAAE;AAAA,EAC/E;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,eAAe,WAAoF;AACvG,WAAO,KAAK,QAA+B,QAAQ,gBAAgB,SAAS,UAAU;AAAA,EACxF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,oBAAoB,WAAoF;AAC5G,WAAO,KAAK,QAA+B,QAAQ,gBAAgB,SAAS,SAAS;AAAA,EACvF;AAAA;AAAA;AAAA;AAAA,EAKQ,iBAAiB,QAA+B;AACtD,YAAQ,QAAQ;AAAA,MACd,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,eAAO;AAAA,MACT;AACE,eAAO;AAAA,IACX;AAAA,EACF;AACF;AAKO,SAAS,mBAAmB,QAAgD;AACjF,SAAO,IAAI,gBAAgB,MAAM;AACnC;;;AC3PO,SAAS,aAAa,QAAgB,UAA0B;AACrE,QAAM,YAAY,SAAS;AAE3B,QAAM,kBAAqF;AAAA,IACzF,KAAK,EAAE,QAAQ,SAAS,uBAAuB,EAAE;AAAA,IACjD,KAAK,EAAE,QAAQ,SAAS,uBAAuB,EAAE;AAAA,IACjD,KAAK,EAAE,QAAQ,SAAS,uBAAuB,EAAE;AAAA,IACjD,KAAK,EAAE,QAAQ,SAAS,uBAAuB,EAAE;AAAA,IACjD,KAAK,EAAE,QAAQ,SAAS,uBAAuB,EAAE;AAAA,IACjD,KAAK,EAAE,QAAQ,SAAS,uBAAuB,EAAE;AAAA,EACnD;AAEA,QAAM,SAAS,gBAAgB,SAAS,YAAY,CAAC,KAAK,EAAE,QAAQ,SAAS,uBAAuB,EAAE;AAEtG,MAAI;AACF,WAAO,IAAI,KAAK,aAAa,OAAO,QAAQ;AAAA,MAC1C,OAAO;AAAA,MACP,UAAU,SAAS,YAAY;AAAA,MAC/B,uBAAuB,OAAO;AAAA,IAChC,CAAC,EAAE,OAAO,SAAS;AAAA,EACrB,QAAQ;AAEN,WAAO,GAAG,QAAQ,IAAI,UAAU,QAAQ,CAAC,CAAC;AAAA,EAC5C;AACF;AAKO,SAAS,kBAAkB,SAAiB,UAAkB;AACnE,QAAM,YAAY,KAAK,IAAI,EAAE,SAAS,EAAE;AACxC,QAAM,SAAS,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,UAAU,GAAG,CAAC;AACxD,SAAO,GAAG,MAAM,IAAI,SAAS,IAAI,MAAM;AACzC;AAKO,SAAS,cAAc,OAAe,UAAkB,MAAe;AAE5E,QAAM,SAAS,MAAM,QAAQ,OAAO,EAAE;AAEtC,QAAM,WAAmC;AAAA,IACvC,IAAI;AAAA;AAAA,IACJ,IAAI;AAAA;AAAA,IACJ,IAAI;AAAA;AAAA,EACN;AAEA,QAAM,UAAU,SAAS,QAAQ,YAAY,CAAC;AAC9C,MAAI,CAAC,QAAS,QAAO,OAAO,UAAU;AAEtC,SAAO,QAAQ,KAAK,MAAM;AAC5B;AAKO,SAAS,YAAY,OAAe,UAAkB,MAAc;AACzE,QAAM,SAAS,MAAM,QAAQ,OAAO,EAAE;AAEtC,MAAI,YAAY,MAAM;AAEpB,QAAI,OAAO,WAAW,KAAK,KAAK,OAAO,WAAW,IAAI;AACpD,YAAM,QAAQ,MAAM,OAAO,MAAM,CAAC;AAClC,aAAO,GAAG,MAAM,MAAM,GAAG,CAAC,CAAC,IAAI,MAAM,MAAM,GAAG,CAAC,CAAC,IAAI,MAAM,MAAM,CAAC,CAAC;AAAA,IACpE;AACA,QAAI,OAAO,WAAW,MAAM,OAAO,WAAW,GAAG,GAAG;AAClD,aAAO,GAAG,OAAO,MAAM,GAAG,CAAC,CAAC,IAAI,OAAO,MAAM,GAAG,CAAC,CAAC,IAAI,OAAO,MAAM,CAAC,CAAC;AAAA,IACvE;AAAA,EACF;AAEA,SAAO;AACT;AAKO,SAAS,cAAc,OAA0C;AACtE,QAAM,SAAS,MAAM,QAAQ,OAAO,EAAE;AAGtC,MAAI;AACJ,MAAI,OAAO,WAAW,KAAK,GAAG;AAC5B,aAAS,OAAO,MAAM,GAAG,CAAC;AAAA,EAC5B,WAAW,OAAO,WAAW,GAAG,GAAG;AACjC,aAAS,OAAO,MAAM,GAAG,CAAC;AAAA,EAC5B,OAAO;AACL,aAAS,OAAO,MAAM,GAAG,CAAC;AAAA,EAC5B;AAGA,QAAM,cAAc,CAAC,MAAM,MAAM,MAAM,MAAM,MAAM,IAAI;AACvD,QAAM,mBAAmB,CAAC,MAAM,IAAI;AACpC,QAAM,qBAAqB,CAAC,MAAM,MAAM,MAAM,IAAI;AAElD,MAAI,YAAY,SAAS,MAAM,EAAG,QAAO;AACzC,MAAI,iBAAiB,SAAS,MAAM,EAAG,QAAO;AAC9C,MAAI,mBAAmB,SAAS,MAAM,EAAG,QAAO;AAEhD,SAAO;AACT;AAKO,SAAS,qBAAqB,OAA4C;AAC/E,QAAM,YAAoC,CAAC;AAE3C,MAAI,MAAM,cAAc;AACtB,cAAU,kBAAkB,IAAI,MAAM;AAAA,EACxC;AACA,MAAI,MAAM,iBAAiB;AACzB,cAAU,aAAa,IAAI,MAAM;AAAA,EACnC;AACA,MAAI,MAAM,WAAW;AACnB,cAAU,eAAe,IAAI,MAAM;AAAA,EACrC;AACA,MAAI,MAAM,cAAc;AACtB,cAAU,iBAAiB,IAAI,MAAM;AAAA,EACvC;AACA,MAAI,MAAM,YAAY;AACpB,cAAU,eAAe,IAAI,MAAM;AAAA,EACrC;AAEA,SAAO;AACT;AAKO,SAAS,MAAM,SAA0D;AAC9E,SAAO,QAAQ,OAAO,OAAO,EAAE,KAAK,GAAG;AACzC;AAKO,SAAS,0BAA0B,UAA0B;AAClE,QAAM,oBAA4C;AAAA,IAChD,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,EACP;AAEA,SAAO,kBAAkB,SAAS,YAAY,CAAC,KAAK;AACtD;;;ACpIO,SAAS,qBAAkC;AAChD,SAAO;AAAA,IACL,QAAQ;AAAA,IACR,eAAe;AAAA,IACf,gBAAgB;AAAA,IAChB,OAAO;AAAA,IACP,QAAQ;AAAA,EACV;AACF;AAKO,SAAS,cAAc,OAAoB,QAAmC;AACnF,UAAQ,OAAO,MAAM;AAAA,IACnB,KAAK;AACH,aAAO,EAAE,GAAG,OAAO,QAAQ,WAAW,OAAO,KAAK;AAAA,IACpD,KAAK;AACH,aAAO,EAAE,GAAG,OAAO,QAAQ,SAAS,eAAe,OAAO,QAAQ;AAAA,IACpE,KAAK;AACH,aAAO,EAAE,GAAG,OAAO,QAAQ,UAAU,OAAO,OAAO,QAAQ;AAAA,IAC7D,KAAK;AACH,aAAO,EAAE,GAAG,OAAO,QAAQ,mBAAmB,gBAAgB,OAAO,QAAQ;AAAA,IAC/E,KAAK;AACH,aAAO,EAAE,GAAG,OAAO,QAAQ,cAAc,OAAO,KAAK;AAAA,IACvD,KAAK;AACH,aAAO,EAAE,GAAG,OAAO,QAAQ,WAAW,QAAQ,OAAO,QAAQ;AAAA,IAC/D,KAAK;AACH,aAAO,EAAE,GAAG,OAAO,QAAQ,UAAU,OAAO,OAAO,QAAQ;AAAA,IAC7D,KAAK;AACH,aAAO,EAAE,GAAG,mBAAmB,GAAG,QAAQ,SAAS,eAAe,MAAM,cAAc;AAAA,IACxF,KAAK;AACH,aAAO,EAAE,GAAG,OAAO,QAAQ,SAAS;AAAA,IACtC;AACE,aAAO;AAAA,EACX;AACF;","names":[]}
1
+ {"version":3,"sources":["../src/api/client.ts","../src/utils.ts","../src/state.ts"],"sourcesContent":["/**\n * Reevit API Client\n * \n * Handles communication with the Reevit backend for payment operations.\n */\n\nimport type { PaymentMethod, ReevitCheckoutConfig, PaymentError } from '../types';\n\n// API Response Types (matching backend handlers_payments.go)\nexport interface CreatePaymentIntentRequest {\n amount: number;\n currency: string;\n method: string;\n country: string;\n customer_id?: string;\n metadata?: Record<string, unknown>;\n description?: string;\n policy?: {\n prefer?: string[];\n max_amount?: number;\n blocked_bins?: string[];\n allowed_bins?: string[];\n velocity_max_per_minute?: number;\n };\n}\n\nexport interface PaymentIntentResponse {\n id: string;\n connection_id: string;\n provider: string;\n status: string;\n client_secret: string;\n psp_public_key: string;\n amount: number;\n currency: string;\n fee_amount: number;\n fee_currency: string;\n net_amount: number;\n reference?: string;\n}\n\nexport interface ConfirmPaymentRequest {\n provider_ref_id: string;\n provider_data?: Record<string, unknown>;\n}\n\nexport interface PaymentDetailResponse {\n id: string;\n connection_id: string;\n provider: string;\n method: string;\n status: string;\n amount: number;\n currency: string;\n fee_amount: number;\n fee_currency: string;\n net_amount: number;\n customer_id?: string;\n client_secret: string;\n provider_ref_id?: string;\n metadata?: Record<string, unknown>;\n created_at: string;\n updated_at: string;\n}\n\nexport interface APIErrorResponse {\n code: string;\n message: string;\n details?: Record<string, string>;\n}\n\n// API Client configuration\nexport interface ReevitAPIClientConfig {\n /** Your Reevit public key */\n publicKey: string;\n /** Base URL for the Reevit API (defaults to production) */\n baseUrl?: string;\n /** Request timeout in milliseconds */\n timeout?: number;\n}\n\n// Default API base URLs\nconst API_BASE_URL_PRODUCTION = 'https://api.reevit.io';\nconst API_BASE_URL_SANDBOX = 'https://sandbox-api.reevit.io';\nconst DEFAULT_TIMEOUT = 30000; // 30 seconds\n\n/**\n * Determines if a public key is for sandbox mode\n */\nexport function isSandboxKey(publicKey: string): boolean {\n return publicKey.startsWith('pk_test_') ||\n publicKey.startsWith('pk_sandbox_') ||\n publicKey.startsWith('pfk_test_') ||\n publicKey.startsWith('pfk_sandbox_');\n}\n\n/**\n * Creates a PaymentError from an API error response\n */\nfunction createPaymentError(response: Response, errorData: APIErrorResponse): PaymentError {\n return {\n code: errorData.code || 'api_error',\n message: errorData.message || 'An unexpected error occurred',\n details: {\n httpStatus: response.status,\n ...errorData.details,\n },\n };\n}\n\n/**\n * Reevit API Client\n */\nexport class ReevitAPIClient {\n private readonly publicKey: string;\n private readonly baseUrl: string;\n private readonly timeout: number;\n\n constructor(config: ReevitAPIClientConfig) {\n this.publicKey = config.publicKey;\n this.baseUrl = config.baseUrl || (isSandboxKey(config.publicKey)\n ? API_BASE_URL_SANDBOX\n : API_BASE_URL_PRODUCTION);\n this.timeout = config.timeout || DEFAULT_TIMEOUT;\n }\n\n /**\n * Makes an authenticated API request\n */\n private async request<T>(\n method: string,\n path: string,\n body?: unknown\n ): Promise<{ data?: T; error?: PaymentError }> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n // Generate headers with idempotency key for mutating requests\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'X-Reevit-Key': this.publicKey,\n 'X-Reevit-Client': '@reevit/core',\n 'X-Reevit-Client-Version': '0.3.2',\n };\n\n if (method === 'POST' || method === 'PATCH' || method === 'PUT') {\n headers['Idempotency-Key'] = `${Date.now()}-${Math.random().toString(36).substring(2, 15)}`;\n }\n\n try {\n const response = await fetch(`${this.baseUrl}${path}`, {\n method,\n headers,\n body: body ? JSON.stringify(body) : undefined,\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n const responseData = await response.json().catch(() => ({}));\n\n if (!response.ok) {\n return {\n error: createPaymentError(response, responseData as APIErrorResponse),\n };\n }\n\n return { data: responseData as T };\n } catch (err) {\n clearTimeout(timeoutId);\n\n if (err instanceof Error) {\n if (err.name === 'AbortError') {\n return {\n error: {\n code: 'request_timeout',\n message: 'The request timed out. Please try again.',\n },\n };\n }\n\n if (err.message.includes('Failed to fetch') || err.message.includes('NetworkError')) {\n return {\n error: {\n code: 'network_error',\n message: 'Unable to connect to Reevit. Please check your internet connection.',\n },\n };\n }\n }\n\n return {\n error: {\n code: 'unknown_error',\n message: 'An unexpected error occurred. Please try again.',\n },\n };\n }\n }\n\n /**\n * Creates a payment intent\n */\n async createPaymentIntent(\n config: ReevitCheckoutConfig,\n method: PaymentMethod,\n country: string = 'GH'\n ): Promise<{ data?: PaymentIntentResponse; error?: PaymentError }> {\n // Build metadata with customer_email for PSP providers that require it\n const metadata: Record<string, unknown> = { ...config.metadata };\n if (config.email) {\n metadata.customer_email = config.email;\n }\n if (config.phone) {\n metadata.customer_phone = config.phone;\n }\n\n const request: CreatePaymentIntentRequest = {\n amount: config.amount,\n currency: config.currency,\n method: this.mapPaymentMethod(method),\n country,\n customer_id: config.email || (config.metadata?.customerId as string | undefined),\n metadata,\n };\n\n return this.request<PaymentIntentResponse>('POST', '/v1/payments/intents', request);\n }\n\n /**\n * Retrieves a payment intent by ID\n */\n async getPaymentIntent(paymentId: string): Promise<{ data?: PaymentDetailResponse; error?: PaymentError }> {\n return this.request<PaymentDetailResponse>('GET', `/v1/payments/${paymentId}`);\n }\n\n /**\n * Confirms a payment after PSP callback\n */\n async confirmPayment(paymentId: string): Promise<{ data?: PaymentDetailResponse; error?: PaymentError }> {\n return this.request<PaymentDetailResponse>('POST', `/v1/payments/${paymentId}/confirm`);\n }\n\n /**\n * Confirms a payment intent using client secret (public endpoint)\n */\n async confirmPaymentIntent(paymentId: string, clientSecret: string): Promise<{ data?: PaymentDetailResponse; error?: PaymentError }> {\n return this.request<PaymentDetailResponse>('POST', `/v1/payments/${paymentId}/confirm-intent?client_secret=${clientSecret}`);\n }\n\n /**\n * Cancels a payment intent\n */\n async cancelPaymentIntent(paymentId: string): Promise<{ data?: PaymentDetailResponse; error?: PaymentError }> {\n return this.request<PaymentDetailResponse>('POST', `/v1/payments/${paymentId}/cancel`);\n }\n\n /**\n * Maps SDK payment method to backend format\n */\n private mapPaymentMethod(method: PaymentMethod): string {\n switch (method) {\n case 'card':\n return 'card';\n case 'mobile_money':\n return 'mobile_money';\n case 'bank_transfer':\n return 'bank_transfer';\n default:\n return method;\n }\n }\n}\n\n/**\n * Creates a new Reevit API client instance\n */\nexport function createReevitClient(config: ReevitAPIClientConfig): ReevitAPIClient {\n return new ReevitAPIClient(config);\n}\n","/**\n * Utility Functions\n * Shared utilities for Reevit SDKs\n */\n\nimport type { MobileMoneyNetwork, ReevitTheme } from './types';\n\n/**\n * Formats an amount from smallest currency unit to display format\n */\nexport function formatAmount(amount: number, currency: string): string {\n const majorUnit = amount / 100;\n\n const currencyFormats: Record<string, { locale: string; minimumFractionDigits: number }> = {\n GHS: { locale: 'en-GH', minimumFractionDigits: 2 },\n NGN: { locale: 'en-NG', minimumFractionDigits: 2 },\n KES: { locale: 'en-KE', minimumFractionDigits: 2 },\n USD: { locale: 'en-US', minimumFractionDigits: 2 },\n EUR: { locale: 'de-DE', minimumFractionDigits: 2 },\n GBP: { locale: 'en-GB', minimumFractionDigits: 2 },\n };\n\n const format = currencyFormats[currency.toUpperCase()] || { locale: 'en-US', minimumFractionDigits: 2 };\n\n try {\n return new Intl.NumberFormat(format.locale, {\n style: 'currency',\n currency: currency.toUpperCase(),\n minimumFractionDigits: format.minimumFractionDigits,\n }).format(majorUnit);\n } catch {\n // Fallback for unsupported currencies\n return `${currency} ${majorUnit.toFixed(2)}`;\n }\n}\n\n/**\n * Generates a unique payment reference\n */\nexport function generateReference(prefix: string = 'reevit'): string {\n const timestamp = Date.now().toString(36);\n const random = Math.random().toString(36).substring(2, 8);\n return `${prefix}_${timestamp}_${random}`;\n}\n\n/**\n * Validates a phone number for mobile money\n */\nexport function validatePhone(phone: string, country: string = 'GH'): boolean {\n // Remove non-digit characters\n const digits = phone.replace(/\\D/g, '');\n\n const patterns: Record<string, RegExp> = {\n GH: /^(?:233|0)?[235][0-9]{8}$/, // Ghana\n NG: /^(?:234|0)?[789][01][0-9]{8}$/, // Nigeria\n KE: /^(?:254|0)?[17][0-9]{8}$/, // Kenya\n };\n\n const pattern = patterns[country.toUpperCase()];\n if (!pattern) return digits.length >= 10;\n\n return pattern.test(digits);\n}\n\n/**\n * Formats a phone number for display\n */\nexport function formatPhone(phone: string, country: string = 'GH'): string {\n const digits = phone.replace(/\\D/g, '');\n\n if (country === 'GH') {\n // Format as 0XX XXX XXXX\n if (digits.startsWith('233') && digits.length === 12) {\n const local = '0' + digits.slice(3);\n return `${local.slice(0, 3)} ${local.slice(3, 6)} ${local.slice(6)}`;\n }\n if (digits.length === 10 && digits.startsWith('0')) {\n return `${digits.slice(0, 3)} ${digits.slice(3, 6)} ${digits.slice(6)}`;\n }\n }\n\n return phone;\n}\n\n/**\n * Detects mobile money network from phone number (Ghana)\n */\nexport function detectNetwork(phone: string): MobileMoneyNetwork | null {\n const digits = phone.replace(/\\D/g, '');\n\n // Get the network prefix (first 3 digits after country code or 0)\n let prefix: string;\n if (digits.startsWith('233')) {\n prefix = digits.slice(3, 5);\n } else if (digits.startsWith('0')) {\n prefix = digits.slice(1, 3);\n } else {\n prefix = digits.slice(0, 2);\n }\n\n // Ghana network prefixes\n const mtnPrefixes = ['24', '25', '53', '54', '55', '59'];\n const vodafonePrefixes = ['20', '50'];\n const airteltigoPrefixes = ['26', '27', '56', '57'];\n\n if (mtnPrefixes.includes(prefix)) return 'mtn';\n if (vodafonePrefixes.includes(prefix)) return 'vodafone';\n if (airteltigoPrefixes.includes(prefix)) return 'airteltigo';\n\n return null;\n}\n\n/**\n * Creates CSS custom property variables from theme\n */\nexport function createThemeVariables(theme: ReevitTheme): Record<string, string> {\n const variables: Record<string, string> = {};\n\n if (theme.primaryColor) {\n variables['--reevit-primary'] = theme.primaryColor;\n }\n if (theme.backgroundColor) {\n variables['--reevit-bg'] = theme.backgroundColor;\n }\n if (theme.textColor) {\n variables['--reevit-text'] = theme.textColor;\n }\n if (theme.borderRadius) {\n variables['--reevit-radius'] = theme.borderRadius;\n }\n if (theme.fontFamily) {\n variables['--reevit-font'] = theme.fontFamily;\n }\n\n return variables;\n}\n\n/**\n * Simple class name concatenation utility\n */\nexport function cn(...classes: (string | boolean | undefined | null)[]): string {\n return classes.filter(Boolean).join(' ');\n}\n\n/**\n * Detects country code from currency\n */\nexport function detectCountryFromCurrency(currency: string): string {\n const currencyToCountry: Record<string, string> = {\n GHS: 'GH',\n NGN: 'NG',\n KES: 'KE',\n UGX: 'UG',\n TZS: 'TZ',\n ZAR: 'ZA',\n XOF: 'CI',\n XAF: 'CM',\n USD: 'US',\n EUR: 'DE',\n GBP: 'GB',\n };\n\n return currencyToCountry[currency.toUpperCase()] || 'GH';\n}\n","/**\n * Reevit State Machine\n * Shared state management logic for all SDKs\n */\n\nimport type { CheckoutState, PaymentIntent, PaymentMethod, PaymentResult, PaymentError } from './types';\n\n// State shape\nexport interface ReevitState {\n status: CheckoutState;\n paymentIntent: PaymentIntent | null;\n selectedMethod: PaymentMethod | null;\n error: PaymentError | null;\n result: PaymentResult | null;\n}\n\n// Actions\nexport type ReevitAction =\n | { type: 'INIT_START' }\n | { type: 'INIT_SUCCESS'; payload: PaymentIntent }\n | { type: 'INIT_ERROR'; payload: PaymentError }\n | { type: 'SELECT_METHOD'; payload: PaymentMethod }\n | { type: 'PROCESS_START' }\n | { type: 'PROCESS_SUCCESS'; payload: PaymentResult }\n | { type: 'PROCESS_ERROR'; payload: PaymentError }\n | { type: 'RESET' }\n | { type: 'CLOSE' };\n\n/**\n * Creates the initial state for the checkout\n */\nexport function createInitialState(): ReevitState {\n return {\n status: 'idle',\n paymentIntent: null,\n selectedMethod: null,\n error: null,\n result: null,\n };\n}\n\n/**\n * State reducer for checkout flow\n */\nexport function reevitReducer(state: ReevitState, action: ReevitAction): ReevitState {\n switch (action.type) {\n case 'INIT_START':\n return { ...state, status: 'loading', error: null };\n case 'INIT_SUCCESS':\n return {\n ...state,\n status: 'ready',\n paymentIntent: action.payload,\n selectedMethod:\n action.payload.availableMethods?.length === 1 ? action.payload.availableMethods[0] : null,\n };\n case 'INIT_ERROR':\n return { ...state, status: 'failed', error: action.payload };\n case 'SELECT_METHOD':\n return { ...state, status: 'method_selected', selectedMethod: action.payload };\n case 'PROCESS_START':\n return { ...state, status: 'processing', error: null };\n case 'PROCESS_SUCCESS':\n return { ...state, status: 'success', result: action.payload };\n case 'PROCESS_ERROR':\n return { ...state, status: 'failed', error: action.payload };\n case 'RESET':\n return { ...createInitialState(), status: 'ready', paymentIntent: state.paymentIntent };\n case 'CLOSE':\n return { ...state, status: 'closed' };\n default:\n return state;\n }\n}\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reevit/core",
3
- "version": "0.2.4",
3
+ "version": "0.3.2",
4
4
  "description": "Core utilities and API client for Reevit payment SDKs",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",