@liquidcommerce/cloud-sdk
v1.6.0
Published
LiquidCommerce Cloud SDK
Downloads
238
Readme
LiquidCommerce Cloud SDK
The LiquidCommerce Cloud SDK provides an easy way to interact with our APIs through a server-side SDK for Node.js and Web JS script.
Table of Contents
Installation
Install the package with:
npm install @liquidcommerce/cloud-sdk
# or
yarn add @liquidcommerce/cloud-sdk
# or
pnpm add @liquidcommerce/cloud-sdk
Configuration
The SDK requires configuration during initialization:
import { LiquidCommerce, LIQUID_COMMERCE_ENV } from '@liquidcommerce/cloud-sdk';
const client = await LiquidCommerce('YOUR_LIQUIDCOMMERCE_API_KEY', {
googlePlacesApiKey: 'YOUR_GOOGLE_PLACES_API_KEY', // Required for address services
env: LIQUID_COMMERCE_ENV.STAGE // STAGE or PROD
});
await client.init();
Response Types
All API responses follow a consistent structure:
interface ApiResponse<T> {
statusCode: number;
message: string;
metadata: {
languages: string[];
timestamp: number;
timezone: string;
requestId: string;
path: string;
version: string;
};
data?: T; // Present in responses with data
}
Services
Address
Services for address validation and lookup:
// Address autocompletion
const autocompleteResponse = await client.address.autocomplete({
input: '100 Madison Ave, New York'
});
// Response type: IApiResponseWithData<IAddressAutocompleteResult[]>
// {
// id: string;
// description: string;
// }
// Get detailed address information
const detailsResponse = await client.address.details({
id: 'ChIJd8BlQ2BZwokRjMKtTjMezRw'
});
// Response type: IApiResponseWithData<IAddressDetailsResult>
// {
// formattedAddress: string;
// coords: {
// lat: number;
// long: number;
// }
// }
Catalog
Product catalog search and availability services:
// Check product availability
const availabilityResponse = await client.catalog.availability({
upcs: ['123456789012', '210987654321'], // UPC codes
grouping: ['group1', 'group2'], // Optional group identifiers
ids: ['id1', 'id2'], // Optional product IDs
loc: {
address: {
one: '123 Main St',
city: 'New York',
state: 'NY',
zip: '10001'
}
},
shouldShowOffHours: true
});
// Search catalog with filters
const searchResponse = await client.catalog.search({
search: 'whiskey',
page: 1,
perPage: 20,
orderBy: ENUM_ORDER_BY.PRICE,
orderDirection: ENUM_NAVIGATION_ORDER_DIRECTION_TYPE.ASC,
filters: [
{
key: ENUM_FILTER_KEYS.CATEGORIES,
values: [ENUM_SPIRITS.WHISKEY]
},
{
key: ENUM_FILTER_KEYS.PRICE,
values: { min: 2000, max: 10000 } // Prices in cents
},
{
key: ENUM_FILTER_KEYS.AVAILABILITY,
values: ENUM_AVAILABILITY_VALUE.IN_STOCK
}
],
loc: {
address: {
one: '123 Main St',
city: 'New York',
state: 'NY',
zip: '10001'
}
}
});
Cart
Shopping cart management:
// Create new cart
const newCart = await client.cart.get();
// Retrieve existing cart
const existingCart = await client.cart.get('cart_id', true); // Second parameter for refresh
// Update cart
const updatedCart = await client.cart.update({
id: 'cart_id',
items: [
{
partNumber: '123456789012_retailer_id', // Required: {UPC}_{retailerId}
quantity: 2,
fulfillmentId: 'fulfillment_id',
engravingLines: ['Line 1', 'Line 2'], // Optional
scheduledFor: '2024-12-25', // Optional
}
],
loc: {
address: {
one: '123 Main St',
city: 'New York',
state: 'NY',
zip: '10001'
}
},
promoCode: 'DISCOUNT10', // Optional
giftCards: ['GC123456'] // Optional
});
User
User profile and preferences management:
// Create/update user session
const userSession = await client.user.session({
email: "[email protected]",
firstName: "John",
lastName: "Smith",
phone: "2125551234",
company: "Company Inc",
profileImage: "https://...",
birthDate: "1990-01-01"
});
// Fetch user by ID or email
const userData = await client.user.fetch('user_id_or_email');
// Address management
const newAddress = await client.user.addAddress({
customerId: 'customer_id',
placesId: 'google_places_id', // Optional if providing address details
one: '100 Madison St',
two: 'Apt 4B',
city: 'New York',
state: 'NY',
zip: '10004',
country: 'US',
lat: 40.7128, // Optional
long: -74.0060, // Optional
type: ENUM_ADDRESS_TYPE.SHIPPING,
isDefault: true
});
const updatedAddress = await client.user.updateAddress({
// Same parameters as addAddress
});
// Payment methods
const newPayment = await client.user.addPayment({
customerId: 'customer_id',
paymentMethodId: 'payment_method_id',
isDefault: true
});
const updatedPayment = await client.user.updatePayment({
customerId: 'customer_id',
paymentMethodId: 'payment_method_id',
isDefault: true // Required for updates
});
// Data removal
await client.user.purge('user_id_or_email');
await client.user.purgeAddress('address_id');
await client.user.purgePayment('customer_id', 'payment_id');
Payment
The payment system uses secure elements for handling sensitive payment data. Before using payment features, you must first create a user session.
Prerequisites
- User Session Creation:
// First create or get a user session
const userSession = await client.user.session({
email: "[email protected]",
// ... other user details
});
// The session response includes necessary payment credentials
const { setupIntent, publicKey } = userSession.data.session;
Payment Element Integration
// Initialize payment form using session credentials
await client.payment.mount({
clientSecret: userSession.data.session.setupIntent, // Required: from session
key: userSession.data.session.publicKey, // Required: from session
elementId: 'payment-element-container', // Your DOM element ID
appearance: {
theme: 'night' // 'default' | 'night' | 'flat'
},
elementOptions: {
layout: 'tabs' // 'tabs' | 'accordion' | 'auto'
}
});
// Monitor payment element state
client.payment.subscribe('ready', () => {
// Element is ready to accept input
});
client.payment.subscribe('change', (event) => {
const { complete, empty, value } = event;
// Handle validation state changes
});
// Process payment when ready
const tokenResult = await client.payment.generateToken();
// Handle the result
if ('error' in tokenResult) {
const { type, message, code } = tokenResult.error;
// type can be: 'validation_error' | 'api_error' | 'client_error' | 'confirm_error'
} else {
// Use tokenResult.id for checkout completion or saving payment method
const { id, card } = tokenResult;
}
// Always clean up when done
client.payment.unmount();
client.payment.destroy();
Security Considerations
PCI Compliance: The payment element handles card data securely within an iframe, ensuring your application never directly touches sensitive payment information.
Token-Based: All payment data is tokenized - you only receive secure tokens that can't be used to retrieve the original card details.
Single Use: Payment tokens are single-use and expire after a short time period.
Domain Validation: Payment elements will only work on domains that have been pre-registered with your account.
Best Practices
- Error Handling: Always implement proper error handling:
try {
const token = await client.payment.generateToken();
if ('error' in token) {
switch(token.error.type) {
case 'validation_error':
// Handle invalid card data
break;
case 'api_error':
// Handle API/network issues
break;
case 'client_error':
// Handle setup/configuration issues
break;
case 'confirm_error':
// Handle payment confirmation failures
break;
}
}
} catch (error) {
// Handle unexpected errors
}
- Cleanup: Always clean up payment elements when done:
- When navigation away from payment page
- After successful payment
- After failed payment attempt
- Before unmounting payment component
- Event Handling: Monitor element state for better user experience:
client.payment.subscribe('change', (event) => {
// Update UI based on validation state
const { complete, empty } = event;
submitButton.disabled = !complete || empty;
});
client.payment.subscribe('loaderror', (event) => {
// Handle element loading failures
console.error('Payment element failed:', event.error);
});
Responsive Design
The payment element automatically adapts to:
- Mobile and desktop viewports
- Right-to-left languages
- Dark/light themes
- Different container sizes
Testing Cards
When testing payments in staging environment, use these test cards:
// Test Visa Card
Card Number: 4242 4242 4242 4242
Expiry: Any future date
CVC: Any 3 digits
ZIP: Any 5 digits
// Test Mastercard
Card Number: 5555 5555 5555 4444
Expiry: Any future date
CVC: Any 3 digits
ZIP: Any 5 digits
// Example test card usage:
/*
Card: 4242 4242 4242 4242
Expiry: 12/29
CVC: 123
ZIP: 10001
*/
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.
Important Notes:
- These cards work only in test/staging environment
- Real cards will be declined in test mode
- Test cards will be declined in production
- All test transactions use simulated funds
- Use test credentials in staging environment
- Never use production credentials in development
- Test all error scenarios
- Verify proper cleanup implementation
- Test on multiple devices and browsers
Checkout
Checkout process management:
// Prepare checkout
const preparedCheckout = await client.checkout.prepare({
cartId: "cart_id",
customer: {
id: "customer_id", // Optional
email: "[email protected]",
firstName: "John",
lastName: "Smith",
phone: "2125551234",
birthDate: "1990-01-01"
},
hasAgeVerify: true,
billingAddress: {
firstName: "John",
lastName: "Smith",
email: "[email protected]",
phone: "2125551234",
one: "123 Main St",
two: "Apt 4B",
city: "New York",
state: "NY",
zip: "10001",
country: "US"
},
hasSubstitutionPolicy: true,
isGift: true,
billingSameAsShipping: false,
giftOptions: {
message: "Happy Birthday!",
recipient: {
name: "Jane Smith",
email: "[email protected]",
phone: "2125555678"
}
},
marketingPreferences: {
canEmail: true,
canSms: true
},
deliveryTips: [
{
fulfillmentId: "fulfillment_id",
tip: 500 // Amount in cents
}
],
acceptedAccountCreation: true,
scheduledDelivery: "2024-12-25T14:00:00Z"
});
// Complete checkout
const completedCheckout = await client.checkout.complete({
token: preparedCheckout.token,
payment: "payment_token"
});
```_
#### Checkout Payment
For direct checkout payments, the flow is similar but uses the checkout session:
```typescript
// 1. First prepare the checkout
const preparedCheckout = await client.checkout.prepare({
cartId: "cart_id",
// ... other checkout details
});
// 2. Initialize payment form with checkout data
await client.payment.mount({
clientSecret: preparedCheckout.payment.clientSecret, // From checkout prepare response
key: preparedCheckout.payment.publicKey, // From checkout prepare response
elementId: 'payment-element-container',
appearance: { theme: 'night' },
elementOptions: { layout: 'tabs' }
});
// 3. Handle payment element events
client.payment.subscribe('change', (event) => {
// Monitor payment form state
const { complete, empty, value } = event;
});
// 4. When ready to complete checkout, generate payment token
const tokenResult = await client.payment.generateToken();
if (!('error' in tokenResult)) {
// 5. Complete checkout with payment token
const completedCheckout = await client.checkout.complete({
token: preparedCheckout.token,
payment: tokenResult.id
});
}
// 6. Clean up
client.payment.unmount();
client.payment.destroy();
Error Handling
The SDK throws errors for various scenarios. Always wrap SDK calls in try-catch blocks:
try {
const result = await client.someMethod();
} catch (error) {
console.error('Operation failed:', error.message);
// Handle specific error cases
}
Common error scenarios:
- Authentication failures
- Invalid parameters
- Network errors
- Resource not found
- Rate limiting
- Validation errors
Price Handling
All monetary values in the SDK are handled in cents (the smallest currency unit). For example:
- $10.00 is represented as 1000
- $5.99 is represented as 599
- $0.50 is represented as 50
Documentation
For more detailed information about each method and its parameters, please refer to our official documentation.