Code Examples
Production-ready code examples for integrating with the Unified Commerce Platform
Showing 8 examples
Setting up the GraphQL Client
Initialize the GraphQL client with your API endpoint and authentication credentials.
1import { ApolloClient, InMemoryCache, createHttpLink } from '@apollo/client';
2import { setContext } from '@apollo/client/link/context';
3
4// Create HTTP link to GraphQL endpoint
5const httpLink = createHttpLink({
6 uri: 'https://api.unifiedcommerce.io/graphql',
7});
8
9// Add authentication headers
10const authLink = setContext((_, { headers }) => {
11 const token = localStorage.getItem('auth_token');
12 return {
13 headers: {
14 ...headers,
15 authorization: token ? `Bearer ${token}` : '',
16 'x-api-key': 'your-api-key-here',
17 }
18 };
19});
20
21// Create Apollo Client instance
22const client = new ApolloClient({
23 link: authLink.concat(httpLink),
24 cache: new InMemoryCache(),
25 defaultOptions: {
26 watchQuery: {
27 fetchPolicy: 'cache-and-network',
28 errorPolicy: 'all',
29 },
30 query: {
31 fetchPolicy: 'network-only',
32 errorPolicy: 'all',
33 },
34 },
35});
36
37export default client;
API Key Authentication
Authenticate using an API key for server-to-server requests.
1import { ApolloClient, InMemoryCache, createHttpLink } from '@apollo/client';
2import { setContext } from '@apollo/client/link/context';
3
4const httpLink = createHttpLink({
5 uri: 'https://api.unifiedcommerce.io/graphql',
6});
7
8const authLink = setContext((_, { headers }) => {
9 return {
10 headers: {
11 ...headers,
12 'x-api-key': process.env.API_KEY,
13 }
14 };
15});
16
17const client = new ApolloClient({
18 link: authLink.concat(httpLink),
19 cache: new InMemoryCache(),
20});
JWT Authentication
Authenticate users with JWT tokens for client applications.
1import { gql, useMutation } from '@apollo/client';
2
3const LOGIN_MUTATION = gql`
4 mutation Login($email: String!, $password: String!) {
5 login(email: $email, password: $password) {
6 token
7 refreshToken
8 user {
9 id
10 email
11 name
12 }
13 }
14 }
15`;
16
17function LoginForm() {
18 const [login, { data, loading, error }] = useMutation(LOGIN_MUTATION);
19
20 const handleLogin = async (email: string, password: string) => {
21 try {
22 const { data } = await login({
23 variables: { email, password }
24 });
25
26 // Store tokens securely
27 localStorage.setItem('auth_token', data.login.token);
28 localStorage.setItem('refresh_token', data.login.refreshToken);
29
30 // Redirect or update UI
31 console.log('Logged in:', data.login.user);
32 } catch (err) {
33 console.error('Login failed:', err);
34 }
35 };
36
37 return (
38 <button onClick={() => handleLogin('user@example.com', 'password')}>
39 {loading ? 'Logging in...' : 'Login'}
40 </button>
41 );
42}
Fetching Products with Filters
Query products with pagination, filtering, and sorting capabilities.
1import { gql, useQuery } from '@apollo/client';
2
3const GET_PRODUCTS = gql`
4 query GetProducts(
5 $first: Int!
6 $after: String
7 $filter: ProductFilter
8 $sortBy: ProductSortInput
9 ) {
10 products(
11 first: $first
12 after: $after
13 filter: $filter
14 sortBy: $sortBy
15 ) {
16 edges {
17 cursor
18 node {
19 id
20 name
21 description
22 price
23 compareAtPrice
24 images {
25 url
26 alt
27 }
28 variants {
29 id
30 name
31 price
32 inventory {
33 quantity
34 available
35 }
36 }
37 categories {
38 id
39 name
40 }
41 }
42 }
43 pageInfo {
44 hasNextPage
45 hasPreviousPage
46 startCursor
47 endCursor
48 }
49 totalCount
50 }
51 }
52`;
53
54function ProductList() {
55 const { data, loading, error, fetchMore } = useQuery(GET_PRODUCTS, {
56 variables: {
57 first: 20,
58 filter: {
59 categories: ['electronics'],
60 priceRange: { min: 100, max: 1000 },
61 inStock: true,
62 },
63 sortBy: { field: 'PRICE', direction: 'ASC' },
64 },
65 });
66
67 if (loading) return <p>Loading products...</p>;
68 if (error) return <p>Error: {error.message}</p>;
69
70 const loadMore = () => {
71 fetchMore({
72 variables: {
73 after: data.products.pageInfo.endCursor,
74 },
75 });
76 };
77
78 return (
79 <div>
80 {data.products.edges.map(({ node }: any) => (
81 <div key={node.id}>
82 <h3>{node.name}</h3>
83 <p>${node.price}</p>
84 <img src={node.images[0]?.url} alt={node.images[0]?.alt} />
85 </div>
86 ))}
87 {data.products.pageInfo.hasNextPage && (
88 <button onClick={loadMore}>Load More</button>
89 )}
90 </div>
91 );
92}
Creating an Order
Create a new order with line items and customer information.
1import { gql, useMutation } from '@apollo/client';
2
3const CREATE_ORDER = gql`
4 mutation CreateOrder($input: CreateOrderInput!) {
5 createOrder(input: $input) {
6 order {
7 id
8 orderNumber
9 status
10 total
11 subtotal
12 tax
13 shipping
14 customer {
15 id
16 email
17 name
18 }
19 lineItems {
20 id
21 productId
22 variantId
23 quantity
24 price
25 total
26 }
27 shippingAddress {
28 street
29 city
30 state
31 postalCode
32 country
33 }
34 createdAt
35 }
36 errors {
37 field
38 message
39 }
40 }
41 }
42`;
43
44function CheckoutButton({ cartItems, customer, shippingAddress }) {
45 const [createOrder, { data, loading, error }] = useMutation(CREATE_ORDER, {
46 onCompleted: (data) => {
47 if (data.createOrder.order) {
48 console.log('Order created:', data.createOrder.order);
49 // Redirect to order confirmation
50 window.location.href = `/orders/${data.createOrder.order.id}`;
51 }
52 },
53 onError: (error) => {
54 console.error('Order creation failed:', error);
55 },
56 });
57
58 const handleCheckout = async () => {
59 try {
60 await createOrder({
61 variables: {
62 input: {
63 customerId: customer.id,
64 lineItems: cartItems.map(item => ({
65 productId: item.productId,
66 variantId: item.variantId,
67 quantity: item.quantity,
68 price: item.price,
69 })),
70 shippingAddress: {
71 street: shippingAddress.street,
72 city: shippingAddress.city,
73 state: shippingAddress.state,
74 postalCode: shippingAddress.postalCode,
75 country: shippingAddress.country,
76 },
77 billingAddress: shippingAddress,
78 },
79 },
80 });
81 } catch (err) {
82 console.error('Checkout error:', err);
83 }
84 };
85
86 return (
87 <button onClick={handleCheckout} disabled={loading}>
88 {loading ? 'Processing...' : 'Complete Order'}
89 </button>
90 );
91}
Adding Items to Cart
Add products to a shopping cart with optimistic UI updates.
1import { gql, useMutation } from '@apollo/client';
2
3const ADD_TO_CART = gql`
4 mutation AddToCart($input: AddToCartInput!) {
5 addToCart(input: $input) {
6 cart {
7 id
8 items {
9 id
10 productId
11 variantId
12 quantity
13 price
14 product {
15 id
16 name
17 images {
18 url
19 }
20 }
21 }
22 subtotal
23 total
24 }
25 errors {
26 field
27 message
28 }
29 }
30 }
31`;
32
33function AddToCartButton({ productId, variantId, quantity = 1 }) {
34 const [addToCart, { loading }] = useMutation(ADD_TO_CART, {
35 optimisticResponse: {
36 __typename: 'Mutation',
37 addToCart: {
38 __typename: 'AddToCartPayload',
39 cart: {
40 __typename: 'Cart',
41 id: 'temp-cart-id',
42 items: [
43 {
44 __typename: 'CartItem',
45 id: 'temp-item-id',
46 productId,
47 variantId,
48 quantity,
49 price: 0, // Will be updated from server
50 product: {
51 __typename: 'Product',
52 id: productId,
53 name: 'Loading...',
54 images: [],
55 },
56 },
57 ],
58 subtotal: 0,
59 total: 0,
60 },
61 errors: null,
62 },
63 },
64 update: (cache, { data }) => {
65 // Update cart count in header
66 const cartCount = data.addToCart.cart.items.reduce(
67 (sum, item) => sum + item.quantity,
68 0
69 );
70
71 // Write to cache or update global state
72 cache.writeQuery({
73 query: GET_CART_COUNT,
74 data: { cartCount },
75 });
76 },
77 onCompleted: (data) => {
78 if (data.addToCart.errors) {
79 console.error('Add to cart failed:', data.addToCart.errors);
80 } else {
81 console.log('Added to cart successfully');
82 }
83 },
84 });
85
86 const handleAddToCart = () => {
87 addToCart({
88 variables: {
89 input: {
90 productId,
91 variantId,
92 quantity,
93 },
94 },
95 });
96 };
97
98 return (
99 <button onClick={handleAddToCart} disabled={loading}>
100 {loading ? 'Adding...' : 'Add to Cart'}
101 </button>
102 );
103}
Processing a Payment
Process a payment using Stripe with error handling and 3D Secure support.
1import { gql, useMutation } from '@apollo/client';
2import { loadStripe } from '@stripe/stripe-js';
3import { useState } from 'react';
4
5const CREATE_PAYMENT_INTENT = gql`
6 mutation CreatePaymentIntent($input: CreatePaymentIntentInput!) {
7 createPaymentIntent(input: $input) {
8 clientSecret
9 paymentIntentId
10 status
11 errors {
12 field
13 message
14 }
15 }
16 }
17`;
18
19const CONFIRM_PAYMENT = gql`
20 mutation ConfirmPayment($input: ConfirmPaymentInput!) {
21 confirmPayment(input: $input) {
22 payment {
23 id
24 status
25 amount
26 orderId
27 }
28 order {
29 id
30 status
31 }
32 errors {
33 field
34 message
35 }
36 }
37 }
38`;
39
40function PaymentForm({ orderId, amount, customerId }) {
41 const [createPaymentIntent] = useMutation(CREATE_PAYMENT_INTENT);
42 const [confirmPayment] = useMutation(CONFIRM_PAYMENT);
43 const [processing, setProcessing] = useState(false);
44
45 const handlePayment = async (paymentMethodId: string) => {
46 setProcessing(true);
47
48 try {
49 // Step 1: Create payment intent
50 const { data: intentData } = await createPaymentIntent({
51 variables: {
52 input: {
53 orderId,
54 amount,
55 currency: 'USD',
56 customerId,
57 paymentMethod: 'stripe',
58 },
59 },
60 });
61
62 if (intentData.createPaymentIntent.errors) {
63 throw new Error(intentData.createPaymentIntent.errors[0].message);
64 }
65
66 const stripe = await loadStripe(process.env.NEXT_PUBLIC_STRIPE_KEY!);
67
68 // Step 2: Confirm payment with Stripe
69 const { error, paymentIntent } = await stripe!.confirmCardPayment(
70 intentData.createPaymentIntent.clientSecret,
71 {
72 payment_method: paymentMethodId,
73 }
74 );
75
76 if (error) {
77 throw new Error(error.message);
78 }
79
80 // Step 3: Confirm payment in our system
81 const { data: confirmData } = await confirmPayment({
82 variables: {
83 input: {
84 paymentIntentId: intentData.createPaymentIntent.paymentIntentId,
85 stripePaymentIntentId: paymentIntent.id,
86 },
87 },
88 });
89
90 if (confirmData.confirmPayment.errors) {
91 throw new Error(confirmData.confirmPayment.errors[0].message);
92 }
93
94 console.log('Payment successful!', confirmData.confirmPayment.payment);
95 // Redirect to success page
96 window.location.href = `/orders/${confirmData.confirmPayment.order.id}/confirmation`;
97
98 } catch (error) {
99 console.error('Payment failed:', error);
100 alert('Payment failed: ' + error.message);
101 } finally {
102 setProcessing(false);
103 }
104 };
105
106 return (
107 <button onClick={() => handlePayment('pm_123')} disabled={processing}>
108 {processing ? 'Processing...' : `Pay $${amount}`}
109 </button>
110 );
111}
Subscribe to Order Updates
Real-time updates for order status changes using GraphQL subscriptions.
1import { gql, useSubscription } from '@apollo/client';
2import { WebSocketLink } from '@apollo/client/link/ws';
3import { split, HttpLink } from '@apollo/client';
4import { getMainDefinition } from '@apollo/client/utilities';
5
6// Configure WebSocket link for subscriptions
7const wsLink = new WebSocketLink({
8 uri: 'wss://api.unifiedcommerce.io/graphql',
9 options: {
10 reconnect: true,
11 connectionParams: {
12 authToken: localStorage.getItem('auth_token'),
13 },
14 },
15});
16
17const httpLink = new HttpLink({
18 uri: 'https://api.unifiedcommerce.io/graphql',
19});
20
21// Split based on operation type
22const splitLink = split(
23 ({ query }) => {
24 const definition = getMainDefinition(query);
25 return (
26 definition.kind === 'OperationDefinition' &&
27 definition.operation === 'subscription'
28 );
29 },
30 wsLink,
31 httpLink,
32);
33
34const ORDER_UPDATED_SUBSCRIPTION = gql`
35 subscription OnOrderUpdated($orderId: ID!) {
36 orderUpdated(orderId: $orderId) {
37 id
38 status
39 trackingNumber
40 estimatedDelivery
41 lineItems {
42 id
43 status
44 quantity
45 }
46 timeline {
47 timestamp
48 status
49 message
50 location
51 }
52 }
53 }
54`;
55
56function OrderTracking({ orderId }) {
57 const { data, loading, error } = useSubscription(
58 ORDER_UPDATED_SUBSCRIPTION,
59 {
60 variables: { orderId },
61 onSubscriptionData: ({ subscriptionData }) => {
62 console.log('Order updated:', subscriptionData.data.orderUpdated);
63
64 // Show notification
65 if (Notification.permission === 'granted') {
66 new Notification('Order Update', {
67 body: `Your order is now ${subscriptionData.data.orderUpdated.status}`,
68 });
69 }
70 },
71 }
72 );
73
74 if (loading) return <p>Connecting to live updates...</p>;
75 if (error) return <p>Error: {error.message}</p>;
76
77 return (
78 <div className="order-tracking">
79 <h2>Order Status: {data?.orderUpdated.status}</h2>
80 {data?.orderUpdated.trackingNumber && (
81 <p>Tracking: {data.orderUpdated.trackingNumber}</p>
82 )}
83
84 <div className="timeline">
85 {data?.orderUpdated.timeline.map((event, index) => (
86 <div key={index} className="timeline-event">
87 <span className="timestamp">
88 {new Date(event.timestamp).toLocaleString()}
89 </span>
90 <span className="status">{event.status}</span>
91 <p>{event.message}</p>
92 {event.location && <p className="location">{event.location}</p>}
93 </div>
94 ))}
95 </div>
96 </div>
97 );
98}