# Building an Order Receiver Service **Summary:** This guide explains how to implement an order receiver service for Norce Commerce. The order receiver is responsible for accepting order requests from Norce Commerce, integrating them into your ERP system, and returning appropriate responses. The integration must be robust, handle retries, and provide clear status updates. ## Overview The order receiver service is a key integration point between Norce Commerce and your ERP system. When a customer completes a checkout, Norce Commerce sends an order request to your service. Your service must process the order, handle business logic, and return a response indicating success or failure. > **Timeliness:** For sales orders, prompt processing is critical to fulfill customer expectations. Norce Commerce uses a direct integration pattern: it calls your service with an order request and expects a synchronous response. If the call fails, Norce Commerce retries for a limited period before escalating to support. ## Responsibilities of the Order Receiver When an order is created in Norce Commerce, it is sent to your order receiver service. The service must: - Map the [OrderRequest](/api-reference/schemas/connectorder#orderrequest) to the target ERP format. - Route the order if multiple targets exist. - Handle errors and log issues. - Notify stakeholders as needed. - Return a correct [OrderResponse](/api-reference/schemas/connectorder#orderresponse). Your service may also enrich or transform the order data before sending it to the ERP system. ## Configuration Order receiver settings are managed in the Norce Commerce Admin UI under the *ERP integration* section. **Image: Order receiver configuration in Admin UI** ![Screenshot of the order receiver configuration page in Norce Commerce Admin. The page shows fields for endpoint type, URL, username, and password.](/assets/orderreceiver-1.c9e7999386c1b667610be4bd7e9b6ea1f8afe6835041bf304cddf0d9fcb5af24.003e135d.png) **Key settings:** - **ERP endpoint type:** Choose between *SOAP*, *REST (Legacy)*, *REST*, or *No Integration*. *REST* is recommended. *No Integration* disables order integration. - **ERP endpoint URL:** The address of your integration endpoint. - **ERP endpoint username/password:** Credentials for basic authentication. > **Security:** In production, endpoints must use HTTPS and require basic authentication. ## OrderRequest Message Structure The [OrderRequest](/api-reference/schemas/connectorder#orderrequest) is a comprehensive contract containing all order details. It is sent as JSON or XML. **Important fields:** - **Header.ApplicationKey:** GUID identifying the application in Norce. - **ClientOrderRef:** Unique order reference, used for duplicate detection. - **Payments.Payment.PaymentRef:** Payment identifier from the payment service provider. - **Items.OrderItem.PartNo:** Product identifier. - **Items.OrderItem.UnitPrice, UnitVat, Quantity:** Line item pricing details. - **AdditionalInfo:** Custom fields added during checkout. details summary An example OrderRequest message ### OrderRequest JSON ```json { "SellTo": { "Company": null, "Person": { "CustomerCode": "CUST0001", "CompanyCode": null, "FirstName": "John", "LastName": "Doe", "JobTitle": null, "PrivatePhone": "0701234567", "CellPhone": "0707654321", "WorkPhone": null, "Email": "john.doe@example.com", "SSN": null, "Address": { "Type": null, "Line1": "123 Example Street", "Line2": null, "Box": "", "ZipCode": "12345", "City": "Anytown", "Region": null, "Country": "SE", "CareOf": null, "ShippingPhoneNumber": null, "Gln": null, "ExtensionData": null }, "AdditionalInfo": [], "IsActive": null } }, "BillTo": { "Company": null, "Person": { "CustomerCode": "BILL0002", "CompanyCode": null, "FirstName": "Jane", "LastName": "Smith", "JobTitle": null, "PrivatePhone": "0812345678", "CellPhone": "0709876543", "WorkPhone": null, "Email": "jane.smith@example.com", "SSN": null, "Address": { "Type": null, "Line1": "456 Invoice Lane", "Line2": null, "Box": "", "ZipCode": "54321", "City": "Billingville", "Region": null, "Country": "SE", "CareOf": null, "ShippingPhoneNumber": null, "Gln": null, "ExtensionData": null }, "AdditionalInfo": [], "IsActive": null } }, "ShipTo": { "Company": null, "Person": { "CustomerCode": "SHIP0003", "CompanyCode": null, "FirstName": "Alice", "LastName": "Johnson", "JobTitle": null, "PrivatePhone": "0105555555", "CellPhone": "0705555555", "WorkPhone": null, "Email": "alice.johnson@example.com", "SSN": null, "Address": { "Type": null, "Line1": "789 Shipping Blvd", "Line2": null, "Box": "", "ZipCode": "67890", "City": "Shipville", "Region": null, "Country": "SE", "CareOf": null, "ShippingPhoneNumber": null, "Gln": null, "ExtensionData": null }, "AdditionalInfo": [], "IsActive": null } }, "SalesContactCode": "SALES001", "SalesContactDivision": "Division A", "DoHold": false, "ClientOrderRef": "REF12345", "SubmitDate": "2024-12-18T12:00:00+01:00", "CustomerOrderRef": "ORDER123", "CustomerOrderComment": "Please handle with care.", "CurrencyCode": "SEK", "ReferId": null, "Payments": [ { "PaymentCode": 10001, "PaymentMethodCode": "credit_card", "PaymentRef": "PAYREF123", "Amount": 1500.00, "CurrencyCode": "SEK", "AdditionalInfo": [ { "Id": 1, "Code": "CardType", "Value": "Visa" }, { "Id": 2, "Code": "CardHolder", "Value": "John Doe" } ], "PaymentName": "Credit Card Payment" } ], "Discounts": [], "ShippingAdvice": { "DeliveryMethodCode": "PostNord", "DoSMSNotify": true, "PickupStore": { "Code": "STORE001", "Name": "Central Warehouse", "IsDropPoint": true }, "IsFeeChargedOnce": true, "IsComplete": true, "ShipAdvisorOrderCode": null, "TmsReference": null }, "Items": [ { "LineNo": 1, "ParentLineNo": null, "Type": "ErpStandard", "TypeGroup": "Physical", "PartNo": "ITEM001", "ErpPartNo": "ITEM001", "InternalProductId": "10001", "Description": "Example Product 1", "Quantity": 2, "UnitOfMeasure": "pcs", "UnitPrice": 300.00, "UnitPriceOriginal": 300.00, "Discount": 0.00, "UnitVat": 75.00, "PriceListNo": 1, "VatRate": 25.00, "Comment": "Urgent delivery", "AdditionalInfo": [ { "Id": 1, "Code": "Warranty", "Value": "2 years" } ], "PriceLists": [ { "PriceListName": "Standard List", "QtyBreak": 1, "UnitPrice": 300.00, "IsStandardPriceList": true, "IsActive": true } ], "Promotions": [], "ManufacturerCode": "example_manufacturer", "Quantity2": 2.000 } ], "Fees": [], "Header": { "ApplicationKey": "123e4567-e89b-12d3-a456-426614174000" }, "OrderType": 1, "Source": "Online", "CustomerInvoiceRef": "INV12345", "DiscountCode": "DISCOUNT2024", "ExtensionData": null } ``` XML ```xml CUST0001 John Doe 0701234567 0707654321 john.doe@example.com
123 Example Street 12345 Anytown SE
BILL0002 Jane Smith 0812345678 0709876543 jane.smith@example.com
456 Invoice Lane 54321 Billingville SE
SHIP0003 Alice Johnson 0105555555 0705555555 alice.johnson@example.com
789 Shipping Blvd 67890 Shipville SE
SALES001 Division A false REF12345 ORDER123 Please handle with care. 2024-12-18T12:00:00+01:00 SEK 10001 credit_card PAYREF123 1500.00 SEK 1 CardType Visa 2 CardHolder John Doe PostNord true STORE001 Central Warehouse true true true 1 ErpStandard Physical ITEM001 ITEM001 10001 Example Product 1 2 pcs 300.00 300.00 0.00 75.00 1 25.00 Urgent delivery Standard List 1 300.00 true true 1 Warranty 2 years
123e4567-e89b-12d3-a456-426614174000
Order
``` Read more about the [OrderRequest](/api-reference/schemas/connectorder#orderrequest) in the Norce Commerce Connect API Reference. ## OrderResponse Message Structure Your service must return an [OrderResponse](/api-reference/schemas/connectorder#orderresponse) in JSON or XML. Norce Commerce expects HTTP 200 and a well-formed response. Otherwise, it will retry the request every 10 minutes for up to six hours. **Response scenarios:** - **OK, without ERP order number:** Order is being processed asynchronously. Status in Norce is set to `Allocated`. You must later confirm using [SendOrderStatus](/api-reference/connect/orderservice/openapi/order/sendorderstatus). - **OK, with ERP order number:** Order is confirmed synchronously. Status in Norce is set to `Confirmed`. - **Failed:** Order processing failed. The error is logged in Norce, and no retry occurs. - **Other HTTP status codes:** Triggers Norce Commerce retry logic. details summary OrderResponse message examples JSON Ok - with ErpOrderNo ```JSON { "StatusCode": "OK", "Description": "No error, order status is set to confirmed.", "HasErpOrderNo": true, "ErpOrderNo": "ErpNo_5670588" } ``` Ok - without ErpOrderNo ```JSON { "StatusCode": "OK", "Description": "No error, order status is set to allocated.", "HasErpOrderNo": false, "ErpOrderNo": null } ``` Error ```JSON { "StatusCode": "Failed", "Description": "Managed Error, this message is logged in Norce Commerce, no retry.", "HasErpOrderNo": false, "ErpOrderNo": null } ``` details summary OrderResponse message examples XML Ok - with ErpOrderNo ```XML OK No error, order status is set to confirmed. true ErpNo_5670588 ``` Ok - without ErpOrderNo ```XML OK No error, order status is set to allocated. false ``` Error ```XML Failed Managed Error, this message is logged in Norce Commerce, no retry. false ``` Read more about the [OrderResponse](/api-reference/schemas/connectorder#orderresponse) in the Connect API Reference. ## Customization You can add custom information to the order during checkout using configurable info types. These appear in the `AdditionalInfo` collections in the OrderRequest. **Configure info types in Admin UI:** - [Customer and companies](https://norce-open-demo.admin-se.playground.norce.tech/customer/settings/infotypes/customer) - [Baskets](https://norce-open-demo.admin-se.playground.norce.tech/shopping/settings/infotypes/basket) - [Basket items](https://norce-open-demo.admin-se.playground.norce.tech/shopping/settings/infotypes/basketitem) ## Receiving an OrderRequest The order receiver service must expose HTTP POST endpoints to accept OrderRequest messages in JSON or XML. **OrderRequest structure:** Contains customer, shipping, payment, and item details. Norce Commerce sends the request to your endpoint. ### Example Endpoints details summary JSON Endpoint Example: JSON Example ```csharp /// /// Receive an OrderRequest from Norce in JSON format /// /// Norce will POST an Enferno.Services.StormConnect.Contracts.Order.OrderRequest /// ERP order data mapped to Enferno.Services.StormConnect.Contracts.Order.OrderResponse [HttpPost("json", Name = "ReceiveOrderRequestJson")] [Consumes("application/json")] // Specifies JSON as input format [Produces("application/json")] // Returns JSON response public async Task PostJson(Enferno.Services.StormConnect.Contracts.Order.OrderRequest norceOrderRequest) { _logger.LogInformation("Order request received for {ClientOrderRef}", norceOrderRequest.ClientOrderRef); // Process the order and send a response var orderResponse = new Enferno.Services.StormConnect.Contracts.Order.OrderResponse { StatusCode = "Ok", HasErpOrderNo = true, ErpOrderNo = Guid.NewGuid().ToString() // Set to order number from Erp }; return Ok(orderResponse); } ``` XML Example ```csharp /// /// Receive an OrderRequest from Norce in XML format /// /// Norce will POST an Enferno.Services.StormConnect.Contracts.Order.OrderRequest in XML /// ERP order data mapped to Enferno.Services.StormConnect.Contracts.Order.OrderResponse [HttpPost("xml", Name = "ReceiveOrderRequestXml")] [Consumes("application/xml")] // Specifies XML as input format [Produces("application/xml")] // Returns XML response public async Task PostXml([FromBody] Enferno.Services.StormConnect.Contracts.Order.OrderRequest norceOrderRequest) { _logger.LogInformation("XML Order request received for {ClientOrderRef}", norceOrderRequest.ClientOrderRef); // Process the order and send a response var orderResponse = new Enferno.Services.StormConnect.Contracts.Order.OrderResponse { StatusCode = "Ok", HasErpOrderNo = true, ErpOrderNo = Guid.NewGuid().ToString() // Set to order number from Erp }; return Ok(orderResponse); } ``` **Explanation:** - Use `[Consumes]` and `[Produces]` attributes to specify input/output formats. - Log the `ClientOrderRef` for traceability. - Return an OrderResponse with appropriate status and ERP order number. ### Required NuGet Package To use the `OrderRequest` and `OrderResponse` types, install the [Enferno.Services.StormConnect.Contracts NuGet package](https://www.nuget.org/packages/Enferno.Services.StormConnect.Contracts): ```cmd Install-Package Enferno.Services.StormConnect.Contracts ``` ## Recommended Practices ### Duplicate Detection Design your integration to handle retries. Use `ClientOrderRef` as a unique key to detect and ignore duplicate orders. ### Error Handling Return a `Failed` status for business or integration errors. Only rely on Norce Commerce retry logic for endpoint or service downtime. ### Service Downtime If your ERP or integration is unavailable, return an appropriate HTTP status (e.g., `ServiceUnavailable`). Norce Commerce will retry automatically. ## Further Reading - [Shopping integration](/developer-portal/system-integration/shopping-integrations) - [Customers and Companies integration](/developer-portal/system-integration/customer-and-company-integrations) - [Norce Commerce Connect API Reference](/api-reference)