@liquidcommerce/cloud-sdk 1.3.0 → 1.5.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 +378 -120
- package/dist/index.cjs +1 -1
- package/dist/index.esm.js +1 -1
- package/dist/liquidcommerce-cloud-sdk.ssr.js +1 -1
- package/dist/types/constants/core.constant.d.ts +8 -0
- package/dist/types/core/cart-helper.service.d.ts +1 -1
- package/dist/types/core/catalog-helper.service.d.ts +24 -4
- package/dist/types/core/checkout-helper.service.d.ts +23 -8
- package/dist/types/core/location-helper.service.d.ts +4 -3
- package/dist/types/core/payment-provider.service.d.ts +16 -1
- package/dist/types/core/singleton.service.d.ts +9 -10
- package/dist/types/{enums.d.ts → enums/enums.d.ts} +62 -92
- package/dist/types/enums/index.d.ts +2 -0
- package/dist/types/enums/taxonomy.d.ts +285 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/types/interfaces/address.interface.d.ts +86 -1
- package/dist/types/interfaces/cart.interface.d.ts +28 -10
- package/dist/types/interfaces/catalog.interface.d.ts +268 -8
- package/dist/types/interfaces/checkout.interface.d.ts +265 -50
- package/dist/types/interfaces/index.d.ts +8 -0
- package/dist/types/interfaces/liquid-commerce-client.interface.d.ts +34 -9
- package/dist/types/interfaces/payment.interface.d.ts +81 -2
- package/dist/types/interfaces/retailer.interface.d.ts +121 -0
- package/dist/types/interfaces/user.interface.d.ts +115 -8
- package/dist/types/liquid-commerce-client.d.ts +3 -192
- package/dist/types/services/address.service.d.ts +2 -18
- package/dist/types/services/cart.service.d.ts +1 -1
- package/dist/types/services/catalog.service.d.ts +1 -12
- package/dist/types/services/checkout.service.d.ts +1 -1
- package/dist/types/services/index.d.ts +5 -0
- package/dist/types/services/payment.service.d.ts +1 -1
- package/dist/types/services/user.service.d.ts +53 -1
- package/dist/types/types.d.ts +11 -5
- package/package.json +105 -105
- package/umd/liquidcommerce-cloud-sdk.min.js +1 -1
- package/dist/types/interfaces/catalog.service.interface.d.ts +0 -65
package/README.md
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
|
|
1
|
+
<p align="start">
|
|
2
|
+
<img
|
|
3
|
+
src="https://storage.googleapis.com/liquid-platform/repo_lc_dark.webp"
|
|
4
|
+
alt="LiquidCommerce Logo"
|
|
5
|
+
style="max-width: 70%; height: auto;"
|
|
6
|
+
/>
|
|
7
|
+
</p>
|
|
2
8
|
|
|
3
9
|
# LiquidCommerce Cloud SDK
|
|
4
10
|
|
|
@@ -7,16 +13,17 @@ The LiquidCommerce Cloud SDK provides an easy way to interact with our APIs thro
|
|
|
7
13
|
## Table of Contents
|
|
8
14
|
|
|
9
15
|
- [Installation](#installation)
|
|
10
|
-
- [
|
|
16
|
+
- [Configuration](#configuration)
|
|
11
17
|
- [Usage](#usage)
|
|
12
|
-
- [
|
|
18
|
+
- [Services](#services)
|
|
13
19
|
- [Address](#address)
|
|
14
20
|
- [Catalog](#catalog)
|
|
15
21
|
- [Cart](#cart)
|
|
16
22
|
- [User](#user)
|
|
17
23
|
- [Payment](#payment)
|
|
18
24
|
- [Checkout](#checkout)
|
|
19
|
-
- [
|
|
25
|
+
- [Response Types](#response-types)
|
|
26
|
+
- [Error Handling](#error-handling)
|
|
20
27
|
- [Documentation](#documentation)
|
|
21
28
|
|
|
22
29
|
## Installation
|
|
@@ -27,57 +34,88 @@ Install the package with:
|
|
|
27
34
|
npm install @liquidcommerce/cloud-sdk
|
|
28
35
|
# or
|
|
29
36
|
yarn add @liquidcommerce/cloud-sdk
|
|
37
|
+
# or
|
|
38
|
+
pnpm add @liquidcommerce/cloud-sdk
|
|
30
39
|
```
|
|
31
40
|
|
|
32
|
-
##
|
|
33
|
-
|
|
34
|
-
The LiquidCommerce library uses API keys to authenticate requests. You can request your keys from your Partnerships liaison.
|
|
35
|
-
|
|
36
|
-
Your API keys carry many privileges, so be sure to keep them secure! Do not share your secret API keys in publicly accessible areas such as GitHub, client-side code, and so forth.
|
|
41
|
+
## Configuration
|
|
37
42
|
|
|
38
|
-
|
|
43
|
+
The SDK requires configuration during initialization:
|
|
39
44
|
|
|
40
|
-
|
|
45
|
+
```typescript
|
|
46
|
+
import { LiquidCommerce, LIQUID_COMMERCE_ENV } from '@liquidcommerce/cloud-sdk';
|
|
41
47
|
|
|
42
|
-
```javascript
|
|
43
|
-
import LiquidCommerce from '@liquidcommerce/cloud-sdk';
|
|
44
|
-
|
|
45
|
-
// Your Account token provided to you through your account representative
|
|
46
48
|
const client = await LiquidCommerce('YOUR_LIQUIDCOMMERCE_API_KEY', {
|
|
47
|
-
googlePlacesApiKey: 'YOUR_GOOGLE_PLACES_API_KEY',
|
|
48
|
-
env:
|
|
49
|
+
googlePlacesApiKey: 'YOUR_GOOGLE_PLACES_API_KEY', // Required for address services
|
|
50
|
+
env: LIQUID_COMMERCE_ENV.STAGE // STAGE or PROD
|
|
49
51
|
});
|
|
50
52
|
|
|
51
|
-
// Initialize the client
|
|
52
53
|
await client.init();
|
|
53
54
|
```
|
|
54
55
|
|
|
55
|
-
##
|
|
56
|
+
## Response Types
|
|
57
|
+
|
|
58
|
+
All API responses follow a consistent structure:
|
|
59
|
+
|
|
60
|
+
```typescript
|
|
61
|
+
interface ApiResponse<T> {
|
|
62
|
+
statusCode: number;
|
|
63
|
+
message: string;
|
|
64
|
+
metadata: {
|
|
65
|
+
languages: string[];
|
|
66
|
+
timestamp: number;
|
|
67
|
+
timezone: string;
|
|
68
|
+
requestId: string;
|
|
69
|
+
path: string;
|
|
70
|
+
version: string;
|
|
71
|
+
};
|
|
72
|
+
data?: T; // Present in responses with data
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Services
|
|
56
77
|
|
|
57
78
|
### Address
|
|
58
79
|
|
|
59
|
-
|
|
80
|
+
Services for address validation and lookup:
|
|
60
81
|
|
|
61
|
-
```
|
|
82
|
+
```typescript
|
|
62
83
|
// Address autocompletion
|
|
63
|
-
const
|
|
84
|
+
const autocompleteResponse = await client.address.autocomplete({
|
|
64
85
|
input: '100 Madison Ave, New York'
|
|
65
86
|
});
|
|
66
87
|
|
|
67
|
-
//
|
|
68
|
-
|
|
88
|
+
// Response type: IApiResponseWithData<IAddressAutocompleteResult[]>
|
|
89
|
+
// {
|
|
90
|
+
// id: string;
|
|
91
|
+
// description: string;
|
|
92
|
+
// }
|
|
93
|
+
|
|
94
|
+
// Get detailed address information
|
|
95
|
+
const detailsResponse = await client.address.details({
|
|
69
96
|
id: 'ChIJd8BlQ2BZwokRjMKtTjMezRw'
|
|
70
97
|
});
|
|
98
|
+
|
|
99
|
+
// Response type: IApiResponseWithData<IAddressDetailsResult>
|
|
100
|
+
// {
|
|
101
|
+
// formattedAddress: string;
|
|
102
|
+
// coords: {
|
|
103
|
+
// lat: number;
|
|
104
|
+
// long: number;
|
|
105
|
+
// }
|
|
106
|
+
// }
|
|
71
107
|
```
|
|
72
108
|
|
|
73
109
|
### Catalog
|
|
74
110
|
|
|
75
|
-
|
|
111
|
+
Product catalog search and availability services:
|
|
76
112
|
|
|
77
|
-
```
|
|
78
|
-
// Check availability
|
|
113
|
+
```typescript
|
|
114
|
+
// Check product availability
|
|
79
115
|
const availabilityResponse = await client.catalog.availability({
|
|
80
|
-
upcs: ['123456789012', '210987654321'],
|
|
116
|
+
upcs: ['123456789012', '210987654321'], // UPC codes
|
|
117
|
+
grouping: ['group1', 'group2'], // Optional group identifiers
|
|
118
|
+
ids: ['id1', 'id2'], // Optional product IDs
|
|
81
119
|
loc: {
|
|
82
120
|
address: {
|
|
83
121
|
one: '123 Main St',
|
|
@@ -89,17 +127,26 @@ const availabilityResponse = await client.catalog.availability({
|
|
|
89
127
|
shouldShowOffHours: true
|
|
90
128
|
});
|
|
91
129
|
|
|
92
|
-
// Search catalog
|
|
93
|
-
const
|
|
130
|
+
// Search catalog with filters
|
|
131
|
+
const searchResponse = await client.catalog.search({
|
|
94
132
|
search: 'whiskey',
|
|
95
|
-
pageToken: '',
|
|
96
133
|
page: 1,
|
|
97
134
|
perPage: 20,
|
|
98
|
-
orderBy:
|
|
99
|
-
orderDirection:
|
|
135
|
+
orderBy: ENUM_ORDER_BY.PRICE,
|
|
136
|
+
orderDirection: ENUM_NAVIGATION_ORDER_DIRECTION_TYPE.ASC,
|
|
100
137
|
filters: [
|
|
101
|
-
{
|
|
102
|
-
|
|
138
|
+
{
|
|
139
|
+
key: ENUM_FILTER_KEYS.CATEGORIES,
|
|
140
|
+
values: [ENUM_SPIRITS.WHISKEY]
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
key: ENUM_FILTER_KEYS.PRICE,
|
|
144
|
+
values: { min: 2000, max: 10000 } // Prices in cents
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
key: ENUM_FILTER_KEYS.AVAILABILITY,
|
|
148
|
+
values: ENUM_AVAILABILITY_VALUE.IN_STOCK
|
|
149
|
+
}
|
|
103
150
|
],
|
|
104
151
|
loc: {
|
|
105
152
|
address: {
|
|
@@ -114,25 +161,25 @@ const searchResults = await client.catalog.search({
|
|
|
114
161
|
|
|
115
162
|
### Cart
|
|
116
163
|
|
|
117
|
-
|
|
164
|
+
Shopping cart management:
|
|
118
165
|
|
|
119
|
-
```
|
|
120
|
-
//
|
|
121
|
-
const
|
|
166
|
+
```typescript
|
|
167
|
+
// Create new cart
|
|
168
|
+
const newCart = await client.cart.get();
|
|
122
169
|
|
|
123
|
-
//
|
|
124
|
-
const existingCart = await client.cart.get('
|
|
170
|
+
// Retrieve existing cart
|
|
171
|
+
const existingCart = await client.cart.get('cart_id', true); // Second parameter for refresh
|
|
125
172
|
|
|
126
173
|
// Update cart
|
|
127
174
|
const updatedCart = await client.cart.update({
|
|
128
|
-
id: '
|
|
175
|
+
id: 'cart_id',
|
|
129
176
|
items: [
|
|
130
177
|
{
|
|
131
|
-
|
|
132
|
-
partNumber: '123456789012_retailer_id',
|
|
178
|
+
partNumber: '123456789012_retailer_id', // Required: {UPC}_{retailerId}
|
|
133
179
|
quantity: 2,
|
|
134
|
-
|
|
135
|
-
|
|
180
|
+
fulfillmentId: 'fulfillment_id',
|
|
181
|
+
engravingLines: ['Line 1', 'Line 2'], // Optional
|
|
182
|
+
scheduledFor: '2024-12-25', // Optional
|
|
136
183
|
}
|
|
137
184
|
],
|
|
138
185
|
loc: {
|
|
@@ -142,154 +189,365 @@ const updatedCart = await client.cart.update({
|
|
|
142
189
|
state: 'NY',
|
|
143
190
|
zip: '10001'
|
|
144
191
|
}
|
|
145
|
-
}
|
|
192
|
+
},
|
|
193
|
+
promoCode: 'DISCOUNT10', // Optional
|
|
194
|
+
giftCards: ['GC123456'] // Optional
|
|
146
195
|
});
|
|
147
196
|
```
|
|
148
197
|
|
|
149
198
|
### User
|
|
150
199
|
|
|
151
|
-
|
|
200
|
+
User profile and preferences management:
|
|
152
201
|
|
|
153
|
-
```
|
|
154
|
-
// Create
|
|
202
|
+
```typescript
|
|
203
|
+
// Create/update user session
|
|
155
204
|
const userSession = await client.user.session({
|
|
156
205
|
email: "user@example.com",
|
|
157
|
-
firstName: "John"
|
|
206
|
+
firstName: "John",
|
|
207
|
+
lastName: "Smith",
|
|
208
|
+
phone: "2125551234",
|
|
209
|
+
company: "Company Inc",
|
|
210
|
+
profileImage: "https://...",
|
|
211
|
+
birthDate: "1990-01-01"
|
|
158
212
|
});
|
|
159
213
|
|
|
160
|
-
//
|
|
214
|
+
// Fetch user by ID or email
|
|
215
|
+
const userData = await client.user.fetch('user_id_or_email');
|
|
216
|
+
|
|
217
|
+
// Address management
|
|
161
218
|
const newAddress = await client.user.addAddress({
|
|
162
|
-
customerId: '
|
|
219
|
+
customerId: 'customer_id',
|
|
220
|
+
placesId: 'google_places_id', // Optional if providing address details
|
|
163
221
|
one: '100 Madison St',
|
|
222
|
+
two: 'Apt 4B',
|
|
164
223
|
city: 'New York',
|
|
165
224
|
state: 'NY',
|
|
166
225
|
zip: '10004',
|
|
167
|
-
|
|
226
|
+
country: 'US',
|
|
227
|
+
lat: 40.7128, // Optional
|
|
228
|
+
long: -74.0060, // Optional
|
|
229
|
+
type: ENUM_ADDRESS_TYPE.SHIPPING,
|
|
168
230
|
isDefault: true
|
|
169
231
|
});
|
|
170
232
|
|
|
171
|
-
// Update an existing address
|
|
172
233
|
const updatedAddress = await client.user.updateAddress({
|
|
173
|
-
|
|
174
|
-
one: '101 Madison St',
|
|
175
|
-
city: 'New York',
|
|
176
|
-
state: 'NY',
|
|
177
|
-
zip: '10004',
|
|
178
|
-
type: 'shipping',
|
|
179
|
-
isDefault: true
|
|
234
|
+
// Same parameters as addAddress
|
|
180
235
|
});
|
|
181
236
|
|
|
182
|
-
//
|
|
237
|
+
// Payment methods
|
|
183
238
|
const newPayment = await client.user.addPayment({
|
|
184
|
-
customerId: '
|
|
185
|
-
paymentMethodId: '
|
|
239
|
+
customerId: 'customer_id',
|
|
240
|
+
paymentMethodId: 'payment_method_id',
|
|
186
241
|
isDefault: true
|
|
187
242
|
});
|
|
188
243
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
// Purge user address
|
|
196
|
-
const addressPurgeResponse = await client.user.purgeAddress('26af8958-0deb-44ec-b9fd-ca150b198e45');
|
|
244
|
+
const updatedPayment = await client.user.updatePayment({
|
|
245
|
+
customerId: 'customer_id',
|
|
246
|
+
paymentMethodId: 'payment_method_id',
|
|
247
|
+
isDefault: true // Required for updates
|
|
248
|
+
});
|
|
197
249
|
|
|
198
|
-
//
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
);
|
|
250
|
+
// Data removal
|
|
251
|
+
await client.user.purge('user_id_or_email');
|
|
252
|
+
await client.user.purgeAddress('address_id');
|
|
253
|
+
await client.user.purgePayment('customer_id', 'payment_id');
|
|
203
254
|
```
|
|
204
255
|
|
|
205
256
|
### Payment
|
|
206
257
|
|
|
207
|
-
The
|
|
258
|
+
The payment system uses secure elements for handling sensitive payment data. Before using payment features, you must first create a user session.
|
|
208
259
|
|
|
209
|
-
|
|
210
|
-
|
|
260
|
+
#### Prerequisites
|
|
261
|
+
|
|
262
|
+
1. User Session Creation:
|
|
263
|
+
```typescript
|
|
264
|
+
// First create or get a user session
|
|
265
|
+
const userSession = await client.user.session({
|
|
266
|
+
email: "user@example.com",
|
|
267
|
+
// ... other user details
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
// The session response includes necessary payment credentials
|
|
271
|
+
const { setupIntent, publicKey } = userSession.data.session;
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
#### Payment Element Integration
|
|
275
|
+
|
|
276
|
+
```typescript
|
|
277
|
+
// Initialize payment form using session credentials
|
|
211
278
|
await client.payment.mount({
|
|
212
|
-
clientSecret:
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
279
|
+
clientSecret: userSession.data.session.setupIntent, // Required: from session
|
|
280
|
+
key: userSession.data.session.publicKey, // Required: from session
|
|
281
|
+
elementId: 'payment-element-container', // Your DOM element ID
|
|
282
|
+
appearance: {
|
|
283
|
+
theme: 'night' // 'default' | 'night' | 'flat'
|
|
284
|
+
},
|
|
285
|
+
elementOptions: {
|
|
286
|
+
layout: 'tabs' // 'tabs' | 'accordion' | 'auto'
|
|
287
|
+
}
|
|
216
288
|
});
|
|
217
289
|
|
|
218
|
-
//
|
|
219
|
-
|
|
290
|
+
// Monitor payment element state
|
|
291
|
+
client.payment.subscribe('ready', () => {
|
|
292
|
+
// Element is ready to accept input
|
|
293
|
+
});
|
|
220
294
|
|
|
221
|
-
// Subscribe to payment events
|
|
222
295
|
client.payment.subscribe('change', (event) => {
|
|
223
|
-
|
|
296
|
+
const { complete, empty, value } = event;
|
|
297
|
+
// Handle validation state changes
|
|
224
298
|
});
|
|
225
299
|
|
|
226
|
-
//
|
|
227
|
-
client.payment.
|
|
300
|
+
// Process payment when ready
|
|
301
|
+
const tokenResult = await client.payment.generateToken();
|
|
228
302
|
|
|
229
|
-
//
|
|
230
|
-
|
|
303
|
+
// Handle the result
|
|
304
|
+
if ('error' in tokenResult) {
|
|
305
|
+
const { type, message, code } = tokenResult.error;
|
|
306
|
+
// type can be: 'validation_error' | 'api_error' | 'client_error' | 'confirm_error'
|
|
307
|
+
} else {
|
|
308
|
+
// Use tokenResult.id for checkout completion or saving payment method
|
|
309
|
+
const { id, card } = tokenResult;
|
|
310
|
+
}
|
|
231
311
|
|
|
232
|
-
//
|
|
312
|
+
// Always clean up when done
|
|
233
313
|
client.payment.unmount();
|
|
234
|
-
|
|
235
|
-
// Destroy the payment element
|
|
236
314
|
client.payment.destroy();
|
|
237
315
|
```
|
|
238
316
|
|
|
317
|
+
#### Security Considerations
|
|
318
|
+
|
|
319
|
+
1. **PCI Compliance**: The payment element handles card data securely within an iframe, ensuring your application never directly touches sensitive payment information.
|
|
320
|
+
|
|
321
|
+
2. **Token-Based**: All payment data is tokenized - you only receive secure tokens that can't be used to retrieve the original card details.
|
|
322
|
+
|
|
323
|
+
3. **Single Use**: Payment tokens are single-use and expire after a short time period.
|
|
324
|
+
|
|
325
|
+
4. **Domain Validation**: Payment elements will only work on domains that have been pre-registered with your account.
|
|
326
|
+
|
|
327
|
+
#### Best Practices
|
|
328
|
+
|
|
329
|
+
1. **Error Handling**: Always implement proper error handling:
|
|
330
|
+
```typescript
|
|
331
|
+
try {
|
|
332
|
+
const token = await client.payment.generateToken();
|
|
333
|
+
if ('error' in token) {
|
|
334
|
+
switch(token.error.type) {
|
|
335
|
+
case 'validation_error':
|
|
336
|
+
// Handle invalid card data
|
|
337
|
+
break;
|
|
338
|
+
case 'api_error':
|
|
339
|
+
// Handle API/network issues
|
|
340
|
+
break;
|
|
341
|
+
case 'client_error':
|
|
342
|
+
// Handle setup/configuration issues
|
|
343
|
+
break;
|
|
344
|
+
case 'confirm_error':
|
|
345
|
+
// Handle payment confirmation failures
|
|
346
|
+
break;
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
} catch (error) {
|
|
350
|
+
// Handle unexpected errors
|
|
351
|
+
}
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
2. **Cleanup**: Always clean up payment elements when done:
|
|
355
|
+
- When navigation away from payment page
|
|
356
|
+
- After successful payment
|
|
357
|
+
- After failed payment attempt
|
|
358
|
+
- Before unmounting payment component
|
|
359
|
+
|
|
360
|
+
3. **Event Handling**: Monitor element state for better user experience:
|
|
361
|
+
```typescript
|
|
362
|
+
client.payment.subscribe('change', (event) => {
|
|
363
|
+
// Update UI based on validation state
|
|
364
|
+
const { complete, empty } = event;
|
|
365
|
+
submitButton.disabled = !complete || empty;
|
|
366
|
+
});
|
|
367
|
+
|
|
368
|
+
client.payment.subscribe('loaderror', (event) => {
|
|
369
|
+
// Handle element loading failures
|
|
370
|
+
console.error('Payment element failed:', event.error);
|
|
371
|
+
});
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
#### Responsive Design
|
|
375
|
+
|
|
376
|
+
The payment element automatically adapts to:
|
|
377
|
+
- Mobile and desktop viewports
|
|
378
|
+
- Right-to-left languages
|
|
379
|
+
- Dark/light themes
|
|
380
|
+
- Different container sizes
|
|
381
|
+
|
|
382
|
+
#### Testing Cards
|
|
383
|
+
|
|
384
|
+
When testing payments in staging environment, use these test cards:
|
|
385
|
+
|
|
386
|
+
```typescript
|
|
387
|
+
// Test Visa Card
|
|
388
|
+
Card Number: 4242 4242 4242 4242
|
|
389
|
+
Expiry: Any future date
|
|
390
|
+
CVC: Any 3 digits
|
|
391
|
+
ZIP: Any 5 digits
|
|
392
|
+
|
|
393
|
+
// Test Mastercard
|
|
394
|
+
Card Number: 5555 5555 5555 4444
|
|
395
|
+
Expiry: Any future date
|
|
396
|
+
CVC: Any 3 digits
|
|
397
|
+
ZIP: Any 5 digits
|
|
398
|
+
|
|
399
|
+
// Example test card usage:
|
|
400
|
+
/*
|
|
401
|
+
Card: 4242 4242 4242 4242
|
|
402
|
+
Expiry: 12/29
|
|
403
|
+
CVC: 123
|
|
404
|
+
ZIP: 10001
|
|
405
|
+
*/
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
These cards will be accepted in test mode and will simulate successful payments. They should only be used in the staging environment, never in production.
|
|
409
|
+
|
|
410
|
+
**Important Notes:**
|
|
411
|
+
- These cards work only in test/staging environment
|
|
412
|
+
- Real cards will be declined in test mode
|
|
413
|
+
- Test cards will be declined in production
|
|
414
|
+
- All test transactions use simulated funds
|
|
415
|
+
- Use test credentials in staging environment
|
|
416
|
+
- Never use production credentials in development
|
|
417
|
+
- Test all error scenarios
|
|
418
|
+
- Verify proper cleanup implementation
|
|
419
|
+
- Test on multiple devices and browsers
|
|
420
|
+
|
|
239
421
|
### Checkout
|
|
240
422
|
|
|
241
|
-
|
|
423
|
+
Checkout process management:
|
|
242
424
|
|
|
243
|
-
```
|
|
425
|
+
```typescript
|
|
244
426
|
// Prepare checkout
|
|
245
427
|
const preparedCheckout = await client.checkout.prepare({
|
|
246
|
-
cartId: "
|
|
247
|
-
|
|
248
|
-
|
|
428
|
+
cartId: "cart_id",
|
|
429
|
+
customer: {
|
|
430
|
+
id: "customer_id", // Optional
|
|
431
|
+
email: "customer@example.com",
|
|
432
|
+
firstName: "John",
|
|
249
433
|
lastName: "Smith",
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
birthDate: "11-22-1998",
|
|
253
|
-
hasAgeVerify: false
|
|
434
|
+
phone: "2125551234",
|
|
435
|
+
birthDate: "1990-01-01"
|
|
254
436
|
},
|
|
437
|
+
hasAgeVerify: true,
|
|
255
438
|
billingAddress: {
|
|
256
|
-
firstName: "
|
|
439
|
+
firstName: "John",
|
|
257
440
|
lastName: "Smith",
|
|
258
|
-
email: "
|
|
259
|
-
phone: "
|
|
260
|
-
one: "
|
|
441
|
+
email: "billing@example.com",
|
|
442
|
+
phone: "2125551234",
|
|
443
|
+
one: "123 Main St",
|
|
444
|
+
two: "Apt 4B",
|
|
261
445
|
city: "New York",
|
|
262
446
|
state: "NY",
|
|
263
|
-
zip: "
|
|
447
|
+
zip: "10001",
|
|
448
|
+
country: "US"
|
|
264
449
|
},
|
|
265
450
|
hasSubstitutionPolicy: true,
|
|
266
|
-
isGift:
|
|
451
|
+
isGift: true,
|
|
267
452
|
billingSameAsShipping: false,
|
|
453
|
+
giftOptions: {
|
|
454
|
+
message: "Happy Birthday!",
|
|
455
|
+
recipient: {
|
|
456
|
+
name: "Jane Smith",
|
|
457
|
+
email: "jane@example.com",
|
|
458
|
+
phone: "2125555678"
|
|
459
|
+
}
|
|
460
|
+
},
|
|
268
461
|
marketingPreferences: {
|
|
269
462
|
canEmail: true,
|
|
270
463
|
canSms: true
|
|
271
464
|
},
|
|
272
465
|
deliveryTips: [
|
|
273
466
|
{
|
|
274
|
-
fulfillmentId: "
|
|
275
|
-
tip:
|
|
467
|
+
fulfillmentId: "fulfillment_id",
|
|
468
|
+
tip: 500 // Amount in cents
|
|
276
469
|
}
|
|
277
|
-
]
|
|
470
|
+
],
|
|
471
|
+
acceptedAccountCreation: true,
|
|
472
|
+
scheduledDelivery: "2024-12-25T14:00:00Z"
|
|
278
473
|
});
|
|
279
474
|
|
|
280
475
|
// Complete checkout
|
|
281
476
|
const completedCheckout = await client.checkout.complete({
|
|
282
|
-
token:
|
|
283
|
-
payment: "
|
|
477
|
+
token: preparedCheckout.token,
|
|
478
|
+
payment: "payment_token"
|
|
479
|
+
});
|
|
480
|
+
```_
|
|
481
|
+
|
|
482
|
+
#### Checkout Payment
|
|
483
|
+
|
|
484
|
+
For direct checkout payments, the flow is similar but uses the checkout session:
|
|
485
|
+
|
|
486
|
+
```typescript
|
|
487
|
+
// 1. First prepare the checkout
|
|
488
|
+
const preparedCheckout = await client.checkout.prepare({
|
|
489
|
+
cartId: "cart_id",
|
|
490
|
+
// ... other checkout details
|
|
491
|
+
});
|
|
492
|
+
|
|
493
|
+
// 2. Initialize payment form with checkout data
|
|
494
|
+
await client.payment.mount({
|
|
495
|
+
clientSecret: preparedCheckout.payment.clientSecret, // From checkout prepare response
|
|
496
|
+
key: preparedCheckout.payment.publicKey, // From checkout prepare response
|
|
497
|
+
elementId: 'payment-element-container',
|
|
498
|
+
appearance: { theme: 'night' },
|
|
499
|
+
elementOptions: { layout: 'tabs' }
|
|
284
500
|
});
|
|
501
|
+
|
|
502
|
+
// 3. Handle payment element events
|
|
503
|
+
client.payment.subscribe('change', (event) => {
|
|
504
|
+
// Monitor payment form state
|
|
505
|
+
const { complete, empty, value } = event;
|
|
506
|
+
});
|
|
507
|
+
|
|
508
|
+
// 4. When ready to complete checkout, generate payment token
|
|
509
|
+
const tokenResult = await client.payment.generateToken();
|
|
510
|
+
if (!('error' in tokenResult)) {
|
|
511
|
+
// 5. Complete checkout with payment token
|
|
512
|
+
const completedCheckout = await client.checkout.complete({
|
|
513
|
+
token: preparedCheckout.token,
|
|
514
|
+
payment: tokenResult.id
|
|
515
|
+
});
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
// 6. Clean up
|
|
519
|
+
client.payment.unmount();
|
|
520
|
+
client.payment.destroy();
|
|
521
|
+
```
|
|
522
|
+
|
|
523
|
+
## Error Handling
|
|
524
|
+
|
|
525
|
+
The SDK throws errors for various scenarios. Always wrap SDK calls in try-catch blocks:
|
|
526
|
+
|
|
527
|
+
```typescript
|
|
528
|
+
try {
|
|
529
|
+
const result = await client.someMethod();
|
|
530
|
+
} catch (error) {
|
|
531
|
+
console.error('Operation failed:', error.message);
|
|
532
|
+
// Handle specific error cases
|
|
533
|
+
}
|
|
285
534
|
```
|
|
286
535
|
|
|
287
|
-
|
|
536
|
+
Common error scenarios:
|
|
537
|
+
- Authentication failures
|
|
538
|
+
- Invalid parameters
|
|
539
|
+
- Network errors
|
|
540
|
+
- Resource not found
|
|
541
|
+
- Rate limiting
|
|
542
|
+
- Validation errors
|
|
288
543
|
|
|
289
|
-
## Price
|
|
544
|
+
## Price Handling
|
|
290
545
|
|
|
291
|
-
All
|
|
546
|
+
All monetary values in the SDK are handled in cents (the smallest currency unit). For example:
|
|
547
|
+
- $10.00 is represented as 1000
|
|
548
|
+
- $5.99 is represented as 599
|
|
549
|
+
- $0.50 is represented as 50
|
|
292
550
|
|
|
293
551
|
## Documentation
|
|
294
552
|
|
|
295
|
-
For more detailed information about each method and its parameters, please refer to our [official documentation](https://docs.liquidcommerce.
|
|
553
|
+
For more detailed information about each method and its parameters, please refer to our [official documentation](https://docs.liquidcommerce.cloud).
|