@inflow_pay/sdk 0.8.0 → 1.0.0

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/README.md CHANGED
@@ -1,6 +1,14 @@
1
- # InflowPay Iframe-based Payment SDK
1
+ # InflowPay SDK v2
2
2
 
3
- Accept card payments with a pre-built, secure payment form. Uses an iframe-based architecture for enhanced security and easy integration.
3
+ Accept card payments with a secure, iframe-based payment form. This version delivers **enhanced security**, a **built-in success UI**, and **automatic 3D Secure handling** - all with just a few lines of code.
4
+
5
+ ## What's Best in This Version
6
+
7
+ - 🔒 **Iframe Architecture**: Card data never touches your server (PCI compliant)
8
+ - ✨ **Built-in Success UI**: Beautiful success screen automatically shown after payment - fully customizable or replaceable
9
+ - 🎯 **Auto 3D Secure**: SDK handles authentication modals automatically
10
+ - 🚀 **Zero Configuration**: Works out of the box with sensible defaults
11
+ - 🎨 **Fully Customizable**: Match your brand with comprehensive styling options
4
12
 
5
13
  ## Installation
6
14
 
@@ -8,80 +16,165 @@ Accept card payments with a pre-built, secure payment form. Uses an iframe-based
8
16
  npm install @inflow_pay/sdk
9
17
  ```
10
18
 
11
- Or use via CDN (jsDelivr) - **for vanilla HTML pages only**:
19
+ **CDN Option** (vanilla HTML pages only):
12
20
 
13
21
  ```html
14
- <!-- Main SDK (vanilla JavaScript) -->
22
+ <script src="https://cdn.jsdelivr.net/npm/@inflow_pay/sdk@1.0.0/dist/sdk.umd.js"></script>
23
+ ```
24
+
25
+ ## Complete Example
26
+
27
+ ### Backend: Create Payment
28
+
29
+ ```javascript
30
+ // backend/api/create-payment.js
31
+ app.post('/api/create-payment', async (req, res) => {
32
+ const response = await fetch('https://api.inflowpay.xyz/api/server/payment', {
33
+ method: 'POST',
34
+ headers: {
35
+ 'Content-Type': 'application/json',
36
+ 'X-Inflow-Api-Key': process.env.INFLOW_PRIVATE_KEY
37
+ },
38
+ body: JSON.stringify({
39
+ products: [{ name: 'Product', price: 4999, quantity: 1 }],
40
+ currency: 'EUR',
41
+ customerEmail: 'customer@example.com',
42
+ firstName: 'John',
43
+ lastName: 'Doe',
44
+ billingCountry: 'FR',
45
+ postalCode: '75001'
46
+ })
47
+ });
48
+
49
+ const data = await response.json();
50
+ res.json({ paymentId: data.payment.id });
51
+ });
52
+ ```
53
+
54
+ ### Frontend: React
55
+
56
+ ```tsx
57
+ import { InflowPayProvider, CardElement, PaymentResultStatus } from '@inflow_pay/sdk/react';
58
+
59
+ export default function CheckoutPage() {
60
+ const [paymentId, setPaymentId] = useState<string | null>(null);
61
+
62
+ useEffect(() => {
63
+ fetch('/api/create-payment', { method: 'POST' })
64
+ .then(res => res.json())
65
+ .then(data => setPaymentId(data.paymentId));
66
+ }, []);
67
+
68
+ if (!paymentId) return <div>Loading...</div>;
69
+
70
+ return (
71
+ <InflowPayProvider config={{ publicKey: 'inflow_pub_xxx' }}>
72
+ <CardElement
73
+ paymentId={paymentId}
74
+ showDefaultSuccessUI={true}
75
+ onComplete={(result) => {
76
+ if (result.status === PaymentResultStatus.SUCCESS) {
77
+ setTimeout(() => window.location.href = '/confirmation', 2000);
78
+ }
79
+ }}
80
+ style={{
81
+ fontFamily: 'Inter',
82
+ button: { backgroundColor: '#0070F3', textColor: '#FFFFFF' }
83
+ }}
84
+ />
85
+ </InflowPayProvider>
86
+ );
87
+ }
88
+ ```
89
+
90
+ ### Frontend: Vanilla JavaScript
91
+
92
+ ```html
93
+ <div id="card-container"></div>
94
+
15
95
  <script src="https://cdn.jsdelivr.net/npm/@inflow_pay/sdk@0.8.0/dist/sdk.umd.js"></script>
16
96
  <script>
