@inflow_pay/sdk 0.8.0 → 1.1.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** 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,428 +16,312 @@ 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) -->
15
- <script src="https://cdn.jsdelivr.net/npm/@inflow_pay/sdk@0.8.0/dist/sdk.umd.js"></script>
16
- <script>
17
- // SDK is available as window.InflowPaySDK
18
- const provider = new InflowPaySDK.InflowPayProvider({
19
- config: { apiKey: 'inflow_pub_xxx' }
20
- });
21
- </script>
22
+ <script src="https://cdn.jsdelivr.net/npm/@inflow_pay/sdk@1.1.0/dist/sdk.umd.js"></script>
22
23
  ```
23
24
 
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.
25
+ ## Complete Example
28
26
 
29
- ## Quick Start
30
-
31
- Get started with the iframe-based SDK:
27
+ ### Backend: Create Payment
32
28
 
33
29
  ```javascript
34
- import { InflowPayProvider } from '@inflow_pay/sdk';
35
-
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
39
- });
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
+ });
40
48
 
41
- // Step 2: Create CardElement (same as React's <CardElement>)
42
- const cardElement = provider.createCardElement({
43
- paymentId: 'pay_xxx', // From your backend
44
- container: '#card-container',
45
- onComplete: (result) => {
46
- if (result.status === 'CHECKOUT_SUCCESS') {
47
- window.location.href = '/success';
48
- }
49
- }
49
+ const data = await response.json();
50
+ res.json({ paymentId: data.payment.id });
50
51
  });
51
-
52
- // Step 3: Mount the CardElement
53
- cardElement.mount();
54
52
  ```
55
53
 
56
- ## How It Works
54
+ ### Frontend: React
57
55
 
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
56
+ ```tsx
57
+ import {
58
+ InflowPayProvider,
59
+ CardElement,
60
+ PaymentResultStatus,
61
+ } from "@inflow_pay/sdk/react";
66
62
 
