@verapay/verapay-js 0.0.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/LICENSE +21 -0
- package/README.md +377 -0
- package/dist/index.cjs +3 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +202 -0
- package/dist/index.d.ts +202 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/package.json +60 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,377 @@
|
|
|
1
|
+
# verapay-js
|
|
2
|
+
|
|
3
|
+
A simple, PCI-compliant TypeScript SDK for Stripe payment processing.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- 🔒 **PCI Compliant**: Uses Stripe.js and Elements for secure tokenization
|
|
8
|
+
- 📘 **TypeScript First**: Full TypeScript support with comprehensive type definitions
|
|
9
|
+
- 🎨 **Customizable**: Flexible styling and layout options
|
|
10
|
+
- ✅ **Validation**: Built-in card validation and error handling
|
|
11
|
+
- 🔐 **3D Secure**: Automatic 3D Secure (SCA) support
|
|
12
|
+
- 🧩 **Extensible**: Plugin architecture for future server-side operations
|
|
13
|
+
- 🌳 **Tree-shakable**: ES Module format for optimal bundle sizes
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install verapay-js
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Quick Start
|
|
22
|
+
|
|
23
|
+
### 1. Set up your backend
|
|
24
|
+
|
|
25
|
+
Create an endpoint to create payment intents:
|
|
26
|
+
|
|
27
|
+
```typescript
|
|
28
|
+
// Backend (Node.js/Express example)
|
|
29
|
+
app.post('/api/payment-intent', async (req, res) => {
|
|
30
|
+
const { amount, currency } = req.body;
|
|
31
|
+
|
|
32
|
+
const paymentIntent = await stripe.paymentIntents.create({
|
|
33
|
+
amount,
|
|
34
|
+
currency,
|
|
35
|
+
automatic_payment_methods: { enabled: true },
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
res.json({ clientSecret: paymentIntent.client_secret });
|
|
39
|
+
});
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### 2. Initialize the SDK and mount the payment form
|
|
43
|
+
|
|
44
|
+
First, get a client secret from your backend, then initialize the SDK and mount the form:
|
|
45
|
+
|
|
46
|
+
```typescript
|
|
47
|
+
import { VerapayClient } from 'verapay-js';
|
|
48
|
+
|
|
49
|
+
// Get client secret from your backend
|
|
50
|
+
const { clientSecret } = await fetch('/api/create-payment-intent', {
|
|
51
|
+
method: 'POST',
|
|
52
|
+
headers: { 'Content-Type': 'application/json' },
|
|
53
|
+
body: JSON.stringify({ amount: 5000, currency: 'usd' })
|
|
54
|
+
}).then(r => r.json());
|
|
55
|
+
|
|
56
|
+
// Initialize with the client secret
|
|
57
|
+
const verapay = new VerapayClient({
|
|
58
|
+
stripePublishableKey: 'pk_test_...',
|
|
59
|
+
clientSecret: clientSecret,
|
|
60
|
+
serverConfig: {
|
|
61
|
+
apiUrl: 'https://your-backend.com/api',
|
|
62
|
+
apiKey: 'your-api-key', // Optional
|
|
63
|
+
},
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
// Mount the payment form
|
|
67
|
+
await verapay.mountPaymentForm('#payment-form');
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### 3. Process payment
|
|
71
|
+
|
|
72
|
+
```typescript
|
|
73
|
+
try {
|
|
74
|
+
const result = await verapay.processPayment({
|
|
75
|
+
amount: 5000, // $50.00 in cents
|
|
76
|
+
currency: 'usd',
|
|
77
|
+
description: 'Order #12345',
|
|
78
|
+
returnUrl: 'https://yoursite.com/payment/complete',
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
if (result.requiresAction) {
|
|
82
|
+
// 3D Secure authentication required
|
|
83
|
+
const confirmed = await verapay.confirmPayment(result.clientSecret);
|
|
84
|
+
console.log('Payment confirmed:', confirmed);
|
|
85
|
+
} else {
|
|
86
|
+
console.log('Payment succeeded:', result);
|
|
87
|
+
}
|
|
88
|
+
} catch (error) {
|
|
89
|
+
if (error instanceof ValidationError) {
|
|
90
|
+
console.error('Validation error:', error.details.formattedMessage);
|
|
91
|
+
} else if (error instanceof PaymentError) {
|
|
92
|
+
console.error('Payment failed:', error.details.formattedMessage);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Advanced Usage
|
|
98
|
+
|
|
99
|
+
### Custom Elements Layout
|
|
100
|
+
|
|
101
|
+
Mount individual card elements for custom layouts:
|
|
102
|
+
|
|
103
|
+
```html
|
|
104
|
+
<div id="card-number"></div>
|
|
105
|
+
<div id="card-expiry"></div>
|
|
106
|
+
<div id="card-cvc"></div>
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
```typescript
|
|
110
|
+
// Get client secret first
|
|
111
|
+
const { clientSecret } = await fetch('/api/create-payment-intent').then(r => r.json());
|
|
112
|
+
|
|
113
|
+
const verapay = new VerapayClient({
|
|
114
|
+
stripePublishableKey: 'pk_test_...',
|
|
115
|
+
clientSecret: clientSecret,
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
await verapay.mountCardNumber('#card-number');
|
|
119
|
+
await verapay.mountCardExpiry('#card-expiry');
|
|
120
|
+
await verapay.mountCardCvc('#card-cvc');
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### Create Payment Method
|
|
124
|
+
|
|
125
|
+
Create a reusable payment method from the card details:
|
|
126
|
+
|
|
127
|
+
```typescript
|
|
128
|
+
try {
|
|
129
|
+
// Create a payment method
|
|
130
|
+
const paymentMethodId = await verapay.createPaymentMethod();
|
|
131
|
+
|
|
132
|
+
// Send to your backend to attach to a customer or create a payment
|
|
133
|
+
await fetch('/api/save-payment-method', {
|
|
134
|
+
method: 'POST',
|
|
135
|
+
body: JSON.stringify({ paymentMethodId }),
|
|
136
|
+
});
|
|
137
|
+
} catch (error) {
|
|
138
|
+
console.error('Failed to create payment method:', error);
|
|
139
|
+
}
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### Validation
|
|
143
|
+
|
|
144
|
+
Validate the payment form before processing:
|
|
145
|
+
|
|
146
|
+
```typescript
|
|
147
|
+
const validation = await verapay.validatePaymentForm();
|
|
148
|
+
if (!validation.isValid) {
|
|
149
|
+
console.error('Invalid form:', validation.errors);
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### Styling Individual Form Elements
|
|
155
|
+
|
|
156
|
+
> This section applies only when mounting individual form elements (`mountCardNumber`, `mountCardExpiry`, `mountCardCvc`). It does not apply to `mountPaymentForm`.
|
|
157
|
+
|
|
158
|
+
The SDK ships with a default style for card fields that works out of the box — no configuration required. If you want to match your own design, pass `elementsConfig` to override specific properties.
|
|
159
|
+
|
|
160
|
+
#### Default appearance
|
|
161
|
+
|
|
162
|
+
```typescript
|
|
163
|
+
const verapay = new VerapayClient({
|
|
164
|
+
merchantId: 'your-merchant-id',
|
|
165
|
+
paymentData: { amount: 5000, currency: 'gbp' },
|
|
166
|
+
// no elementsConfig needed — sensible defaults are applied automatically
|
|
167
|
+
});
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
#### Overriding styles
|
|
171
|
+
|
|
172
|
+
Pass only the properties you want to change. Your values are merged with the defaults, so unspecified properties are preserved.
|
|
173
|
+
|
|
174
|
+
```typescript
|
|
175
|
+
const verapay = new VerapayClient({
|
|
176
|
+
merchantId: 'your-merchant-id',
|
|
177
|
+
paymentData: { amount: 5000, currency: 'gbp' },
|
|
178
|
+
elementsConfig: {
|
|
179
|
+
style: {
|
|
180
|
+
base: {
|
|
181
|
+
color: '#1a1a1a',
|
|
182
|
+
fontSize: '14px',
|
|
183
|
+
},
|
|
184
|
+
complete: {
|
|
185
|
+
color: '#30a46c', // applied when the field has valid, complete input defaults to black
|
|
186
|
+
},
|
|
187
|
+
empty: {
|
|
188
|
+
// applied when the field has no input
|
|
189
|
+
},
|
|
190
|
+
invalid: {
|
|
191
|
+
color: '#ff4d4f', // applied when the field has invalid input
|
|
192
|
+
},
|
|
193
|
+
},
|
|
194
|
+
placeholders: {
|
|
195
|
+
cardNumber: '1234 1234 1234 1234',
|
|
196
|
+
cardExpiry: 'MM / YY',
|
|
197
|
+
cardCvc: 'CVC',
|
|
198
|
+
},
|
|
199
|
+
iconStyle: 'default', // 'default' | 'solid' — defaults to 'solid'
|
|
200
|
+
showIcon: true, // defaults to true
|
|
201
|
+
},
|
|
202
|
+
});
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
#### Container styling
|
|
206
|
+
|
|
207
|
+
The card field containers are standard `div` elements in your page — style them with your own CSS:
|
|
208
|
+
|
|
209
|
+
```css
|
|
210
|
+
.card-field {
|
|
211
|
+
border: 1px solid #e0e0e0;
|
|
212
|
+
border-radius: 4px;
|
|
213
|
+
padding: 12px;
|
|
214
|
+
background: white;
|
|
215
|
+
}
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
#### Custom fonts
|
|
219
|
+
|
|
220
|
+
Stripe Elements run inside sandboxed iframes and cannot access fonts loaded on your page. To use a custom font, pass it via `fonts` and reference it in `elementsConfig.style.base.fontFamily`:
|
|
221
|
+
|
|
222
|
+
```typescript
|
|
223
|
+
const verapay = new VerapayClient({
|
|
224
|
+
merchantId: 'your-merchant-id',
|
|
225
|
+
paymentData: { amount: 5000, currency: 'gbp' },
|
|
226
|
+
fonts: [
|
|
227
|
+
{ cssSrc: 'https://fonts.googleapis.com/css?family=Inter' },
|
|
228
|
+
],
|
|
229
|
+
elementsConfig: {
|
|
230
|
+
style: {
|
|
231
|
+
base: { fontFamily: 'Inter, sans-serif' },
|
|
232
|
+
},
|
|
233
|
+
},
|
|
234
|
+
});
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
## Error Handling
|
|
238
|
+
|
|
239
|
+
The SDK provides user-friendly error messages:
|
|
240
|
+
|
|
241
|
+
```typescript
|
|
242
|
+
import {
|
|
243
|
+
VerapayError,
|
|
244
|
+
ValidationError,
|
|
245
|
+
PaymentError,
|
|
246
|
+
ErrorFormatter
|
|
247
|
+
} from 'verapay-js';
|
|
248
|
+
|
|
249
|
+
try {
|
|
250
|
+
await verapay.processPayment(request);
|
|
251
|
+
} catch (error) {
|
|
252
|
+
if (error instanceof ValidationError) {
|
|
253
|
+
// Field validation error
|
|
254
|
+
console.log(error.details.field); // e.g., 'amount'
|
|
255
|
+
console.log(error.details.formattedMessage); // User-friendly message
|
|
256
|
+
} else if (error instanceof PaymentError) {
|
|
257
|
+
// Payment processing error
|
|
258
|
+
console.log(error.details.code); // e.g., 'CARD_DECLINED'
|
|
259
|
+
console.log(error.details.stripeCode); // Original Stripe code
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// Format for display
|
|
263
|
+
const userMessage = ErrorFormatter.formatForUser(error);
|
|
264
|
+
alert(userMessage);
|
|
265
|
+
}
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
## TypeScript Support
|
|
269
|
+
|
|
270
|
+
Full TypeScript support with comprehensive type definitions:
|
|
271
|
+
|
|
272
|
+
```typescript
|
|
273
|
+
import type {
|
|
274
|
+
VerapayConfig,
|
|
275
|
+
PaymentRequest,
|
|
276
|
+
PaymentResult,
|
|
277
|
+
PaymentConfirmation,
|
|
278
|
+
ValidationResult,
|
|
279
|
+
CardValidation,
|
|
280
|
+
ErrorCode,
|
|
281
|
+
} from 'verapay-js';
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
## Extension Architecture
|
|
285
|
+
|
|
286
|
+
The SDK supports extensions for future server-side operations:
|
|
287
|
+
|
|
288
|
+
```typescript
|
|
289
|
+
import type { ServerExtension } from 'verapay-js';
|
|
290
|
+
|
|
291
|
+
const analyticsExtension: ServerExtension = {
|
|
292
|
+
name: 'analytics',
|
|
293
|
+
version: '1.0.0',
|
|
294
|
+
|
|
295
|
+
async beforePayment(request) {
|
|
296
|
+
// Track payment attempt
|
|
297
|
+
return request;
|
|
298
|
+
},
|
|
299
|
+
|
|
300
|
+
async afterPayment(result) {
|
|
301
|
+
// Track payment success
|
|
302
|
+
},
|
|
303
|
+
|
|
304
|
+
async onPaymentError(error) {
|
|
305
|
+
// Track payment failure
|
|
306
|
+
},
|
|
307
|
+
};
|
|
308
|
+
|
|
309
|
+
verapay.addExtension(analyticsExtension);
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
## Testing with Stripe
|
|
313
|
+
|
|
314
|
+
Use Stripe's test cards:
|
|
315
|
+
|
|
316
|
+
- **Successful payment**: `4242 4242 4242 4242`
|
|
317
|
+
- **3D Secure required**: `4000 0027 6000 3184`
|
|
318
|
+
- **Declined**: `4000 0000 0000 0002`
|
|
319
|
+
|
|
320
|
+
[Full list of test cards](https://stripe.com/docs/testing)
|
|
321
|
+
|
|
322
|
+
## Browser Support
|
|
323
|
+
|
|
324
|
+
- Chrome (latest)
|
|
325
|
+
- Firefox (latest)
|
|
326
|
+
- Safari (latest)
|
|
327
|
+
- Edge (latest)
|
|
328
|
+
|
|
329
|
+
## Security & PCI Compliance
|
|
330
|
+
|
|
331
|
+
This SDK maintains PCI compliance by:
|
|
332
|
+
|
|
333
|
+
1. **Never touching raw card data**: All card input is handled by Stripe Elements (isolated iframes)
|
|
334
|
+
2. **Tokenization**: Card data is tokenized by Stripe.js before reaching your code
|
|
335
|
+
3. **No storage**: SDK never stores or transmits raw card details
|
|
336
|
+
|
|
337
|
+
Your application needs to:
|
|
338
|
+
- Use HTTPS in production
|
|
339
|
+
- Implement backend validation
|
|
340
|
+
- Follow Stripe's security best practices
|
|
341
|
+
|
|
342
|
+
## API Reference
|
|
343
|
+
|
|
344
|
+
### VerapayClient
|
|
345
|
+
|
|
346
|
+
#### Constructor
|
|
347
|
+
|
|
348
|
+
```typescript
|
|
349
|
+
new VerapayClient(config: VerapayConfig)
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
#### Methods
|
|
353
|
+
|
|
354
|
+
- `initialize(): Promise<void>` - Initialize Stripe.js
|
|
355
|
+
- `mountPaymentForm(selector: string): Promise<void>` - Mount complete payment form
|
|
356
|
+
- `mountCardNumber(selector: string): Promise<void>` - Mount card number field
|
|
357
|
+
- `mountCardExpiry(selector: string): Promise<void>` - Mount expiry date field
|
|
358
|
+
- `mountCardCvc(selector: string): Promise<void>` - Mount CVC field
|
|
359
|
+
- `validatePaymentForm(): Promise<ValidationResult>` - Validate form
|
|
360
|
+
- `createPaymentMethod(): Promise<string>` - Create a payment method and return its ID
|
|
361
|
+
- `processPayment(request: PaymentRequest): Promise<PaymentResult>` - Process payment
|
|
362
|
+
- `confirmPayment(clientSecret: string): Promise<PaymentConfirmation>` - Confirm 3DS
|
|
363
|
+
- `addExtension(extension: ServerExtension): void` - Add extension
|
|
364
|
+
|
|
365
|
+
## License
|
|
366
|
+
|
|
367
|
+
MIT
|
|
368
|
+
|
|
369
|
+
## Support
|
|
370
|
+
|
|
371
|
+
For issues and questions:
|
|
372
|
+
- [GitHub Issues](https://github.com/your-org/verapay-js/issues)
|
|
373
|
+
- [Stripe Documentation](https://stripe.com/docs)
|
|
374
|
+
|
|
375
|
+
## Contributing
|
|
376
|
+
|
|
377
|
+
Contributions are welcome! Please read our contributing guidelines.
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
'use strict';var stripeJs=require('@stripe/stripe-js'),tsMoney=require('ts-money');var i=class s extends Error{constructor(e,t="PAYMENT_FAILED",r){super(e),this.name="VerapayError",this.code=t,this.details={code:t,message:e,formattedMessage:this.formatMessage(e,t),...r},Error.captureStackTrace&&Error.captureStackTrace(this,s);}formatMessage(e,t){return {VALIDATION_ERROR:"Please check your payment information and try again.",PAYMENT_FAILED:"Your payment could not be processed. Please try again.",AUTHENTICATION_FAILED:"Payment authentication failed. Please try again.",NETWORK_ERROR:"Network error. Please check your connection and try again.",STRIPE_ERROR:"Payment service error. Please try again later.",CONFIGURATION_ERROR:"Configuration error. Please contact support.",CARD_DECLINED:"Your card was declined. Please use a different payment method.",INSUFFICIENT_FUNDS:"Insufficient funds. Please use a different payment method.",EXPIRED_CARD:"Your card has expired. Please use a different payment method."}[t]||e}toJSON(){return {name:this.name,code:this.code,message:this.message,details:this.details}}};var l=class extends i{constructor(e,t,r){super(e,"VALIDATION_ERROR",{field:t,metadata:r}),this.name="ValidationError";}};var m=class s extends i{constructor(e,t,r){let n=s.mapStripeCode(t);super(e,n,{stripeCode:t,metadata:r}),this.name="PaymentError";}static mapStripeCode(e){return e?{card_declined:"CARD_DECLINED",insufficient_funds:"INSUFFICIENT_FUNDS",expired_card:"EXPIRED_CARD",incorrect_cvc:"VALIDATION_ERROR",processing_error:"PAYMENT_FAILED",authentication_failed:"AUTHENTICATION_FAILED"}[e]||"PAYMENT_FAILED":"PAYMENT_FAILED"}};var y=class{static formatForUser(e){return "formattedMessage"in e?e.formattedMessage:"details"in e&&e.details&&typeof e.details=="object"&&"formattedMessage"in e.details&&typeof e.details.formattedMessage=="string"?e.details.formattedMessage:"An unexpected error occurred. Please try again."}static formatForDeveloper(e){return "code"in e&&"message"in e?`[${e.code}] ${e.message}`:e.message||"Unknown error"}static toJSON(e){return "toJSON"in e&&typeof e.toJSON=="function"?e.toJSON():{name:e.name||"Error",message:e.message,..."code"in e&&{code:e.code},..."details"in e&&{details:e.details}}}};var u=class{constructor(e){this.stripe=e;}async confirmPayment(e,t,r){let n=await this.stripe.confirmPayment({clientSecret:t,confirmParams:{payment_method:e,return_url:r||window.location.href},redirect:"if_required"});if(n.error)throw new m(n.error.message||"Payment failed",n.error.code);return n}async confirmCardPayment(e,t){let r=await this.stripe.confirmCardPayment(t,{payment_method:e});if(r.error)throw new m(r.error.message||"Payment failed",r.error.code);return r}async createPaymentMethod(e,t=false){let r;if(!t)r=await this.stripe.createPaymentMethod({elements:e});else {let a=(await e.getElement("address",{mode:"billing"}).getValue()).value;r=await this.stripe.createPaymentMethod({type:"card",card:e.getElement("cardNumber"),billing_details:{name:a.name,address:{...a.address,line2:a.address.line2??void 0}}});}if(r.error||!r.paymentMethod)throw new m(r.error?.message||"Failed to create payment method",r.error?.code);return r.paymentMethod.id}};var d={showIcon:true,iconStyle:"solid",placeholders:{cardNumber:"1234 1234 1234 1234",cardExpiry:"MM / YY",cardCvc:"CVC"},style:{base:{color:"#333333",fontFamily:"system-ui, -apple-system, sans-serif",fontSize:"16px","::placeholder":{color:"#aab7c4"}},complete:{color:"#333333"},empty:{},invalid:{color:"#df1b41"}}},C={cardNumber:"Card number",cardExpiry:"Expiry date",cardCvc:"CVC",address:"Address"},E=class{constructor(e,t,r){this.stripe=e;this.config=t;this.clientSecret=r;this.elements=null;this.mountedElements=new Map;this.elementStates=new Map;if(!r)throw new i("Client secret not initialized","CONFIGURATION_ERROR")}mountPaymentElement(e){if(!this.elements){let n={clientSecret:this.clientSecret,appearance:this.config.appearance,locale:this.config.locale,fonts:this.config.fonts,paymentMethodCreation:"manual"};this.elements=this.stripe.elements(n);}if(!document.querySelector(e))throw new i(`Element not found: ${e}`,"CONFIGURATION_ERROR");let r=this.elements.create("payment",{layout:"tabs"});r.mount(e),this.mountedElements.set("payment",r);}mountCardNumberElement(e){this.mountIndividualFormElement(e,"cardNumber",this.cardElementOptions("cardNumber"));}mountCardExpiryElement(e){this.mountIndividualFormElement(e,"cardExpiry",this.cardElementOptions("cardExpiry"));}mountCardCvcElement(e){this.mountIndividualFormElement(e,"cardCvc",this.cardElementOptions("cardCvc"));}mountAddressElement(e,t){this.mountIndividualFormElement(e,"address",{mode:t});}cardElementOptions(e){let{elementsConfig:t}=this.config,r={placeholder:t?.placeholders?.[e]??d.placeholders[e],style:{base:{...d.style.base,...t?.style?.base},complete:{...d.style.complete,...t?.style?.complete},empty:{...d.style.empty,...t?.style?.empty},invalid:{...d.style.invalid,...t?.style?.invalid}}};return e==="cardNumber"&&(r.showIcon=t?.showIcon??d.showIcon,r.iconStyle=t?.iconStyle??d.iconStyle),r}mountIndividualFormElement(e,t,r){if(!document.querySelector(e))throw new i(`Element not found: ${e}`,"CONFIGURATION_ERROR");let a=this.createIndividualFormElement(t,r);a.mount(e),this.mountedElements.set(t,a),this.trackElementState(t,a);}createIndividualFormElement(e,t){return this.elements||(this.elements=this.stripe.elements({appearance:this.config.appearance,locale:this.config.locale,fonts:this.config.fonts,paymentMethodCreation:"manual"})),this.elements.create(e,t)}async validate(){let e=[];for(let[t,r]of this.elementStates.entries())r.complete||e.push({field:t,message:r.error??`${C[t]??t} failed validation`});return {isValid:e.length===0,errors:e}}getElements(){return this.elements}unmountAll(){for(let e of this.mountedElements.values())e.unmount();this.mountedElements.clear(),this.elementStates.clear();}trackElementState(e,t){this.elementStates.set(e,{complete:false});let r=n=>{this.elementStates.set(e,{complete:n.complete,error:n.error?.message});};t.on("change",r);}};var f=class{constructor(){this.extensions=[];}add(e){this.extensions.push(e);}async runBeforePayment(e){let t=e;for(let r of this.extensions)r.beforePayment&&(t=await r.beforePayment(t));return t}async runAfterPayment(e){await Promise.all(this.extensions.filter(t=>t.afterPayment).map(t=>t.afterPayment(e)));}async runOnError(e){await Promise.all(this.extensions.filter(t=>t.onPaymentError).map(t=>t.onPaymentError(e)));}};var g=class{constructor(e,t,r){this.stripeAdapter=e;this.elementsManager=t;this.verapayService=r;}async process(e,t){let r=this.elementsManager.getElements();await this.validatePaymentCanProceed(r,t),await r.submit();let n=await this.stripeAdapter.createPaymentMethod(r,t.isUsingIndividualFormElements);return await this.verapayService.processPrePayment({merchantId:t.merchantId,paymentIntentId:t.paymentIntentId,paymentMethodId:n,customerData:{email:e.customerEmail,firstName:"",lastName:""},metadata:e.metadata}),this.confirmPayment(e,n,t)}async validatePaymentCanProceed(e,t){if(!e)throw new i("Payment form not mounted","CONFIGURATION_ERROR");if(t.isUsingStripePaymentElement&&t.isUsingIndividualFormElements)throw new i("Both forms of payment form in use");if(t.isUsingIndividualFormElements){let r=await this.elementsManager.validate();if(!r.isValid)throw new i(r.errors[0].message,"VALIDATION_ERROR")}}async confirmPayment(e,t,r){let{clientSecret:n,isUsingStripePaymentElement:a,isUsingIndividualFormElements:o}=r,R;return a?R=await this.stripeAdapter.confirmPayment(t,n,e.returnUrl):o&&(R=await this.stripeAdapter.confirmCardPayment(t,n)),this.formatPaymentResult(R)}formatPaymentResult(e){return {success:e.paymentIntent.status==="succeeded",paymentIntentId:e.paymentIntent.id,status:e.paymentIntent.status}}};var p=class{constructor(e="http://localhost:3333"){this.baseUrl=e;}async initialisePayment(e){let{merchantId:t,paymentData:r}=e;try{let n=await fetch(`${this.baseUrl}/api/initialise-payment`,{method:"POST",headers:{"Content-Type":"application/json","x-api-key":"example.api.key"},body:JSON.stringify({merchantId:t,paymentData:{...r,paymentMethodType:"card"}})});if(!n.ok){let o=await n.json().catch(()=>({}));throw new i(o.error||`HTTP error! status: ${n.status}`,"CONFIGURATION_ERROR")}let a=await n.json();if(!a.clientSecret||!a.paymentIntentId)throw new i("Missing clientSecret or paymentIntentId in server response","CONFIGURATION_ERROR");return {paymentIntentId:a.paymentIntentId,clientSecret:a.clientSecret,connectAccountId:a.connectAccountId}}catch(n){throw n instanceof i?n:new i(n instanceof Error?n.message:"Unknown error occurred","CONFIGURATION_ERROR")}}async processPrePayment(e){try{let t=await fetch(`${this.baseUrl}/api/process-prepayment`,{method:"POST",headers:{"Content-Type":"application/json","x-forwarded-for":"example.ip.addr"},body:JSON.stringify({merchantId:e.merchantId,paymentIntentId:e.paymentIntentId,paymentMethodId:e.paymentMethodId,customerData:e.customerData,metadata:e.metadata})});if(!t.ok){let r=await t.json().catch(()=>({}));throw new i(r.error||`HTTP error! status: ${t.status}`,"CONFIGURATION_ERROR")}}catch(t){throw t instanceof i?t:new i(t instanceof Error?t.message:"Unknown error occurred","CONFIGURATION_ERROR")}}};var h=class h{constructor(e){this.stripeAdapter=null;this.elementsManager=null;this.paymentService=null;this.isUsingStripePaymentElement=false;this.isUsingIndividualFormElements=false;this.clientSecret=null;this.paymentIntentId=null;this.config=e,this.verapayService=new p,this.extensionsManager=new f;}async initialize(){this.validatePaymentInitialisation();let{clientSecret:e,paymentIntentId:t}=await this.verapayService.initialisePayment({merchantId:this.config.merchantId,paymentData:this.config.paymentData});this.clientSecret=e,this.paymentIntentId=t;let r=await stripeJs.loadStripe(h.STRIPE_PUBLISHABLE_KEY);if(!r)throw new i("Failed to load Stripe","CONFIGURATION_ERROR");this.stripeAdapter=new u(r),this.elementsManager=new E(r,this.config,e),this.paymentService=new g(this.stripeAdapter,this.elementsManager,this.verapayService);}async processPayment(e){await this.ensureInitialized();let t=await this.extensionsManager.runBeforePayment(e);try{let r=await this.paymentService.process(t,{merchantId:this.config.merchantId,paymentIntentId:this.paymentIntentId,clientSecret:this.clientSecret,isUsingStripePaymentElement:this.isUsingStripePaymentElement,isUsingIndividualFormElements:this.isUsingIndividualFormElements});return await this.extensionsManager.runAfterPayment(r),r}catch(r){throw await this.extensionsManager.runOnError(r),this.handlePaymentError(r)}}async mountPaymentForm(e){await this.ensureInitialized(),this.elementsManager.mountPaymentElement(e),this.isUsingStripePaymentElement=true;}async mountCardNumber(e){await this.ensureInitialized(),this.elementsManager.mountCardNumberElement(e),this.isUsingIndividualFormElements=true;}async mountCardExpiry(e){await this.ensureInitialized(),this.elementsManager.mountCardExpiryElement(e),this.isUsingIndividualFormElements=true;}async mountCardCvc(e){await this.ensureInitialized(),this.elementsManager.mountCardCvcElement(e),this.isUsingIndividualFormElements=true;}async mountAddress(e,t){await this.ensureInitialized(),this.elementsManager.mountAddressElement(e,t),this.isUsingIndividualFormElements=true;}addExtension(e){this.extensionsManager.add(e);}async ensureInitialized(){this.stripeAdapter||await this.initialize();}validatePaymentInitialisation(){let{amount:e,currency:t,partnerFee:r}=this.config.paymentData;if(!t)throw new l("Currency is required","currency");let n=t.toUpperCase(),a=this.toMoney(e,n,"amount");if(a.isZero()||a.isNegative())throw new l("Amount must be greater than 0","amount");if(r!==void 0&&this.toMoney(r,n,"partnerFee").isNegative())throw new l("partnerFee cannot be negative","partnerFee")}toMoney(e,t,r){try{return tsMoney.Money.fromInteger(e,t)}catch{throw new l(`${r} must be an integer in the smallest currency unit (e.g., cents for USD)`,r)}}handlePaymentError(e){return e instanceof i?e:new m(e.message||"Payment failed",e.code)}};h.STRIPE_PUBLISHABLE_KEY="pk_test_51T6ts0GU0Zq3ZuYLSciVz44jEsdaUBd4HRHIQCFSRt7VfBJt9vTJGJAXKYMynC64Ot0cCw9XjTGxCd8ZC44tfMkl00jWhD2UNq";var v=h;var I=class{validateCardNumber(e){let t=e.replace(/\D/g,"");if(t.length<13||t.length>19)return false;let r=0,n=false;for(let a=t.length-1;a>=0;a--){let o=parseInt(t[a],10);n&&(o*=2,o>9&&(o-=9)),r+=o,n=!n;}return r%10===0}detectCardType(e){let t=e.replace(/\D/g,"");return /^4/.test(t)?"visa":/^5[1-5]/.test(t)?"mastercard":/^3[47]/.test(t)?"amex":/^6(?:011|5)/.test(t)?"discover":"unknown"}validateExpiry(e,t){let r=new Date,n=r.getFullYear(),a=r.getMonth()+1;if(e<1||e>12)return false;let o=t<100?2e3+t:t;return !(o<n||o===n&&e<a)}validateCVC(e,t="unknown"){let r=e.replace(/\D/g,"");return t==="amex"?r.length===4:r.length===3||r.length===4}validateAll(e,t,r,n){let a=this.detectCardType(e);return {number:{isValid:this.validateCardNumber(e),cardType:a},expiry:{isValid:this.validateExpiry(t,r),month:t,year:r},cvc:{isValid:this.validateCVC(n,a),length:n.replace(/\D/g,"").length}}}};var P=class{static sanitizeCardNumber(e){return e.replace(/\D/g,"")}static formatCardNumber(e){return this.sanitizeCardNumber(e).replace(/(\d{4})/g,"$1 ").trim()}static sanitizeCVC(e){return e.replace(/\D/g,"").slice(0,4)}static sanitizeExpiry(e){let t=e.replace(/\D/g,"");return t.length===4?{month:parseInt(t.slice(0,2),10),year:parseInt(t.slice(2,4),10)}:t.length===6?{month:parseInt(t.slice(0,2),10),year:parseInt(t.slice(2,6),10)}:null}};var Ee="0.0.1";
|
|
2
|
+
exports.CardValidator=I;exports.ErrorFormatter=y;exports.InputSanitizer=P;exports.PaymentError=m;exports.VERSION=Ee;exports.ValidationError=l;exports.VerapayClient=v;exports.VerapayError=i;exports.VerapayService=p;//# sourceMappingURL=index.cjs.map
|
|
3
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/errors/VerapayError.ts","../src/errors/ValidationError.ts","../src/errors/PaymentError.ts","../src/errors/errorFormatter.ts","../src/client/StripeAdapter.ts","../src/client/ElementsManager.ts","../src/client/PaymentExtensionsManager.ts","../src/services/PaymentService.ts","../src/services/VerapayService.ts","../src/client/VerapayClient.ts","../src/validation/cardValidator.ts","../src/validation/inputSanitizer.ts","../src/index.ts"],"names":["VerapayError","_VerapayError","message","code","details","ValidationError","field","metadata","PaymentError","_PaymentError","stripeCode","ErrorFormatter","error","StripeAdapter","stripe","paymentMethodId","clientSecret","returnUrl","result","elements","isUsingIndividualFormElements","address","DEFAULT_CARD_ELEMENT_CONFIG","FIELD_LABELS","ElementsManager","config","selector","elementsConfig","element","mode","fieldType","options","formFieldType","errors","state","handleElementChange","event","PaymentExtensionsManager","extension","request","modifiedRequest","ext","PaymentService","stripeAdapter","elementsManager","verapayService","context","validation","isUsingStripePaymentElement","VerapayService","baseUrl","merchantId","paymentData","response","errorData","data","_VerapayClient","paymentIntentId","loadStripe","paymentResult","amount","currency","partnerFee","uppercaseCurrency","paymentAmount","value","fieldName","Money","VerapayClient","CardValidator","cardNumber","cleaned","sum","isEven","i","digit","month","year","now","currentYear","currentMonth","fullYear","cvc","cardType","expiryMonth","expiryYear","InputSanitizer","input","VERSION"],"mappings":"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","file":"index.cjs","sourcesContent":["import type { ErrorDetails } from '../types';\nimport { ErrorCode } from '../types';\n\nexport class VerapayError extends Error {\n public readonly code: ErrorCode;\n public readonly details: ErrorDetails;\n\n constructor(\n message: string,\n code: ErrorCode = ErrorCode.PAYMENT_FAILED,\n details?: Partial<ErrorDetails>\n ) {\n super(message);\n this.name = 'VerapayError';\n this.code = code;\n this.details = {\n code,\n message,\n formattedMessage: this.formatMessage(message, code),\n ...details,\n };\n\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, VerapayError);\n }\n }\n\n private formatMessage(message: string, code: ErrorCode): string {\n const messageMap: Record<ErrorCode, string> = {\n [ErrorCode.VALIDATION_ERROR]:\n 'Please check your payment information and try again.',\n [ErrorCode.PAYMENT_FAILED]:\n 'Your payment could not be processed. Please try again.',\n [ErrorCode.AUTHENTICATION_FAILED]:\n 'Payment authentication failed. Please try again.',\n [ErrorCode.NETWORK_ERROR]:\n 'Network error. Please check your connection and try again.',\n [ErrorCode.STRIPE_ERROR]:\n 'Payment service error. Please try again later.',\n [ErrorCode.CONFIGURATION_ERROR]:\n 'Configuration error. Please contact support.',\n [ErrorCode.CARD_DECLINED]:\n 'Your card was declined. Please use a different payment method.',\n [ErrorCode.INSUFFICIENT_FUNDS]:\n 'Insufficient funds. Please use a different payment method.',\n [ErrorCode.EXPIRED_CARD]:\n 'Your card has expired. Please use a different payment method.',\n };\n\n return messageMap[code] || message;\n }\n\n toJSON() {\n return {\n name: this.name,\n code: this.code,\n message: this.message,\n details: this.details,\n };\n }\n}\n","import { VerapayError } from './VerapayError';\nimport { ErrorCode } from '../types';\n\nexport class ValidationError extends VerapayError {\n constructor(message: string, field?: string, metadata?: Record<string, any>) {\n super(message, ErrorCode.VALIDATION_ERROR, {\n field,\n metadata,\n });\n this.name = 'ValidationError';\n }\n}\n","import { VerapayError } from './VerapayError';\nimport { ErrorCode } from '../types';\n\nexport class PaymentError extends VerapayError {\n constructor(\n message: string,\n stripeCode?: string,\n metadata?: Record<string, any>\n ) {\n const code = PaymentError.mapStripeCode(stripeCode);\n super(message, code, {\n stripeCode,\n metadata,\n });\n this.name = 'PaymentError';\n }\n\n private static mapStripeCode(stripeCode?: string): ErrorCode {\n if (!stripeCode) return ErrorCode.PAYMENT_FAILED;\n\n const codeMap: Record<string, ErrorCode> = {\n card_declined: ErrorCode.CARD_DECLINED,\n insufficient_funds: ErrorCode.INSUFFICIENT_FUNDS,\n expired_card: ErrorCode.EXPIRED_CARD,\n incorrect_cvc: ErrorCode.VALIDATION_ERROR,\n processing_error: ErrorCode.PAYMENT_FAILED,\n authentication_failed: ErrorCode.AUTHENTICATION_FAILED,\n };\n\n return codeMap[stripeCode] || ErrorCode.PAYMENT_FAILED;\n }\n}\n","import type { ErrorDetails } from '../types';\n\nexport class ErrorFormatter {\n static formatForUser(error: Error | ErrorDetails): string {\n if ('formattedMessage' in error) {\n return error.formattedMessage;\n }\n if (\n 'details' in error &&\n error.details &&\n typeof error.details === 'object' &&\n 'formattedMessage' in error.details &&\n typeof error.details.formattedMessage === 'string'\n ) {\n return error.details.formattedMessage;\n }\n return 'An unexpected error occurred. Please try again.';\n }\n\n static formatForDeveloper(error: Error | ErrorDetails): string {\n if ('code' in error && 'message' in error) {\n return `[${error.code}] ${error.message}`;\n }\n return error.message || 'Unknown error';\n }\n\n static toJSON(error: Error | ErrorDetails): Record<string, any> {\n if ('toJSON' in error && typeof error.toJSON === 'function') {\n return error.toJSON();\n }\n\n return {\n name: (error as Error).name || 'Error',\n message: error.message,\n ...('code' in error && { code: error.code }),\n ...('details' in error && { details: error.details }),\n };\n }\n}\n","import type { PaymentIntent, Stripe, StripeElements } from '@stripe/stripe-js';\nimport { PaymentError } from '../errors';\n\nexport class StripeAdapter {\n constructor(private stripe: Stripe) {}\n\n async confirmPayment(\n paymentMethodId: string,\n clientSecret: string,\n returnUrl?: string\n ): Promise<{ paymentIntent: PaymentIntent }> {\n const result = await this.stripe.confirmPayment({\n clientSecret,\n confirmParams: {\n payment_method: paymentMethodId,\n return_url: returnUrl || window.location.href,\n },\n redirect: 'if_required',\n });\n\n if (result.error) {\n throw new PaymentError(\n result.error.message || 'Payment failed',\n result.error.code\n );\n }\n\n return result as { paymentIntent: PaymentIntent };\n }\n\n async confirmCardPayment(\n paymentMethodId: string,\n clientSecret: string\n ): Promise<{ paymentIntent: PaymentIntent }> {\n const result = await this.stripe.confirmCardPayment(clientSecret, {\n payment_method: paymentMethodId,\n });\n\n if (result.error) {\n throw new PaymentError(\n result.error.message || 'Payment failed',\n result.error.code\n );\n }\n\n return result as { paymentIntent: PaymentIntent };\n }\n\n async createPaymentMethod(\n elements: StripeElements,\n isUsingIndividualFormElements: boolean = false\n ): Promise<string> {\n let result;\n\n if (!isUsingIndividualFormElements) {\n result = await this.stripe.createPaymentMethod({\n elements,\n });\n } else {\n // @ts-ignore - Stripe types don't include mode parameter for getElement\n const addressElement = await elements.getElement('address', { mode: 'billing' })!.getValue();\n const address = addressElement!.value;\n\n result = await this.stripe.createPaymentMethod({\n type: 'card',\n card: elements.getElement('cardNumber')!,\n billing_details: {\n name: address.name,\n address: {\n ...address.address,\n line2: address.address.line2 ?? undefined,\n },\n },\n });\n }\n\n if (result.error || !result.paymentMethod) {\n throw new PaymentError(\n result.error?.message || 'Failed to create payment method',\n result.error?.code\n );\n }\n\n return result.paymentMethod.id;\n }\n}\n","import type {\n Stripe,\n StripeElements,\n StripeElement,\n StripePaymentElement,\n StripeCardNumberElement,\n} from '@stripe/stripe-js';\nimport type { VerapayConfig, ValidationError, ValidationResult } from '../types';\nimport { VerapayError, ErrorCode } from '../errors';\n\ntype ElementState = { complete: boolean; error?: string }\n\nconst DEFAULT_CARD_ELEMENT_CONFIG = {\n showIcon: true,\n iconStyle: 'solid' as const,\n placeholders: {\n cardNumber: '1234 1234 1234 1234',\n cardExpiry: 'MM / YY',\n cardCvc: 'CVC',\n },\n style: {\n base: {\n color: '#333333',\n fontFamily: 'system-ui, -apple-system, sans-serif',\n fontSize: '16px',\n '::placeholder': { color: '#aab7c4' },\n },\n complete: {\n color: '#333333',\n },\n empty: {},\n invalid: {\n color: '#df1b41',\n },\n },\n}\n\nconst FIELD_LABELS: Record<string, string> = {\n cardNumber: 'Card number',\n cardExpiry: 'Expiry date',\n cardCvc: 'CVC',\n address: 'Address',\n}\n\nexport class ElementsManager {\n private elements: StripeElements | null = null;\n private mountedElements: Map<string, StripeElement> = new Map();\n private elementStates: Map<string, ElementState> = new Map();\n\n constructor(\n private stripe: Stripe,\n private config: VerapayConfig,\n private clientSecret: string\n ) {\n if (!clientSecret) {\n throw new VerapayError(\n 'Client secret not initialized',\n ErrorCode.CONFIGURATION_ERROR\n );\n }\n }\n\n mountPaymentElement(selector: string): void {\n if (!this.elements) {\n const elementsConfig = {\n clientSecret: this.clientSecret,\n appearance: this.config.appearance,\n locale: this.config.locale,\n fonts: this.config.fonts,\n paymentMethodCreation: 'manual',\n };\n\n this.elements = this.stripe.elements(elementsConfig);\n }\n\n const container = document.querySelector(selector);\n\n if (!container) {\n throw new VerapayError(\n `Element not found: ${selector}`,\n ErrorCode.CONFIGURATION_ERROR\n );\n }\n\n const element = this.elements.create('payment', {\n layout: 'tabs',\n }) as StripePaymentElement;\n\n element.mount(selector);\n this.mountedElements.set('payment', element);\n }\n\n mountCardNumberElement(selector: string): void {\n this.mountIndividualFormElement(selector, 'cardNumber', this.cardElementOptions('cardNumber'));\n }\n\n mountCardExpiryElement(selector: string): void {\n this.mountIndividualFormElement(selector, 'cardExpiry', this.cardElementOptions('cardExpiry'));\n }\n\n mountCardCvcElement(selector: string): void {\n this.mountIndividualFormElement(selector, 'cardCvc', this.cardElementOptions('cardCvc'));\n }\n\n mountAddressElement(selector: string, mode: 'billing' | 'shipping'): void {\n this.mountIndividualFormElement(selector, 'address', { mode });\n }\n\n private cardElementOptions(fieldType: 'cardNumber' | 'cardExpiry' | 'cardCvc'): Record<string, unknown> {\n const { elementsConfig } = this.config;\n const options: Record<string, unknown> = {\n placeholder: elementsConfig?.placeholders?.[fieldType] ?? DEFAULT_CARD_ELEMENT_CONFIG.placeholders[fieldType],\n style: {\n base: { ...DEFAULT_CARD_ELEMENT_CONFIG.style.base, ...elementsConfig?.style?.base },\n complete: { ...DEFAULT_CARD_ELEMENT_CONFIG.style.complete, ...elementsConfig?.style?.complete },\n empty: { ...DEFAULT_CARD_ELEMENT_CONFIG.style.empty, ...elementsConfig?.style?.empty },\n invalid: { ...DEFAULT_CARD_ELEMENT_CONFIG.style.invalid, ...elementsConfig?.style?.invalid },\n },\n };\n\n if (fieldType === 'cardNumber') {\n options.showIcon = elementsConfig?.showIcon ?? DEFAULT_CARD_ELEMENT_CONFIG.showIcon;\n options.iconStyle = elementsConfig?.iconStyle ?? DEFAULT_CARD_ELEMENT_CONFIG.iconStyle;\n }\n\n return options;\n }\n\n private mountIndividualFormElement(selector: string, formFieldType: 'cardNumber' | 'cardExpiry' | 'cardCvc' | 'address', options?: Record<string, unknown>) {\n const container = document.querySelector(selector);\n\n if (!container) {\n throw new VerapayError(\n `Element not found: ${selector}`,\n ErrorCode.CONFIGURATION_ERROR\n );\n }\n\n const element = this.createIndividualFormElement(formFieldType, options) as StripeCardNumberElement;\n element.mount(selector);\n\n this.mountedElements.set(formFieldType, element);\n this.trackElementState(formFieldType, element);\n }\n\n private createIndividualFormElement(\n formFieldType: any,\n options?: Record<string, unknown>\n ): StripeElement {\n if (!this.elements) {\n // For individual card elements, don't pass clientSecret\n // It's only needed when creating Payment Element or confirming payment\n this.elements = this.stripe.elements({\n appearance: this.config.appearance,\n locale: this.config.locale,\n fonts: this.config.fonts,\n paymentMethodCreation: 'manual',\n });\n }\n\n return this.elements.create(formFieldType, options);\n }\n\n async validate(): Promise<ValidationResult> {\n const errors: ValidationError[] = []\n\n for (const [field, state] of this.elementStates.entries()) {\n if (!state.complete) {\n errors.push({\n field,\n message: state.error ?? `${FIELD_LABELS[field] ?? field} failed validation`,\n })\n }\n }\n\n return { isValid: errors.length === 0, errors }\n }\n\n getElements(): StripeElements | null {\n return this.elements;\n }\n\n unmountAll(): void {\n for (const element of this.mountedElements.values()) {\n element.unmount();\n }\n this.mountedElements.clear();\n this.elementStates.clear();\n }\n\n private trackElementState(field: string, element: StripeElement): void {\n this.elementStates.set(field, { complete: false })\n\n const handleElementChange = (event: { complete: boolean; error?: { message: string } }) => {\n this.elementStates.set(field, { complete: event.complete, error: event.error?.message })\n };\n\n (element as any).on('change', handleElementChange)\n }\n}\n","import type { ProcessPaymentRequest, PaymentResult } from '../types'\n\nexport interface PaymentExtension {\n name: string\n beforePayment?(request: ProcessPaymentRequest): Promise<ProcessPaymentRequest>\n afterPayment?(result: PaymentResult): Promise<void>\n onPaymentError?(error: Error): Promise<void>\n}\n\nexport class PaymentExtensionsManager {\n private extensions: PaymentExtension[] = []\n\n add(extension: PaymentExtension): void {\n this.extensions.push(extension)\n }\n\n async runBeforePayment(request: ProcessPaymentRequest): Promise<ProcessPaymentRequest> {\n let modifiedRequest = request\n for (const ext of this.extensions) {\n if (ext.beforePayment) {\n modifiedRequest = await ext.beforePayment(modifiedRequest)\n }\n }\n return modifiedRequest\n }\n\n async runAfterPayment(result: PaymentResult): Promise<void> {\n await Promise.all(\n this.extensions\n .filter((ext) => ext.afterPayment)\n .map((ext) => ext.afterPayment!(result)),\n )\n }\n\n async runOnError(error: Error): Promise<void> {\n await Promise.all(\n this.extensions\n .filter((ext) => ext.onPaymentError)\n .map((ext) => ext.onPaymentError!(error)),\n )\n }\n}\n","import { StripeAdapter } from '../client/StripeAdapter'\nimport { ElementsManager } from '../client/ElementsManager'\nimport { ErrorCode, VerapayError } from '../errors'\nimport { VerapayService } from './VerapayService'\nimport type { ProcessPaymentRequest, PaymentResult } from '../types'\nimport { StripeElements } from '@stripe/stripe-js';\n\nexport interface ProcessPaymentContext {\n merchantId: string\n paymentIntentId: string\n clientSecret: string\n isUsingStripePaymentElement: boolean\n isUsingIndividualFormElements: boolean\n}\n\nexport class PaymentService {\n constructor(\n private stripeAdapter: StripeAdapter,\n private elementsManager: ElementsManager,\n private verapayService: VerapayService,\n ) {}\n\n async process(request: ProcessPaymentRequest, context: ProcessPaymentContext): Promise<PaymentResult> {\n const elements = this.elementsManager.getElements()\n\n await this.validatePaymentCanProceed(elements, context);\n\n await elements!.submit()\n\n const paymentMethodId = await this.stripeAdapter.createPaymentMethod(\n elements!,\n context.isUsingIndividualFormElements,\n )\n\n await this.verapayService.processPrePayment({\n merchantId: context.merchantId,\n paymentIntentId: context.paymentIntentId,\n paymentMethodId,\n customerData: {\n email: request.customerEmail,\n firstName: '',\n lastName: '',\n },\n metadata: request.metadata,\n })\n\n return this.confirmPayment(request, paymentMethodId, context)\n }\n\n private async validatePaymentCanProceed(elements: StripeElements | null, context: ProcessPaymentContext) {\n if (!elements) {\n throw new VerapayError('Payment form not mounted', ErrorCode.CONFIGURATION_ERROR)\n }\n\n if (context.isUsingStripePaymentElement && context.isUsingIndividualFormElements) {\n throw new VerapayError('Both forms of payment form in use');\n }\n\n if (context.isUsingIndividualFormElements) {\n const validation = await this.elementsManager.validate()\n if (!validation.isValid) {\n throw new VerapayError(validation.errors[0].message, ErrorCode.VALIDATION_ERROR)\n }\n }\n }\n\n private async confirmPayment(\n request: ProcessPaymentRequest,\n paymentMethodId: string,\n context: ProcessPaymentContext,\n ): Promise<PaymentResult> {\n const { clientSecret, isUsingStripePaymentElement, isUsingIndividualFormElements } = context\n\n let result\n\n if (isUsingStripePaymentElement) {\n result = await this.stripeAdapter.confirmPayment(paymentMethodId, clientSecret, request.returnUrl)\n } else if (isUsingIndividualFormElements) {\n result = await this.stripeAdapter.confirmCardPayment(paymentMethodId, clientSecret)\n }\n\n return this.formatPaymentResult(result)\n }\n\n private formatPaymentResult(result: any): PaymentResult {\n return {\n success: result.paymentIntent.status === 'succeeded',\n paymentIntentId: result.paymentIntent.id,\n status: result.paymentIntent.status,\n }\n }\n}\n","import { ErrorCode, VerapayError } from '../errors';\nimport { PaymentData } from '../types';\n\nexport interface InitialisePaymentRequest {\n merchantId: string;\n paymentData: PaymentData;\n}\n\nexport interface InitialisePaymentResponse {\n paymentIntentId: string;\n clientSecret: string;\n connectAccountId: string;\n}\n\nexport interface ProcessPrePaymentRequest {\n merchantId: string;\n paymentIntentId: string;\n paymentMethodId: string;\n customerData: Record<string, any>;\n metadata?: Record<string, string>;\n}\n\nexport class VerapayService {\n private readonly baseUrl: string;\n\n constructor(baseUrl: string = 'http://localhost:3333') {\n this.baseUrl = baseUrl;\n }\n\n async initialisePayment(\n request: InitialisePaymentRequest\n ): Promise<InitialisePaymentResponse> {\n const { merchantId, paymentData } = request;\n\n try {\n const response = await fetch(`${this.baseUrl}/api/initialise-payment`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'x-api-key': 'example.api.key',\n },\n body: JSON.stringify({\n merchantId,\n paymentData: { ...paymentData, paymentMethodType: 'card' },\n }),\n });\n\n if (!response.ok) {\n const errorData = await response.json().catch(() => ({}));\n throw new VerapayError(\n errorData.error || `HTTP error! status: ${response.status}`,\n ErrorCode.CONFIGURATION_ERROR\n );\n }\n\n const data = await response.json();\n\n if (!data.clientSecret || !data.paymentIntentId) {\n throw new VerapayError(\n 'Missing clientSecret or paymentIntentId in server response',\n ErrorCode.CONFIGURATION_ERROR\n );\n }\n\n return {\n paymentIntentId: data.paymentIntentId,\n clientSecret: data.clientSecret,\n connectAccountId: data.connectAccountId,\n };\n } catch (error) {\n if (error instanceof VerapayError) {\n throw error;\n }\n throw new VerapayError(\n error instanceof Error ? error.message : 'Unknown error occurred',\n ErrorCode.CONFIGURATION_ERROR\n );\n }\n }\n\n async processPrePayment(request: ProcessPrePaymentRequest): Promise<void> {\n try {\n const response = await fetch(`${this.baseUrl}/api/process-prepayment`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'x-forwarded-for': 'example.ip.addr',\n },\n body: JSON.stringify({\n merchantId: request.merchantId,\n paymentIntentId: request.paymentIntentId,\n paymentMethodId: request.paymentMethodId,\n customerData: request.customerData,\n metadata: request.metadata,\n }),\n });\n\n if (!response.ok) {\n const errorData = await response.json().catch(() => ({}));\n throw new VerapayError(\n errorData.error || `HTTP error! status: ${response.status}`,\n ErrorCode.CONFIGURATION_ERROR\n );\n }\n } catch (error) {\n if (error instanceof VerapayError) {\n throw error;\n }\n throw new VerapayError(\n error instanceof Error ? error.message : 'Unknown error occurred',\n ErrorCode.CONFIGURATION_ERROR\n );\n }\n }\n}\n","import { loadStripe } from '@stripe/stripe-js';\nimport { Money } from 'ts-money';\nimport { StripeAdapter } from './StripeAdapter';\nimport { ElementsManager } from './ElementsManager';\nimport type { PaymentExtension } from './PaymentExtensionsManager';\nimport { PaymentExtensionsManager } from './PaymentExtensionsManager';\nimport { PaymentService } from '../services/PaymentService';\nimport {\n ErrorCode,\n VerapayError,\n PaymentError,\n ValidationError,\n} from '../errors';\nimport { VerapayService } from '../services/VerapayService';\nimport type {\n VerapayConfig,\n ProcessPaymentRequest,\n PaymentResult,\n} from '../types';\n\nexport class VerapayClient {\n private static readonly STRIPE_PUBLISHABLE_KEY =\n 'pk_test_51T6ts0GU0Zq3ZuYLSciVz44jEsdaUBd4HRHIQCFSRt7VfBJt9vTJGJAXKYMynC64Ot0cCw9XjTGxCd8ZC44tfMkl00jWhD2UNq';\n\n private config: VerapayConfig;\n private verapayService: VerapayService;\n private extensionsManager: PaymentExtensionsManager;\n\n private stripeAdapter: StripeAdapter | null = null;\n private elementsManager: ElementsManager | null = null;\n private paymentService: PaymentService | null = null;\n\n private isUsingStripePaymentElement: boolean = false;\n private isUsingIndividualFormElements: boolean = false;\n\n private clientSecret: string | null = null;\n private paymentIntentId: string | null = null;\n\n constructor(config: VerapayConfig) {\n this.config = config;\n this.verapayService = new VerapayService();\n this.extensionsManager = new PaymentExtensionsManager();\n }\n\n async initialize(): Promise<void> {\n this.validatePaymentInitialisation()\n\n const { clientSecret, paymentIntentId } =\n await this.verapayService.initialisePayment({\n merchantId: this.config.merchantId,\n paymentData: this.config.paymentData\n });\n\n this.clientSecret = clientSecret;\n this.paymentIntentId = paymentIntentId;\n\n const stripe = await loadStripe(VerapayClient.STRIPE_PUBLISHABLE_KEY);\n\n if (!stripe) {\n throw new VerapayError(\n 'Failed to load Stripe',\n ErrorCode.CONFIGURATION_ERROR\n );\n }\n\n this.stripeAdapter = new StripeAdapter(stripe);\n this.elementsManager = new ElementsManager(\n stripe,\n this.config,\n clientSecret\n );\n this.paymentService = new PaymentService(\n this.stripeAdapter,\n this.elementsManager,\n this.verapayService\n );\n }\n\n async processPayment(request: ProcessPaymentRequest): Promise<PaymentResult> {\n await this.ensureInitialized();\n\n let modifiedRequest =\n await this.extensionsManager.runBeforePayment(request);\n\n try {\n const paymentResult = await this.paymentService!.process(\n modifiedRequest,\n {\n merchantId: this.config.merchantId,\n paymentIntentId: this.paymentIntentId!,\n clientSecret: this.clientSecret!,\n isUsingStripePaymentElement: this.isUsingStripePaymentElement,\n isUsingIndividualFormElements: this.isUsingIndividualFormElements,\n }\n );\n\n await this.extensionsManager.runAfterPayment(paymentResult);\n\n return paymentResult;\n } catch (error) {\n await this.extensionsManager.runOnError(error as Error);\n throw this.handlePaymentError(error);\n }\n }\n\n async mountPaymentForm(selector: string): Promise<void> {\n await this.ensureInitialized();\n this.elementsManager!.mountPaymentElement(selector);\n this.isUsingStripePaymentElement = true;\n }\n\n async mountCardNumber(selector: string): Promise<void> {\n await this.ensureInitialized();\n this.elementsManager!.mountCardNumberElement(selector);\n this.isUsingIndividualFormElements = true;\n }\n\n async mountCardExpiry(selector: string): Promise<void> {\n await this.ensureInitialized();\n this.elementsManager!.mountCardExpiryElement(selector);\n this.isUsingIndividualFormElements = true;\n }\n\n async mountCardCvc(selector: string): Promise<void> {\n await this.ensureInitialized();\n this.elementsManager!.mountCardCvcElement(selector);\n this.isUsingIndividualFormElements = true;\n }\n\n async mountAddress(\n selector: string,\n mode: 'billing' | 'shipping'\n ): Promise<void> {\n await this.ensureInitialized();\n this.elementsManager!.mountAddressElement(selector, mode);\n this.isUsingIndividualFormElements = true;\n }\n\n addExtension(extension: PaymentExtension): void {\n this.extensionsManager.add(extension);\n }\n\n private async ensureInitialized(): Promise<void> {\n if (!this.stripeAdapter) {\n await this.initialize();\n }\n }\n\n private validatePaymentInitialisation(): void {\n const { amount, currency, partnerFee } = this.config.paymentData;\n\n if (!currency) {\n throw new ValidationError('Currency is required', 'currency');\n }\n\n const uppercaseCurrency = currency.toUpperCase();\n\n const paymentAmount = this.toMoney(amount, uppercaseCurrency, 'amount');\n\n if (paymentAmount.isZero() || paymentAmount.isNegative()) {\n throw new ValidationError('Amount must be greater than 0', 'amount');\n }\n\n if (partnerFee !== undefined) {\n const partnerFeeAmount = this.toMoney(partnerFee, uppercaseCurrency, 'partnerFee');\n\n if (partnerFeeAmount.isNegative()) {\n throw new ValidationError('partnerFee cannot be negative', 'partnerFee');\n }\n }\n }\n\n private toMoney(value: number, currency: string, fieldName: string): Money {\n try {\n return Money.fromInteger(value, currency);\n } catch {\n throw new ValidationError(\n `${fieldName} must be an integer in the smallest currency unit (e.g., cents for USD)`,\n fieldName\n );\n }\n }\n\n private handlePaymentError(error: any): Error {\n if (error instanceof VerapayError) {\n return error;\n }\n return new PaymentError(error.message || 'Payment failed', error.code);\n }\n}\n","import type { CardValidation } from '../types';\n\nexport class CardValidator {\n validateCardNumber(cardNumber: string): boolean {\n const cleaned = cardNumber.replace(/\\D/g, '');\n\n if (cleaned.length < 13 || cleaned.length > 19) {\n return false;\n }\n\n let sum = 0;\n let isEven = false;\n\n for (let i = cleaned.length - 1; i >= 0; i--) {\n let digit = parseInt(cleaned[i], 10);\n\n if (isEven) {\n digit *= 2;\n if (digit > 9) {\n digit -= 9;\n }\n }\n\n sum += digit;\n isEven = !isEven;\n }\n\n return sum % 10 === 0;\n }\n\n detectCardType(cardNumber: string): string {\n const cleaned = cardNumber.replace(/\\D/g, '');\n\n if (/^4/.test(cleaned)) return 'visa';\n if (/^5[1-5]/.test(cleaned)) return 'mastercard';\n if (/^3[47]/.test(cleaned)) return 'amex';\n if (/^6(?:011|5)/.test(cleaned)) return 'discover';\n\n return 'unknown';\n }\n\n validateExpiry(month: number, year: number): boolean {\n const now = new Date();\n const currentYear = now.getFullYear();\n const currentMonth = now.getMonth() + 1;\n\n if (month < 1 || month > 12) {\n return false;\n }\n\n const fullYear = year < 100 ? 2000 + year : year;\n\n if (fullYear < currentYear) {\n return false;\n }\n\n if (fullYear === currentYear && month < currentMonth) {\n return false;\n }\n\n return true;\n }\n\n validateCVC(cvc: string, cardType: string = 'unknown'): boolean {\n const cleaned = cvc.replace(/\\D/g, '');\n\n if (cardType === 'amex') {\n return cleaned.length === 4;\n }\n\n return cleaned.length === 3 || cleaned.length === 4;\n }\n\n validateAll(\n cardNumber: string,\n expiryMonth: number,\n expiryYear: number,\n cvc: string\n ): CardValidation {\n const cardType = this.detectCardType(cardNumber);\n\n return {\n number: {\n isValid: this.validateCardNumber(cardNumber),\n cardType: cardType as any,\n },\n expiry: {\n isValid: this.validateExpiry(expiryMonth, expiryYear),\n month: expiryMonth,\n year: expiryYear,\n },\n cvc: {\n isValid: this.validateCVC(cvc, cardType),\n length: cvc.replace(/\\D/g, '').length,\n },\n };\n }\n}\n","export class InputSanitizer {\n static sanitizeCardNumber(input: string): string {\n return input.replace(/\\D/g, '');\n }\n\n static formatCardNumber(input: string): string {\n const cleaned = this.sanitizeCardNumber(input);\n return cleaned.replace(/(\\d{4})/g, '$1 ').trim();\n }\n\n static sanitizeCVC(input: string): string {\n return input.replace(/\\D/g, '').slice(0, 4);\n }\n\n static sanitizeExpiry(input: string): { month: number; year: number } | null {\n const cleaned = input.replace(/\\D/g, '');\n\n if (cleaned.length === 4) {\n return {\n month: parseInt(cleaned.slice(0, 2), 10),\n year: parseInt(cleaned.slice(2, 4), 10),\n };\n } else if (cleaned.length === 6) {\n return {\n month: parseInt(cleaned.slice(0, 2), 10),\n year: parseInt(cleaned.slice(2, 6), 10),\n };\n }\n\n return null;\n }\n}\n","export { VerapayClient } from './client/VerapayClient';\nexport { VerapayService } from './services/VerapayService';\n\nexport type {\n InitialisePaymentRequest,\n InitialisePaymentResponse,\n ProcessPrePaymentRequest,\n} from './services/VerapayService';\n\nexport type {\n VerapayConfig,\n ElementsConfig,\n ProcessPaymentRequest,\n PaymentResult,\n CardValidation,\n ErrorDetails,\n ErrorCode,\n} from './types';\n\nexport {\n VerapayError,\n ValidationError,\n PaymentError,\n ErrorFormatter,\n} from './errors';\n\nexport { CardValidator, InputSanitizer } from './validation';\n\nexport type {\n ServerExtension,\n DatabaseExtension,\n AnalyticsExtension,\n} from './extensions';\n\nexport const VERSION = '0.0.1';\n"]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
import { Appearance, StripeElementLocale, StripeElementsOptions } from '@stripe/stripe-js';
|
|
2
|
+
|
|
3
|
+
interface VerapayConfig {
|
|
4
|
+
merchantId: string;
|
|
5
|
+
paymentData: PaymentData;
|
|
6
|
+
appearance?: Appearance;
|
|
7
|
+
locale?: StripeElementLocale;
|
|
8
|
+
fonts?: StripeElementsOptions['fonts'];
|
|
9
|
+
elementsConfig?: ElementsConfig;
|
|
10
|
+
}
|
|
11
|
+
interface PaymentData {
|
|
12
|
+
amount: number;
|
|
13
|
+
currency: string;
|
|
14
|
+
partnerFee?: number;
|
|
15
|
+
}
|
|
16
|
+
interface ElementsConfig {
|
|
17
|
+
style?: {
|
|
18
|
+
base?: Record<string, string>;
|
|
19
|
+
complete?: Record<string, string>;
|
|
20
|
+
empty?: Record<string, string>;
|
|
21
|
+
invalid?: Record<string, string>;
|
|
22
|
+
};
|
|
23
|
+
placeholders?: {
|
|
24
|
+
cardNumber?: string;
|
|
25
|
+
cardExpiry?: string;
|
|
26
|
+
cardCvc?: string;
|
|
27
|
+
};
|
|
28
|
+
showIcon?: boolean;
|
|
29
|
+
iconStyle?: 'default' | 'solid';
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
interface ProcessPaymentRequest {
|
|
33
|
+
description?: string;
|
|
34
|
+
metadata?: Record<string, string>;
|
|
35
|
+
returnUrl?: string;
|
|
36
|
+
customerEmail?: string;
|
|
37
|
+
}
|
|
38
|
+
interface PaymentResult {
|
|
39
|
+
success: boolean;
|
|
40
|
+
paymentIntentId?: string;
|
|
41
|
+
status: 'succeeded' | 'processing' | 'failed';
|
|
42
|
+
error?: string;
|
|
43
|
+
}
|
|
44
|
+
interface CardValidation {
|
|
45
|
+
number: {
|
|
46
|
+
isValid: boolean;
|
|
47
|
+
cardType?: 'visa' | 'mastercard' | 'amex' | 'discover' | 'unknown';
|
|
48
|
+
};
|
|
49
|
+
expiry: {
|
|
50
|
+
isValid: boolean;
|
|
51
|
+
month?: number;
|
|
52
|
+
year?: number;
|
|
53
|
+
};
|
|
54
|
+
cvc: {
|
|
55
|
+
isValid: boolean;
|
|
56
|
+
length?: number;
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
declare enum ErrorCode {
|
|
61
|
+
VALIDATION_ERROR = "VALIDATION_ERROR",
|
|
62
|
+
PAYMENT_FAILED = "PAYMENT_FAILED",
|
|
63
|
+
AUTHENTICATION_FAILED = "AUTHENTICATION_FAILED",
|
|
64
|
+
NETWORK_ERROR = "NETWORK_ERROR",
|
|
65
|
+
STRIPE_ERROR = "STRIPE_ERROR",
|
|
66
|
+
CONFIGURATION_ERROR = "CONFIGURATION_ERROR",
|
|
67
|
+
CARD_DECLINED = "CARD_DECLINED",
|
|
68
|
+
INSUFFICIENT_FUNDS = "INSUFFICIENT_FUNDS",
|
|
69
|
+
EXPIRED_CARD = "EXPIRED_CARD"
|
|
70
|
+
}
|
|
71
|
+
interface ErrorDetails {
|
|
72
|
+
code: ErrorCode;
|
|
73
|
+
message: string;
|
|
74
|
+
formattedMessage: string;
|
|
75
|
+
field?: string;
|
|
76
|
+
stripeCode?: string;
|
|
77
|
+
metadata?: Record<string, any>;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
interface PaymentExtension {
|
|
81
|
+
name: string;
|
|
82
|
+
beforePayment?(request: ProcessPaymentRequest): Promise<ProcessPaymentRequest>;
|
|
83
|
+
afterPayment?(result: PaymentResult): Promise<void>;
|
|
84
|
+
onPaymentError?(error: Error): Promise<void>;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
declare class VerapayClient {
|
|
88
|
+
private static readonly STRIPE_PUBLISHABLE_KEY;
|
|
89
|
+
private config;
|
|
90
|
+
private verapayService;
|
|
91
|
+
private extensionsManager;
|
|
92
|
+
private stripeAdapter;
|
|
93
|
+
private elementsManager;
|
|
94
|
+
private paymentService;
|
|
95
|
+
private isUsingStripePaymentElement;
|
|
96
|
+
private isUsingIndividualFormElements;
|
|
97
|
+
private clientSecret;
|
|
98
|
+
private paymentIntentId;
|
|
99
|
+
constructor(config: VerapayConfig);
|
|
100
|
+
initialize(): Promise<void>;
|
|
101
|
+
processPayment(request: ProcessPaymentRequest): Promise<PaymentResult>;
|
|
102
|
+
mountPaymentForm(selector: string): Promise<void>;
|
|
103
|
+
mountCardNumber(selector: string): Promise<void>;
|
|
104
|
+
mountCardExpiry(selector: string): Promise<void>;
|
|
105
|
+
mountCardCvc(selector: string): Promise<void>;
|
|
106
|
+
mountAddress(selector: string, mode: 'billing' | 'shipping'): Promise<void>;
|
|
107
|
+
addExtension(extension: PaymentExtension): void;
|
|
108
|
+
private ensureInitialized;
|
|
109
|
+
private validatePaymentInitialisation;
|
|
110
|
+
private toMoney;
|
|
111
|
+
private handlePaymentError;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
interface InitialisePaymentRequest {
|
|
115
|
+
merchantId: string;
|
|
116
|
+
paymentData: PaymentData;
|
|
117
|
+
}
|
|
118
|
+
interface InitialisePaymentResponse {
|
|
119
|
+
paymentIntentId: string;
|
|
120
|
+
clientSecret: string;
|
|
121
|
+
connectAccountId: string;
|
|
122
|
+
}
|
|
123
|
+
interface ProcessPrePaymentRequest {
|
|
124
|
+
merchantId: string;
|
|
125
|
+
paymentIntentId: string;
|
|
126
|
+
paymentMethodId: string;
|
|
127
|
+
customerData: Record<string, any>;
|
|
128
|
+
metadata?: Record<string, string>;
|
|
129
|
+
}
|
|
130
|
+
declare class VerapayService {
|
|
131
|
+
private readonly baseUrl;
|
|
132
|
+
constructor(baseUrl?: string);
|
|
133
|
+
initialisePayment(request: InitialisePaymentRequest): Promise<InitialisePaymentResponse>;
|
|
134
|
+
processPrePayment(request: ProcessPrePaymentRequest): Promise<void>;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
declare class VerapayError extends Error {
|
|
138
|
+
readonly code: ErrorCode;
|
|
139
|
+
readonly details: ErrorDetails;
|
|
140
|
+
constructor(message: string, code?: ErrorCode, details?: Partial<ErrorDetails>);
|
|
141
|
+
private formatMessage;
|
|
142
|
+
toJSON(): {
|
|
143
|
+
name: string;
|
|
144
|
+
code: ErrorCode;
|
|
145
|
+
message: string;
|
|
146
|
+
details: ErrorDetails;
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
declare class ValidationError extends VerapayError {
|
|
151
|
+
constructor(message: string, field?: string, metadata?: Record<string, any>);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
declare class PaymentError extends VerapayError {
|
|
155
|
+
constructor(message: string, stripeCode?: string, metadata?: Record<string, any>);
|
|
156
|
+
private static mapStripeCode;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
declare class ErrorFormatter {
|
|
160
|
+
static formatForUser(error: Error | ErrorDetails): string;
|
|
161
|
+
static formatForDeveloper(error: Error | ErrorDetails): string;
|
|
162
|
+
static toJSON(error: Error | ErrorDetails): Record<string, any>;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
declare class CardValidator {
|
|
166
|
+
validateCardNumber(cardNumber: string): boolean;
|
|
167
|
+
detectCardType(cardNumber: string): string;
|
|
168
|
+
validateExpiry(month: number, year: number): boolean;
|
|
169
|
+
validateCVC(cvc: string, cardType?: string): boolean;
|
|
170
|
+
validateAll(cardNumber: string, expiryMonth: number, expiryYear: number, cvc: string): CardValidation;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
declare class InputSanitizer {
|
|
174
|
+
static sanitizeCardNumber(input: string): string;
|
|
175
|
+
static formatCardNumber(input: string): string;
|
|
176
|
+
static sanitizeCVC(input: string): string;
|
|
177
|
+
static sanitizeExpiry(input: string): {
|
|
178
|
+
month: number;
|
|
179
|
+
year: number;
|
|
180
|
+
} | null;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
interface ServerExtension {
|
|
184
|
+
name: string;
|
|
185
|
+
version: string;
|
|
186
|
+
beforePayment?(request: ProcessPaymentRequest): Promise<ProcessPaymentRequest>;
|
|
187
|
+
afterPayment?(result: PaymentResult): Promise<void>;
|
|
188
|
+
onPaymentError?(error: Error): Promise<void>;
|
|
189
|
+
}
|
|
190
|
+
interface DatabaseExtension extends ServerExtension {
|
|
191
|
+
recordPayment(payment: PaymentResult): Promise<void>;
|
|
192
|
+
getPaymentHistory(userId: string): Promise<PaymentResult[]>;
|
|
193
|
+
}
|
|
194
|
+
interface AnalyticsExtension extends ServerExtension {
|
|
195
|
+
trackPaymentAttempt(request: ProcessPaymentRequest): Promise<void>;
|
|
196
|
+
trackPaymentSuccess(result: PaymentResult): Promise<void>;
|
|
197
|
+
trackPaymentFailure(error: Error): Promise<void>;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
declare const VERSION = "0.0.1";
|
|
201
|
+
|
|
202
|
+
export { type AnalyticsExtension, type CardValidation, CardValidator, type DatabaseExtension, type ElementsConfig, ErrorCode, type ErrorDetails, ErrorFormatter, type InitialisePaymentRequest, type InitialisePaymentResponse, InputSanitizer, PaymentError, type PaymentResult, type ProcessPaymentRequest, type ProcessPrePaymentRequest, type ServerExtension, VERSION, ValidationError, VerapayClient, type VerapayConfig, VerapayError, VerapayService };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
import { Appearance, StripeElementLocale, StripeElementsOptions } from '@stripe/stripe-js';
|
|
2
|
+
|
|
3
|
+
interface VerapayConfig {
|
|
4
|
+
merchantId: string;
|
|
5
|
+
paymentData: PaymentData;
|
|
6
|
+
appearance?: Appearance;
|
|
7
|
+
locale?: StripeElementLocale;
|
|
8
|
+
fonts?: StripeElementsOptions['fonts'];
|
|
9
|
+
elementsConfig?: ElementsConfig;
|
|
10
|
+
}
|
|
11
|
+
interface PaymentData {
|
|
12
|
+
amount: number;
|
|
13
|
+
currency: string;
|
|
14
|
+
partnerFee?: number;
|
|
15
|
+
}
|
|
16
|
+
interface ElementsConfig {
|
|
17
|
+
style?: {
|
|
18
|
+
base?: Record<string, string>;
|
|
19
|
+
complete?: Record<string, string>;
|
|
20
|
+
empty?: Record<string, string>;
|
|
21
|
+
invalid?: Record<string, string>;
|
|
22
|
+
};
|
|
23
|
+
placeholders?: {
|
|
24
|
+
cardNumber?: string;
|
|
25
|
+
cardExpiry?: string;
|
|
26
|
+
cardCvc?: string;
|
|
27
|
+
};
|
|
28
|
+
showIcon?: boolean;
|
|
29
|
+
iconStyle?: 'default' | 'solid';
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
interface ProcessPaymentRequest {
|
|
33
|
+
description?: string;
|
|
34
|
+
metadata?: Record<string, string>;
|
|
35
|
+
returnUrl?: string;
|
|
36
|
+
customerEmail?: string;
|
|
37
|
+
}
|
|
38
|
+
interface PaymentResult {
|
|
39
|
+
success: boolean;
|
|
40
|
+
paymentIntentId?: string;
|
|
41
|
+
status: 'succeeded' | 'processing' | 'failed';
|
|
42
|
+
error?: string;
|
|
43
|
+
}
|
|
44
|
+
interface CardValidation {
|
|
45
|
+
number: {
|
|
46
|
+
isValid: boolean;
|
|
47
|
+
cardType?: 'visa' | 'mastercard' | 'amex' | 'discover' | 'unknown';
|
|
48
|
+
};
|
|
49
|
+
expiry: {
|
|
50
|
+
isValid: boolean;
|
|
51
|
+
month?: number;
|
|
52
|
+
year?: number;
|
|
53
|
+
};
|
|
54
|
+
cvc: {
|
|
55
|
+
isValid: boolean;
|
|
56
|
+
length?: number;
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
declare enum ErrorCode {
|
|
61
|
+
VALIDATION_ERROR = "VALIDATION_ERROR",
|
|
62
|
+
PAYMENT_FAILED = "PAYMENT_FAILED",
|
|
63
|
+
AUTHENTICATION_FAILED = "AUTHENTICATION_FAILED",
|
|
64
|
+
NETWORK_ERROR = "NETWORK_ERROR",
|
|
65
|
+
STRIPE_ERROR = "STRIPE_ERROR",
|
|
66
|
+
CONFIGURATION_ERROR = "CONFIGURATION_ERROR",
|
|
67
|
+
CARD_DECLINED = "CARD_DECLINED",
|
|
68
|
+
INSUFFICIENT_FUNDS = "INSUFFICIENT_FUNDS",
|
|
69
|
+
EXPIRED_CARD = "EXPIRED_CARD"
|
|
70
|
+
}
|
|
71
|
+
interface ErrorDetails {
|
|
72
|
+
code: ErrorCode;
|
|
73
|
+
message: string;
|
|
74
|
+
formattedMessage: string;
|
|
75
|
+
field?: string;
|
|
76
|
+
stripeCode?: string;
|
|
77
|
+
metadata?: Record<string, any>;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
interface PaymentExtension {
|
|
81
|
+
name: string;
|
|
82
|
+
beforePayment?(request: ProcessPaymentRequest): Promise<ProcessPaymentRequest>;
|
|
83
|
+
afterPayment?(result: PaymentResult): Promise<void>;
|
|
84
|
+
onPaymentError?(error: Error): Promise<void>;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
declare class VerapayClient {
|
|
88
|
+
private static readonly STRIPE_PUBLISHABLE_KEY;
|
|
89
|
+
private config;
|
|
90
|
+
private verapayService;
|
|
91
|
+
private extensionsManager;
|
|
92
|
+
private stripeAdapter;
|
|
93
|
+
private elementsManager;
|
|
94
|
+
private paymentService;
|
|
95
|
+
private isUsingStripePaymentElement;
|
|
96
|
+
private isUsingIndividualFormElements;
|
|
97
|
+
private clientSecret;
|
|
98
|
+
private paymentIntentId;
|
|
99
|
+
constructor(config: VerapayConfig);
|
|
100
|
+
initialize(): Promise<void>;
|
|
101
|
+
processPayment(request: ProcessPaymentRequest): Promise<PaymentResult>;
|
|
102
|
+
mountPaymentForm(selector: string): Promise<void>;
|
|
103
|
+
mountCardNumber(selector: string): Promise<void>;
|
|
104
|
+
mountCardExpiry(selector: string): Promise<void>;
|
|
105
|
+
mountCardCvc(selector: string): Promise<void>;
|
|
106
|
+
mountAddress(selector: string, mode: 'billing' | 'shipping'): Promise<void>;
|
|
107
|
+
addExtension(extension: PaymentExtension): void;
|
|
108
|
+
private ensureInitialized;
|
|
109
|
+
private validatePaymentInitialisation;
|
|
110
|
+
private toMoney;
|
|
111
|
+
private handlePaymentError;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
interface InitialisePaymentRequest {
|
|
115
|
+
merchantId: string;
|
|
116
|
+
paymentData: PaymentData;
|
|
117
|
+
}
|
|
118
|
+
interface InitialisePaymentResponse {
|
|
119
|
+
paymentIntentId: string;
|
|
120
|
+
clientSecret: string;
|
|
121
|
+
connectAccountId: string;
|
|
122
|
+
}
|
|
123
|
+
interface ProcessPrePaymentRequest {
|
|
124
|
+
merchantId: string;
|
|
125
|
+
paymentIntentId: string;
|
|
126
|
+
paymentMethodId: string;
|
|
127
|
+
customerData: Record<string, any>;
|
|
128
|
+
metadata?: Record<string, string>;
|
|
129
|
+
}
|
|
130
|
+
declare class VerapayService {
|
|
131
|
+
private readonly baseUrl;
|
|
132
|
+
constructor(baseUrl?: string);
|
|
133
|
+
initialisePayment(request: InitialisePaymentRequest): Promise<InitialisePaymentResponse>;
|
|
134
|
+
processPrePayment(request: ProcessPrePaymentRequest): Promise<void>;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
declare class VerapayError extends Error {
|
|
138
|
+
readonly code: ErrorCode;
|
|
139
|
+
readonly details: ErrorDetails;
|
|
140
|
+
constructor(message: string, code?: ErrorCode, details?: Partial<ErrorDetails>);
|
|
141
|
+
private formatMessage;
|
|
142
|
+
toJSON(): {
|
|
143
|
+
name: string;
|
|
144
|
+
code: ErrorCode;
|
|
145
|
+
message: string;
|
|
146
|
+
details: ErrorDetails;
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
declare class ValidationError extends VerapayError {
|
|
151
|
+
constructor(message: string, field?: string, metadata?: Record<string, any>);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
declare class PaymentError extends VerapayError {
|
|
155
|
+
constructor(message: string, stripeCode?: string, metadata?: Record<string, any>);
|
|
156
|
+
private static mapStripeCode;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
declare class ErrorFormatter {
|
|
160
|
+
static formatForUser(error: Error | ErrorDetails): string;
|
|
161
|
+
static formatForDeveloper(error: Error | ErrorDetails): string;
|
|
162
|
+
static toJSON(error: Error | ErrorDetails): Record<string, any>;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
declare class CardValidator {
|
|
166
|
+
validateCardNumber(cardNumber: string): boolean;
|
|
167
|
+
detectCardType(cardNumber: string): string;
|
|
168
|
+
validateExpiry(month: number, year: number): boolean;
|
|
169
|
+
validateCVC(cvc: string, cardType?: string): boolean;
|
|
170
|
+
validateAll(cardNumber: string, expiryMonth: number, expiryYear: number, cvc: string): CardValidation;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
declare class InputSanitizer {
|
|
174
|
+
static sanitizeCardNumber(input: string): string;
|
|
175
|
+
static formatCardNumber(input: string): string;
|
|
176
|
+
static sanitizeCVC(input: string): string;
|
|
177
|
+
static sanitizeExpiry(input: string): {
|
|
178
|
+
month: number;
|
|
179
|
+
year: number;
|
|
180
|
+
} | null;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
interface ServerExtension {
|
|
184
|
+
name: string;
|
|
185
|
+
version: string;
|
|
186
|
+
beforePayment?(request: ProcessPaymentRequest): Promise<ProcessPaymentRequest>;
|
|
187
|
+
afterPayment?(result: PaymentResult): Promise<void>;
|
|
188
|
+
onPaymentError?(error: Error): Promise<void>;
|
|
189
|
+
}
|
|
190
|
+
interface DatabaseExtension extends ServerExtension {
|
|
191
|
+
recordPayment(payment: PaymentResult): Promise<void>;
|
|
192
|
+
getPaymentHistory(userId: string): Promise<PaymentResult[]>;
|
|
193
|
+
}
|
|
194
|
+
interface AnalyticsExtension extends ServerExtension {
|
|
195
|
+
trackPaymentAttempt(request: ProcessPaymentRequest): Promise<void>;
|
|
196
|
+
trackPaymentSuccess(result: PaymentResult): Promise<void>;
|
|
197
|
+
trackPaymentFailure(error: Error): Promise<void>;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
declare const VERSION = "0.0.1";
|
|
201
|
+
|
|
202
|
+
export { type AnalyticsExtension, type CardValidation, CardValidator, type DatabaseExtension, type ElementsConfig, ErrorCode, type ErrorDetails, ErrorFormatter, type InitialisePaymentRequest, type InitialisePaymentResponse, InputSanitizer, PaymentError, type PaymentResult, type ProcessPaymentRequest, type ProcessPrePaymentRequest, type ServerExtension, VERSION, ValidationError, VerapayClient, type VerapayConfig, VerapayError, VerapayService };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import {loadStripe}from'@stripe/stripe-js';import {Money}from'ts-money';var i=class s extends Error{constructor(e,t="PAYMENT_FAILED",r){super(e),this.name="VerapayError",this.code=t,this.details={code:t,message:e,formattedMessage:this.formatMessage(e,t),...r},Error.captureStackTrace&&Error.captureStackTrace(this,s);}formatMessage(e,t){return {VALIDATION_ERROR:"Please check your payment information and try again.",PAYMENT_FAILED:"Your payment could not be processed. Please try again.",AUTHENTICATION_FAILED:"Payment authentication failed. Please try again.",NETWORK_ERROR:"Network error. Please check your connection and try again.",STRIPE_ERROR:"Payment service error. Please try again later.",CONFIGURATION_ERROR:"Configuration error. Please contact support.",CARD_DECLINED:"Your card was declined. Please use a different payment method.",INSUFFICIENT_FUNDS:"Insufficient funds. Please use a different payment method.",EXPIRED_CARD:"Your card has expired. Please use a different payment method."}[t]||e}toJSON(){return {name:this.name,code:this.code,message:this.message,details:this.details}}};var l=class extends i{constructor(e,t,r){super(e,"VALIDATION_ERROR",{field:t,metadata:r}),this.name="ValidationError";}};var m=class s extends i{constructor(e,t,r){let n=s.mapStripeCode(t);super(e,n,{stripeCode:t,metadata:r}),this.name="PaymentError";}static mapStripeCode(e){return e?{card_declined:"CARD_DECLINED",insufficient_funds:"INSUFFICIENT_FUNDS",expired_card:"EXPIRED_CARD",incorrect_cvc:"VALIDATION_ERROR",processing_error:"PAYMENT_FAILED",authentication_failed:"AUTHENTICATION_FAILED"}[e]||"PAYMENT_FAILED":"PAYMENT_FAILED"}};var y=class{static formatForUser(e){return "formattedMessage"in e?e.formattedMessage:"details"in e&&e.details&&typeof e.details=="object"&&"formattedMessage"in e.details&&typeof e.details.formattedMessage=="string"?e.details.formattedMessage:"An unexpected error occurred. Please try again."}static formatForDeveloper(e){return "code"in e&&"message"in e?`[${e.code}] ${e.message}`:e.message||"Unknown error"}static toJSON(e){return "toJSON"in e&&typeof e.toJSON=="function"?e.toJSON():{name:e.name||"Error",message:e.message,..."code"in e&&{code:e.code},..."details"in e&&{details:e.details}}}};var u=class{constructor(e){this.stripe=e;}async confirmPayment(e,t,r){let n=await this.stripe.confirmPayment({clientSecret:t,confirmParams:{payment_method:e,return_url:r||window.location.href},redirect:"if_required"});if(n.error)throw new m(n.error.message||"Payment failed",n.error.code);return n}async confirmCardPayment(e,t){let r=await this.stripe.confirmCardPayment(t,{payment_method:e});if(r.error)throw new m(r.error.message||"Payment failed",r.error.code);return r}async createPaymentMethod(e,t=false){let r;if(!t)r=await this.stripe.createPaymentMethod({elements:e});else {let a=(await e.getElement("address",{mode:"billing"}).getValue()).value;r=await this.stripe.createPaymentMethod({type:"card",card:e.getElement("cardNumber"),billing_details:{name:a.name,address:{...a.address,line2:a.address.line2??void 0}}});}if(r.error||!r.paymentMethod)throw new m(r.error?.message||"Failed to create payment method",r.error?.code);return r.paymentMethod.id}};var d={showIcon:true,iconStyle:"solid",placeholders:{cardNumber:"1234 1234 1234 1234",cardExpiry:"MM / YY",cardCvc:"CVC"},style:{base:{color:"#333333",fontFamily:"system-ui, -apple-system, sans-serif",fontSize:"16px","::placeholder":{color:"#aab7c4"}},complete:{color:"#333333"},empty:{},invalid:{color:"#df1b41"}}},C={cardNumber:"Card number",cardExpiry:"Expiry date",cardCvc:"CVC",address:"Address"},E=class{constructor(e,t,r){this.stripe=e;this.config=t;this.clientSecret=r;this.elements=null;this.mountedElements=new Map;this.elementStates=new Map;if(!r)throw new i("Client secret not initialized","CONFIGURATION_ERROR")}mountPaymentElement(e){if(!this.elements){let n={clientSecret:this.clientSecret,appearance:this.config.appearance,locale:this.config.locale,fonts:this.config.fonts,paymentMethodCreation:"manual"};this.elements=this.stripe.elements(n);}if(!document.querySelector(e))throw new i(`Element not found: ${e}`,"CONFIGURATION_ERROR");let r=this.elements.create("payment",{layout:"tabs"});r.mount(e),this.mountedElements.set("payment",r);}mountCardNumberElement(e){this.mountIndividualFormElement(e,"cardNumber",this.cardElementOptions("cardNumber"));}mountCardExpiryElement(e){this.mountIndividualFormElement(e,"cardExpiry",this.cardElementOptions("cardExpiry"));}mountCardCvcElement(e){this.mountIndividualFormElement(e,"cardCvc",this.cardElementOptions("cardCvc"));}mountAddressElement(e,t){this.mountIndividualFormElement(e,"address",{mode:t});}cardElementOptions(e){let{elementsConfig:t}=this.config,r={placeholder:t?.placeholders?.[e]??d.placeholders[e],style:{base:{...d.style.base,...t?.style?.base},complete:{...d.style.complete,...t?.style?.complete},empty:{...d.style.empty,...t?.style?.empty},invalid:{...d.style.invalid,...t?.style?.invalid}}};return e==="cardNumber"&&(r.showIcon=t?.showIcon??d.showIcon,r.iconStyle=t?.iconStyle??d.iconStyle),r}mountIndividualFormElement(e,t,r){if(!document.querySelector(e))throw new i(`Element not found: ${e}`,"CONFIGURATION_ERROR");let a=this.createIndividualFormElement(t,r);a.mount(e),this.mountedElements.set(t,a),this.trackElementState(t,a);}createIndividualFormElement(e,t){return this.elements||(this.elements=this.stripe.elements({appearance:this.config.appearance,locale:this.config.locale,fonts:this.config.fonts,paymentMethodCreation:"manual"})),this.elements.create(e,t)}async validate(){let e=[];for(let[t,r]of this.elementStates.entries())r.complete||e.push({field:t,message:r.error??`${C[t]??t} failed validation`});return {isValid:e.length===0,errors:e}}getElements(){return this.elements}unmountAll(){for(let e of this.mountedElements.values())e.unmount();this.mountedElements.clear(),this.elementStates.clear();}trackElementState(e,t){this.elementStates.set(e,{complete:false});let r=n=>{this.elementStates.set(e,{complete:n.complete,error:n.error?.message});};t.on("change",r);}};var f=class{constructor(){this.extensions=[];}add(e){this.extensions.push(e);}async runBeforePayment(e){let t=e;for(let r of this.extensions)r.beforePayment&&(t=await r.beforePayment(t));return t}async runAfterPayment(e){await Promise.all(this.extensions.filter(t=>t.afterPayment).map(t=>t.afterPayment(e)));}async runOnError(e){await Promise.all(this.extensions.filter(t=>t.onPaymentError).map(t=>t.onPaymentError(e)));}};var g=class{constructor(e,t,r){this.stripeAdapter=e;this.elementsManager=t;this.verapayService=r;}async process(e,t){let r=this.elementsManager.getElements();await this.validatePaymentCanProceed(r,t),await r.submit();let n=await this.stripeAdapter.createPaymentMethod(r,t.isUsingIndividualFormElements);return await this.verapayService.processPrePayment({merchantId:t.merchantId,paymentIntentId:t.paymentIntentId,paymentMethodId:n,customerData:{email:e.customerEmail,firstName:"",lastName:""},metadata:e.metadata}),this.confirmPayment(e,n,t)}async validatePaymentCanProceed(e,t){if(!e)throw new i("Payment form not mounted","CONFIGURATION_ERROR");if(t.isUsingStripePaymentElement&&t.isUsingIndividualFormElements)throw new i("Both forms of payment form in use");if(t.isUsingIndividualFormElements){let r=await this.elementsManager.validate();if(!r.isValid)throw new i(r.errors[0].message,"VALIDATION_ERROR")}}async confirmPayment(e,t,r){let{clientSecret:n,isUsingStripePaymentElement:a,isUsingIndividualFormElements:o}=r,R;return a?R=await this.stripeAdapter.confirmPayment(t,n,e.returnUrl):o&&(R=await this.stripeAdapter.confirmCardPayment(t,n)),this.formatPaymentResult(R)}formatPaymentResult(e){return {success:e.paymentIntent.status==="succeeded",paymentIntentId:e.paymentIntent.id,status:e.paymentIntent.status}}};var p=class{constructor(e="http://localhost:3333"){this.baseUrl=e;}async initialisePayment(e){let{merchantId:t,paymentData:r}=e;try{let n=await fetch(`${this.baseUrl}/api/initialise-payment`,{method:"POST",headers:{"Content-Type":"application/json","x-api-key":"example.api.key"},body:JSON.stringify({merchantId:t,paymentData:{...r,paymentMethodType:"card"}})});if(!n.ok){let o=await n.json().catch(()=>({}));throw new i(o.error||`HTTP error! status: ${n.status}`,"CONFIGURATION_ERROR")}let a=await n.json();if(!a.clientSecret||!a.paymentIntentId)throw new i("Missing clientSecret or paymentIntentId in server response","CONFIGURATION_ERROR");return {paymentIntentId:a.paymentIntentId,clientSecret:a.clientSecret,connectAccountId:a.connectAccountId}}catch(n){throw n instanceof i?n:new i(n instanceof Error?n.message:"Unknown error occurred","CONFIGURATION_ERROR")}}async processPrePayment(e){try{let t=await fetch(`${this.baseUrl}/api/process-prepayment`,{method:"POST",headers:{"Content-Type":"application/json","x-forwarded-for":"example.ip.addr"},body:JSON.stringify({merchantId:e.merchantId,paymentIntentId:e.paymentIntentId,paymentMethodId:e.paymentMethodId,customerData:e.customerData,metadata:e.metadata})});if(!t.ok){let r=await t.json().catch(()=>({}));throw new i(r.error||`HTTP error! status: ${t.status}`,"CONFIGURATION_ERROR")}}catch(t){throw t instanceof i?t:new i(t instanceof Error?t.message:"Unknown error occurred","CONFIGURATION_ERROR")}}};var h=class h{constructor(e){this.stripeAdapter=null;this.elementsManager=null;this.paymentService=null;this.isUsingStripePaymentElement=false;this.isUsingIndividualFormElements=false;this.clientSecret=null;this.paymentIntentId=null;this.config=e,this.verapayService=new p,this.extensionsManager=new f;}async initialize(){this.validatePaymentInitialisation();let{clientSecret:e,paymentIntentId:t}=await this.verapayService.initialisePayment({merchantId:this.config.merchantId,paymentData:this.config.paymentData});this.clientSecret=e,this.paymentIntentId=t;let r=await loadStripe(h.STRIPE_PUBLISHABLE_KEY);if(!r)throw new i("Failed to load Stripe","CONFIGURATION_ERROR");this.stripeAdapter=new u(r),this.elementsManager=new E(r,this.config,e),this.paymentService=new g(this.stripeAdapter,this.elementsManager,this.verapayService);}async processPayment(e){await this.ensureInitialized();let t=await this.extensionsManager.runBeforePayment(e);try{let r=await this.paymentService.process(t,{merchantId:this.config.merchantId,paymentIntentId:this.paymentIntentId,clientSecret:this.clientSecret,isUsingStripePaymentElement:this.isUsingStripePaymentElement,isUsingIndividualFormElements:this.isUsingIndividualFormElements});return await this.extensionsManager.runAfterPayment(r),r}catch(r){throw await this.extensionsManager.runOnError(r),this.handlePaymentError(r)}}async mountPaymentForm(e){await this.ensureInitialized(),this.elementsManager.mountPaymentElement(e),this.isUsingStripePaymentElement=true;}async mountCardNumber(e){await this.ensureInitialized(),this.elementsManager.mountCardNumberElement(e),this.isUsingIndividualFormElements=true;}async mountCardExpiry(e){await this.ensureInitialized(),this.elementsManager.mountCardExpiryElement(e),this.isUsingIndividualFormElements=true;}async mountCardCvc(e){await this.ensureInitialized(),this.elementsManager.mountCardCvcElement(e),this.isUsingIndividualFormElements=true;}async mountAddress(e,t){await this.ensureInitialized(),this.elementsManager.mountAddressElement(e,t),this.isUsingIndividualFormElements=true;}addExtension(e){this.extensionsManager.add(e);}async ensureInitialized(){this.stripeAdapter||await this.initialize();}validatePaymentInitialisation(){let{amount:e,currency:t,partnerFee:r}=this.config.paymentData;if(!t)throw new l("Currency is required","currency");let n=t.toUpperCase(),a=this.toMoney(e,n,"amount");if(a.isZero()||a.isNegative())throw new l("Amount must be greater than 0","amount");if(r!==void 0&&this.toMoney(r,n,"partnerFee").isNegative())throw new l("partnerFee cannot be negative","partnerFee")}toMoney(e,t,r){try{return Money.fromInteger(e,t)}catch{throw new l(`${r} must be an integer in the smallest currency unit (e.g., cents for USD)`,r)}}handlePaymentError(e){return e instanceof i?e:new m(e.message||"Payment failed",e.code)}};h.STRIPE_PUBLISHABLE_KEY="pk_test_51T6ts0GU0Zq3ZuYLSciVz44jEsdaUBd4HRHIQCFSRt7VfBJt9vTJGJAXKYMynC64Ot0cCw9XjTGxCd8ZC44tfMkl00jWhD2UNq";var v=h;var I=class{validateCardNumber(e){let t=e.replace(/\D/g,"");if(t.length<13||t.length>19)return false;let r=0,n=false;for(let a=t.length-1;a>=0;a--){let o=parseInt(t[a],10);n&&(o*=2,o>9&&(o-=9)),r+=o,n=!n;}return r%10===0}detectCardType(e){let t=e.replace(/\D/g,"");return /^4/.test(t)?"visa":/^5[1-5]/.test(t)?"mastercard":/^3[47]/.test(t)?"amex":/^6(?:011|5)/.test(t)?"discover":"unknown"}validateExpiry(e,t){let r=new Date,n=r.getFullYear(),a=r.getMonth()+1;if(e<1||e>12)return false;let o=t<100?2e3+t:t;return !(o<n||o===n&&e<a)}validateCVC(e,t="unknown"){let r=e.replace(/\D/g,"");return t==="amex"?r.length===4:r.length===3||r.length===4}validateAll(e,t,r,n){let a=this.detectCardType(e);return {number:{isValid:this.validateCardNumber(e),cardType:a},expiry:{isValid:this.validateExpiry(t,r),month:t,year:r},cvc:{isValid:this.validateCVC(n,a),length:n.replace(/\D/g,"").length}}}};var P=class{static sanitizeCardNumber(e){return e.replace(/\D/g,"")}static formatCardNumber(e){return this.sanitizeCardNumber(e).replace(/(\d{4})/g,"$1 ").trim()}static sanitizeCVC(e){return e.replace(/\D/g,"").slice(0,4)}static sanitizeExpiry(e){let t=e.replace(/\D/g,"");return t.length===4?{month:parseInt(t.slice(0,2),10),year:parseInt(t.slice(2,4),10)}:t.length===6?{month:parseInt(t.slice(0,2),10),year:parseInt(t.slice(2,6),10)}:null}};var Ee="0.0.1";
|
|
2
|
+
export{I as CardValidator,y as ErrorFormatter,P as InputSanitizer,m as PaymentError,Ee as VERSION,l as ValidationError,v as VerapayClient,i as VerapayError,p as VerapayService};//# sourceMappingURL=index.js.map
|
|
3
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/errors/VerapayError.ts","../src/errors/ValidationError.ts","../src/errors/PaymentError.ts","../src/errors/errorFormatter.ts","../src/client/StripeAdapter.ts","../src/client/ElementsManager.ts","../src/client/PaymentExtensionsManager.ts","../src/services/PaymentService.ts","../src/services/VerapayService.ts","../src/client/VerapayClient.ts","../src/validation/cardValidator.ts","../src/validation/inputSanitizer.ts","../src/index.ts"],"names":["VerapayError","_VerapayError","message","code","details","ValidationError","field","metadata","PaymentError","_PaymentError","stripeCode","ErrorFormatter","error","StripeAdapter","stripe","paymentMethodId","clientSecret","returnUrl","result","elements","isUsingIndividualFormElements","address","DEFAULT_CARD_ELEMENT_CONFIG","FIELD_LABELS","ElementsManager","config","selector","elementsConfig","element","mode","fieldType","options","formFieldType","errors","state","handleElementChange","event","PaymentExtensionsManager","extension","request","modifiedRequest","ext","PaymentService","stripeAdapter","elementsManager","verapayService","context","validation","isUsingStripePaymentElement","VerapayService","baseUrl","merchantId","paymentData","response","errorData","data","_VerapayClient","paymentIntentId","loadStripe","paymentResult","amount","currency","partnerFee","uppercaseCurrency","paymentAmount","value","fieldName","Money","VerapayClient","CardValidator","cardNumber","cleaned","sum","isEven","i","digit","month","year","now","currentYear","currentMonth","fullYear","cvc","cardType","expiryMonth","expiryYear","InputSanitizer","input","VERSION"],"mappings":"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","file":"index.js","sourcesContent":["import type { ErrorDetails } from '../types';\nimport { ErrorCode } from '../types';\n\nexport class VerapayError extends Error {\n public readonly code: ErrorCode;\n public readonly details: ErrorDetails;\n\n constructor(\n message: string,\n code: ErrorCode = ErrorCode.PAYMENT_FAILED,\n details?: Partial<ErrorDetails>\n ) {\n super(message);\n this.name = 'VerapayError';\n this.code = code;\n this.details = {\n code,\n message,\n formattedMessage: this.formatMessage(message, code),\n ...details,\n };\n\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, VerapayError);\n }\n }\n\n private formatMessage(message: string, code: ErrorCode): string {\n const messageMap: Record<ErrorCode, string> = {\n [ErrorCode.VALIDATION_ERROR]:\n 'Please check your payment information and try again.',\n [ErrorCode.PAYMENT_FAILED]:\n 'Your payment could not be processed. Please try again.',\n [ErrorCode.AUTHENTICATION_FAILED]:\n 'Payment authentication failed. Please try again.',\n [ErrorCode.NETWORK_ERROR]:\n 'Network error. Please check your connection and try again.',\n [ErrorCode.STRIPE_ERROR]:\n 'Payment service error. Please try again later.',\n [ErrorCode.CONFIGURATION_ERROR]:\n 'Configuration error. Please contact support.',\n [ErrorCode.CARD_DECLINED]:\n 'Your card was declined. Please use a different payment method.',\n [ErrorCode.INSUFFICIENT_FUNDS]:\n 'Insufficient funds. Please use a different payment method.',\n [ErrorCode.EXPIRED_CARD]:\n 'Your card has expired. Please use a different payment method.',\n };\n\n return messageMap[code] || message;\n }\n\n toJSON() {\n return {\n name: this.name,\n code: this.code,\n message: this.message,\n details: this.details,\n };\n }\n}\n","import { VerapayError } from './VerapayError';\nimport { ErrorCode } from '../types';\n\nexport class ValidationError extends VerapayError {\n constructor(message: string, field?: string, metadata?: Record<string, any>) {\n super(message, ErrorCode.VALIDATION_ERROR, {\n field,\n metadata,\n });\n this.name = 'ValidationError';\n }\n}\n","import { VerapayError } from './VerapayError';\nimport { ErrorCode } from '../types';\n\nexport class PaymentError extends VerapayError {\n constructor(\n message: string,\n stripeCode?: string,\n metadata?: Record<string, any>\n ) {\n const code = PaymentError.mapStripeCode(stripeCode);\n super(message, code, {\n stripeCode,\n metadata,\n });\n this.name = 'PaymentError';\n }\n\n private static mapStripeCode(stripeCode?: string): ErrorCode {\n if (!stripeCode) return ErrorCode.PAYMENT_FAILED;\n\n const codeMap: Record<string, ErrorCode> = {\n card_declined: ErrorCode.CARD_DECLINED,\n insufficient_funds: ErrorCode.INSUFFICIENT_FUNDS,\n expired_card: ErrorCode.EXPIRED_CARD,\n incorrect_cvc: ErrorCode.VALIDATION_ERROR,\n processing_error: ErrorCode.PAYMENT_FAILED,\n authentication_failed: ErrorCode.AUTHENTICATION_FAILED,\n };\n\n return codeMap[stripeCode] || ErrorCode.PAYMENT_FAILED;\n }\n}\n","import type { ErrorDetails } from '../types';\n\nexport class ErrorFormatter {\n static formatForUser(error: Error | ErrorDetails): string {\n if ('formattedMessage' in error) {\n return error.formattedMessage;\n }\n if (\n 'details' in error &&\n error.details &&\n typeof error.details === 'object' &&\n 'formattedMessage' in error.details &&\n typeof error.details.formattedMessage === 'string'\n ) {\n return error.details.formattedMessage;\n }\n return 'An unexpected error occurred. Please try again.';\n }\n\n static formatForDeveloper(error: Error | ErrorDetails): string {\n if ('code' in error && 'message' in error) {\n return `[${error.code}] ${error.message}`;\n }\n return error.message || 'Unknown error';\n }\n\n static toJSON(error: Error | ErrorDetails): Record<string, any> {\n if ('toJSON' in error && typeof error.toJSON === 'function') {\n return error.toJSON();\n }\n\n return {\n name: (error as Error).name || 'Error',\n message: error.message,\n ...('code' in error && { code: error.code }),\n ...('details' in error && { details: error.details }),\n };\n }\n}\n","import type { PaymentIntent, Stripe, StripeElements } from '@stripe/stripe-js';\nimport { PaymentError } from '../errors';\n\nexport class StripeAdapter {\n constructor(private stripe: Stripe) {}\n\n async confirmPayment(\n paymentMethodId: string,\n clientSecret: string,\n returnUrl?: string\n ): Promise<{ paymentIntent: PaymentIntent }> {\n const result = await this.stripe.confirmPayment({\n clientSecret,\n confirmParams: {\n payment_method: paymentMethodId,\n return_url: returnUrl || window.location.href,\n },\n redirect: 'if_required',\n });\n\n if (result.error) {\n throw new PaymentError(\n result.error.message || 'Payment failed',\n result.error.code\n );\n }\n\n return result as { paymentIntent: PaymentIntent };\n }\n\n async confirmCardPayment(\n paymentMethodId: string,\n clientSecret: string\n ): Promise<{ paymentIntent: PaymentIntent }> {\n const result = await this.stripe.confirmCardPayment(clientSecret, {\n payment_method: paymentMethodId,\n });\n\n if (result.error) {\n throw new PaymentError(\n result.error.message || 'Payment failed',\n result.error.code\n );\n }\n\n return result as { paymentIntent: PaymentIntent };\n }\n\n async createPaymentMethod(\n elements: StripeElements,\n isUsingIndividualFormElements: boolean = false\n ): Promise<string> {\n let result;\n\n if (!isUsingIndividualFormElements) {\n result = await this.stripe.createPaymentMethod({\n elements,\n });\n } else {\n // @ts-ignore - Stripe types don't include mode parameter for getElement\n const addressElement = await elements.getElement('address', { mode: 'billing' })!.getValue();\n const address = addressElement!.value;\n\n result = await this.stripe.createPaymentMethod({\n type: 'card',\n card: elements.getElement('cardNumber')!,\n billing_details: {\n name: address.name,\n address: {\n ...address.address,\n line2: address.address.line2 ?? undefined,\n },\n },\n });\n }\n\n if (result.error || !result.paymentMethod) {\n throw new PaymentError(\n result.error?.message || 'Failed to create payment method',\n result.error?.code\n );\n }\n\n return result.paymentMethod.id;\n }\n}\n","import type {\n Stripe,\n StripeElements,\n StripeElement,\n StripePaymentElement,\n StripeCardNumberElement,\n} from '@stripe/stripe-js';\nimport type { VerapayConfig, ValidationError, ValidationResult } from '../types';\nimport { VerapayError, ErrorCode } from '../errors';\n\ntype ElementState = { complete: boolean; error?: string }\n\nconst DEFAULT_CARD_ELEMENT_CONFIG = {\n showIcon: true,\n iconStyle: 'solid' as const,\n placeholders: {\n cardNumber: '1234 1234 1234 1234',\n cardExpiry: 'MM / YY',\n cardCvc: 'CVC',\n },\n style: {\n base: {\n color: '#333333',\n fontFamily: 'system-ui, -apple-system, sans-serif',\n fontSize: '16px',\n '::placeholder': { color: '#aab7c4' },\n },\n complete: {\n color: '#333333',\n },\n empty: {},\n invalid: {\n color: '#df1b41',\n },\n },\n}\n\nconst FIELD_LABELS: Record<string, string> = {\n cardNumber: 'Card number',\n cardExpiry: 'Expiry date',\n cardCvc: 'CVC',\n address: 'Address',\n}\n\nexport class ElementsManager {\n private elements: StripeElements | null = null;\n private mountedElements: Map<string, StripeElement> = new Map();\n private elementStates: Map<string, ElementState> = new Map();\n\n constructor(\n private stripe: Stripe,\n private config: VerapayConfig,\n private clientSecret: string\n ) {\n if (!clientSecret) {\n throw new VerapayError(\n 'Client secret not initialized',\n ErrorCode.CONFIGURATION_ERROR\n );\n }\n }\n\n mountPaymentElement(selector: string): void {\n if (!this.elements) {\n const elementsConfig = {\n clientSecret: this.clientSecret,\n appearance: this.config.appearance,\n locale: this.config.locale,\n fonts: this.config.fonts,\n paymentMethodCreation: 'manual',\n };\n\n this.elements = this.stripe.elements(elementsConfig);\n }\n\n const container = document.querySelector(selector);\n\n if (!container) {\n throw new VerapayError(\n `Element not found: ${selector}`,\n ErrorCode.CONFIGURATION_ERROR\n );\n }\n\n const element = this.elements.create('payment', {\n layout: 'tabs',\n }) as StripePaymentElement;\n\n element.mount(selector);\n this.mountedElements.set('payment', element);\n }\n\n mountCardNumberElement(selector: string): void {\n this.mountIndividualFormElement(selector, 'cardNumber', this.cardElementOptions('cardNumber'));\n }\n\n mountCardExpiryElement(selector: string): void {\n this.mountIndividualFormElement(selector, 'cardExpiry', this.cardElementOptions('cardExpiry'));\n }\n\n mountCardCvcElement(selector: string): void {\n this.mountIndividualFormElement(selector, 'cardCvc', this.cardElementOptions('cardCvc'));\n }\n\n mountAddressElement(selector: string, mode: 'billing' | 'shipping'): void {\n this.mountIndividualFormElement(selector, 'address', { mode });\n }\n\n private cardElementOptions(fieldType: 'cardNumber' | 'cardExpiry' | 'cardCvc'): Record<string, unknown> {\n const { elementsConfig } = this.config;\n const options: Record<string, unknown> = {\n placeholder: elementsConfig?.placeholders?.[fieldType] ?? DEFAULT_CARD_ELEMENT_CONFIG.placeholders[fieldType],\n style: {\n base: { ...DEFAULT_CARD_ELEMENT_CONFIG.style.base, ...elementsConfig?.style?.base },\n complete: { ...DEFAULT_CARD_ELEMENT_CONFIG.style.complete, ...elementsConfig?.style?.complete },\n empty: { ...DEFAULT_CARD_ELEMENT_CONFIG.style.empty, ...elementsConfig?.style?.empty },\n invalid: { ...DEFAULT_CARD_ELEMENT_CONFIG.style.invalid, ...elementsConfig?.style?.invalid },\n },\n };\n\n if (fieldType === 'cardNumber') {\n options.showIcon = elementsConfig?.showIcon ?? DEFAULT_CARD_ELEMENT_CONFIG.showIcon;\n options.iconStyle = elementsConfig?.iconStyle ?? DEFAULT_CARD_ELEMENT_CONFIG.iconStyle;\n }\n\n return options;\n }\n\n private mountIndividualFormElement(selector: string, formFieldType: 'cardNumber' | 'cardExpiry' | 'cardCvc' | 'address', options?: Record<string, unknown>) {\n const container = document.querySelector(selector);\n\n if (!container) {\n throw new VerapayError(\n `Element not found: ${selector}`,\n ErrorCode.CONFIGURATION_ERROR\n );\n }\n\n const element = this.createIndividualFormElement(formFieldType, options) as StripeCardNumberElement;\n element.mount(selector);\n\n this.mountedElements.set(formFieldType, element);\n this.trackElementState(formFieldType, element);\n }\n\n private createIndividualFormElement(\n formFieldType: any,\n options?: Record<string, unknown>\n ): StripeElement {\n if (!this.elements) {\n // For individual card elements, don't pass clientSecret\n // It's only needed when creating Payment Element or confirming payment\n this.elements = this.stripe.elements({\n appearance: this.config.appearance,\n locale: this.config.locale,\n fonts: this.config.fonts,\n paymentMethodCreation: 'manual',\n });\n }\n\n return this.elements.create(formFieldType, options);\n }\n\n async validate(): Promise<ValidationResult> {\n const errors: ValidationError[] = []\n\n for (const [field, state] of this.elementStates.entries()) {\n if (!state.complete) {\n errors.push({\n field,\n message: state.error ?? `${FIELD_LABELS[field] ?? field} failed validation`,\n })\n }\n }\n\n return { isValid: errors.length === 0, errors }\n }\n\n getElements(): StripeElements | null {\n return this.elements;\n }\n\n unmountAll(): void {\n for (const element of this.mountedElements.values()) {\n element.unmount();\n }\n this.mountedElements.clear();\n this.elementStates.clear();\n }\n\n private trackElementState(field: string, element: StripeElement): void {\n this.elementStates.set(field, { complete: false })\n\n const handleElementChange = (event: { complete: boolean; error?: { message: string } }) => {\n this.elementStates.set(field, { complete: event.complete, error: event.error?.message })\n };\n\n (element as any).on('change', handleElementChange)\n }\n}\n","import type { ProcessPaymentRequest, PaymentResult } from '../types'\n\nexport interface PaymentExtension {\n name: string\n beforePayment?(request: ProcessPaymentRequest): Promise<ProcessPaymentRequest>\n afterPayment?(result: PaymentResult): Promise<void>\n onPaymentError?(error: Error): Promise<void>\n}\n\nexport class PaymentExtensionsManager {\n private extensions: PaymentExtension[] = []\n\n add(extension: PaymentExtension): void {\n this.extensions.push(extension)\n }\n\n async runBeforePayment(request: ProcessPaymentRequest): Promise<ProcessPaymentRequest> {\n let modifiedRequest = request\n for (const ext of this.extensions) {\n if (ext.beforePayment) {\n modifiedRequest = await ext.beforePayment(modifiedRequest)\n }\n }\n return modifiedRequest\n }\n\n async runAfterPayment(result: PaymentResult): Promise<void> {\n await Promise.all(\n this.extensions\n .filter((ext) => ext.afterPayment)\n .map((ext) => ext.afterPayment!(result)),\n )\n }\n\n async runOnError(error: Error): Promise<void> {\n await Promise.all(\n this.extensions\n .filter((ext) => ext.onPaymentError)\n .map((ext) => ext.onPaymentError!(error)),\n )\n }\n}\n","import { StripeAdapter } from '../client/StripeAdapter'\nimport { ElementsManager } from '../client/ElementsManager'\nimport { ErrorCode, VerapayError } from '../errors'\nimport { VerapayService } from './VerapayService'\nimport type { ProcessPaymentRequest, PaymentResult } from '../types'\nimport { StripeElements } from '@stripe/stripe-js';\n\nexport interface ProcessPaymentContext {\n merchantId: string\n paymentIntentId: string\n clientSecret: string\n isUsingStripePaymentElement: boolean\n isUsingIndividualFormElements: boolean\n}\n\nexport class PaymentService {\n constructor(\n private stripeAdapter: StripeAdapter,\n private elementsManager: ElementsManager,\n private verapayService: VerapayService,\n ) {}\n\n async process(request: ProcessPaymentRequest, context: ProcessPaymentContext): Promise<PaymentResult> {\n const elements = this.elementsManager.getElements()\n\n await this.validatePaymentCanProceed(elements, context);\n\n await elements!.submit()\n\n const paymentMethodId = await this.stripeAdapter.createPaymentMethod(\n elements!,\n context.isUsingIndividualFormElements,\n )\n\n await this.verapayService.processPrePayment({\n merchantId: context.merchantId,\n paymentIntentId: context.paymentIntentId,\n paymentMethodId,\n customerData: {\n email: request.customerEmail,\n firstName: '',\n lastName: '',\n },\n metadata: request.metadata,\n })\n\n return this.confirmPayment(request, paymentMethodId, context)\n }\n\n private async validatePaymentCanProceed(elements: StripeElements | null, context: ProcessPaymentContext) {\n if (!elements) {\n throw new VerapayError('Payment form not mounted', ErrorCode.CONFIGURATION_ERROR)\n }\n\n if (context.isUsingStripePaymentElement && context.isUsingIndividualFormElements) {\n throw new VerapayError('Both forms of payment form in use');\n }\n\n if (context.isUsingIndividualFormElements) {\n const validation = await this.elementsManager.validate()\n if (!validation.isValid) {\n throw new VerapayError(validation.errors[0].message, ErrorCode.VALIDATION_ERROR)\n }\n }\n }\n\n private async confirmPayment(\n request: ProcessPaymentRequest,\n paymentMethodId: string,\n context: ProcessPaymentContext,\n ): Promise<PaymentResult> {\n const { clientSecret, isUsingStripePaymentElement, isUsingIndividualFormElements } = context\n\n let result\n\n if (isUsingStripePaymentElement) {\n result = await this.stripeAdapter.confirmPayment(paymentMethodId, clientSecret, request.returnUrl)\n } else if (isUsingIndividualFormElements) {\n result = await this.stripeAdapter.confirmCardPayment(paymentMethodId, clientSecret)\n }\n\n return this.formatPaymentResult(result)\n }\n\n private formatPaymentResult(result: any): PaymentResult {\n return {\n success: result.paymentIntent.status === 'succeeded',\n paymentIntentId: result.paymentIntent.id,\n status: result.paymentIntent.status,\n }\n }\n}\n","import { ErrorCode, VerapayError } from '../errors';\nimport { PaymentData } from '../types';\n\nexport interface InitialisePaymentRequest {\n merchantId: string;\n paymentData: PaymentData;\n}\n\nexport interface InitialisePaymentResponse {\n paymentIntentId: string;\n clientSecret: string;\n connectAccountId: string;\n}\n\nexport interface ProcessPrePaymentRequest {\n merchantId: string;\n paymentIntentId: string;\n paymentMethodId: string;\n customerData: Record<string, any>;\n metadata?: Record<string, string>;\n}\n\nexport class VerapayService {\n private readonly baseUrl: string;\n\n constructor(baseUrl: string = 'http://localhost:3333') {\n this.baseUrl = baseUrl;\n }\n\n async initialisePayment(\n request: InitialisePaymentRequest\n ): Promise<InitialisePaymentResponse> {\n const { merchantId, paymentData } = request;\n\n try {\n const response = await fetch(`${this.baseUrl}/api/initialise-payment`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'x-api-key': 'example.api.key',\n },\n body: JSON.stringify({\n merchantId,\n paymentData: { ...paymentData, paymentMethodType: 'card' },\n }),\n });\n\n if (!response.ok) {\n const errorData = await response.json().catch(() => ({}));\n throw new VerapayError(\n errorData.error || `HTTP error! status: ${response.status}`,\n ErrorCode.CONFIGURATION_ERROR\n );\n }\n\n const data = await response.json();\n\n if (!data.clientSecret || !data.paymentIntentId) {\n throw new VerapayError(\n 'Missing clientSecret or paymentIntentId in server response',\n ErrorCode.CONFIGURATION_ERROR\n );\n }\n\n return {\n paymentIntentId: data.paymentIntentId,\n clientSecret: data.clientSecret,\n connectAccountId: data.connectAccountId,\n };\n } catch (error) {\n if (error instanceof VerapayError) {\n throw error;\n }\n throw new VerapayError(\n error instanceof Error ? error.message : 'Unknown error occurred',\n ErrorCode.CONFIGURATION_ERROR\n );\n }\n }\n\n async processPrePayment(request: ProcessPrePaymentRequest): Promise<void> {\n try {\n const response = await fetch(`${this.baseUrl}/api/process-prepayment`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'x-forwarded-for': 'example.ip.addr',\n },\n body: JSON.stringify({\n merchantId: request.merchantId,\n paymentIntentId: request.paymentIntentId,\n paymentMethodId: request.paymentMethodId,\n customerData: request.customerData,\n metadata: request.metadata,\n }),\n });\n\n if (!response.ok) {\n const errorData = await response.json().catch(() => ({}));\n throw new VerapayError(\n errorData.error || `HTTP error! status: ${response.status}`,\n ErrorCode.CONFIGURATION_ERROR\n );\n }\n } catch (error) {\n if (error instanceof VerapayError) {\n throw error;\n }\n throw new VerapayError(\n error instanceof Error ? error.message : 'Unknown error occurred',\n ErrorCode.CONFIGURATION_ERROR\n );\n }\n }\n}\n","import { loadStripe } from '@stripe/stripe-js';\nimport { Money } from 'ts-money';\nimport { StripeAdapter } from './StripeAdapter';\nimport { ElementsManager } from './ElementsManager';\nimport type { PaymentExtension } from './PaymentExtensionsManager';\nimport { PaymentExtensionsManager } from './PaymentExtensionsManager';\nimport { PaymentService } from '../services/PaymentService';\nimport {\n ErrorCode,\n VerapayError,\n PaymentError,\n ValidationError,\n} from '../errors';\nimport { VerapayService } from '../services/VerapayService';\nimport type {\n VerapayConfig,\n ProcessPaymentRequest,\n PaymentResult,\n} from '../types';\n\nexport class VerapayClient {\n private static readonly STRIPE_PUBLISHABLE_KEY =\n 'pk_test_51T6ts0GU0Zq3ZuYLSciVz44jEsdaUBd4HRHIQCFSRt7VfBJt9vTJGJAXKYMynC64Ot0cCw9XjTGxCd8ZC44tfMkl00jWhD2UNq';\n\n private config: VerapayConfig;\n private verapayService: VerapayService;\n private extensionsManager: PaymentExtensionsManager;\n\n private stripeAdapter: StripeAdapter | null = null;\n private elementsManager: ElementsManager | null = null;\n private paymentService: PaymentService | null = null;\n\n private isUsingStripePaymentElement: boolean = false;\n private isUsingIndividualFormElements: boolean = false;\n\n private clientSecret: string | null = null;\n private paymentIntentId: string | null = null;\n\n constructor(config: VerapayConfig) {\n this.config = config;\n this.verapayService = new VerapayService();\n this.extensionsManager = new PaymentExtensionsManager();\n }\n\n async initialize(): Promise<void> {\n this.validatePaymentInitialisation()\n\n const { clientSecret, paymentIntentId } =\n await this.verapayService.initialisePayment({\n merchantId: this.config.merchantId,\n paymentData: this.config.paymentData\n });\n\n this.clientSecret = clientSecret;\n this.paymentIntentId = paymentIntentId;\n\n const stripe = await loadStripe(VerapayClient.STRIPE_PUBLISHABLE_KEY);\n\n if (!stripe) {\n throw new VerapayError(\n 'Failed to load Stripe',\n ErrorCode.CONFIGURATION_ERROR\n );\n }\n\n this.stripeAdapter = new StripeAdapter(stripe);\n this.elementsManager = new ElementsManager(\n stripe,\n this.config,\n clientSecret\n );\n this.paymentService = new PaymentService(\n this.stripeAdapter,\n this.elementsManager,\n this.verapayService\n );\n }\n\n async processPayment(request: ProcessPaymentRequest): Promise<PaymentResult> {\n await this.ensureInitialized();\n\n let modifiedRequest =\n await this.extensionsManager.runBeforePayment(request);\n\n try {\n const paymentResult = await this.paymentService!.process(\n modifiedRequest,\n {\n merchantId: this.config.merchantId,\n paymentIntentId: this.paymentIntentId!,\n clientSecret: this.clientSecret!,\n isUsingStripePaymentElement: this.isUsingStripePaymentElement,\n isUsingIndividualFormElements: this.isUsingIndividualFormElements,\n }\n );\n\n await this.extensionsManager.runAfterPayment(paymentResult);\n\n return paymentResult;\n } catch (error) {\n await this.extensionsManager.runOnError(error as Error);\n throw this.handlePaymentError(error);\n }\n }\n\n async mountPaymentForm(selector: string): Promise<void> {\n await this.ensureInitialized();\n this.elementsManager!.mountPaymentElement(selector);\n this.isUsingStripePaymentElement = true;\n }\n\n async mountCardNumber(selector: string): Promise<void> {\n await this.ensureInitialized();\n this.elementsManager!.mountCardNumberElement(selector);\n this.isUsingIndividualFormElements = true;\n }\n\n async mountCardExpiry(selector: string): Promise<void> {\n await this.ensureInitialized();\n this.elementsManager!.mountCardExpiryElement(selector);\n this.isUsingIndividualFormElements = true;\n }\n\n async mountCardCvc(selector: string): Promise<void> {\n await this.ensureInitialized();\n this.elementsManager!.mountCardCvcElement(selector);\n this.isUsingIndividualFormElements = true;\n }\n\n async mountAddress(\n selector: string,\n mode: 'billing' | 'shipping'\n ): Promise<void> {\n await this.ensureInitialized();\n this.elementsManager!.mountAddressElement(selector, mode);\n this.isUsingIndividualFormElements = true;\n }\n\n addExtension(extension: PaymentExtension): void {\n this.extensionsManager.add(extension);\n }\n\n private async ensureInitialized(): Promise<void> {\n if (!this.stripeAdapter) {\n await this.initialize();\n }\n }\n\n private validatePaymentInitialisation(): void {\n const { amount, currency, partnerFee } = this.config.paymentData;\n\n if (!currency) {\n throw new ValidationError('Currency is required', 'currency');\n }\n\n const uppercaseCurrency = currency.toUpperCase();\n\n const paymentAmount = this.toMoney(amount, uppercaseCurrency, 'amount');\n\n if (paymentAmount.isZero() || paymentAmount.isNegative()) {\n throw new ValidationError('Amount must be greater than 0', 'amount');\n }\n\n if (partnerFee !== undefined) {\n const partnerFeeAmount = this.toMoney(partnerFee, uppercaseCurrency, 'partnerFee');\n\n if (partnerFeeAmount.isNegative()) {\n throw new ValidationError('partnerFee cannot be negative', 'partnerFee');\n }\n }\n }\n\n private toMoney(value: number, currency: string, fieldName: string): Money {\n try {\n return Money.fromInteger(value, currency);\n } catch {\n throw new ValidationError(\n `${fieldName} must be an integer in the smallest currency unit (e.g., cents for USD)`,\n fieldName\n );\n }\n }\n\n private handlePaymentError(error: any): Error {\n if (error instanceof VerapayError) {\n return error;\n }\n return new PaymentError(error.message || 'Payment failed', error.code);\n }\n}\n","import type { CardValidation } from '../types';\n\nexport class CardValidator {\n validateCardNumber(cardNumber: string): boolean {\n const cleaned = cardNumber.replace(/\\D/g, '');\n\n if (cleaned.length < 13 || cleaned.length > 19) {\n return false;\n }\n\n let sum = 0;\n let isEven = false;\n\n for (let i = cleaned.length - 1; i >= 0; i--) {\n let digit = parseInt(cleaned[i], 10);\n\n if (isEven) {\n digit *= 2;\n if (digit > 9) {\n digit -= 9;\n }\n }\n\n sum += digit;\n isEven = !isEven;\n }\n\n return sum % 10 === 0;\n }\n\n detectCardType(cardNumber: string): string {\n const cleaned = cardNumber.replace(/\\D/g, '');\n\n if (/^4/.test(cleaned)) return 'visa';\n if (/^5[1-5]/.test(cleaned)) return 'mastercard';\n if (/^3[47]/.test(cleaned)) return 'amex';\n if (/^6(?:011|5)/.test(cleaned)) return 'discover';\n\n return 'unknown';\n }\n\n validateExpiry(month: number, year: number): boolean {\n const now = new Date();\n const currentYear = now.getFullYear();\n const currentMonth = now.getMonth() + 1;\n\n if (month < 1 || month > 12) {\n return false;\n }\n\n const fullYear = year < 100 ? 2000 + year : year;\n\n if (fullYear < currentYear) {\n return false;\n }\n\n if (fullYear === currentYear && month < currentMonth) {\n return false;\n }\n\n return true;\n }\n\n validateCVC(cvc: string, cardType: string = 'unknown'): boolean {\n const cleaned = cvc.replace(/\\D/g, '');\n\n if (cardType === 'amex') {\n return cleaned.length === 4;\n }\n\n return cleaned.length === 3 || cleaned.length === 4;\n }\n\n validateAll(\n cardNumber: string,\n expiryMonth: number,\n expiryYear: number,\n cvc: string\n ): CardValidation {\n const cardType = this.detectCardType(cardNumber);\n\n return {\n number: {\n isValid: this.validateCardNumber(cardNumber),\n cardType: cardType as any,\n },\n expiry: {\n isValid: this.validateExpiry(expiryMonth, expiryYear),\n month: expiryMonth,\n year: expiryYear,\n },\n cvc: {\n isValid: this.validateCVC(cvc, cardType),\n length: cvc.replace(/\\D/g, '').length,\n },\n };\n }\n}\n","export class InputSanitizer {\n static sanitizeCardNumber(input: string): string {\n return input.replace(/\\D/g, '');\n }\n\n static formatCardNumber(input: string): string {\n const cleaned = this.sanitizeCardNumber(input);\n return cleaned.replace(/(\\d{4})/g, '$1 ').trim();\n }\n\n static sanitizeCVC(input: string): string {\n return input.replace(/\\D/g, '').slice(0, 4);\n }\n\n static sanitizeExpiry(input: string): { month: number; year: number } | null {\n const cleaned = input.replace(/\\D/g, '');\n\n if (cleaned.length === 4) {\n return {\n month: parseInt(cleaned.slice(0, 2), 10),\n year: parseInt(cleaned.slice(2, 4), 10),\n };\n } else if (cleaned.length === 6) {\n return {\n month: parseInt(cleaned.slice(0, 2), 10),\n year: parseInt(cleaned.slice(2, 6), 10),\n };\n }\n\n return null;\n }\n}\n","export { VerapayClient } from './client/VerapayClient';\nexport { VerapayService } from './services/VerapayService';\n\nexport type {\n InitialisePaymentRequest,\n InitialisePaymentResponse,\n ProcessPrePaymentRequest,\n} from './services/VerapayService';\n\nexport type {\n VerapayConfig,\n ElementsConfig,\n ProcessPaymentRequest,\n PaymentResult,\n CardValidation,\n ErrorDetails,\n ErrorCode,\n} from './types';\n\nexport {\n VerapayError,\n ValidationError,\n PaymentError,\n ErrorFormatter,\n} from './errors';\n\nexport { CardValidator, InputSanitizer } from './validation';\n\nexport type {\n ServerExtension,\n DatabaseExtension,\n AnalyticsExtension,\n} from './extensions';\n\nexport const VERSION = '0.0.1';\n"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@verapay/verapay-js",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "Simple TypeScript SDK for Stripe payment processing",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.cjs",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"import": "./dist/index.js",
|
|
12
|
+
"require": "./dist/index.cjs",
|
|
13
|
+
"types": "./dist/index.d.ts"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"dist",
|
|
18
|
+
"README.md",
|
|
19
|
+
"LICENSE"
|
|
20
|
+
],
|
|
21
|
+
"scripts": {
|
|
22
|
+
"build": "tsup src/index.ts --format esm,cjs --dts --clean",
|
|
23
|
+
"dev": "tsup src/index.ts --format esm,cjs --dts --watch",
|
|
24
|
+
"test": "vitest",
|
|
25
|
+
"test:coverage": "vitest --coverage",
|
|
26
|
+
"lint": "eslint src --ext .ts",
|
|
27
|
+
"format": "prettier --write \"src/**/*.ts\"",
|
|
28
|
+
"typecheck": "tsc --noEmit",
|
|
29
|
+
"prepublishOnly": "npm run typecheck && npm run test && npm run build"
|
|
30
|
+
},
|
|
31
|
+
"keywords": [
|
|
32
|
+
"stripe",
|
|
33
|
+
"payment",
|
|
34
|
+
"sdk",
|
|
35
|
+
"typescript",
|
|
36
|
+
"payments",
|
|
37
|
+
"stripe-js",
|
|
38
|
+
"pci-compliant"
|
|
39
|
+
],
|
|
40
|
+
"author": "",
|
|
41
|
+
"license": "MIT",
|
|
42
|
+
"peerDependencies": {
|
|
43
|
+
"@stripe/stripe-js": "^2.4.0"
|
|
44
|
+
},
|
|
45
|
+
"devDependencies": {
|
|
46
|
+
"@types/node": "^20.10.0",
|
|
47
|
+
"@typescript-eslint/eslint-plugin": "^6.15.0",
|
|
48
|
+
"@typescript-eslint/parser": "^6.15.0",
|
|
49
|
+
"@vitest/coverage-v8": "^1.1.0",
|
|
50
|
+
"eslint": "^8.56.0",
|
|
51
|
+
"prettier": "^3.1.1",
|
|
52
|
+
"tsup": "^8.0.1",
|
|
53
|
+
"typescript": "^5.3.3",
|
|
54
|
+
"vitest": "^1.1.0"
|
|
55
|
+
},
|
|
56
|
+
"dependencies": {
|
|
57
|
+
"@stripe/stripe-js": "^2.4.0",
|
|
58
|
+
"ts-money": "^0.4.8"
|
|
59
|
+
}
|
|
60
|
+
}
|