17
- // SDK is available as window.InflowPaySDK
18
97
  const provider = new InflowPaySDK.InflowPayProvider({
19
- config: { apiKey: 'inflow_pub_xxx' }
98
+ config: { publicKey: 'inflow_pub_xxx' }
20
99
  });
100
+
101
+ fetch('/api/create-payment', { method: 'POST' })
102
+ .then(res => res.json())
103
+ .then(data => {
104
+ const cardElement = provider.createCardElement({
105
+ paymentId: data.paymentId,
106
+ container: '#card-container',
107
+ showDefaultSuccessUI: true,
108
+ onComplete: (result) => {
109
+ if (result.status === InflowPaySDK.PaymentResultStatus.SUCCESS) {
110
+ setTimeout(() => window.location.href = '/confirmation', 2000);
111
+ }
112
+ }
113
+ });
114
+ cardElement.mount();
115
+ });
21
116
  </script>
22
117
  ```
23
118
 
24
- **Note:**
25
- - The example uses exact version `@0.8.0` for production safety (prevents unexpected changes)
26
- - You can update to newer versions manually when ready (e.g., `@0.8.0`)
27
- - If you're building a React app (create-react-app, Next.js, etc.), use `npm install` instead of CDN. See [Migration from React SDK](#migration-from-react-sdk) section.
119
+ ## Built-in Success UI Explained
28
120
 
29
- ## Quick Start
121
+ The SDK includes a polished success screen that appears automatically after successful payment:
30
122
 
31
- Get started with the iframe-based SDK:
123
+ **What it shows:**
124
+ - ✅ Success icon and "Payment successful!" message
125
+ - 💳 Payment amount (when available from your payment data)
126
+ - 🎨 Automatically matches your brand colors and theme
127
+ - 🌙 Dark mode support
32
128
 
33
- ```javascript
34
- import { InflowPayProvider } from '@inflow_pay/sdk';
129
+ **How to use it:**
35
130
 
