@voxepay/checkout 0.0.1-security → 0.5.19

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.

Potentially problematic release.


This version of @voxepay/checkout might be problematic. Click here for more details.

package/README.md CHANGED
@@ -1,5 +1,142 @@
1
- # Security holding package
1
+ # @voxepay/checkout
2
2
 
3
- This package contained malicious code and was removed from the registry by the npm security team. A placeholder was published to ensure users are not affected in the future.
3
+ Modern, beautiful payment checkout modal for the web by **VoxePay**.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @voxepay/checkout
9
+ ```
10
+
11
+ ## Quick Start
12
+
13
+ ### Via Script Tag (CDN)
14
+
15
+ ```html
16
+ <script src="https://unpkg.com/@voxepay/checkout/dist/voxepay-checkout.min.js"></script>
17
+ <script>
18
+ VoxePay.init({ apiKey: 'pk_live_xxxxx' });
19
+
20
+ document.getElementById('pay-btn').addEventListener('click', () => {
21
+ VoxePay.checkout({
22
+ amount: 500000, // ₦5,000 in kobo
23
+ currency: 'NGN',
24
+ description: 'Premium Plan',
25
+ customerEmail: 'customer@example.com',
26
+ onSuccess: (result) => {
27
+ console.log('Payment successful!', result);
28
+ },
29
+ onError: (error) => {
30
+ console.error('Payment failed:', error.message);
31
+ },
32
+ });
33
+ });
34
+ </script>
35
+ ```
36
+
37
+ ### Via ES Modules
38
+
39
+ ```javascript
40
+ import { VoxePay } from '@voxepay/checkout';
41
+
42
+ // Initialize once
43
+ VoxePay.init({
44
+ apiKey: 'pk_live_xxxxx',
45
+ theme: 'dark', // 'dark' | 'light' | 'auto'
46
+ });
47
+
48
+ // Open checkout
49
+ VoxePay.checkout({
50
+ amount: 500000, // Amount in kobo (₦5,000)
51
+ currency: 'NGN',
52
+ description: 'Premium Plan',
53
+ customerEmail: 'customer@example.com',
54
+ onSuccess: (result) => {
55
+ console.log('Paid!', result);
56
+ },
57
+ onError: (error) => {
58
+ console.error('Failed:', error.message);
59
+ },
60
+ onClose: () => {
61
+ console.log('Modal closed');
62
+ },
63
+ });
64
+ ```
65
+
66
+ ## API Reference
67
+
68
+ ### `VoxePay.init(config)`
69
+
70
+ Initialize the SDK. Call this once before using `checkout()`.
71
+
72
+ | Parameter | Type | Required | Description |
73
+ |-----------|------|----------|-------------|
74
+ | `apiKey` | `string` | ✅ | Your VoxePay API key |
75
+ | `theme` | `'dark' \| 'light' \| 'auto'` | ❌ | Theme mode (default: `'dark'`) |
76
+ | `locale` | `string` | ❌ | Locale for formatting (default: `'en-US'`) |
77
+ | `customStyles` | `Partial<VoxePayTheme>` | ❌ | Custom CSS variables |
78
+
79
+ ### `VoxePay.checkout(options)`
80
+
81
+ Open the checkout modal.
82
+
83
+ | Parameter | Type | Required | Description |
84
+ |-----------|------|----------|-------------|
85
+ | `amount` | `number` | ✅ | Amount in smallest currency unit (kobo/cents) |
86
+ | `currency` | `string` | ✅ | ISO 4217 currency code (e.g., `'NGN'`, `'USD'`) |
87
+ | `description` | `string` | ❌ | Payment description shown in modal |
88
+ | `customerEmail` | `string` | ❌ | Customer email for receipts |
89
+ | `metadata` | `Record<string, unknown>` | ❌ | Additional metadata |
90
+ | `onSuccess` | `(result: PaymentResult) => void` | ✅ | Success callback |
91
+ | `onError` | `(error: PaymentError) => void` | ✅ | Error callback |
92
+ | `onClose` | `() => void` | ❌ | Modal close callback |
93
+
94
+ ### `VoxePay.closeModal()`
95
+
96
+ Programmatically close the checkout modal.
97
+
98
+ ### `VoxePay.setTheme(theme)`
99
+
100
+ Change the theme dynamically.
101
+
102
+ ## Utilities
103
+
104
+ ```javascript
105
+ import {
106
+ formatAmount,
107
+ getCurrencySymbol,
108
+ validateCardNumber,
109
+ detectCardBrand,
110
+ } from '@voxepay/checkout';
111
+
112
+ formatAmount(500000, 'NGN'); // "₦5,000.00"
113
+ getCurrencySymbol('NGN'); // "₦"
114
+ validateCardNumber('4111111111111111'); // { valid: true }
115
+ detectCardBrand('4111111111111111'); // { name: 'Visa', code: 'visa', ... }
116
+ ```
117
+
118
+ ## Theming
119
+
120
+ ### Custom Colors
121
+
122
+ ```javascript
123
+ VoxePay.init({
124
+ apiKey: 'pk_live_xxxxx',
125
+ customStyles: {
126
+ '--voxepay-primary': '#0061FF',
127
+ '--voxepay-secondary': '#0047CC',
128
+ '--voxepay-border-radius': '16px',
129
+ },
130
+ });
131
+ ```
132
+
133
+ ## Supported Cards
134
+
135
+ - Visa
136
+ - Mastercard
137
+ - Verve
138
+ - American Express
139
+ - Discover
140
+
141
+ ## License
4
142
 
5
- Please refer to www.npmjs.com/advisories?search=%40voxepay%2Fcheckout for more information.
@@ -0,0 +1,146 @@
1
+ /**
2
+ * VoxePay Payment API Client
3
+ * Handles communication with the VoxePay payment gateway
4
+ */
5
+ export interface InitiatePaymentRequest {
6
+ organizationId: string;
7
+ transactionRef: string;
8
+ customerId?: string;
9
+ customerEmail?: string;
10
+ customerPhone?: string;
11
+ customerName?: string;
12
+ amount: number;
13
+ currency: string;
14
+ paymentMethod: 'CARD' | 'BANK_TRANSFER';
15
+ authData: string;
16
+ narration?: string;
17
+ /** Virtual account validity in minutes (5-1440). Only for BANK_TRANSFER. Default: 30 */
18
+ durationMinutes?: number;
19
+ }
20
+ export interface VirtualAccountResponse {
21
+ account_number: string;
22
+ account_name: string;
23
+ bank_name: string;
24
+ bank_code: string;
25
+ expires_at: string;
26
+ status: string;
27
+ }
28
+ export interface InitiatePaymentResponse {
29
+ /** Backend sends `id` (not `paymentId`) for payment-links/public/.../pay */
30
+ id: string;
31
+ transactionRef: string;
32
+ status: string;
33
+ message: string;
34
+ /** Legacy field — some endpoints may still return this */
35
+ paymentId?: string;
36
+ transactionId?: string;
37
+ eciFlag?: string;
38
+ otpRequired?: boolean;
39
+ virtualAccount?: VirtualAccountResponse;
40
+ feeDetails?: {
41
+ transactionFee: number;
42
+ transactionFeeVat: number;
43
+ totalFees: number;
44
+ grossAmount: number;
45
+ currency: string;
46
+ };
47
+ [key: string]: unknown;
48
+ }
49
+ export type DVAPaymentStatus = 'INITIATED' | 'PENDING_PAYMENT' | 'PAYMENT_RECEIVED' | 'COMPLETED' | 'PARTIAL_PAYMENT' | 'OVERPAID' | 'EXPIRED' | 'FAILED' | 'CANCELLED';
50
+ export interface PaymentStatusResponse {
51
+ id: string;
52
+ transactionRef: string;
53
+ customerId?: string;
54
+ amount: number;
55
+ currency: string;
56
+ paymentMethod: 'CARD' | 'BANK_TRANSFER';
57
+ status: DVAPaymentStatus;
58
+ paymentId?: string;
59
+ otpRequired?: boolean;
60
+ authorizationUrl?: string;
61
+ message?: string;
62
+ otpAttempts?: number;
63
+ maxOtpAttempts?: number;
64
+ createdAt: string;
65
+ completedAt?: string;
66
+ virtualAccount?: {
67
+ account_number: string;
68
+ account_name: string;
69
+ bank_name: string;
70
+ bank_code: string;
71
+ expires_at: string;
72
+ status: string;
73
+ };
74
+ feeDetails?: {
75
+ transactionFee: number;
76
+ transactionFeeVat: number;
77
+ totalFees: number;
78
+ grossAmount: number;
79
+ currency: string;
80
+ };
81
+ }
82
+ export interface ValidateOTPRequest {
83
+ paymentId: string;
84
+ otp: string;
85
+ /** Legacy field — some backends expect `transactionId` */
86
+ transactionId?: string;
87
+ /** Backend payment-links uses `transactionRef` as the identifier */
88
+ transactionRef?: string;
89
+ eciFlag?: string;
90
+ organizationId: string;
91
+ }
92
+ export interface ValidateOTPResponse {
93
+ status: string;
94
+ message: string;
95
+ paymentId: string;
96
+ transactionRef?: string;
97
+ amount?: number;
98
+ currency?: string;
99
+ [key: string]: unknown;
100
+ }
101
+ export interface ResendOTPRequest {
102
+ transactionRef: string;
103
+ organizationId: string;
104
+ }
105
+ export declare class VoxePayApiClient {
106
+ private apiKey?;
107
+ private bearerToken?;
108
+ private baseUrl;
109
+ constructor(apiKey?: string, baseUrl?: string, bearerToken?: string);
110
+ /**
111
+ * Set Bearer token for authenticated endpoints (like getPaymentStatus)
112
+ */
113
+ setBearerToken(token: string): void;
114
+ private request;
115
+ private get;
116
+ /**
117
+ * Initiate payment (card or bank transfer) via public payment-link endpoint.
118
+ */
119
+ initiatePayment(paymentLinkSlug: string, data: InitiatePaymentRequest): Promise<InitiatePaymentResponse>;
120
+ /**
121
+ * @deprecated Use initiatePayment with a paymentLinkSlug instead.
122
+ */
123
+ initiateTransferPayment(paymentLinkSlug: string, data: InitiatePaymentRequest): Promise<InitiatePaymentResponse>;
124
+ /**
125
+ * Validate OTP for a payment
126
+ * @param slug - The payment link slug
127
+ * @param data - OTP validation payload
128
+ */
129
+ validateOTP(slug: string, data: ValidateOTPRequest): Promise<ValidateOTPResponse>;
130
+ /**
131
+ * Resend OTP for a payment
132
+ * @param slug - The payment link slug
133
+ * @param data - Resend OTP payload
134
+ */
135
+ resendOTP(slug: string, data: ResendOTPRequest): Promise<void>;
136
+ /**
137
+ * Get payment status by transaction reference (used for polling DVA payments)
138
+ * Uses public endpoint - no authentication required
139
+ * @param transactionRef - The transaction reference to check
140
+ * @param options - Optional query parameters (simulateWebhook, bypassKey)
141
+ */
142
+ getPaymentStatus(transactionRef: string, options?: {
143
+ simulateWebhook?: boolean;
144
+ bypassKey?: string;
145
+ }): Promise<PaymentStatusResponse>;
146
+ }
@@ -0,0 +1,190 @@
1
+ /**
2
+ * VoxePay Checkout Modal Component
3
+ * A modern, glassmorphism payment modal
4
+ */
5
+ import type { CheckoutOptions, BankTransferDetails, PaymentMethod } from '../types';
6
+ export interface ModalState {
7
+ cardNumber: string;
8
+ expiry: string;
9
+ cvv: string;
10
+ pin: string;
11
+ otp: string;
12
+ errors: {
13
+ cardNumber?: string;
14
+ expiry?: string;
15
+ cvv?: string;
16
+ pin?: string;
17
+ otp?: string;
18
+ };
19
+ isProcessing: boolean;
20
+ isSuccess: boolean;
21
+ isOtpStep: boolean;
22
+ otpTimer: number;
23
+ canResendOtp: boolean;
24
+ otpTimerInterval: number | null;
25
+ paymentMethod: PaymentMethod;
26
+ transferTimer: number;
27
+ transferTimerInterval: number | null;
28
+ bankTransferDetails: BankTransferDetails | null;
29
+ paymentId: string | null;
30
+ transactionId: string | null;
31
+ transactionRef: string | null;
32
+ eciFlag: string | null;
33
+ otpDeliveryMessage: string | null;
34
+ feeDetails?: {
35
+ transactionFee: number;
36
+ transactionFeeVat: number;
37
+ totalFees: number;
38
+ grossAmount: number;
39
+ currency: string;
40
+ };
41
+ }
42
+ export declare class VoxePayModal {
43
+ private options;
44
+ private state;
45
+ private container;
46
+ private overlay;
47
+ private apiClient;
48
+ constructor(options: CheckoutOptions);
49
+ /**
50
+ * Open the checkout modal
51
+ */
52
+ open(): void;
53
+ /**
54
+ * Close the checkout modal
55
+ */
56
+ close(): void;
57
+ /**
58
+ * Inject styles if not already present
59
+ */
60
+ private injectStyles;
61
+ /**
62
+ * Render the modal HTML
63
+ */
64
+ private render;
65
+ /**
66
+ * Get available payment methods
67
+ */
68
+ private getPaymentMethods;
69
+ /**
70
+ * Get modal HTML
71
+ */
72
+ private getModalHTML;
73
+ /**
74
+ * Get card form HTML
75
+ */
76
+ private getCardFormHTML;
77
+ /**
78
+ * Get bank transfer HTML
79
+ */
80
+ private getBankTransferHTML;
81
+ /**
82
+ * Format countdown seconds to MM:SS
83
+ */
84
+ private formatCountdown;
85
+ /**
86
+ * Render success view
87
+ */
88
+ private renderSuccessView;
89
+ /**
90
+ * Render error modal view
91
+ */
92
+ private renderErrorModal;
93
+ /**
94
+ * Show error — inline for field errors, modal for fatal errors
95
+ */
96
+ private showErrorModal;
97
+ /**
98
+ * Render OTP verification view
99
+ */
100
+ private renderOTPView;
101
+ /**
102
+ * Attach OTP-specific event listeners
103
+ */
104
+ private attachOTPEventListeners;
105
+ private handleOTPInput;
106
+ private handleOTPKeydown;
107
+ private handleOTPPaste;
108
+ private updateOTPState;
109
+ private startOTPTimer;
110
+ private handleOTPSubmit;
111
+ private setOTPProcessing;
112
+ private verifyOTP;
113
+ private handleResendOTP;
114
+ private handleBackToCard;
115
+ /**
116
+ * Attach event listeners
117
+ */
118
+ private attachEventListeners;
119
+ /**
120
+ * Attach bank transfer specific event listeners
121
+ */
122
+ private attachBankTransferListeners;
123
+ /**
124
+ * Switch between payment methods
125
+ */
126
+ private switchPaymentMethod;
127
+ /**
128
+ * Load bank transfer details (from callback or via API)
129
+ */
130
+ private loadBankTransferDetails;
131
+ /**
132
+ * Get user-friendly error title for DVA error codes
133
+ */
134
+ private getDVAErrorTitle;
135
+ /**
136
+ * Copy text to clipboard with visual feedback
137
+ */
138
+ private copyToClipboard;
139
+ /** Polling interval ID for DVA status checks */
140
+ private statusPollingInterval;
141
+ /** Polling timeout (auto-stop after 30 minutes) */
142
+ private statusPollingTimeout;
143
+ /**
144
+ * Handle "I've sent the money" confirmation — starts polling for payment status
145
+ */
146
+ private handleTransferConfirm;
147
+ /**
148
+ * Render the "waiting for payment confirmation" polling view
149
+ */
150
+ private renderPollingView;
151
+ /**
152
+ * Start polling payment status every 5 seconds
153
+ */
154
+ private startStatusPolling;
155
+ /**
156
+ * Stop payment status polling
157
+ */
158
+ private stopStatusPolling;
159
+ /**
160
+ * Handle status updates from polling
161
+ */
162
+ private handlePollingStatusUpdate;
163
+ /**
164
+ * Render error view for transfer issues with retry option
165
+ */
166
+ private renderTransferErrorView;
167
+ /**
168
+ * Start the transfer countdown timer
169
+ */
170
+ private startTransferTimer;
171
+ /**
172
+ * Stop the transfer countdown timer
173
+ */
174
+ private stopTransferTimer;
175
+ private handleEscape;
176
+ private handleCardInput;
177
+ private handleExpiryInput;
178
+ private handleCVVInput;
179
+ private handlePinInput;
180
+ private validateField;
181
+ private showError;
182
+ private clearError;
183
+ private handleSubmit;
184
+ private setProcessing;
185
+ private processPayment;
186
+ /**
187
+ * Get VoxePay branded styles
188
+ */
189
+ private getStyles;
190
+ }