@voxepay/checkout 0.5.0 → 0.5.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/src/api/client.ts CHANGED
@@ -119,16 +119,21 @@ export class VoxePayApiClient {
119
119
  this.bearerToken = token;
120
120
  }
121
121
 
122
- private async request<T>(endpoint: string, body: unknown): Promise<T> {
122
+ private async request<T>(endpoint: string, body: unknown, includeApiKey = true): Promise<T> {
123
123
  const url = `${this.baseUrl}${endpoint}`;
124
124
 
125
+ const headers: Record<string, string> = {
126
+ 'Content-Type': 'application/json',
127
+ 'Accept': 'application/json',
128
+ };
129
+
130
+ if (includeApiKey) {
131
+ headers['X-API-Key'] = this.apiKey;
132
+ }
133
+
125
134
  const response = await fetch(url, {
126
135
  method: 'POST',
127
- headers: {
128
- 'Content-Type': 'application/json',
129
- 'X-API-Key': this.apiKey,
130
- 'Accept': 'application/json',
131
- },
136
+ headers,
132
137
  body: JSON.stringify(body),
133
138
  });
134
139
 
@@ -146,18 +151,19 @@ export class VoxePayApiClient {
146
151
  return data as T;
147
152
  }
148
153
 
149
- private async get<T>(endpoint: string, useBearerAuth = false): Promise<T> {
154
+ private async get<T>(endpoint: string, authType: 'api-key' | 'bearer' | 'none' = 'api-key'): Promise<T> {
150
155
  const url = `${this.baseUrl}${endpoint}`;
151
156
 
152
157
  const headers: Record<string, string> = {
153
158
  'Accept': 'application/json',
154
159
  };
155
160
 
156
- if (useBearerAuth && this.bearerToken) {
161
+ if (authType === 'bearer' && this.bearerToken) {
157
162
  headers['Authorization'] = `Bearer ${this.bearerToken}`;
158
- } else {
163
+ } else if (authType === 'api-key') {
159
164
  headers['X-API-Key'] = this.apiKey;
160
165
  }
166
+ // authType === 'none' → no auth header added
161
167
 
162
168
  const response = await fetch(url, {
163
169
  method: 'GET',
@@ -181,11 +187,15 @@ export class VoxePayApiClient {
181
187
 
182
188
  /**
183
189
  * Initiate a payment (card or bank transfer)
190
+ * BANK_TRANSFER uses the public endpoint — no X-API-Key required
191
+ * CARD uses X-API-Key authentication
184
192
  */
185
193
  async initiatePayment(data: InitiatePaymentRequest): Promise<InitiatePaymentResponse> {
194
+ const includeApiKey = data.paymentMethod !== 'BANK_TRANSFER';
186
195
  const response = await this.request<{ success?: boolean; data?: InitiatePaymentResponse } & InitiatePaymentResponse>(
187
196
  '/api/v1/payments/initiate',
188
- data
197
+ data,
198
+ includeApiKey
189
199
  );
190
200
  // Handle both wrapped { success, data: {...} } and flat response formats
191
201
  if (response.data && typeof response.data === 'object' && 'transactionRef' in response.data) {
@@ -234,7 +244,7 @@ export class VoxePayApiClient {
234
244
 
235
245
  const response = await this.get<{ success: boolean; message: string; data: PaymentStatusResponse; errorCode?: string }>(
236
246
  endpoint,
237
- false // Use X-API-Key (public endpoint doesn't need Bearer token)
247
+ 'none' // Public endpoint no auth required
238
248
  );
239
249
 
240
250
  if (!response.success) {
@@ -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;