36
- // Step 1: Create InflowPayProvider (same as React's <InflowPayProvider>)
37
- const provider = new InflowPayProvider({
38
- config: { apiKey: 'inflow_pub_xxx', locale: 'en' } // locale optional, defaults to browser language
131
+ ```javascript
132
+ // Option 1: Use default success UI (recommended)
133
+ const cardElement = provider.createCardElement({
134
+ paymentId: 'pay_xxx',
135
+ container: '#card-container',
136
+ showDefaultSuccessUI: true, // Shows built-in success screen
137
+ onComplete: (result) => {
138
+ if (result.status === PaymentResultStatus.SUCCESS) {
139
+ // Success UI is already showing in the iframe
140
+ // Optional: redirect after 2 seconds
141
+ setTimeout(() => window.location.href = '/confirmation', 2000);
142
+ }
143
+ }
39
144
  });
40
145
 
41
- // Step 2: Create CardElement (same as React's <CardElement>)
146
+ // Option 2: Use your own custom success UI
42
147
  const cardElement = provider.createCardElement({
43
- paymentId: 'pay_xxx', // From your backend
148
+ paymentId: 'pay_xxx',
44
149
  container: '#card-container',
150
+ showDefaultSuccessUI: false, // Iframe unmounts on success
45
151
  onComplete: (result) => {
46
- if (result.status === 'CHECKOUT_SUCCESS') {
47
- window.location.href = '/success';
152
+ if (result.status === PaymentResultStatus.SUCCESS) {
153
+ // Show your custom success UI
154
+ document.getElementById('card-container').innerHTML = `
155
+ <div class="custom-success">
156
+ <h2>Thank you for your purchase!</h2>
157
+ <p>Order ID: ${result.paymentId}</p>
158
+ </div>
159
+ `;
48
160
  }
49
161
  }
50
162
  });
51
-
52
- // Step 3: Mount the CardElement
53
- cardElement.mount();
54
163
  ```
55
164
 
56
- ## How It Works
57
-
58
- 1. **Backend**: Create a payment with billing info (your private key)
59
- 2. **Frontend**: Create `InflowPayProvider` with your API key
60
- 3. **Frontend**: Create `CardElement` with the `paymentId`
61
- 4. **User**: Enters card details and submits
62
- 5. **SDK**: Handles tokenization, 3DS, and payment completion
63
- 6. **Your app**: Receives success/error via callback
64
-
65
- ## Payment Status
165
+ **When to use each option:**
166
+ - **Default UI** (`showDefaultSuccessUI: true`): Quick integration, consistent experience, looks great out of the box
167
+ - **Custom UI** (`showDefaultSuccessUI: false`): Full control when you need custom branding or additional information
66
168
 
67
- Payments progress through these statuses:
169
+ ## Payment Flow
68
170
 
69
- | Status | Description | Success? |
70
- |--------|-------------|----------|
71
- | `CHECKOUT_SUCCESS` | Payment confirmed | Yes |
72
- | `PAYMENT_RECEIVED` | Funds received | ✅ Yes |
73
- | `PAYMENT_SUCCESS` | Complete | Yes |
74
- | `PAYMENT_FAILED` | Failed | No |
75
-
76
- **Check for success:**
77
-
78
- ```javascript
79
- if (result.status === 'CHECKOUT_SUCCESS' ||
80
- result.status === 'PAYMENT_RECEIVED' ||
81
- result.status === 'PAYMENT_SUCCESS') {
82
- // Payment successful
83
- }
84
- ```
171
+ 1. Backend creates payment returns `paymentId`
172
+ 2. Frontend initializes SDK with `paymentId` and public key
173
+ 3. User enters card details in secure iframe
174
+ 4. SDK tokenizes card and processes payment
175
+ 5. 3D Secure authentication (if required) - automatic modal
176
+ 6. Success UI displays (built-in or custom)
177
+ 7. `onComplete` callback fires → redirect or update UI
85
178
 
86
179
  ## API Reference
87
180
 
@@ -90,346 +183,125 @@ if (result.status === 'CHECKOUT_SUCCESS' ||
90
183
  ```javascript
91
184
  const provider = new InflowPayProvider({
92
185
  config: {
93
- apiKey: 'inflow_pub_xxx', // Required
94
- iframeUrl: 'https://...', // Optional, auto-detected from API key
95
- locale: 'en', // Optional, UI language (default: auto-detected from browser). Supported: en, de, es, fr, it, nl, pl, pt
96
- timeout: 30000, // Optional, default: 30000
97
- debug: false // Optional, default: false
186
+ publicKey: 'inflow_pub_xxx', // Required
187
+ locale: 'en' // Optional - defaults to browser language
98
188
  }
99
189
  });
100
190
  ```
101
191
 
102
- **Locale:** Use `locale` in config to set UI language (e.g. `'fr'`); omit to use the browser language. Supported: en, de, es, fr, it, nl, pl, pt.
192
+ **Supported locales:** `en`, `de`, `es`, `fr`, `it`, `nl`, `pl`, `pt`
103
193
 
104
194
  ### CardElement
105
195
 
106
196
  ```javascript
107
197
  const cardElement = provider.createCardElement({
108
- paymentId: 'pay_xxx', // Required
109
- container: '#card-container', // Required (CSS selector or HTMLElement)
198
+ paymentId: 'pay_xxx', // Required - from your backend
199
+ container: '#card-container', // Required - CSS selector or HTMLElement
200
+ showDefaultSuccessUI: true, // Optional - default true
110
201
 
111
- // Styling (optional)
112
- style: {
113
- fontFamily: 'Inter',
114
- button: {
115
- backgroundColor: '#0070F3',
116
- textColor: '#FFFFFF'
202
+ // Callbacks
203
+ onComplete: (result) => {
204
+ if (result.status === PaymentResultStatus.SUCCESS) {
205
+ // Payment successful
206
+ } else if (result.status === PaymentResultStatus.FAILED) {
207
+ // Payment failed - result.error contains details
117
208
  }
118
209
  },
119
210
 
120
- // Custom button text (optional)
121
- buttonText: 'Complete Payment',
122
-
123
- // Custom placeholders (optional)
124
- placeholders: {
125
- cardNumber: '1234 5678 9012 3456',
126
- expiry: 'MM/YY',
127
- cvc: 'CVC'
128
- },
129
-
130
- // Callbacks (same as React SDK)
131
211
  onReady: () => {
132
- // Card element is mounted and ready
212
+ // Card element mounted and ready
133
213
  },
134
214
 
135
215
  onChange: (state) => {
136
- // Track validation state
137
216
  // state.complete - whether form is valid
138
217
  },
139
218
 
140
- onComplete: (result) => {
141
- // Payment complete (success or failure)
142
- if (result.error) {
143
- console.error(result.error.message);
144
- }
219
+ onError: (error) => {
220
+ // SDK-level errors
145
221
  },
146
222
 
147
- onError: (error) => {
148
- // SDK-level errors (network, validation)
149
- console.error(error);
223
+ // Styling (optional)
224
+ style: {
225
+ fontFamily: 'Inter',
226
+ button: {
227
+ backgroundColor: '#0070F3',
228
+ textColor: '#FFFFFF'
229
+ }
150
230
  },
151
231
 
152
- onClose: () => {
153
- // User closed the payment
232
+ // Custom text (optional)
233
+ buttonText: 'Pay Now',
234
+ placeholders: {
235
+ cardNumber: '1234 5678 9012 3456',
236
+ expiry: 'MM/YY',
237
+ cvc: 'CVC'
154
238
  }
155
239
  });
156
240
 
157
- // Mount the CardElement
158
241
  cardElement.mount();
159
242
  ```
160
243
 
161
- ### CardElement Methods
162
-
163
- #### `mount(): void`
164
-
165
- Mounts the CardElement to the DOM. This will create and display the iframe.
166
-
167
- ```javascript
168
- cardElement.mount();
169
- ```
170
-
171
- #### `destroy(): void`
172
-
173
- Destroys the CardElement and cleans up resources.
174
-
175
- ```javascript
176
- cardElement.destroy();
177
- ```
244
+ ### Payment Result
178
245
 
179
- ## HTML Example
180
-
181
- ```html
182
- <!DOCTYPE html>
183
- <html>
184
- <head>
185
- <title>My Payment Page</title>
186
- </head>
187
- <body>
188
- <div id="card-container"></div>
189
-
190
- <script src="https://cdn.jsdelivr.net/npm/@inflow_pay/sdk@0.8.0/dist/sdk.umd.js"></script>
191
- <script>
192
- // SDK is available as window.InflowPaySDK
193
- const provider = new InflowPaySDK.InflowPayProvider({
194
- config: { apiKey: 'inflow_pub_xxx' }
195
- });
196
-
197
- const cardElement = provider.createCardElement({
198
- paymentId: 'pay_xxx',
199
- container: '#card-container',
200
- onComplete: (result) => {
201
- if (result.status === InflowPaySDK.PaymentStatus.CHECKOUT_SUCCESS) {
202
- alert('Payment successful!');
203
- }
204
- }
205
- });
206
-
207
- cardElement.mount();
208
- </script>
209
- </body>
210
- </html>
211
- ```
212
-
213
- ## Error Handling
214
-
215
- Errors are automatically mapped to user-friendly messages:
216
-
217
- ```javascript
218
- cardElement.onComplete = (result) => {
219
- if (result.error) {
220
- console.log(result.error.message); // User-friendly
221
- console.log(result.error.retryable); // Can retry?
246
+ ```typescript
247
+ interface PaymentResult {
248
+ status: 'SUCCESS' | 'FAILED';
249
+ paymentId: string;
250
+ error?: {
251
+ code: string; // Error code (e.g., 'THREE_DS_FAILED')
252
+ message: string; // User-friendly message
253
+ retryable: boolean; // Can retry?
222
254
  }
223
- };
224
- ```
225
-
226
- **Common errors:**
227
-
228
- - `card_declined` - Card was declined
229
- - `insufficient_funds` - Not enough funds
230
- - `invalid_card_number` - Invalid card
231
- - `THREE_DS_FAILED` - 3DS authentication failed
232
-
233
- ## 3D Secure
234
-
235
- 3DS is handled automatically. When required:
236
-
237
- 1. SDK opens a modal with the authentication page
238
- 2. User completes authentication
239
- 3. Modal closes automatically
240
- 4. Your `onComplete` callback receives the final result
241
-
242
- **No setup required!** The SDK automatically handles 3DS redirects.
243
-
244
- ## Backend Integration
245
-
246
- Create payments on your backend with your **private key**:
247
-
248
- ```javascript
249
- // Your backend (Node.js example)
250
- const response = await fetch('https://api.inflowpay.xyz/api/server/payment', {
251
- method: 'POST',
252
- headers: {
253
- 'Accept': 'application/json',
254
- 'Content-Type': 'application/json',
255
- 'X-Inflow-Api-Key': 'inflow_priv_xxx' // Private key
256
- },
257
- body: JSON.stringify({
258
- products: [{ name: 'Product', price: 4999, quantity: 1 }],
259
- currency: 'EUR',
260
- customerEmail: 'customer@example.com',
261
- billingCountry: 'FR',
262
- postalCode: '75001',
263
- firstName: 'John',
264
- lastName: 'Doe',
265
- purchasingAsBusiness: false,
266
- successUrl: 'https://yourdomain.com/success',
267
- cancelUrl: 'https://yourdomain.com/cancel'
268
- })
269
- });
270
-
271
- const { payment } = await response.json();
272
- // Send payment.id to your frontend
273
- ```
274
-
275
- See [API documentation](https://docs.inflowpay.com/v0/reference/createpayment) for full backend API reference.
276
-
277
- ## Migration from React SDK
278
-
279
- The iframe-based SDK maintains similar component APIs, but **styling has changed**. You have two options:
280
-
281
- ### Option 1: Keep Using React (Recommended for React Apps)
282
-
283
- If you're using React, you can use the React components with a similar API:
284
-
285
- ```tsx
286
- // Change the import path
287
- import { InflowPayProvider, CardElement } from '@inflow_pay/sdk/react';
288
-
289
- function App() {
290
- return (
291
- <InflowPayProvider config={{ apiKey: 'inflow_pub_xxx', locale: 'en' }}>
292
- <CardElement
293
- paymentId={paymentId}
294
- style={{
295
- // ⚠️ Styling API has changed - see Styling section below
296
- fontFamily: 'Inter',
297
- button: {
298
- backgroundColor: '#0070F3',
299
- textColor: '#FFFFFF'
300
- }
301
- }}
302
- onComplete={(result) => {
303
- if (result.status === 'CHECKOUT_SUCCESS') {
304
- window.location.href = '/success';
305
- }
306
- }}
307
- />
308
- </InflowPayProvider>
309
- );
310
255
  }
311
256
  ```
312
257
 
313
- **Important:** The component API is similar, but **styling customization has changed**. See the [Styling](#styling) section for the new styling structure.
314
-
315
- ### Option 2: Vanilla JavaScript (For Non-React Apps)
316
-
317
- If you're not using React, you can use the vanilla JavaScript API:
258
+ ### CardElement Methods
318
259
 
319
260
  ```javascript
320
- import { InflowPayProvider } from '@inflow_pay/sdk';
321
-
322
- const provider = new InflowPayProvider({
323
- config: { apiKey: 'inflow_pub_xxx' }
324
- });
325
-
326
- const cardElement = provider.createCardElement({
327
- paymentId: paymentId,
328
- container: '#card-container',
329
- onComplete: (result) => {
330
- if (result.status === 'CHECKOUT_SUCCESS') {
331
- window.location.href = '/success';
332
- }
333
- }
334
- });
335
-
336
- cardElement.mount();
337
- ```
338
-
339
- **Key differences from React version:**
340
- - No React required - works with vanilla JavaScript
341
- - Explicit `container` prop (CSS selector or HTMLElement) instead of JSX
342
- - Call `mount()` explicitly instead of automatic React mounting
343
- - Same callbacks, same status codes, same error handling
344
- - **Styling API has changed** - see [Styling](#styling) section for details
345
-
346
- ## TypeScript
347
-
348
- Full type definitions included:
349
-
350
- ```typescript
351
- import { InflowPayProvider, PaymentStatus } from '@inflow_pay/sdk';
352
- import type { PaymentResult, PaymentError } from '@inflow_pay/sdk';
353
-
354
- const provider = new InflowPayProvider({
355
- config: { apiKey: 'inflow_pub_xxx' }
356
- });
357
-
358
- const cardElement = provider.createCardElement({
359
- paymentId: 'pay_xxx',
360
- container: '#card-container',
361
- onComplete: (result: PaymentResult) => {
362
- if (result.status === PaymentStatus.CHECKOUT_SUCCESS) {
363
- // Success
364
- }
365
- },
366
- onError: (error: PaymentError) => {
367
- console.error(error);
368
- }
369
- });
261
+ cardElement.mount(); // Mount to DOM
262
+ cardElement.destroy(); // Cleanup and unmount
370
263
  ```
371
264
 
372
265
  ## Styling
373
266
 
374
- The iframe-based SDK provides a comprehensive styling API to match your brand. **Note: The styling structure is different from the original React SDK.** All styles are fully typed with TypeScript.
375
-
376
- ### Basic Styling
267
+ Customize the payment form to match your brand:
377
268
 
378
269
  ```javascript
379
- const cardElement = provider.createCardElement({
380
- paymentId: 'pay_xxx',
381
- container: '#card-container',
382
- style: {
383
- fontFamily: 'Inter',
384
- fillParent: true,
385
- inputContainer: {
386
- backgroundColor: '#F5F5F5',
387
- borderRadius: '8px',
388
- borderEnabled: true,
389
- borderColor: '#E0E0E0'
390
- },
391
- input: {
392
- textColor: '#1A1A1A',
393
- placeholderColor: '#999999'
394
- },
395
- button: {
396
- backgroundColor: '#0070F3',
397
- textColor: '#FFFFFF',
398
- borderRadius: '8px',
399
- fontSize: '16px',
400
- fontWeight: 600,
401
- opacity: 1,
402
- hover: {
403
- backgroundColor: '#0051CC'
404
- },
405
- disabled: {
406
- opacity: 0.5
407
- }
408
- },
409
- dark: {
410
- button: {
411
- backgroundColor: '#0066CC'
412
- }
413
- }
414
- }
415
- });
416
- ```
417
-
418
- ### Dark Mode
419
-
420
- Use the `dark` property to customize dark mode styles:
421
-
422
- ```tsx
423
270
  style: {
424
- fontFamily: 'Inter',
425
- button: {
426
- backgroundColor: '#0070F3',
427
- textColor: '#FFFFFF'
428
- },
271
+ fontFamily: 'Inter', // 'DM Sans' | 'Inter' | 'Poppins' | 'Nunito' | etc.
272
+ fillParent: true,
273
+
274
+ // Input container
429
275
  inputContainer: {
430
- backgroundColor: '#FFFFFF',
276
+ backgroundColor: '#F5F5F5',
277
+ borderRadius: '8px',
278
+ borderEnabled: true,
431
279
  borderColor: '#E0E0E0'
432
280
  },
281
+
282
+ // Input fields
283
+ input: {
284
+ textColor: '#1A1A1A',
285
+ placeholderColor: '#999999',
286
+ backgroundColor: 'transparent'
287
+ },
288
+
289
+ // Button
290
+ button: {
291
+ backgroundColor: '#0070F3',
292
+ textColor: '#FFFFFF',
293
+ borderRadius: '8px',
294
+ fontSize: '16px',
295
+ fontWeight: 600,
296
+ hover: {
297
+ backgroundColor: '#0051CC'
298
+ },
299
+ disabled: {
300
+ opacity: 0.5
301
+ }
302
+ },
303
+
304
+ // Dark mode
433
305
  dark: {
434
306
  inputContainer: {
435
307
  backgroundColor: '#1A1A1A',
@@ -437,7 +309,7 @@ style: {
437
309
  },
438
310
  input: {
439
311
  textColor: '#FFFFFF',
440
- backgroundColor: '#2A2A2A'
312
+ placeholderColor: '#959499'
441
313
  },
442
314
  button: {
443
315
  backgroundColor: '#0066CC'
@@ -446,272 +318,64 @@ style: {
446
318
  }
447
319
  ```
448
320
 
449
- ### Available Font Families
321
+ **Available style properties:** `inputContainer`, `input`, `button`, `generalError`, `generalSuccess`, `disclaimerColor`, `fieldErrorColor`, `dark` (for dark mode overrides)
450
322
 
451
- ```typescript
452
- type FontFamily =
453
- | 'DM Sans'
454
- | 'Inter'
455
- | 'Poppins'
456
- | 'Nunito'
457
- | 'Work Sans'
458
- | 'Manrope'
459
- | 'Rubik'
460
- | 'Karla'
461
- | 'Figtree'
462
- | 'Outfit'
463
- | 'Space Grotesk'
464
- | 'Urbanist';
465
- ```
323
+ See full TypeScript types in the package for all styling options.
466
324
 
467
- ### Complete Styling API
325
+ ## Error Handling
468
326
 
469
- All available styling properties:
327
+ ```javascript
328
+ import { PaymentResultStatus, PaymentResultErrorCode } from '@inflow_pay/sdk';
470
329
 
471
- ```tsx
472
- interface CSSProperties {
473
- // Global
474
- fontFamily?: FontFamily; // 'DM Sans' | 'Inter' | 'Poppins' | etc.
475
- fillParent?: boolean; // Make element fill parent container
476
-
477
- // Input container (wrapper around all card inputs)
478
- inputContainer?: {
479
- backgroundColor?: string;
480
- borderColor?: string;
481
- borderEnabled?: boolean; // Must be true to show border
482
- borderRadius?: string;
483
- };
484
-
485
- // Individual input fields
486
- input?: {
487
- backgroundColor?: string;
488
- borderColor?: string;
489
- borderEnabled?: boolean;
490
- borderRadius?: string;
491
- textColor?: string;
492
- placeholderColor?: string;
493
- };
494
-
495
- // Button styles
496
- button?: {
497
- backgroundColor?: string;
498
- textColor?: string;
499
- borderRadius?: string;
500
- borderColor?: string;
501
- borderEnabled?: boolean; // Must be true to show border
502
- fontSize?: string;
503
- fontWeight?: FontWeight; // 100-900 | 'normal' | 'bold' | 'lighter' | 'bolder'
504
- opacity?: Opacity; // number (0-1) | string ('0.5' | '50%')
505
- hover?: { // Hover state
506
- backgroundColor?: string;
507
- textColor?: string;
508
- borderRadius?: string;
509
- borderColor?: string;
510
- borderEnabled?: boolean;
511
- fontSize?: string;
512
- fontWeight?: FontWeight;
513
- opacity?: Opacity;
514
- };
515
- disabled?: { // Disabled state
516
- backgroundColor?: string;
517
- textColor?: string;
518
- borderRadius?: string;
519
- borderColor?: string;
520
- borderEnabled?: boolean;
521
- fontSize?: string;
522
- fontWeight?: FontWeight;
523
- opacity?: Opacity;
524
- };
525
- loaderColor?: string; // Loading spinner color
526
- };
527
-
528
- // General error message
529
- generalError?: {
530
- textColor?: string;
531
- backgroundColor?: string;
532
- borderEnabled?: boolean;
533
- borderRadius?: string;
534
- borderColor?: string;
535
- };
536
-
537
- // General success message
538
- generalSuccess?: {
539
- textColor?: string;
540
- backgroundColor?: string;
541
- borderEnabled?: boolean;
542
- borderRadius?: string;
543
- borderColor?: string;
544
- };
545
-
546
- // Other colors
547
- disclaimerColor?: string; // Disclaimer text and icon color
548
- fieldErrorColor?: string; // Field validation error text color
549
-
550
- // Dark mode overrides
551
- dark?: {
552
- inputContainer?: InputContainerStyles;
553
- input?: InputStyles;
554
- button?: ButtonStyles;
555
- disclaimerColor?: string;
556
- fieldErrorColor?: string;
557
- generalError?: GeneralMessageStyles;
558
- generalSuccess?: GeneralMessageStyles;
559
- };
330
+ onComplete: (result) => {
331
+ if (result.status === PaymentResultStatus.FAILED && result.error) {
332
+ console.log(result.error.code); // e.g., 'THREE_DS_FAILED'
333
+ console.log(result.error.message); // User-friendly message
334
+ console.log(result.error.retryable); // Can user retry?
335
+ }
560
336
  }
561
337
  ```
562
338
 
563
- ### Custom Placeholders
339
+ **Common error codes:** `THREE_DS_FAILED`, `PAYMENT_PROCESSING_ERROR`
564
340
 
565
- ```javascript
566
- placeholders: {
567
- cardNumber: '1234 5678 9012 3456',
568
- expiry: 'MM/YY',
569
- cvc: 'CVC'
570
- }
571
- ```
341
+ ## 3D Secure
572
342
 
573
- ### Custom Button Text
343
+ 3DS is handled automatically by the SDK. When required, a modal opens for bank authentication, then closes automatically. No setup needed.
574
344
 
575
- ```javascript
576
- buttonText: 'Pay Now'
577
- ```
345
+ ## Migration from React SDK
578
346
 
579
- ### React Example with All Styling Properties
347
+ **For React apps:** Import from `@inflow_pay/sdk/react` instead. The component API is similar, but the styling structure has changed (see [Styling](#styling) section).
580
348
 
581
- ```tsx
582
- import { InflowPayProvider, CardElement } from '@inflow_pay/sdk/react';
349
+ **For non-React apps:** Use the vanilla JavaScript API shown in the examples above.
583
350
 
584
- function App() {
585
- return (
586
- <InflowPayProvider config={{ apiKey: 'inflow_pub_xxx' }}>
587
- <CardElement
588
- paymentId="pay_xxx"
589
- style={{
590
- fontFamily: 'Inter',
591
- fillParent: true,
592
-
593
- // Input container
594
- inputContainer: {
595
- backgroundColor: '#F5F5F5',
596
- borderRadius: '8px',
597
- borderEnabled: true,
598
- borderColor: '#E0E0E0'
599
- },
600
-
601
- // Input fields
602
- input: {
603
- textColor: '#1A1A1A',
604
- placeholderColor: '#999999',
605
- backgroundColor: 'transparent',
606
- borderColor: '#CECECE',
607
- borderEnabled: true,
608
- borderRadius: '6px'
609
- },
610
-
611
- // Button
612
- button: {
613
- backgroundColor: '#0070F3',
614
- textColor: '#FFFFFF',
615
- borderRadius: '8px',
616
- fontSize: '16px',
617
- fontWeight: 600,
618
- opacity: 1,
619
- borderEnabled: false,
620
- hover: {
621
- backgroundColor: '#0051CC',
622
- opacity: 1
623
- },
624
- disabled: {
625
- opacity: 0.5
626
- },
627
- loaderColor: '#FFFFFF'
628
- },
629
-
630
- // General messages
631
- generalError: {
632
- textColor: '#FF443F',
633
- backgroundColor: '#ffd6cc',
634
- borderColor: '#FF443F',
635
- borderEnabled: true,
636
- borderRadius: '6px'
637
- },
638
-
639
- generalSuccess: {
640
- textColor: '#29a329',
641
- backgroundColor: '#d6f5d6',
642
- borderColor: '#29a329',
643
- borderEnabled: true,
644
- borderRadius: '6px'
645
- },
646
-
647
- // Other colors
648
- disclaimerColor: '#7A7A7A',
649
- fieldErrorColor: '#ef4444',
650
-
651
- // Dark mode
652
- dark: {
653
- inputContainer: {
654
- backgroundColor: '#2d2d2d',
655
- borderColor: '#7A7A7A'
656
- },
657
- input: {
658
- textColor: '#FFFFFF',
659
- placeholderColor: '#959499',
660
- borderColor: '#7A7A7A'
661
- },
662
- button: {
663
- backgroundColor: '#0066CC'
664
- },
665
- generalError: {
666
- textColor: '#ffc2b3',
667
- backgroundColor: '#991f00',
668
- borderColor: '#e62e00'
669
- },
670
- generalSuccess: {
671
- textColor: '#adebad',
672
- backgroundColor: '#196619',
673
- borderColor: '#2eb82e'
674
- },
675
- disclaimerColor: '#959499',
676
- fieldErrorColor: '#ef4444'
677
- }
678
- }}
679
- buttonText="Complete Payment"
680
- onComplete={(result) => {
681
- if (result.status === 'CHECKOUT_SUCCESS') {
682
- alert('Payment successful!');
683
- }
684
- }}
685
- />
686
- </InflowPayProvider>
687
- );
688
- }
689
- ```
351
+ ## TypeScript
352
+
353
+ Full type definitions included:
690
354
 
691
- ## Security
355
+ ```typescript
356
+ import { InflowPayProvider, PaymentResultStatus } from '@inflow_pay/sdk';
357
+ import type { PaymentResult, PaymentError } from '@inflow_pay/sdk';
692
358
 
693
- - Card data is tokenized before reaching your server (PCI compliant)
694
- - Public keys can be safely exposed in browser
695
- - ✅ Private keys should never be in frontend code
696
- - ✅ All requests over HTTPS
697
- - ✅ Iframe isolation for security
359
+ const provider = new InflowPayProvider({
360
+ config: { publicKey: 'inflow_pub_xxx' }
361
+ });
362
+ ```
698
363
 
699
364
  ## Features
700
365
 
701
- - ✅ **Dynamic Height**: Automatically adjusts iframe height based on content
702
- - ✅ **Skeleton Loader**: Beautiful loading state with shimmer effect
703
- - ✅ **Dark Mode Support**: Automatic theme detection with manual overrides
704
- - ✅ **TypeScript**: Full type definitions included
705
- - ✅ **Responsive**: Works on all screen sizes
706
- - ✅ **Accessible**: WCAG compliant
707
- - ✅ **Secure**: PCI compliant, iframe isolation
366
+ - ✅ Dynamic height adjustment
367
+ - ✅ Skeleton loader with shimmer effect
368
+ - ✅ Dark mode support
369
+ - ✅ Responsive design
370
+ - ✅ WCAG compliant
371
+ - ✅ Multi-language support
708
372
 
709
373
  ## Support
710
374
 
711
- - **Documentation:** https://docs.inflowpay.com/v0/reference/createpayment
375
+ - **Docs:** https://docs.inflowpay.com/v0/reference/createpayment
712
376
  - **Email:** support@inflowpay.com
713
377
  - **GitHub:** https://github.com/inflowpay/sdk
714
- - **Changelog:** See [CHANGELOG.md](./CHANGELOG.md) for version history
378
+ - **Changelog:** [CHANGELOG.md](./CHANGELOG.md)
715
379
 
716
380
  ## License
717
381