@inflow_pay/sdk 1.0.0 → 1.2.0-beta.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 +234 -113
- package/dist/payment-sdk-DhJS0NRo.js +169 -0
- package/dist/payment-sdk-DhJS0NRo.js.map +1 -0
- package/dist/payment-sdk-DqfuWSo1.mjs +661 -0
- package/dist/payment-sdk-DqfuWSo1.mjs.map +1 -0
- package/dist/react/index.d.ts +52 -19
- package/dist/react.cjs +1 -2
- package/dist/react.esm.js +2 -11
- package/dist/react.umd.js +57 -73
- package/dist/react.umd.js.map +1 -1
- package/dist/sdk.cjs +2 -2
- package/dist/sdk.cjs.map +1 -1
- package/dist/sdk.d.ts +50 -18
- package/dist/sdk.esm.js +48 -65
- package/dist/sdk.esm.js.map +1 -1
- package/dist/sdk.umd.js +56 -88
- package/dist/sdk.umd.js.map +1 -1
- package/package.json +7 -2
- package/dist/payment-sdk-CC-mm-nt.js +0 -169
- package/dist/payment-sdk-CC-mm-nt.js.map +0 -1
- package/dist/payment-sdk-oRqgQSx5.mjs +0 -821
- package/dist/payment-sdk-oRqgQSx5.mjs.map +0 -1
- package/dist/react.cjs.map +0 -1
- package/dist/react.esm.js.map +0 -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
|
|
|
@@ -9,6 +9,7 @@ Accept card payments with a secure, iframe-based payment form. This version deli
|
|
|
9
9
|
- 🎯 **Auto 3D Secure**: SDK handles authentication modals automatically
|
|
10
10
|
- 🚀 **Zero Configuration**: Works out of the box with sensible defaults
|
|
11
11
|
- 🎨 **Fully Customizable**: Match your brand with comprehensive styling options
|
|
12
|
+
- 💳 **Save card (setup)**: Collect and tokenize a card without charging, using a `CustomerPaymentMethodRequest` ID (`setupId`)
|
|
12
13
|
|
|
13
14
|
## Installation
|
|
14
15
|
|
|
@@ -16,10 +17,16 @@ Accept card payments with a secure, iframe-based payment form. This version deli
|
|
|
16
17
|
npm install @inflow_pay/sdk
|
|
17
18
|
```
|
|
18
19
|
|
|
20
|
+
**React apps** — import from `@inflow_pay/sdk/react` and ensure peer dependencies are installed:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
npm install @inflow_pay/sdk react react-dom
|
|
24
|
+
```
|
|
25
|
+
|
|
19
26
|
**CDN Option** (vanilla HTML pages only):
|
|
20
27
|
|
|
21
28
|
```html
|
|
22
|
-
<script src="https://cdn.jsdelivr.net/npm/@inflow_pay/sdk@1.
|
|
29
|
+
<script src="https://cdn.jsdelivr.net/npm/@inflow_pay/sdk@1.1.0/dist/sdk.umd.js"></script>
|
|
23
30
|
```
|
|
24
31
|
|
|
25
32
|
## Complete Example
|
|
@@ -28,22 +35,22 @@ npm install @inflow_pay/sdk
|
|
|
28
35
|
|
|
29
36
|
```javascript
|
|
30
37
|
// backend/api/create-payment.js
|
|
31
|
-
app.post(
|
|
32
|
-
const response = await fetch(
|
|
33
|
-
method:
|
|
38
|
+
app.post("/api/create-payment", async (req, res) => {
|
|
39
|
+
const response = await fetch("https://api.inflowpay.xyz/api/server/payment", {
|
|
40
|
+
method: "POST",
|
|
34
41
|
headers: {
|
|
35
|
-
|
|
36
|
-
|
|
42
|
+
"Content-Type": "application/json",
|
|
43
|
+
"X-Inflow-Api-Key": process.env.INFLOW_PRIVATE_KEY,
|
|
37
44
|
},
|
|
38
45
|
body: JSON.stringify({
|
|
39
|
-
products: [{ name:
|
|
40
|
-
currency:
|
|
41
|
-
customerEmail:
|
|
42
|
-
firstName:
|
|
43
|
-
lastName:
|
|
44
|
-
billingCountry:
|
|
45
|
-
postalCode:
|
|
46
|
-
})
|
|
46
|
+
products: [{ name: "Product", price: 4999, quantity: 1 }],
|
|
47
|
+
currency: "EUR",
|
|
48
|
+
customerEmail: "customer@example.com",
|
|
49
|
+
firstName: "John",
|
|
50
|
+
lastName: "Doe",
|
|
51
|
+
billingCountry: "FR",
|
|
52
|
+
postalCode: "75001",
|
|
53
|
+
}),
|
|
47
54
|
});
|
|
48
55
|
|
|
49
56
|
const data = await response.json();
|
|
@@ -54,32 +61,64 @@ app.post('/api/create-payment', async (req, res) => {
|
|
|
54
61
|
### Frontend: React
|
|
55
62
|
|
|
56
63
|
```tsx
|
|
57
|
-
import {
|
|
64
|
+
import {
|
|
65
|
+
InflowPayProvider,
|
|
66
|
+
CardElement,
|
|
67
|
+
PaymentResultStatus,
|
|
68
|
+
} from "@inflow_pay/sdk/react";
|
|
58
69
|
|
|
59
70
|
export default function CheckoutPage() {
|
|
60
71
|
const [paymentId, setPaymentId] = useState<string | null>(null);
|
|
61
72
|
|
|
62
73
|
useEffect(() => {
|
|
63
|
-
fetch(
|
|
64
|
-
.then(res => res.json())
|
|
65
|
-
.then(data => setPaymentId(data.paymentId));
|
|
74
|
+
fetch("/api/create-payment", { method: "POST" })
|
|
75
|
+
.then((res) => res.json())
|
|
76
|
+
.then((data) => setPaymentId(data.paymentId));
|
|
66
77
|
}, []);
|
|
67
78
|
|
|
68
79
|
if (!paymentId) return <div>Loading...</div>;
|
|
69
80
|
|
|
70
81
|
return (
|
|
71
|
-
<InflowPayProvider config={{ publicKey:
|
|
82
|
+
<InflowPayProvider config={{ publicKey: "inflow_pub_xxx" }}>
|
|
72
83
|
<CardElement
|
|
73
84
|
paymentId={paymentId}
|
|
74
|
-
showDefaultSuccessUI={true}
|
|
75
85
|
onComplete={(result) => {
|
|
76
86
|
if (result.status === PaymentResultStatus.SUCCESS) {
|
|
77
|
-
setTimeout(() => window.location.href =
|
|
87
|
+
setTimeout(() => (window.location.href = "/confirmation"), 2000);
|
|
78
88
|
}
|
|
79
89
|
}}
|
|
80
90
|
style={{
|
|
81
|
-
fontFamily:
|
|
82
|
-
button: { backgroundColor:
|
|
91
|
+
fontFamily: "Inter",
|
|
92
|
+
button: { backgroundColor: "#0070F3", textColor: "#FFFFFF" },
|
|
93
|
+
}}
|
|
94
|
+
/>
|
|
95
|
+
</InflowPayProvider>
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Save card (setup) — React
|
|
101
|
+
|
|
102
|
+
Use **`setupId`** (ID returned when you create a **CustomerPaymentMethodRequest** on your server) instead of **`paymentId`**. The two are mutually exclusive. On success, `onComplete` receives a **`SaveCardResult`** with `status` and `setupId`.
|
|
103
|
+
|
|
104
|
+
```tsx
|
|
105
|
+
import {
|
|
106
|
+
InflowPayProvider,
|
|
107
|
+
CardElement,
|
|
108
|
+
PaymentResultStatus,
|
|
109
|
+
type SaveCardResult,
|
|
110
|
+
} from "@inflow_pay/sdk/react";
|
|
111
|
+
|
|
112
|
+
export default function AddCardPage({ setupId }: { setupId: string }) {
|
|
113
|
+
return (
|
|
114
|
+
<InflowPayProvider config={{ publicKey: "inflow_pub_xxx" }}>
|
|
115
|
+
<CardElement
|
|
116
|
+
setupId={setupId}
|
|
117
|
+
onComplete={(result) => {
|
|
118
|
+
if (result.status === PaymentResultStatus.SUCCESS) {
|
|
119
|
+
const save = result as SaveCardResult;
|
|
120
|
+
console.log("Card saved for request:", save.setupId);
|
|
121
|
+
}
|
|
83
122
|
}}
|
|
84
123
|
/>
|
|
85
124
|
</InflowPayProvider>
|
|
@@ -87,94 +126,139 @@ export default function CheckoutPage() {
|
|
|
87
126
|
}
|
|
88
127
|
```
|
|
89
128
|
|
|
129
|
+
Your backend should create the customer payment method request with your **private** API key and expose only the returned request ID to the browser as `setupId`.
|
|
130
|
+
|
|
90
131
|
### Frontend: Vanilla JavaScript
|
|
91
132
|
|
|
92
133
|
```html
|
|
93
134
|
<div id="card-container"></div>
|
|
94
135
|
|
|
95
|
-
<script src="https://cdn.jsdelivr.net/npm/@inflow_pay/sdk@
|
|
136
|
+
<script src="https://cdn.jsdelivr.net/npm/@inflow_pay/sdk@1.1.0/dist/sdk.umd.js"></script>
|
|
96
137
|
<script>
|
|
97
138
|
const provider = new InflowPaySDK.InflowPayProvider({
|
|
98
|
-
config: { publicKey:
|
|
139
|
+
config: { publicKey: "inflow_pub_xxx" },
|
|
99
140
|
});
|
|
100
141
|
|
|
101
|
-
fetch(
|
|
102
|
-
.then(res => res.json())
|
|
103
|
-
.then(data => {
|
|
142
|
+
fetch("/api/create-payment", { method: "POST" })
|
|
143
|
+
.then((res) => res.json())
|
|
144
|
+
.then((data) => {
|
|
104
145
|
const cardElement = provider.createCardElement({
|
|
105
146
|
paymentId: data.paymentId,
|
|
106
|
-
container:
|
|
107
|
-
showDefaultSuccessUI: true,
|
|
147
|
+
container: "#card-container",
|
|
108
148
|
onComplete: (result) => {
|
|
109
149
|
if (result.status === InflowPaySDK.PaymentResultStatus.SUCCESS) {
|
|
110
|
-
setTimeout(() => window.location.href =
|
|
150
|
+
setTimeout(() => (window.location.href = "/confirmation"), 2000);
|
|
111
151
|
}
|
|
112
|
-
}
|
|
152
|
+
},
|
|
113
153
|
});
|
|
114
154
|
cardElement.mount();
|
|
115
155
|
});
|
|
116
156
|
</script>
|
|
117
157
|
```
|
|
118
158
|
|
|
159
|
+
### Save card (setup) — Vanilla JavaScript
|
|
160
|
+
|
|
161
|
+
```javascript
|
|
162
|
+
const provider = new InflowPaySDK.InflowPayProvider({
|
|
163
|
+
config: { publicKey: "inflow_pub_xxx" },
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
fetch("/api/create-card-setup", { method: "POST" })
|
|
167
|
+
.then((res) => res.json())
|
|
168
|
+
.then((data) => {
|
|
169
|
+
const cardElement = provider.createCardElement({
|
|
170
|
+
setupId: data.setupId,
|
|
171
|
+
container: "#card-container",
|
|
172
|
+
onComplete: (result) => {
|
|
173
|
+
if (result.status === InflowPaySDK.PaymentResultStatus.SUCCESS) {
|
|
174
|
+
console.log("setupId:", result.setupId);
|
|
175
|
+
}
|
|
176
|
+
},
|
|
177
|
+
});
|
|
178
|
+
cardElement.mount();
|
|
179
|
+
});
|
|
180
|
+
```
|
|
181
|
+
|
|
119
182
|
## Built-in Success UI Explained
|
|
120
183
|
|
|
121
184
|
The SDK includes a polished success screen that appears automatically after successful payment:
|
|
122
185
|
|
|
123
186
|
**What it shows:**
|
|
187
|
+
|
|
124
188
|
- ✅ Success icon and "Payment successful!" message
|
|
125
189
|
- 💳 Payment amount (when available from your payment data)
|
|
126
|
-
- 🎨 Automatically matches your brand colors and theme
|
|
127
|
-
- 🌙 Dark mode support
|
|
128
190
|
|
|
129
|
-
**
|
|
191
|
+
**Default vs custom:**
|
|
130
192
|
|
|
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
|
-
});
|
|
193
|
+
- **Default UI** (default): Built-in success screen shows automatically. You don't need to do anything — quick integration, looks great out of the box.
|
|
194
|
+
- **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
195
|
|
|
146
|
-
|
|
196
|
+
_Vanilla JS:_
|
|
197
|
+
|
|
198
|
+
```javascript
|
|
147
199
|
const cardElement = provider.createCardElement({
|
|
148
|
-
paymentId:
|
|
149
|
-
container:
|
|
150
|
-
showDefaultSuccessUI: false,
|
|
200
|
+
paymentId: "pay_xxx",
|
|
201
|
+
container: "#card-container",
|
|
202
|
+
showDefaultSuccessUI: false,
|
|
151
203
|
onComplete: (result) => {
|
|
152
204
|
if (result.status === PaymentResultStatus.SUCCESS) {
|
|
153
|
-
|
|
154
|
-
document.getElementById('card-container').innerHTML = `
|
|
205
|
+
document.getElementById("card-container").innerHTML = `
|
|
155
206
|
<div class="custom-success">
|
|
156
207
|
<h2>Thank you for your purchase!</h2>
|
|
157
208
|
<p>Order ID: ${result.paymentId}</p>
|
|
158
209
|
</div>
|
|
159
210
|
`;
|
|
160
211
|
}
|
|
161
|
-
}
|
|
212
|
+
},
|
|
162
213
|
});
|
|
163
214
|
```
|
|
164
215
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
216
|
+
_React:_
|
|
217
|
+
|
|
218
|
+
```tsx
|
|
219
|
+
const [result, setResult] = useState<PaymentResult | null>(null);
|
|
220
|
+
|
|
221
|
+
return (
|
|
222
|
+
<>
|
|
223
|
+
{result ? (
|
|
224
|
+
<div className="custom-success">
|
|
225
|
+
<h2>Thank you for your purchase!</h2>
|
|
226
|
+
<p>Your payment was successful.</p>
|
|
227
|
+
</div>
|
|
228
|
+
) : (
|
|
229
|
+
<InflowPayProvider config={{ publicKey: "inflow_pub_xxx" }}>
|
|
230
|
+
<CardElement
|
|
231
|
+
paymentId="pay_xxx"
|
|
232
|
+
showDefaultSuccessUI={false}
|
|
233
|
+
onComplete={(res) => {
|
|
234
|
+
if (res.status === PaymentResultStatus.SUCCESS) {
|
|
235
|
+
setResult(res);
|
|
236
|
+
}
|
|
237
|
+
}}
|
|
238
|
+
/>
|
|
239
|
+
</InflowPayProvider>
|
|
240
|
+
)}
|
|
241
|
+
</>
|
|
242
|
+
);
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
## Payment flow
|
|
246
|
+
|
|
247
|
+
**Charge (payment)**
|
|
248
|
+
|
|
249
|
+
1. Backend creates a payment → returns `paymentId`
|
|
250
|
+
2. Frontend mounts `CardElement` with `paymentId` and your public key
|
|
251
|
+
3. User enters card details in the secure iframe
|
|
252
|
+
4. SDK tokenizes the card and processes the payment
|
|
253
|
+
5. 3D Secure (if required) — handled automatically
|
|
254
|
+
6. `onComplete` fires with a **`PaymentResult`** → redirect or update UI
|
|
168
255
|
|
|
169
|
-
|
|
256
|
+
**Save card (setup)**
|
|
170
257
|
|
|
171
|
-
1. Backend creates
|
|
172
|
-
2. Frontend
|
|
173
|
-
3. User
|
|
174
|
-
4.
|
|
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
|
|
258
|
+
1. Backend creates a **CustomerPaymentMethodRequest** → returns its ID as `setupId`
|
|
259
|
+
2. Frontend mounts `CardElement` with **`setupId`** (not `paymentId`)
|
|
260
|
+
3. User completes the card form; 3DS may still run when the issuer requires it
|
|
261
|
+
4. `onComplete` fires with a **`SaveCardResult`** (`setupId` + `status`, and `error` on failure)
|
|
178
262
|
|
|
179
263
|
## API Reference
|
|
180
264
|
|
|
@@ -183,9 +267,9 @@ const cardElement = provider.createCardElement({
|
|
|
183
267
|
```javascript
|
|
184
268
|
const provider = new InflowPayProvider({
|
|
185
269
|
config: {
|
|
186
|
-
publicKey:
|
|
187
|
-
locale:
|
|
188
|
-
}
|
|
270
|
+
publicKey: "inflow_pub_xxx", // Required
|
|
271
|
+
locale: "en", // Optional - defaults to browser language
|
|
272
|
+
},
|
|
189
273
|
});
|
|
190
274
|
```
|
|
191
275
|
|
|
@@ -193,12 +277,14 @@ const provider = new InflowPayProvider({
|
|
|
193
277
|
|
|
194
278
|
### CardElement
|
|
195
279
|
|
|
280
|
+
Pass exactly one of **`paymentId`** (checkout) or **`setupId`** (save card). Passing both or neither throws.
|
|
281
|
+
|
|
196
282
|
```javascript
|
|
197
283
|
const cardElement = provider.createCardElement({
|
|
198
|
-
paymentId:
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
284
|
+
paymentId: "pay_xxx", // XOR setupId — from your backend
|
|
285
|
+
// setupId: "cus_pm_req_xxx", // save-card flow (CustomerPaymentMethodRequest ID)
|
|
286
|
+
container: "#card-container", // Required - CSS selector or HTMLElement
|
|
287
|
+
|
|
202
288
|
// Callbacks
|
|
203
289
|
onComplete: (result) => {
|
|
204
290
|
if (result.status === PaymentResultStatus.SUCCESS) {
|
|
@@ -207,59 +293,71 @@ const cardElement = provider.createCardElement({
|
|
|
207
293
|
// Payment failed - result.error contains details
|
|
208
294
|
}
|
|
209
295
|
},
|
|
210
|
-
|
|
296
|
+
|
|
211
297
|
onReady: () => {
|
|
212
298
|
// Card element mounted and ready
|
|
213
299
|
},
|
|
214
|
-
|
|
300
|
+
|
|
215
301
|
onChange: (state) => {
|
|
216
302
|
// state.complete - whether form is valid
|
|
217
303
|
},
|
|
218
|
-
|
|
304
|
+
|
|
219
305
|
onError: (error) => {
|
|
220
306
|
// SDK-level errors
|
|
221
307
|
},
|
|
222
|
-
|
|
308
|
+
|
|
223
309
|
// Styling (optional)
|
|
224
310
|
style: {
|
|
225
|
-
fontFamily:
|
|
311
|
+
fontFamily: "Inter",
|
|
226
312
|
button: {
|
|
227
|
-
backgroundColor:
|
|
228
|
-
textColor:
|
|
229
|
-
}
|
|
313
|
+
backgroundColor: "#0070F3",
|
|
314
|
+
textColor: "#FFFFFF",
|
|
315
|
+
},
|
|
230
316
|
},
|
|
231
|
-
|
|
317
|
+
|
|
232
318
|
// Custom text (optional)
|
|
233
|
-
buttonText:
|
|
319
|
+
buttonText: "Pay Now",
|
|
234
320
|
placeholders: {
|
|
235
|
-
cardNumber:
|
|
236
|
-
expiry:
|
|
237
|
-
cvc:
|
|
238
|
-
}
|
|
321
|
+
cardNumber: "1234 5678 9012 3456",
|
|
322
|
+
expiry: "MM/YY",
|
|
323
|
+
cvc: "CVC",
|
|
324
|
+
},
|
|
239
325
|
});
|
|
240
326
|
|
|
241
327
|
cardElement.mount();
|
|
242
328
|
```
|
|
243
329
|
|
|
244
|
-
### Payment
|
|
330
|
+
### Payment and save-card results
|
|
245
331
|
|
|
246
332
|
```typescript
|
|
247
333
|
interface PaymentResult {
|
|
248
|
-
status:
|
|
334
|
+
status: "SUCCESS" | "FAILED";
|
|
249
335
|
paymentId: string;
|
|
250
336
|
error?: {
|
|
251
|
-
code: string;
|
|
252
|
-
message: string;
|
|
253
|
-
retryable: boolean;
|
|
254
|
-
}
|
|
337
|
+
code: string; // Error code (e.g., 'THREE_DS_FAILED')
|
|
338
|
+
message: string; // User-friendly message
|
|
339
|
+
retryable: boolean; // Can retry?
|
|
340
|
+
};
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
interface SaveCardResult {
|
|
344
|
+
status: "SUCCESS" | "FAILED";
|
|
345
|
+
setupId: string;
|
|
346
|
+
error?: {
|
|
347
|
+
code: string;
|
|
348
|
+
message: string;
|
|
349
|
+
retryable: boolean;
|
|
350
|
+
};
|
|
255
351
|
}
|
|
256
352
|
```
|
|
257
353
|
|
|
354
|
+
In **React**, `onComplete` is typed as `(result: PaymentResult | SaveCardResult) => void`. Use `result.status` and narrow with `'paymentId' in result` vs `'setupId' in result`, or cast when you know which mode you mounted.
|
|
355
|
+
|
|
258
356
|
### CardElement Methods
|
|
259
357
|
|
|
260
358
|
```javascript
|
|
261
|
-
cardElement.mount();
|
|
262
|
-
cardElement.destroy();
|
|
359
|
+
cardElement.mount(); // Mount to DOM
|
|
360
|
+
cardElement.destroy(); // Cleanup and unmount
|
|
263
361
|
```
|
|
264
362
|
|
|
265
363
|
## Styling
|
|
@@ -270,7 +368,7 @@ Customize the payment form to match your brand:
|
|
|
270
368
|
style: {
|
|
271
369
|
fontFamily: 'Inter', // 'DM Sans' | 'Inter' | 'Poppins' | 'Nunito' | etc.
|
|
272
370
|
fillParent: true,
|
|
273
|
-
|
|
371
|
+
|
|
274
372
|
// Input container
|
|
275
373
|
inputContainer: {
|
|
276
374
|
backgroundColor: '#F5F5F5',
|
|
@@ -278,14 +376,14 @@ style: {
|
|
|
278
376
|
borderEnabled: true,
|
|
279
377
|
borderColor: '#E0E0E0'
|
|
280
378
|
},
|
|
281
|
-
|
|
379
|
+
|
|
282
380
|
// Input fields
|
|
283
381
|
input: {
|
|
284
382
|
textColor: '#1A1A1A',
|
|
285
383
|
placeholderColor: '#999999',
|
|
286
384
|
backgroundColor: 'transparent'
|
|
287
385
|
},
|
|
288
|
-
|
|
386
|
+
|
|
289
387
|
// Button
|
|
290
388
|
button: {
|
|
291
389
|
backgroundColor: '#0070F3',
|
|
@@ -300,7 +398,14 @@ style: {
|
|
|
300
398
|
opacity: 0.5
|
|
301
399
|
}
|
|
302
400
|
},
|
|
303
|
-
|
|
401
|
+
|
|
402
|
+
// Success screen (shown by default; customize with successUI)
|
|
403
|
+
successUI: {
|
|
404
|
+
backgroundColor: '#F5F5F5',
|
|
405
|
+
primaryTextColor: '#1A1A1A', // title and amount
|
|
406
|
+
secondaryTextColor: '#999999' // subtitle
|
|
407
|
+
},
|
|
408
|
+
|
|
304
409
|
// Dark mode
|
|
305
410
|
dark: {
|
|
306
411
|
inputContainer: {
|
|
@@ -313,27 +418,32 @@ style: {
|
|
|
313
418
|
},
|
|
314
419
|
button: {
|
|
315
420
|
backgroundColor: '#0066CC'
|
|
421
|
+
},
|
|
422
|
+
successUI: {
|
|
423
|
+
backgroundColor: '#1A1A1A',
|
|
424
|
+
primaryTextColor: '#FFFFFF',
|
|
425
|
+
secondaryTextColor: '#959499'
|
|
316
426
|
}
|
|
317
427
|
}
|
|
318
428
|
}
|
|
319
429
|
```
|
|
320
430
|
|
|
321
|
-
**Available style properties:** `inputContainer`, `input`, `button`, `
|
|
431
|
+
**Available style properties:** `inputContainer`, `input`, `button`, `successUI`, `generalError`, `disclaimerColor`, `fieldErrorColor`, `dark` (for dark mode overrides)
|
|
322
432
|
|
|
323
433
|
See full TypeScript types in the package for all styling options.
|
|
324
434
|
|
|
325
435
|
## Error Handling
|
|
326
436
|
|
|
327
437
|
```javascript
|
|
328
|
-
import { PaymentResultStatus, PaymentResultErrorCode } from
|
|
438
|
+
import { PaymentResultStatus, PaymentResultErrorCode } from "@inflow_pay/sdk";
|
|
329
439
|
|
|
330
440
|
onComplete: (result) => {
|
|
331
441
|
if (result.status === PaymentResultStatus.FAILED && result.error) {
|
|
332
|
-
console.log(result.error.code);
|
|
333
|
-
console.log(result.error.message);
|
|
442
|
+
console.log(result.error.code); // e.g., 'THREE_DS_FAILED'
|
|
443
|
+
console.log(result.error.message); // User-friendly message
|
|
334
444
|
console.log(result.error.retryable); // Can user retry?
|
|
335
445
|
}
|
|
336
|
-
}
|
|
446
|
+
};
|
|
337
447
|
```
|
|
338
448
|
|
|
339
449
|
**Common error codes:** `THREE_DS_FAILED`, `PAYMENT_PROCESSING_ERROR`
|
|
@@ -350,17 +460,28 @@ onComplete: (result) => {
|
|
|
350
460
|
|
|
351
461
|
## TypeScript
|
|
352
462
|
|
|
353
|
-
Full type definitions included:
|
|
463
|
+
Full type definitions are included for both entry points:
|
|
354
464
|
|
|
355
465
|
```typescript
|
|
356
|
-
|
|
357
|
-
import
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
}
|
|
466
|
+
// Vanilla (InflowPayProvider, PaymentSDK, CardElement)
|
|
467
|
+
import {
|
|
468
|
+
InflowPayProvider,
|
|
469
|
+
PaymentResultStatus,
|
|
470
|
+
} from "@inflow_pay/sdk";
|
|
471
|
+
import type { PaymentResult, SaveCardResult, PaymentError } from "@inflow_pay/sdk";
|
|
472
|
+
|
|
473
|
+
// React components and hooks
|
|
474
|
+
import {
|
|
475
|
+
InflowPayProvider,
|
|
476
|
+
CardElement,
|
|
477
|
+
useInflowPay,
|
|
478
|
+
PaymentResultStatus,
|
|
479
|
+
} from "@inflow_pay/sdk/react";
|
|
480
|
+
import type { PaymentResult, SaveCardResult } from "@inflow_pay/sdk/react";
|
|
362
481
|
```
|
|
363
482
|
|
|
483
|
+
`useInflowPay()` returns the shared `PaymentSDK` instance from `InflowPayProvider` (e.g. for advanced use).
|
|
484
|
+
|
|
364
485
|
## Features
|
|
365
486
|
|
|
366
487
|
- ✅ Dynamic height adjustment
|