67
- Payments progress through these statuses:
63
+ export default function CheckoutPage() {
64
+ const [paymentId, setPaymentId] = useState<string | null>(null);
68
65
 
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 |
66
+ useEffect(() => {
67
+ fetch("/api/create-payment", { method: "POST" })
68
+ .then((res) => res.json())
69
+ .then((data) => setPaymentId(data.paymentId));
70
+ }, []);
75
71
 
76
- **Check for success:**
72
+ if (!paymentId) return <div>Loading...</div>;
77
73
 
78
- ```javascript
79
- if (result.status === 'CHECKOUT_SUCCESS' ||
80
- result.status === 'PAYMENT_RECEIVED' ||
81
- result.status === 'PAYMENT_SUCCESS') {
82
- // Payment successful
74
+ return (
75
+ <InflowPayProvider config={{ publicKey: "inflow_pub_xxx" }}>
76
+ <CardElement
77
+ paymentId={paymentId}
78
+ onComplete={(result) => {
79
+ if (result.status === PaymentResultStatus.SUCCESS) {
80
+ setTimeout(() => (window.location.href = "/confirmation"), 2000);
81
+ }
82
+ }}
83
+ style={{
84
+ fontFamily: "Inter",
85
+ button: { backgroundColor: "#0070F3", textColor: "#FFFFFF" },
86
+ }}
87
+ />
88
+ </InflowPayProvider>
89
+ );
83
90
  }
84
91
  ```
85
92
 
86
- ## API Reference
87
-
88
- ### InflowPayProvider
93
+ ### Frontend: Vanilla JavaScript
89
94
 
90
- ```javascript
91
- const provider = new InflowPayProvider({
92
- 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
98
- }
99
- });
100
- ```
101
-
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.
103
-
104
- ### CardElement
105
-
106
- ```javascript
107
- const cardElement = provider.createCardElement({
108
- paymentId: 'pay_xxx', // Required
109
- container: '#card-container', // Required (CSS selector or HTMLElement)
110
-
111
- // Styling (optional)
112
- style: {
113
- fontFamily: 'Inter',
114
- button: {
115
- backgroundColor: '#0070F3',
116
- textColor: '#FFFFFF'
117
- }
118
- },
119
-
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
- onReady: () => {
132
- // Card element is mounted and ready
133
- },
134
-
135
- onChange: (state) => {
136
- // Track validation state
137
- // state.complete - whether form is valid
138
- },
139
-
140
- onComplete: (result) => {
141
- // Payment complete (success or failure)
142
- if (result.error) {
143
- console.error(result.error.message);
144
- }
145
- },
146
-
147
- onError: (error) => {
148
- // SDK-level errors (network, validation)
149
- console.error(error);
150
- },
151
-
152
- onClose: () => {
153
- // User closed the payment
154
- }
155
- });
156
-
157
- // Mount the CardElement
158
- cardElement.mount();
159
- ```
160
-
161
- ### CardElement Methods
162
-
163
- #### `mount(): void`
95
+ ```html
96
+ <div id="card-container"></div>
164
97
 
165
- Mounts the CardElement to the DOM. This will create and display the iframe.
98
+ <script src="https://cdn.jsdelivr.net/npm/@inflow_pay/sdk@1.1.0/dist/sdk.umd.js"></script>
99
+ <script>
100
+ const provider = new InflowPaySDK.InflowPayProvider({
101
+ config: { publicKey: "inflow_pub_xxx" },
102
+ });
166
103
 
167
- ```javascript
168
- cardElement.mount();
104
+ fetch("/api/create-payment", { method: "POST" })
105
+ .then((res) => res.json())
106
+ .then((data) => {
107
+ const cardElement = provider.createCardElement({
108
+ paymentId: data.paymentId,
109
+ container: "#card-container",
110
+ onComplete: (result) => {
111
+ if (result.status === InflowPaySDK.PaymentResultStatus.SUCCESS) {
112
+ setTimeout(() => (window.location.href = "/confirmation"), 2000);
113
+ }
114
+ },
115
+ });
116
+ cardElement.mount();
117
+ });
118
+ </script>
169
119
  ```
170
120
 
171
- #### `destroy(): void`
121
+ ## Built-in Success UI Explained
172
122
 
173
- Destroys the CardElement and cleans up resources.
123
+ The SDK includes a polished success screen that appears automatically after successful payment:
174
124
 
175
- ```javascript
176
- cardElement.destroy();
177
- ```
125
+ **What it shows:**
178
126
 
179
- ## HTML Example
127
+ - Success icon and "Payment successful!" message
128
+ - 💳 Payment amount (when available from your payment data)
180
129
 
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
- });
130
+ **Default vs custom:**
196
131
 
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
- });
132
+ - **Default UI** (default): Built-in success screen shows automatically. You don't need to do anything — quick integration, looks great out of the box.
133
+ - **Custom UI:** Set `showDefaultSuccessUI: false` and add your own success UI. Manage the logic in `onComplete`. Full control for custom branding or additional information. Examples below:
206
134
 
207
- cardElement.mount();
208
- </script>
209
- </body>
210
- </html>
211
- ```
212
-
213
- ## Error Handling
214
-
215
- Errors are automatically mapped to user-friendly messages:
135
+ _Vanilla JS:_
216
136
 
217
137
  ```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?
222
- }
223
- };
138
+ const cardElement = provider.createCardElement({
139
+ paymentId: "pay_xxx",
140
+ container: "#card-container",
141
+ showDefaultSuccessUI: false,
142
+ onComplete: (result) => {
143
+ if (result.status === PaymentResultStatus.SUCCESS) {
144
+ document.getElementById("card-container").innerHTML = `
145
+ <div class="custom-success">
146
+ <h2>Thank you for your purchase!</h2>
147
+ <p>Order ID: ${result.paymentId}</p>
148
+ </div>
149
+ `;
150
+ }
151
+ },
152
+ });
224
153
  ```
225
154
 
226
- **Common errors:**
155
+ _React:_
227
156
 
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:
157
+ ```tsx
158
+ const [result, setResult] = useState<PaymentResult | null>(null);
159
+
160
+ return (
161
+ <>
162
+ {result ? (
163
+ <div className="custom-success">
164
+ <h2>Thank you for your purchase!</h2>
165
+ <p>Your payment was successful.</p>
166
+ </div>
167
+ ) : (
168
+ <InflowPayProvider config={{ publicKey: "inflow_pub_xxx" }}>
169
+ <CardElement
170
+ paymentId="pay_xxx"
171
+ showDefaultSuccessUI={false}
172
+ onComplete={(res) => {
173
+ if (res.status === PaymentResultStatus.SUCCESS) {
174
+ setResult(res);
175
+ }
176
+ }}
177
+ />
178
+ </InflowPayProvider>
179
+ )}
180
+ </>
181
+ );
182
+ ```
236
183
 
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
184
+ ## Payment Flow
241
185
 
242
- **No setup required!** The SDK automatically handles 3DS redirects.
186
+ 1. Backend creates payment returns `paymentId`
187
+ 2. Frontend initializes SDK with `paymentId` and public key
188
+ 3. User enters card details in secure iframe
189
+ 4. SDK tokenizes card and processes payment
190
+ 5. 3D Secure authentication (if required) - automatic modal
191
+ 6. `onComplete` callback fires → redirect or update UI
243
192
 
244
- ## Backend Integration
193
+ ## API Reference
245
194
 
246
- Create payments on your backend with your **private key**:
195
+ ### InflowPayProvider
247
196
 
248
197
  ```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
198
+ const provider = new InflowPayProvider({
199
+ config: {
200
+ publicKey: "inflow_pub_xxx", // Required
201
+ locale: "en", // Optional - defaults to browser language
256
202
  },
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
203
  });
270
-
271
- const { payment } = await response.json();
272
- // Send payment.id to your frontend
273
204
  ```
274
205
 
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:
206
+ **Supported locales:** `en`, `de`, `es`, `fr`, `it`, `nl`, `pl`, `pt`
280
207
 
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';
208
+ ### CardElement
288
209
 
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
- }
311
- ```
210
+ ```javascript
211
+ const cardElement = provider.createCardElement({
212
+ paymentId: "pay_xxx", // Required - from your backend
213
+ container: "#card-container", // Required - CSS selector or HTMLElement
312
214
 
313
- **Important:** The component API is similar, but **styling customization has changed**. See the [Styling](#styling) section for the new styling structure.
215
+ // Callbacks
216
+ onComplete: (result) => {
217
+ if (result.status === PaymentResultStatus.SUCCESS) {
218
+ // Payment successful
219
+ } else if (result.status === PaymentResultStatus.FAILED) {
220
+ // Payment failed - result.error contains details
221
+ }
222
+ },
314
223
 
315
- ### Option 2: Vanilla JavaScript (For Non-React Apps)
224
+ onReady: () => {
225
+ // Card element mounted and ready
226
+ },
316
227
 
317
- If you're not using React, you can use the vanilla JavaScript API:
228
+ onChange: (state) => {
229
+ // state.complete - whether form is valid
230
+ },
318
231
 
319
- ```javascript
320
- import { InflowPayProvider } from '@inflow_pay/sdk';
232
+ onError: (error) => {
233
+ // SDK-level errors
234
+ },
321
235
 
322
- const provider = new InflowPayProvider({
323
- config: { apiKey: 'inflow_pub_xxx' }
324
- });
236
+ // Styling (optional)
237
+ style: {
238
+ fontFamily: "Inter",
239
+ button: {
240
+ backgroundColor: "#0070F3",
241
+ textColor: "#FFFFFF",
242
+ },
243
+ },
325
244
 
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
- }
245
+ // Custom text (optional)
246
+ buttonText: "Pay Now",
247
+ placeholders: {
248
+ cardNumber: "1234 5678 9012 3456",
249
+ expiry: "MM/YY",
250
+ cvc: "CVC",
251
+ },
334
252
  });
335
253
 
336
254
  cardElement.mount();
337
255
  ```
338
256
 
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:
257
+ ### Payment Result
349
258
 
350
259
  ```typescript
351
- import { InflowPayProvider, PaymentStatus } from '@inflow_pay/sdk';
352
- import type { PaymentResult, PaymentError } from '@inflow_pay/sdk';
260
+ interface PaymentResult {
261
+ status: "SUCCESS" | "FAILED";
262
+ paymentId: string;
263
+ error?: {
264
+ code: string; // Error code (e.g., 'THREE_DS_FAILED')
265
+ message: string; // User-friendly message
266
+ retryable: boolean; // Can retry?
267
+ };
268
+ }
269
+ ```
353
270
 
354
- const provider = new InflowPayProvider({
355
- config: { apiKey: 'inflow_pub_xxx' }
356
- });
271
+ ### CardElement Methods
357
272
 
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
- });
273
+ ```javascript
274
+ cardElement.mount(); // Mount to DOM
275
+ cardElement.destroy(); // Cleanup and unmount
370
276
  ```
371
277
 
372
278
  ## Styling
373
279
 
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
280
+ Customize the payment form to match your brand:
377
281
 
378
282
  ```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
- ```
283
+ style: {
284
+ fontFamily: 'Inter', // 'DM Sans' | 'Inter' | 'Poppins' | 'Nunito' | etc.
285
+ fillParent: true,
417
286
 
418
- ### Dark Mode
287
+ // Input container
288
+ inputContainer: {
289
+ backgroundColor: '#F5F5F5',
290
+ borderRadius: '8px',
291
+ borderEnabled: true,
292
+ borderColor: '#E0E0E0'
293
+ },
419
294
 
420
- Use the `dark` property to customize dark mode styles:
295
+ // Input fields
296
+ input: {
297
+ textColor: '#1A1A1A',
298
+ placeholderColor: '#999999',
299
+ backgroundColor: 'transparent'
300
+ },
421
301
 
422
- ```tsx
423
- style: {
424
- fontFamily: 'Inter',
302
+ // Button
425
303
  button: {
426
304
  backgroundColor: '#0070F3',
427
- textColor: '#FFFFFF'
305
+ textColor: '#FFFFFF',
306
+ borderRadius: '8px',
307
+ fontSize: '16px',
308
+ fontWeight: 600,
309
+ hover: {
310
+ backgroundColor: '#0051CC'
311
+ },
312
+ disabled: {
313
+ opacity: 0.5
314
+ }
428
315
  },
429
- inputContainer: {
430
- backgroundColor: '#FFFFFF',
431
- borderColor: '#E0E0E0'
316
+
317
+ // Success screen (shown by default; customize with successUI)
318
+ successUI: {
319
+ backgroundColor: '#F5F5F5',
320
+ primaryTextColor: '#1A1A1A', // title and amount
321
+ secondaryTextColor: '#999999' // subtitle
432
322
  },
323
+
324
+ // Dark mode
433
325
  dark: {
434
326
  inputContainer: {
435
327
  backgroundColor: '#1A1A1A',
@@ -437,281 +329,78 @@ style: {
437
329
  },
438
330
  input: {
439
331
  textColor: '#FFFFFF',
440
- backgroundColor: '#2A2A2A'
332
+ placeholderColor: '#959499'
441
333
  },
442
334
  button: {
443
335
  backgroundColor: '#0066CC'
336
+ },
337
+ successUI: {
338
+ backgroundColor: '#1A1A1A',
339
+ primaryTextColor: '#FFFFFF',
340
+ secondaryTextColor: '#959499'
444
341
  }
445
342
  }
446
343
  }
447
344
  ```
448
345
 
449
- ### Available Font Families
346
+ **Available style properties:** `inputContainer`, `input`, `button`, `successUI`, `generalError`, `disclaimerColor`, `fieldErrorColor`, `dark` (for dark mode overrides)
450
347
 
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
- ```
348
+ See full TypeScript types in the package for all styling options.
466
349
 
467
- ### Complete Styling API
350
+ ## Error Handling
468
351
 
469
- All available styling properties:
352
+ ```javascript
353
+ import { PaymentResultStatus, PaymentResultErrorCode } from "@inflow_pay/sdk";
470
354
 
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
- };
560
- }
355
+ onComplete: (result) => {
356
+ if (result.status === PaymentResultStatus.FAILED && result.error) {
357
+ console.log(result.error.code); // e.g., 'THREE_DS_FAILED'
358
+ console.log(result.error.message); // User-friendly message
359
+ console.log(result.error.retryable); // Can user retry?
360
+ }
361
+ };
561
362
  ```
562
363
 
563
- ### Custom Placeholders
364
+ **Common error codes:** `THREE_DS_FAILED`, `PAYMENT_PROCESSING_ERROR`
564
365
 
565
- ```javascript
566
- placeholders: {
567
- cardNumber: '1234 5678 9012 3456',
568
- expiry: 'MM/YY',
569
- cvc: 'CVC'
570
- }
571
- ```
366
+ ## 3D Secure
572
367
 
573
- ### Custom Button Text
368
+ 3DS is handled automatically by the SDK. When required, a modal opens for bank authentication, then closes automatically. No setup needed.
574
369
 
575
- ```javascript
576
- buttonText: 'Pay Now'
577
- ```
370
+ ## Migration from React SDK
578
371
 
579
- ### React Example with All Styling Properties
372
+ **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
373
 
581
- ```tsx
582
- import { InflowPayProvider, CardElement } from '@inflow_pay/sdk/react';
374
+ **For non-React apps:** Use the vanilla JavaScript API shown in the examples above.
583
375
 
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
- ```
376
+ ## TypeScript
377
+
378
+ Full type definitions included:
690
379
 
691
- ## Security
380
+ ```typescript
381
+ import { InflowPayProvider, PaymentResultStatus } from "@inflow_pay/sdk";
382
+ import type { PaymentResult, PaymentError } from "@inflow_pay/sdk";
692
383
 
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
384
+ const provider = new InflowPayProvider({
385
+ config: { publicKey: "inflow_pub_xxx" },
386
+ });
387
+ ```
698
388
 
699
389
  ## Features
700
390
 
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
391
+ - ✅ Dynamic height adjustment
392
+ - ✅ Skeleton loader with shimmer effect
393
+ - ✅ Dark mode support
394
+ - ✅ Responsive design
395
+ - ✅ WCAG compliant
396
+ - ✅ Multi-language support
708
397
 
709
398
  ## Support
710
399
 
711
- - **Documentation:** https://docs.inflowpay.com/v0/reference/createpayment
400
+ - **Docs:** https://docs.inflowpay.com/v0/reference/createpayment
712
401
  - **Email:** support@inflowpay.com
713
402
  - **GitHub:** https://github.com/inflowpay/sdk
714
- - **Changelog:** See [CHANGELOG.md](./CHANGELOG.md) for version history
403
+ - **Changelog:** [CHANGELOG.md](./CHANGELOG.md)
715
404
 
716
405
  ## License
717
406