@inflow_pay/sdk 1.0.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/CHANGELOG.md +11 -0
- package/README.md +127 -102
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [1.1.0] - 2026-02-23
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- **Default success UI customization** – Style the built-in success screen via `style.successUI` (e.g. `backgroundColor`, `primaryTextColor`, `secondaryTextColor`). Use `dark.successUI` for dark mode overrides.
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
- **Dynamic height for success UI** – Iframe now reports content height when the success screen is shown, so the SDK container resizes correctly and no longer leaves extra empty space or overflow.
|
|
17
|
+
|
|
18
|
+
### Deprecated
|
|
19
|
+
- **General success styling** – `style.generalSuccess` and `style.dark.generalSuccess` are deprecated and have no effect (general success UI was removed from the iframe). They will be removed in the next major version. Use the default success UI and `style.successUI` instead.
|
|
20
|
+
|
|
10
21
|
## [0.8.0] - 2026-01-30
|
|
11
22
|
|
|
12
23
|
### Added
|
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# InflowPay SDK v2
|
|
2
2
|
|
|
3
|
-
Accept card payments with a secure, iframe-based payment form. This version delivers **enhanced security
|
|
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
4
|
|
|
5
5
|
## What's Best in This Version
|
|
6
6
|
|
|
@@ -19,7 +19,7 @@ npm install @inflow_pay/sdk
|
|
|
19
19
|
**CDN Option** (vanilla HTML pages only):
|
|
20
20
|
|
|
21
21
|
```html
|
|
22
|
-
<script src="https://cdn.jsdelivr.net/npm/@inflow_pay/sdk@1.
|
|
22
|
+
<script src="https://cdn.jsdelivr.net/npm/@inflow_pay/sdk@1.1.0/dist/sdk.umd.js"></script>
|
|
23
23
|
```
|
|
24
24
|
|
|
25
25
|
## Complete Example
|
|
@@ -28,22 +28,22 @@ npm install @inflow_pay/sdk
|
|
|
28
28
|
|
|
29
29
|
```javascript
|
|
30
30
|
// backend/api/create-payment.js
|
|
31
|
-
app.post(
|
|
32
|
-
const response = await fetch(
|
|
33
|
-
method:
|
|
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
34
|
headers: {
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
"Content-Type": "application/json",
|
|
36
|
+
"X-Inflow-Api-Key": process.env.INFLOW_PRIVATE_KEY,
|
|
37
37
|
},
|
|
38
38
|
body: JSON.stringify({
|
|
39
|
-
products: [{ name:
|
|
40
|
-
currency:
|
|
41
|
-
customerEmail:
|
|
42
|
-
firstName:
|
|
43
|
-
lastName:
|
|
44
|
-
billingCountry:
|
|
45
|
-
postalCode:
|
|
46
|
-
})
|
|
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
47
|
});
|
|
48
48
|
|
|
49
49
|
const data = await response.json();
|
|
@@ -54,32 +54,35 @@ app.post('/api/create-payment', async (req, res) => {
|
|
|
54
54
|
### Frontend: React
|
|
55
55
|
|
|
56
56
|
```tsx
|
|
57
|
-
import {
|
|
57
|
+
import {
|
|
58
|
+
InflowPayProvider,
|
|
59
|
+
CardElement,
|
|
60
|
+
PaymentResultStatus,
|
|
61
|
+
} from "@inflow_pay/sdk/react";
|
|
58
62
|
|
|
59
63
|
export default function CheckoutPage() {
|
|
60
64
|
const [paymentId, setPaymentId] = useState<string | null>(null);
|
|
61
65
|
|
|
62
66
|
useEffect(() => {
|
|
63
|
-
fetch(
|
|
64
|
-
.then(res => res.json())
|
|
65
|
-
.then(data => setPaymentId(data.paymentId));
|
|
67
|
+
fetch("/api/create-payment", { method: "POST" })
|
|
68
|
+
.then((res) => res.json())
|
|
69
|
+
.then((data) => setPaymentId(data.paymentId));
|
|
66
70
|
}, []);
|
|
67
71
|
|
|
68
72
|
if (!paymentId) return <div>Loading...</div>;
|
|
69
73
|
|
|
70
74
|
return (
|
|
71
|
-
<InflowPayProvider config={{ publicKey:
|
|
75
|
+
<InflowPayProvider config={{ publicKey: "inflow_pub_xxx" }}>
|
|
72
76
|
<CardElement
|
|
73
77
|
paymentId={paymentId}
|
|
74
|
-
showDefaultSuccessUI={true}
|
|
75
78
|
onComplete={(result) => {
|
|
76
79
|
if (result.status === PaymentResultStatus.SUCCESS) {
|
|
77
|
-
setTimeout(() => window.location.href =
|
|
80
|
+
setTimeout(() => (window.location.href = "/confirmation"), 2000);
|
|
78
81
|
}
|
|
79
82
|
}}
|
|
80
83
|
style={{
|
|
81
|
-
fontFamily:
|
|
82
|
-
button: { backgroundColor:
|
|
84
|
+
fontFamily: "Inter",
|
|
85
|
+
button: { backgroundColor: "#0070F3", textColor: "#FFFFFF" },
|
|
83
86
|
}}
|
|
84
87
|
/>
|
|
85
88
|
</InflowPayProvider>
|
|
@@ -92,24 +95,23 @@ export default function CheckoutPage() {
|
|
|
92
95
|
```html
|
|
93
96
|
<div id="card-container"></div>
|
|
94
97
|
|
|
95
|
-
<script src="https://cdn.jsdelivr.net/npm/@inflow_pay/sdk@
|
|
98
|
+
<script src="https://cdn.jsdelivr.net/npm/@inflow_pay/sdk@1.1.0/dist/sdk.umd.js"></script>
|
|
96
99
|
<script>
|
|
97
100
|
const provider = new InflowPaySDK.InflowPayProvider({
|
|
98
|
-
config: { publicKey:
|
|
101
|
+
config: { publicKey: "inflow_pub_xxx" },
|
|
99
102
|
});
|
|
100
103
|
|
|
101
|
-
fetch(
|
|
102
|
-
.then(res => res.json())
|
|
103
|
-
.then(data => {
|
|
104
|
+
fetch("/api/create-payment", { method: "POST" })
|
|
105
|
+
.then((res) => res.json())
|
|
106
|
+
.then((data) => {
|
|
104
107
|
const cardElement = provider.createCardElement({
|
|
105
108
|
paymentId: data.paymentId,
|
|
106
|
-
container:
|
|
107
|
-
showDefaultSuccessUI: true,
|
|
109
|
+
container: "#card-container",
|
|
108
110
|
onComplete: (result) => {
|
|
109
111
|
if (result.status === InflowPaySDK.PaymentResultStatus.SUCCESS) {
|
|
110
|
-
setTimeout(() => window.location.href =
|
|
112
|
+
setTimeout(() => (window.location.href = "/confirmation"), 2000);
|
|
111
113
|
}
|
|
112
|
-
}
|
|
114
|
+
},
|
|
113
115
|
});
|
|
114
116
|
cardElement.mount();
|
|
115
117
|
});
|
|
@@ -121,50 +123,63 @@ export default function CheckoutPage() {
|
|
|
121
123
|
The SDK includes a polished success screen that appears automatically after successful payment:
|
|
122
124
|
|
|
123
125
|
**What it shows:**
|
|
126
|
+
|
|
124
127
|
- ✅ Success icon and "Payment successful!" message
|
|
125
128
|
- 💳 Payment amount (when available from your payment data)
|
|
126
|
-
- 🎨 Automatically matches your brand colors and theme
|
|
127
|
-
- 🌙 Dark mode support
|
|
128
129
|
|
|
129
|
-
**
|
|
130
|
+
**Default vs custom:**
|
|
130
131
|
|
|
131
|
-
|
|
132
|
-
|
|
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
|
-
}
|
|
144
|
-
});
|
|
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:
|
|
145
134
|
|
|
146
|
-
|
|
135
|
+
_Vanilla JS:_
|
|
136
|
+
|
|
137
|
+
```javascript
|
|
147
138
|
const cardElement = provider.createCardElement({
|
|
148
|
-
paymentId:
|
|
149
|
-
container:
|
|
150
|
-
showDefaultSuccessUI: false,
|
|
139
|
+
paymentId: "pay_xxx",
|
|
140
|
+
container: "#card-container",
|
|
141
|
+
showDefaultSuccessUI: false,
|
|
151
142
|
onComplete: (result) => {
|
|
152
143
|
if (result.status === PaymentResultStatus.SUCCESS) {
|
|
153
|
-
|
|
154
|
-
document.getElementById('card-container').innerHTML = `
|
|
144
|
+
document.getElementById("card-container").innerHTML = `
|
|
155
145
|
<div class="custom-success">
|
|
156
146
|
<h2>Thank you for your purchase!</h2>
|
|
157
147
|
<p>Order ID: ${result.paymentId}</p>
|
|
158
148
|
</div>
|
|
159
149
|
`;
|
|
160
150
|
}
|
|
161
|
-
}
|
|
151
|
+
},
|
|
162
152
|
});
|
|
163
153
|
```
|
|
164
154
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
155
|
+
_React:_
|
|
156
|
+
|
|
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
|
+
```
|
|
168
183
|
|
|
169
184
|
## Payment Flow
|
|
170
185
|
|
|
@@ -173,8 +188,7 @@ const cardElement = provider.createCardElement({
|
|
|
173
188
|
3. User enters card details in secure iframe
|
|
174
189
|
4. SDK tokenizes card and processes payment
|
|
175
190
|
5. 3D Secure authentication (if required) - automatic modal
|
|
176
|
-
6.
|
|
177
|
-
7. `onComplete` callback fires → redirect or update UI
|
|
191
|
+
6. `onComplete` callback fires → redirect or update UI
|
|
178
192
|
|
|
179
193
|
## API Reference
|
|
180
194
|
|
|
@@ -183,9 +197,9 @@ const cardElement = provider.createCardElement({
|
|
|
183
197
|
```javascript
|
|
184
198
|
const provider = new InflowPayProvider({
|
|
185
199
|
config: {
|
|
186
|
-
publicKey:
|
|
187
|
-
locale:
|
|
188
|
-
}
|
|
200
|
+
publicKey: "inflow_pub_xxx", // Required
|
|
201
|
+
locale: "en", // Optional - defaults to browser language
|
|
202
|
+
},
|
|
189
203
|
});
|
|
190
204
|
```
|
|
191
205
|
|
|
@@ -195,10 +209,9 @@ const provider = new InflowPayProvider({
|
|
|
195
209
|
|
|
196
210
|
```javascript
|
|
197
211
|
const cardElement = provider.createCardElement({
|
|
198
|
-
paymentId:
|
|
199
|
-
container:
|
|
200
|
-
|
|
201
|
-
|
|
212
|
+
paymentId: "pay_xxx", // Required - from your backend
|
|
213
|
+
container: "#card-container", // Required - CSS selector or HTMLElement
|
|
214
|
+
|
|
202
215
|
// Callbacks
|
|
203
216
|
onComplete: (result) => {
|
|
204
217
|
if (result.status === PaymentResultStatus.SUCCESS) {
|
|
@@ -207,35 +220,35 @@ const cardElement = provider.createCardElement({
|
|
|
207
220
|
// Payment failed - result.error contains details
|
|
208
221
|
}
|
|
209
222
|
},
|
|
210
|
-
|
|
223
|
+
|
|
211
224
|
onReady: () => {
|
|
212
225
|
// Card element mounted and ready
|
|
213
226
|
},
|
|
214
|
-
|
|
227
|
+
|
|
215
228
|
onChange: (state) => {
|
|
216
229
|
// state.complete - whether form is valid
|
|
217
230
|
},
|
|
218
|
-
|
|
231
|
+
|
|
219
232
|
onError: (error) => {
|
|
220
233
|
// SDK-level errors
|
|
221
234
|
},
|
|
222
|
-
|
|
235
|
+
|
|
223
236
|
// Styling (optional)
|
|
224
237
|
style: {
|
|
225
|
-
fontFamily:
|
|
238
|
+
fontFamily: "Inter",
|
|
226
239
|
button: {
|
|
227
|
-
backgroundColor:
|
|
228
|
-
textColor:
|
|
229
|
-
}
|
|
240
|
+
backgroundColor: "#0070F3",
|
|
241
|
+
textColor: "#FFFFFF",
|
|
242
|
+
},
|
|
230
243
|
},
|
|
231
|
-
|
|
244
|
+
|
|
232
245
|
// Custom text (optional)
|
|
233
|
-
buttonText:
|
|
246
|
+
buttonText: "Pay Now",
|
|
234
247
|
placeholders: {
|
|
235
|
-
cardNumber:
|
|
236
|
-
expiry:
|
|
237
|
-
cvc:
|
|
238
|
-
}
|
|
248
|
+
cardNumber: "1234 5678 9012 3456",
|
|
249
|
+
expiry: "MM/YY",
|
|
250
|
+
cvc: "CVC",
|
|
251
|
+
},
|
|
239
252
|
});
|
|
240
253
|
|
|
241
254
|
cardElement.mount();
|
|
@@ -245,21 +258,21 @@ cardElement.mount();
|
|
|
245
258
|
|
|
246
259
|
```typescript
|
|
247
260
|
interface PaymentResult {
|
|
248
|
-
status:
|
|
261
|
+
status: "SUCCESS" | "FAILED";
|
|
249
262
|
paymentId: string;
|
|
250
263
|
error?: {
|
|
251
|
-
code: string;
|
|
252
|
-
message: string;
|
|
253
|
-
retryable: boolean;
|
|
254
|
-
}
|
|
264
|
+
code: string; // Error code (e.g., 'THREE_DS_FAILED')
|
|
265
|
+
message: string; // User-friendly message
|
|
266
|
+
retryable: boolean; // Can retry?
|
|
267
|
+
};
|
|
255
268
|
}
|
|
256
269
|
```
|
|
257
270
|
|
|
258
271
|
### CardElement Methods
|
|
259
272
|
|
|
260
273
|
```javascript
|
|
261
|
-
cardElement.mount();
|
|
262
|
-
cardElement.destroy();
|
|
274
|
+
cardElement.mount(); // Mount to DOM
|
|
275
|
+
cardElement.destroy(); // Cleanup and unmount
|
|
263
276
|
```
|
|
264
277
|
|
|
265
278
|
## Styling
|
|
@@ -270,7 +283,7 @@ Customize the payment form to match your brand:
|
|
|
270
283
|
style: {
|
|
271
284
|
fontFamily: 'Inter', // 'DM Sans' | 'Inter' | 'Poppins' | 'Nunito' | etc.
|
|
272
285
|
fillParent: true,
|
|
273
|
-
|
|
286
|
+
|
|
274
287
|
// Input container
|
|
275
288
|
inputContainer: {
|
|
276
289
|
backgroundColor: '#F5F5F5',
|
|
@@ -278,14 +291,14 @@ style: {
|
|
|
278
291
|
borderEnabled: true,
|
|
279
292
|
borderColor: '#E0E0E0'
|
|
280
293
|
},
|
|
281
|
-
|
|
294
|
+
|
|
282
295
|
// Input fields
|
|
283
296
|
input: {
|
|
284
297
|
textColor: '#1A1A1A',
|
|
285
298
|
placeholderColor: '#999999',
|
|
286
299
|
backgroundColor: 'transparent'
|
|
287
300
|
},
|
|
288
|
-
|
|
301
|
+
|
|
289
302
|
// Button
|
|
290
303
|
button: {
|
|
291
304
|
backgroundColor: '#0070F3',
|
|
@@ -300,7 +313,14 @@ style: {
|
|
|
300
313
|
opacity: 0.5
|
|
301
314
|
}
|
|
302
315
|
},
|
|
303
|
-
|
|
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
|
|
322
|
+
},
|
|
323
|
+
|
|
304
324
|
// Dark mode
|
|
305
325
|
dark: {
|
|
306
326
|
inputContainer: {
|
|
@@ -313,27 +333,32 @@ style: {
|
|
|
313
333
|
},
|
|
314
334
|
button: {
|
|
315
335
|
backgroundColor: '#0066CC'
|
|
336
|
+
},
|
|
337
|
+
successUI: {
|
|
338
|
+
backgroundColor: '#1A1A1A',
|
|
339
|
+
primaryTextColor: '#FFFFFF',
|
|
340
|
+
secondaryTextColor: '#959499'
|
|
316
341
|
}
|
|
317
342
|
}
|
|
318
343
|
}
|
|
319
344
|
```
|
|
320
345
|
|
|
321
|
-
**Available style properties:** `inputContainer`, `input`, `button`, `
|
|
346
|
+
**Available style properties:** `inputContainer`, `input`, `button`, `successUI`, `generalError`, `disclaimerColor`, `fieldErrorColor`, `dark` (for dark mode overrides)
|
|
322
347
|
|
|
323
348
|
See full TypeScript types in the package for all styling options.
|
|
324
349
|
|
|
325
350
|
## Error Handling
|
|
326
351
|
|
|
327
352
|
```javascript
|
|
328
|
-
import { PaymentResultStatus, PaymentResultErrorCode } from
|
|
353
|
+
import { PaymentResultStatus, PaymentResultErrorCode } from "@inflow_pay/sdk";
|
|
329
354
|
|
|
330
355
|
onComplete: (result) => {
|
|
331
356
|
if (result.status === PaymentResultStatus.FAILED && result.error) {
|
|
332
|
-
console.log(result.error.code);
|
|
333
|
-
console.log(result.error.message);
|
|
357
|
+
console.log(result.error.code); // e.g., 'THREE_DS_FAILED'
|
|
358
|
+
console.log(result.error.message); // User-friendly message
|
|
334
359
|
console.log(result.error.retryable); // Can user retry?
|
|
335
360
|
}
|
|
336
|
-
}
|
|
361
|
+
};
|
|
337
362
|
```
|
|
338
363
|
|
|
339
364
|
**Common error codes:** `THREE_DS_FAILED`, `PAYMENT_PROCESSING_ERROR`
|
|
@@ -353,11 +378,11 @@ onComplete: (result) => {
|
|
|
353
378
|
Full type definitions included:
|
|
354
379
|
|
|
355
380
|
```typescript
|
|
356
|
-
import { InflowPayProvider, PaymentResultStatus } from
|
|
357
|
-
import type { PaymentResult, PaymentError } from
|
|
381
|
+
import { InflowPayProvider, PaymentResultStatus } from "@inflow_pay/sdk";
|
|
382
|
+
import type { PaymentResult, PaymentError } from "@inflow_pay/sdk";
|
|
358
383
|
|
|
359
384
|
const provider = new InflowPayProvider({
|
|
360
|
-
config: { publicKey:
|
|
385
|
+
config: { publicKey: "inflow_pub_xxx" },
|
|
361
386
|
});
|
|
362
387
|
```
|
|
363
388
|
|