Fluent Commerce Logo
Docs

Order Sync - commercetools Connector

Essential knowledge

Intended Audience:

Technical User

Author:

Fluent Commerce

Changed on:

17 June 2026

Overview

The Order Sync module manages the two-way pipeline responsible for exporting newly placed orders from commercetools to Fluent Order Management and receiving asynchronous order updates back. This module acts as the core operational anchor for the integration, exposing a foundational webhook that downstream extensions—such as fulfillment and consignment—leverage to track and synchronize order lifecycles across platforms.

Key points

  • Core Function & Outcome: You will learn how the module handles order exports from commercetools to Fluent Order Management, automates integrated customer profile creation, and establishes the webhook ecosystem for order status processing.
  • Out-of-the-Box Capabilities: Out-of-the-box (OOTB) functionality natively supports Home Delivery (HD) and Click and Collect (CC) order structures, complete with automated type-specific order number generation patterns.
  • System & Sync Limitations: The module is designed strictly for new transactions and does not synchronize historical orders created prior to extension installation. Additionally, the order update and modification handlers must be customized to fit your specific implementation needs.
  • Extensible Pipeline Architecture: The message routing and handler framework is completely decoupled. Developers can easily update message names, override standard classes, or extend the baseline order creation logic to attach custom operational attributes.

Data Pipeline Execution

No alt provided

1. Storefront Trigger (Subscription/External Queue)

Order exports follow a real-time event-driven trigger mechanism:
  • Stage 1 (Subscription): commercetools emits an `OrderCreated` event. The platform’s Subscription service captures this and publishes it to the `CT-Queue` (e.g., AWS EventBridge or SQS).
  • Stage 2 (Listener): The `CT Queue Listener` consumes the message, verifying the event origin, and pushes the message to the internal `Event Queue` for processing.

2. Route Filtering & Message Routing

  • Stage 3 (Routing): The `Message Router` reads the message name (`commercetools.connect.order.create`) and filters based on the `inclusion-filter` property defined in `application-connector.yml`. Only resources matching `ResourceCreated` proceed to the execution layer.

3. Fluent API Delivery (GraphQL Mutation)

  • Stage 4 (Handler Execution): The `OrderCreateHandler` fetches detailed order data (including tax breakdowns and custom fields) from the commercetools SDK. It calculates the `orderType` (HD or CC) based on the shipping method, generates a patterned order number if required, ensures the customer exists in Fluent, and dispatches the `createOrder` mutation.

Data Storage & Schema Mapping

commercetools AttributeFluent OMS TargetLogic/Pattern
`orderNumber``ref`Auto-generated if blank (e.g., `order-CC20...`)
`shippingInfo``shippingMethod`Mapped via `fc.connect...shipping-method-mapping`
`customer``customerRef`Identified/Created in Fluent via GraphQL
`customFields``attributes`Serialized into Fluent attribute list

Developer Extension Points

For more details on how to extend please refer to the extend guidelines

1. Message Routing Configuration (`application-connector.yml`)

1fluent-connect:
2  routes:
3    - name: "commercetools.connect.order.create"
4      handler: "OrderCreateHandler"
5      props:
6        query: "ct-order.graphql"
7        mutation: "ct-updateorderNumber.graphql"
8        inclusion-filter:
9          - "ResourceCreated"

2. Auto Order Number Creation Logic

1//Auto order number creation logic
2final String orderType = getOrderType(context, order.get().getShippingInfo().getShippingMethod().getKey());
3if (StringUtils.isBlank(orderType)) {
4    throw new UnprocessableMessageException("Order type is missing");
5}
6String orderNumber = order.get().getOrderNumber();
7if(StringUtils.isEmpty(orderNumber)) {
8    orderNumber = generateOrderNumber(orderType, accountReference.getRetailerId());
9    updateOrderNumber(ctApiClient, getQuery(context, "mutation"), order.get(), orderNumber);
10}

3. Customer GraphQL Mutation Logic

