Order placement validation

As a shopper places an order, a third-party system is used to confirm that the items added to the order can be shipped to the selected address.

Webhook name

PaaS Only plugin.magento.sales.api.order_management.place

SaaS Only plugin.sales.api.order_management.place

data-variant=info
data-slots=text
You can create a similar webhook with observer.sales_order_place_before (PaaS) or observer.sales_order_place_before (SaaS). It contains similar data described in this use case, but the placement of the order information within the payload structure differs.

Payloads

In the following example default payload, some data has been removed for brevity.

data-slots=heading, code
data-repeat=2
data-languages=JSON, JSON

Default payload

{
    "order": {
        "base_currency_code": "USD",
        "base_discount_amount": 0.0,
        "base_grand_total": 110.0,
        "base_discount_tax_compensation_amount": 0.0,
        "base_shipping_amount": 20.0,
        ...
        "items": [
            {
                "sku": "Pr-1",
                "name": "Product 1",
                ...
            },
            {
                "sku": "Pr-2",
                "name": "Product 2",
                ...
            }
        ],
        "status_histories": [
           ...
        ],
        "extension_attributes": [
            ...
        ],
        "addresses": [
            {
                "region_id": "57",
                "postcode": 78768,
                "country_id": "US",
                "address_type": "shipping",
                ...
            },
            {
                "region_id": "57",
                "postcode": 78768,
                "country_id": "US",
                "address_type": "billing",
                ...
            }
        ],
        "shipping_method": "tablerate_bestway",
        "payment": {
          "method": "checkmo",
          "additional_data": null,
          ...
        },
        "gift_cards": "[]",
        "gift_cards_amount": 0,
        ...
    }
}

Configured payload

{
   "order": {
        "items": [
            {
                "sku": "Pr-1"
            },
            {
                "sku": "Pr-2"
            }
        ],
        "addresses": [
            {
                "region_id": "57",
                "postcode": 78768,
                "country_id": "US",
                "address_type": "shipping",
                ...
            },
            {
                "region_id": "57",
                "postcode": 78768,
                "country_id": "US",
                "address_type": "billing",
                ...
            }
        ]
    }
}

Configuration

data-slots=heading, code
data-repeat=2
data-languages=XML, YAML

webhook.xml (PaaS)

<method name="plugin.magento.sales.api.order_management.place" type="before">
    <hooks>
        <batch name="order_validation" order="200">
            <hook name="validate_product_shipping_address" url="{env:APP_BUILDER_URL}/validate-order" priority="100" fallbackErrorMessage="Could not validate the shipping address" timeout="5000" softTimeout="1000" required="true" active="true" method="POST">
                <headers>
                    <header name="x-gw-ims-org-id">{env:APP_BUILDER_IMS_ORG_ID}</header>
                    <header name="Authorization">Bearer {env:APP_BUILDER_AUTH_TOKEN}</header>
                </headers>
                <fields>
                    <field name="order.items[].sku"/>
                    <field name="order.addresses"/>
                </fields>
            </hook>
        </batch>
    </hooks>
</method>

Admin (SaaS)

Hook Settings

Webhook method: plugin.sales.api.order_management.place
Webhook type: before
Batch name: order_validation
Batch order: 200
Hook name: validate_product_shipping_address
Hook priority: 100
URL: <Host>/validate-order
Timeout: 5000
Soft timeout: 1000
Fallback Error Message: Could not validate the shipping address
Required: Required
Active: Yes
Method: POST

Developer Console OAuth

Client ID: The client ID for the OAuth credential.
Client Secret: The client secret for the OAuth credential.
Organization ID: The organization ID for the OAuth credential.

Hook Fields

Name: order.items[].sku
Source: order.items[].sku
Active: Yes

Name: order.addresses
Source: order.addresses
Active: Yes

Endpoint code example

The following code example shows how to implement the webhook on your custom endpoint.

const { Core } = require('@adobe/aio-sdk')
const { errorResponse, stringParameters, checkMissingRequestInputs } = require('../utils')

// main function that will be executed by Adobe I/O Runtime
async function main (params) {
  // create a Logger
  const logger = Core.Logger('main', { level: params.LOG_LEVEL || 'info' })

  try {
    // 'info' is the default level if not set
    logger.info('Calling the main action')

    // log parameters, only if params.LOG_LEVEL === 'debug'
    logger.debug(stringParameters(params))

    // check for missing request input parameters and headers
    const requiredParams = [/* add required params */]
    const requiredHeaders = ['Authorization']
    const errorMessage = checkMissingRequestInputs(params, requiredParams, requiredHeaders)
    if (errorMessage) {
      // return and log client errors
      return errorResponse(400, errorMessage, logger)
    }

    // Place the real call to a 3rd party endpoint here.
    // In this example, we check if the shipping address' postcode is greater than 70000.
    // If it is, an exception with a message about being unable to ship is thrown.

    const response = {statusCode: 200}
    for (let i = 0; i < params.order.addresses.length; i++) {
      let address = params.order.addresses[i]
      if (address.address_type === 'shipping' && address.postcode > 70000) {
        response.body = JSON.stringify({
            op: "exception",
            message: `App Builder Webhook Response: Products can not be shipped to postcode "${address.postcode}"`
        })
        return response;
      }
    }

    response.body = JSON.stringify({
      op: "success"
    })
    return response
  } catch (error) {
    // log any server errors
    logger.error(error)
    // return with 500
    return errorResponse(500, 'server error', logger)
  }
}

exports.main = main

If the products in the order cannot be shipped to the selected address, the runtime AppBuilder action returns an exception message. The message is visible to the customer.

response.body = JSON.stringify({
    op: "exception",
    message: `App Builder Webhook Response: Products can not be shipped to postcode "${address.postcode}"`
})