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}