1//Customer identification/creation logic
2String customerId;
3  if (null == customerQueryData.customer()) {
4      createCustomer(context, accountReference, order.get());
5      customerId = context.ofFluentContext().executeQuery(customerQuery, GetCustomerQuery.Data.class).customer().id();
6  } else {
7      customerId = customerQueryData.customer().id();
8  }

4. Custom Message Handler Implementation

1@Slf4j
2@Component
3@HandlerInfo(name = "FluentOrderCreateHandler", description = "Create a order at Fluent OMS")
4public class FluentOrderCreateHandler extends MessageHandler {
5    private static final String ORDER_ATTRIBUTE = "order";
6    // write your logic
7}

5. Order Queries and Mutations

1mutation CreateOrder($input: CreateOrderInput) {
2  createOrder(input: $input) {
3      ref
4      id
5      status
6  }
7}
1query GetOrder($ref: String!) {
2  order(ref: $ref) {
3    ref
4    id
5    status
6    attributes{
7      name
8      type
9      value
10    }
11  }
12}
1query Search($id: String, $orderNumber: String) {
2  search: order(id: $id, orderNumber: $orderNumber) {
3    id
4    version
5    orderNumber
6    totalPrice {
7      type
8      currencyCode
9      centAmount
10      fractionDigits
11    }
12    taxedPrice {
13      totalNet {
14        type
15        currencyCode
16        centAmount
17        fractionDigits
18      }
19      totalGross {
20        type
21        currencyCode
22        centAmount
23        fractionDigits
24      }
25      totalTax {
26        type
27        currencyCode
28        centAmount
29        fractionDigits
30      }
31    }
32    custom {
33      customFieldsRaw {
34        name
35        value
36      }
37    }
38    customer {
39      id
40      email
41      firstName
42      lastName
43      title
44      defaultShippingAddress {
45        phone
46      }
47      defaultBillingAddress {
48        phone
49      }
50    }
51    lineItems {
52      id
53      variant {
54        sku
55      }
56      quantity
57      state {
58        quantity
59        state {
60          id
61          key
62        }
63      }
64      custom {
65        customFieldsRaw {
66          name
67          value
68        }
69      }
70      taxedPrice {
71        totalNet {
72          type
73          currencyCode
74          centAmount
75          fractionDigits
76        }
77        totalGross {
78          type
79          currencyCode
80          centAmount
81          fractionDigits
82        }
83        totalTax {
84          type
85          currencyCode
86          centAmount
87          fractionDigits
88        }
89      }
90    }
91    shippingInfo {
92      deliveries {
93        id
94        custom {
95          customFieldsRaw {
96            name
97            value
98          }
99        }
100        parcels {
101          id
102          trackingData {
103            trackingId
104            carrier
105            provider
106            providerTransaction
107            isReturn
108          }
109        }
110      }
111      shippingMethodName
112      shippingMethod {
113        name
114        key
115        predicate
116      }
117      taxedPrice {
118        totalNet {
119          type
120          currencyCode
121          centAmount
122          fractionDigits
123        }
124        totalGross {
125          type
126          currencyCode
127          centAmount
128          fractionDigits
129        }
130        totalTax {
131          type
132          currencyCode
133          centAmount
134          fractionDigits
135        }
136      }
137    }
138    shippingAddress {
139      title
140      firstName
141      lastName
142      streetName
143      streetNumber
144      additionalStreetInfo
145      postalCode
146      city
147      region
148      state
149      country
150      company
151      department
152      building
153      apartment
154      pOBox
155      phone
156      mobile
157      email
158      fax
159      additionalAddressInfo
160      externalId
161      key
162    }
163    billingAddress {
164      title
165      firstName
166      lastName
167      streetName
168      streetNumber
169      additionalStreetInfo
170      postalCode
171      city
172      region
173      state
174      country
175      company
176      department
177      building
178      apartment
179      pOBox
180      phone
181      mobile
182      email
183      fax
184      additionalAddressInfo
185      externalId
186      key
187    }
188  }
189}
1mutation Search($id: String!, $version: Long!, $actions: [OrderUpdateAction!]!) {
2  search: updateOrder(id: $id, version: $version, actions: $actions) {
3    id
4  }
5}