@voxepay/checkout 0.4.0 → 0.5.1

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/src/api/client.ts CHANGED
@@ -55,15 +55,27 @@ export type DVAPaymentStatus =
55
55
  export interface PaymentStatusResponse {
56
56
  id: string;
57
57
  transactionRef: string;
58
- status: DVAPaymentStatus;
58
+ customerId?: string;
59
59
  amount: number;
60
- paymentMethod: string;
60
+ currency: string;
61
+ paymentMethod: 'CARD' | 'BANK_TRANSFER';
62
+ status: DVAPaymentStatus;
63
+ paymentId?: string;
64
+ otpRequired?: boolean;
65
+ authorizationUrl?: string;
66
+ message?: string;
67
+ otpAttempts?: number;
68
+ maxOtpAttempts?: number;
69
+ createdAt: string;
61
70
  completedAt?: string;
62
71
  virtualAccount?: {
63
72
  account_number: string;
73
+ account_name: string;
74
+ bank_name: string;
75
+ bank_code: string;
76
+ expires_at: string;
64
77
  status: string;
65
78
  };
66
- [key: string]: unknown;
67
79
  }
68
80
 
69
81
  export interface ValidateOTPRequest {
@@ -91,13 +103,22 @@ export interface ResendOTPRequest {
91
103
 
92
104
  export class VoxePayApiClient {
93
105
  private apiKey: string;
106
+ private bearerToken?: string;
94
107
  private baseUrl: string;
95
108
 
96
- constructor(apiKey: string, baseUrl?: string) {
109
+ constructor(apiKey: string, baseUrl?: string, bearerToken?: string) {
97
110
  this.apiKey = apiKey;
111
+ this.bearerToken = bearerToken;
98
112
  this.baseUrl = baseUrl || DEFAULT_BASE_URL;
99
113
  }
100
114
 
115
+ /**
116
+ * Set Bearer token for authenticated endpoints (like getPaymentStatus)
117
+ */
118
+ setBearerToken(token: string): void {
119
+ this.bearerToken = token;
120
+ }
121
+
101
122
  private async request<T>(endpoint: string, body: unknown): Promise<T> {
102
123
  const url = `${this.baseUrl}${endpoint}`;
103
124
 
@@ -125,15 +146,22 @@ export class VoxePayApiClient {
125
146
  return data as T;
126
147
  }
127
148
 
128
- private async get<T>(endpoint: string): Promise<T> {
149
+ private async get<T>(endpoint: string, useBearerAuth = false): Promise<T> {
129
150
  const url = `${this.baseUrl}${endpoint}`;
130
151
 
152
+ const headers: Record<string, string> = {
153
+ 'Accept': 'application/json',
154
+ };
155
+
156
+ if (useBearerAuth && this.bearerToken) {
157
+ headers['Authorization'] = `Bearer ${this.bearerToken}`;
158
+ } else {
159
+ headers['X-API-Key'] = this.apiKey;
160
+ }
161
+
131
162
  const response = await fetch(url, {
132
163
  method: 'GET',
133
- headers: {
134
- 'X-API-Key': this.apiKey,
135
- 'Accept': 'application/json',
136
- },
164
+ headers,
137
165
  });
138
166
 
139
167
  const data = await response.json();
@@ -144,6 +172,7 @@ export class VoxePayApiClient {
144
172
  error.code = data?.errorCode || data?.code || `HTTP_${response.status}`;
145
173
  error.status = response.status;
146
174
  error.data = data;
175
+ error.success = data?.success;
147
176
  throw error;
148
177
  }
149
178
 
@@ -181,11 +210,40 @@ export class VoxePayApiClient {
181
210
 
182
211
  /**
183
212
  * Get payment status by transaction reference (used for polling DVA payments)
213
+ * Uses public endpoint - no authentication required
214
+ * @param transactionRef - The transaction reference to check
215
+ * @param options - Optional query parameters (simulateWebhook, bypassKey)
184
216
  */
185
- async getPaymentStatus(transactionRef: string): Promise<PaymentStatusResponse> {
186
- const response = await this.get<{ success: boolean; data: PaymentStatusResponse }>(
187
- `/api/v1/payments/${encodeURIComponent(transactionRef)}`
217
+ async getPaymentStatus(
218
+ transactionRef: string,
219
+ options?: { simulateWebhook?: boolean; bypassKey?: string }
220
+ ): Promise<PaymentStatusResponse> {
221
+ let endpoint = `/api/v1/payments/public/${encodeURIComponent(transactionRef)}`;
222
+
223
+ // Add query parameters if provided
224
+ const queryParams: string[] = [];
225
+ if (options?.simulateWebhook !== undefined) {
226
+ queryParams.push(`simulateWebhook=${options.simulateWebhook}`);
227
+ }
228
+ if (options?.bypassKey) {
229
+ queryParams.push(`bypassKey=${encodeURIComponent(options.bypassKey)}`);
230
+ }
231
+ if (queryParams.length > 0) {
232
+ endpoint += `?${queryParams.join('&')}`;
233
+ }
234
+
235
+ const response = await this.get<{ success: boolean; message: string; data: PaymentStatusResponse; errorCode?: string }>(
236
+ endpoint,
237
+ false // Use X-API-Key (public endpoint doesn't need Bearer token)
188
238
  );
239
+
240
+ if (!response.success) {
241
+ const error: any = new Error(response.message || 'Payment not found');
242
+ error.code = response.errorCode || 'PAYMENT_NOT_FOUND';
243
+ error.success = false;
244
+ throw error;
245
+ }
246
+
189
247
  return response.data;
190
248
  }
191
249
  }
@@ -999,7 +999,13 @@ export class VoxePayModal {
999
999
  if (!this.apiClient || !this.state.transactionRef) return;
1000
1000
 
1001
1001
  try {
1002
- const statusData = await this.apiClient.getPaymentStatus(this.state.transactionRef);
1002
+ const statusData = await this.apiClient.getPaymentStatus(
1003
+ this.state.transactionRef,
1004
+ {
1005
+ simulateWebhook: this.options._sdkConfig?.simulateWebhook,
1006
+ bypassKey: this.options._sdkConfig?.bypassKey,
1007
+ }
1008
+ );
1003
1009
  this.handlePollingStatusUpdate(statusData.status, statusData);
1004
1010
  } catch (error: any) {
1005
1011
  console.error('[VoxePay] Status polling error:', error);
package/src/types.ts CHANGED
@@ -18,6 +18,16 @@ export interface VoxePayConfig {
18
18
  locale?: string;
19
19
  /** Custom CSS variables to override default theme */
20
20
  customStyles?: Partial<VoxePayTheme>;
21
+ /**
22
+ * Simulate webhook on payment status polling (useful for testing in dev/sandbox).
23
+ * When true, the API will trigger a simulated webhook on each status check.
24
+ */
25
+ simulateWebhook?: boolean;
26
+ /**
27
+ * Bypass key required when simulateWebhook is true.
28
+ * Only needed in sandbox/testing environments.
29
+ */
30
+ bypassKey?: string;
21
31
  }
22
32
 
23
33
  /**
@@ -83,6 +93,8 @@ export interface CheckoutOptions {
83
93
  apiKey: string;
84
94
  organizationId: string;
85
95
  baseUrl?: string;
96
+ simulateWebhook?: boolean;
97
+ bypassKey?: string;
86
98
  };
87
99
  /** Callback when payment succeeds */
88
100
  onSuccess: (result: PaymentResult) => void;
package/src/voxepay.ts CHANGED
@@ -109,6 +109,8 @@ class VoxePaySDK {
109
109
  apiKey: this.config!.apiKey,
110
110
  organizationId: this.config!.organizationId,
111
111
  baseUrl: this.config!.baseUrl,
112
+ simulateWebhook: this.config!.simulateWebhook,
113
+ bypassKey: this.config!.bypassKey,
112
114
  },
113
115
  onClose: () => {
114
116
  this.currentModal = null;