@voxepay/checkout 0.3.2 → 0.3.3
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/package.json +2 -1
- package/src/api/client.ts +110 -0
- package/src/components/modal.ts +1244 -0
- package/src/index.ts +73 -0
- package/src/types.ts +141 -0
- package/src/utils/card-validator.ts +181 -0
- package/src/utils/encryption.ts +496 -0
- package/src/utils/formatter.ts +71 -0
- package/src/voxepay.ts +202 -0
package/src/voxepay.ts
ADDED
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* VoxePay - Modern Payment Checkout SDK
|
|
3
|
+
*
|
|
4
|
+
* A beautiful, modern payment modal for the web.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```javascript
|
|
8
|
+
* // Initialize VoxePay
|
|
9
|
+
* VoxePay.init({ apiKey: 'pk_live_xxxxx' });
|
|
10
|
+
*
|
|
11
|
+
* // Open checkout
|
|
12
|
+
* VoxePay.checkout({
|
|
13
|
+
* amount: 4999,
|
|
14
|
+
* currency: 'NGN',
|
|
15
|
+
* description: 'Premium Plan',
|
|
16
|
+
* onSuccess: (result) => console.log('Paid!', result),
|
|
17
|
+
* onError: (error) => console.error('Failed', error),
|
|
18
|
+
* });
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
import { VoxePayModal } from './components/modal';
|
|
23
|
+
import type { VoxePayConfig, CheckoutOptions, VoxePayTheme } from './types';
|
|
24
|
+
|
|
25
|
+
class VoxePaySDK {
|
|
26
|
+
private config: VoxePayConfig | null = null;
|
|
27
|
+
private currentModal: VoxePayModal | null = null;
|
|
28
|
+
private initialized = false;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Initialize VoxePay with your configuration
|
|
32
|
+
* @param config - Configuration object with API key and optional settings
|
|
33
|
+
*/
|
|
34
|
+
init(config: VoxePayConfig): void {
|
|
35
|
+
if (!config.apiKey) {
|
|
36
|
+
console.error('[VoxePay] API key is required. Get your API key from the VoxePay dashboard: Settings > API Keys');
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (!config.organizationId) {
|
|
41
|
+
console.error('[VoxePay] Organization ID is required. Find it in your VoxePay dashboard.');
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
this.config = {
|
|
46
|
+
theme: 'dark',
|
|
47
|
+
locale: 'en-US',
|
|
48
|
+
...config,
|
|
49
|
+
};
|
|
50
|
+
this.initialized = true;
|
|
51
|
+
|
|
52
|
+
// Apply theme
|
|
53
|
+
if (config.theme === 'auto') {
|
|
54
|
+
this.applyAutoTheme();
|
|
55
|
+
} else if (config.theme === 'light') {
|
|
56
|
+
document.documentElement.classList.add('voxepay-light');
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Apply custom styles
|
|
60
|
+
if (config.customStyles) {
|
|
61
|
+
this.applyCustomStyles(config.customStyles);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
console.log('[VoxePay] Initialized successfully');
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Open the checkout modal
|
|
69
|
+
* @param options - Checkout options including amount, currency, and callbacks
|
|
70
|
+
*/
|
|
71
|
+
checkout(options: CheckoutOptions): void {
|
|
72
|
+
if (!this.initialized) {
|
|
73
|
+
console.error('[VoxePay] Not initialized. Call VoxePay.init() first.');
|
|
74
|
+
options.onError({
|
|
75
|
+
code: 'NOT_INITIALIZED',
|
|
76
|
+
message: 'VoxePay SDK not initialized. Call VoxePay.init() first.',
|
|
77
|
+
recoverable: false,
|
|
78
|
+
});
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (!options.amount || options.amount <= 0) {
|
|
83
|
+
console.error('[VoxePay] Invalid amount');
|
|
84
|
+
options.onError({
|
|
85
|
+
code: 'INVALID_AMOUNT',
|
|
86
|
+
message: 'Payment amount must be greater than 0',
|
|
87
|
+
recoverable: false,
|
|
88
|
+
});
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (!options.currency) {
|
|
93
|
+
console.error('[VoxePay] Currency is required');
|
|
94
|
+
options.onError({
|
|
95
|
+
code: 'INVALID_CURRENCY',
|
|
96
|
+
message: 'Currency code is required',
|
|
97
|
+
recoverable: false,
|
|
98
|
+
});
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Close any existing modal
|
|
103
|
+
this.closeModal();
|
|
104
|
+
|
|
105
|
+
// Create and open new modal
|
|
106
|
+
this.currentModal = new VoxePayModal({
|
|
107
|
+
...options,
|
|
108
|
+
_sdkConfig: {
|
|
109
|
+
apiKey: this.config!.apiKey,
|
|
110
|
+
organizationId: this.config!.organizationId,
|
|
111
|
+
baseUrl: this.config!.baseUrl,
|
|
112
|
+
},
|
|
113
|
+
onClose: () => {
|
|
114
|
+
this.currentModal = null;
|
|
115
|
+
options.onClose?.();
|
|
116
|
+
},
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
this.currentModal.open();
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Close the current checkout modal
|
|
124
|
+
*/
|
|
125
|
+
closeModal(): void {
|
|
126
|
+
if (this.currentModal) {
|
|
127
|
+
this.currentModal.close();
|
|
128
|
+
this.currentModal = null;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Set the theme
|
|
134
|
+
* @param theme - 'dark', 'light', or 'auto'
|
|
135
|
+
*/
|
|
136
|
+
setTheme(theme: 'dark' | 'light' | 'auto'): void {
|
|
137
|
+
document.documentElement.classList.remove('voxepay-light');
|
|
138
|
+
|
|
139
|
+
if (theme === 'light') {
|
|
140
|
+
document.documentElement.classList.add('voxepay-light');
|
|
141
|
+
} else if (theme === 'auto') {
|
|
142
|
+
this.applyAutoTheme();
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
if (this.config) {
|
|
146
|
+
this.config.theme = theme;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Apply system theme preference
|
|
152
|
+
*/
|
|
153
|
+
private applyAutoTheme(): void {
|
|
154
|
+
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
|
|
155
|
+
if (!prefersDark) {
|
|
156
|
+
document.documentElement.classList.add('voxepay-light');
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', (e) => {
|
|
160
|
+
if (this.config?.theme === 'auto') {
|
|
161
|
+
document.documentElement.classList.toggle('voxepay-light', !e.matches);
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Apply custom CSS variables
|
|
168
|
+
*/
|
|
169
|
+
private applyCustomStyles(styles: Partial<VoxePayTheme>): void {
|
|
170
|
+
const root = document.documentElement;
|
|
171
|
+
for (const [key, value] of Object.entries(styles)) {
|
|
172
|
+
if (value) {
|
|
173
|
+
root.style.setProperty(key, value);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Get the SDK version
|
|
180
|
+
*/
|
|
181
|
+
get version(): string {
|
|
182
|
+
return '0.3.0';
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Check if SDK is initialized
|
|
187
|
+
*/
|
|
188
|
+
get isInitialized(): boolean {
|
|
189
|
+
return this.initialized;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// Create singleton instance
|
|
194
|
+
const VoxePay = new VoxePaySDK();
|
|
195
|
+
|
|
196
|
+
// Export for different module systems
|
|
197
|
+
export { VoxePay, VoxePaySDK };
|
|
198
|
+
|
|
199
|
+
// Make available on window for script tag usage
|
|
200
|
+
if (typeof window !== 'undefined') {
|
|
201
|
+
(window as unknown as { VoxePay: VoxePaySDK }).VoxePay = VoxePay;
|
|
202
|
+
}
|