Skip to content
Last updated

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 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.

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.

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 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.
An example OrderRequest message

OrderRequest

{
  "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
}

Read more about the OrderRequest in the Norce Commerce Connect API Reference.


OrderResponse Message Structure

Your service must return an 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.
  • 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.
OrderResponse message examples JSON

Ok - with ErpOrderNo


{
  "StatusCode": "OK",
  "Description": "No error, order status is set to confirmed.",
  "HasErpOrderNo": true,
  "ErpOrderNo": "ErpNo_5670588"
}

Ok - without ErpOrderNo

{
  "StatusCode": "OK",
  "Description": "No error, order status is set to allocated.",
  "HasErpOrderNo": false,
  "ErpOrderNo": null
}

Error

{
  "StatusCode": "Failed",
  "Description": "Managed Error, this message is logged in Norce Commerce, no retry.",
  "HasErpOrderNo": false,
  "ErpOrderNo": null
}
OrderResponse message examples XML

Ok - with ErpOrderNo

<OrderResponse xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="Enferno.Services.StormConnect.Contracts.Order">
  <StatusCode>OK</StatusCode>
  <Description>No error, order status is set to confirmed.</Description>
  <HasErpOrderNo>true</HasErpOrderNo>
  <ErpOrderNo>ErpNo_5670588</ErpOrderNo>
</OrderResponse>

Ok - without ErpOrderNo

<OrderResponse xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="Enferno.Services.StormConnect.Contracts.Order">
  <StatusCode>OK</StatusCode>
  <Description>No error, order status is set to allocated.</Description>
  <HasErpOrderNo>false</HasErpOrderNo>
  <ErpOrderNo/>
</OrderResponse>

Error

<OrderResponse xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="Enferno.Services.StormConnect.Contracts.Order">
  <StatusCode>Failed</StatusCode>
  <Description>Managed Error, this message is logged in Norce Commerce, no retry.</Description>
  <HasErpOrderNo>false</HasErpOrderNo>
  <ErpOrderNo/>
</OrderResponse>

Read more about the 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:


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

JSON Endpoint Example:
/// <summary>
/// Receive an OrderRequest from Norce in JSON format
/// </summary>
/// <param name="norceOrderRequest">Norce will POST an Enferno.Services.StormConnect.Contracts.Order.OrderRequest</param>
/// <returns>ERP order data mapped to Enferno.Services.StormConnect.Contracts.Order.OrderResponse</returns>
[HttpPost("json", Name = "ReceiveOrderRequestJson")]
[Consumes("application/json")] // Specifies JSON as input format
[Produces("application/json")] // Returns JSON response
public async Task<IActionResult> 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);
}

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:

Install-Package Enferno.Services.StormConnect.Contracts

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