adobe / commerce-integration-starter-kit

Adobe's integration starter kit uses Adobe Developer App Builder to improve real-time connection reliability and reduce the time-to-market for integrations between Adobe Commerce and other back-office systems, such as ERPs, CRMs, and PIMs.
Apache License 2.0
9 stars 2 forks source link

Commerce Integration Starter Kit

Node.js CI

Welcome to Adobe Commerce Integration Starter Kit.

Integrating an e-commerce platform with your ERP, OMS, or CRM is a mission-critical requirement. Companies can spend tens of thousands of dollars building these integrations. To reduce the cost of integrating with Enterprise Resource Planning (ERP) solutions and to improve the reliability of real-time connections, Adobe is introducing an integration starter kit for back-office integrations using Adobe Developer App Builder. The kit includes reference integrations for commonly used commerce data like orders, products, and customers. It also includes onboarding scripts and a standardized architecture for developers to build on following best practices.

The public documentation can be found at Adobe Developer Starter Kit docs

Alt text

Prerequisites

Create App Builder project

Go to the Adobe developer console portal

Configure a new Integration in commerce

Configure a new Integration to secure the calls to Commerce from App Builder using OAuth by following these steps:

Install Commerce Eventing module (only required when running Adobe Commerce versions 2.4.4 or 2.4.5)

Install Adobe I/O Events for Adobe Commerce module in your commerce instance following this documentation

Note

By upgrading the Adobe I/O Events for Adobe Commerce module to version 1.6.0 or greater, you will benefit from some additional automated steps during onboarding.

Starter Kit first deploy & onboarding

Following the next steps, you will deploy and onboard the starter kit for the first time. The onboarding process sets up event providers and registrations based on your selection.

Download the project

Configure the project

Install the npm dependencies using the command:

npm install

This step will connect your starter kit project to the App builder project you created earlier. Ensure to select the proper Organization > Project > Workspace with the following commands:

aio login
aio console org select
aio console project select
aio console workspace select

Sync your local application with the App Builder project using the following command:

aio app use
# Choose the option 'm' (merge) 

Edit the file app.config.yaml if you want to deploy specific entities by commenting on the entities you don't need (e.g., product-backoffice if you don't need to sync products from an external back-office application):

application:
  runtimeManifest:
    packages:
      product-commerce:
        license: Apache-2.0
        actions:
          $include: ./actions/product/commerce/actions.config.yaml
    #  product-backoffice:
    #    license: Apache-2.0
    #    actions:
    #      $include: ./actions/product/external/actions.config.yaml
      customer-commerce:
        license: Apache-2.0
        actions:
          $include: ./actions/customer/commerce/actions.config.yaml
      customer-backoffice:
        license: Apache-2.0
        actions:
          $include: ./actions/customer/external/actions.config.yaml
    #  ...

Deploy

Run the following command to deploy the project; this will deploy the runtime actions needed for the onboarding step:

aio app deploy

You can confirm the success of the deployment in the Adobe Developer Console by navigating to the Runtime section on your workspace: Alt text

Onboarding

Configure the event registrations

By default, the registrations' config file creates all the registrations for all entities. You can edit the ./onboarding/custom/starter-kit-registrations.json file if you don't need a registration. If you don't want to receive events from commerce, remove commerce from the entity array; for backoffice updates, remove backoffice. e.g., In the previous onboarding step (Configure the project), we commented on the product-backoffice package. In this case, we have to remove backoffice from the product entity:

{
  "product": ["commerce"],
  "customer": ["commerce", "backoffice"],
  "order": ["commerce", "backoffice"],
  "stock": ["commerce", "backoffice"]
}

Execute the onboarding

This step will generate the IO Events providers and the registrations for your starter kit project. If your Commerce instance Adobe I/O Events for Adobe Commerce module version 1.6.0 or greater, the module will also be automatically configured by the onboarding script.
To start the process run the command:

npm run onboard

The console will return the provider's IDs and save this information:

Check your App developer console to confirm the creation of the registrations:
![Alt text](docs/console-event-registrations.png "Workspace registrations")

### Complete the Adobe Commerce eventing configuration

> **Note**
>
> If your Commerce instance Adobe I/O Events for Adobe Commerce module version is 1.6.0 or greater and the onboarding script completed successfully, the following steps are not required. The onboarding script will configure the Adobe Commerce instance automatically.
> Follow the steps in the next section to validate that the configuration is correct or skip to the next section.

You will configure your Adobe Commerce instance to send events to your App builder project using the following steps

#### Configure Adobe I/O Events in Adobe Commerce instance
To configure the provider in Commerce, do the following:
- In the Adobe Commerce Admin, navigate to Stores > Settings > Configuration > Adobe Services > Adobe I/O Events > General configuration. The following screen displays.
  ![Alt text](docs/commerce-events-configuration.webp "Commerce eventing configuration")
- Select `OAuth (Recommended)` from the `Adobe I/O Authorization Type` menu.
- Copy the contents of the `<workspace-name>.json` (Workspace configuration JSON you downloaded in the previous step [`Create app builder project`](#create-app-builder-project)) into the `Adobe I/O Workspace Configuration` field.
- Copy the commerce provider instance ID you saved in the previous step [`Execute the onboarding](#execute-the-onboarding) into the `Adobe Commerce Instance ID` field.
- Copy the commerce provider ID  you saved in the previous step [`Execute the onboarding`](#execute-the-onboarding) into the `Adobe I/O Event Provider ID` field.
- Click `Save Config`.
- Enable Commerce Eventing by setting the `Enabled` menu to Yes. (Note: You must enable cron so that Commerce can send events to the endpoint.)
- Enter the merchant's company name in the `Merchant ID` field. You must use alphanumeric and underscores only.
- In the `Environment ID` field, enter a temporary name for your workspaces while in development mode. When you are ready for production, change this value to a permanent value, such as `Production`.
- (Optional) By default, if an error occurs when Adobe Commerce attempts to send an event to Adobe I/O, Commerce retries a maximum of seven times. To change this value, uncheck the Use system value checkbox and set a new value in the Maximum retries to send events field.
- (Optional) By default, Adobe Commerce runs a cron job (clean_event_data) every 24 hours that delete event data three days old. To change the number of days to retain event data, uncheck the Use system value checkbox and set a new value in the Event retention time (in days) field.
- Click `Save Config`.

#### Subscribe to events in Adobe Commerce instance
> **Note**
>
> If your Commerce instance Adobe I/O Events for Adobe Commerce module version is 1.6.0 or greater, run the commerce-event-subscribe script to automatically subscribe to the Commerce events in `scripts/commerce-event-subscribe/config/commerce-event-subscribe.json`
> ```bash
> npm run commerce-event-subscribe
> ```
> Otherwise, follow the steps below to subscribe to the events manually.

To subscribe to events, follow this [documentation](https://developer.adobe.com/commerce/extensibility/events/configure-commerce/#subscribe-and-register-events).
For events of type 'plugin' you can also check this [documentation](https://developer.adobe.com/commerce/extensibility/events/commands/#subscribe-to-an-event).

Here are the events with the minimal required fields you need to subscribe to, it includes the REST API endpoints that could trigger this events:

| Entity         | Event                                                  | Required fields             | REST API Ref                                                                                                                                                                                                                                                                                                                                                                                                                                |
|----------------|--------------------------------------------------------|-----------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Product        | observer.catalog_product_delete_commit_after           | sku                         | product [delete](https://adobe-commerce.redoc.ly/2.4.6-admin/tag/productssku#operation/DeleteV1ProductsSku)                                                                                                                                                                                                                                                                                                                                 |
| Product        | observer.catalog_product_save_commit_after             | sku, created_at, updated_at | product [create](https://adobe-commerce.redoc.ly/2.4.6-admin/tag/products#operation/GetV1Products) / [update](https://adobe-commerce.redoc.ly/2.4.6-admin/tag/productssku#operation/PutV1ProductsSku)                                                                                                                                                                                                                                       |
| Customer       | observer.customer_save_commit_after                    | created_at, updated_at      | customer  [create](https://adobe-commerce.redoc.ly/2.4.6-admin/tag/customers#operation/PostV1Customers) / [update](https://adobe-commerce.redoc.ly/2.4.6-admin/tag/customerscustomerId#operation/PutV1CustomersCustomerId)                                                                                                                                                                                                                  |
| Customer       | observer.customer_delete_commit_after                  | entity_id                   | customer [delete](https://adobe-commerce.redoc.ly/2.4.6-admin/tag/customerscustomerId#operation/DeleteV1CustomersCustomerId)                                                                                                                                                                                                                                                                                                                |
| Customer group | observer.customer_group_save_commit_after              | customer_group_code         | customer group [create](https://adobe-commerce.redoc.ly/2.4.6-admin/tag/customerGroups#operation/PostV1CustomerGroups) / [update](https://adobe-commerce.redoc.ly/2.4.6-admin/tag/customerGroupsid#operation/PutV1CustomerGroupsId)                                                                                                                                                                                                         |
| Customer group | observer.customer_group_delete_commit_after            | customer_group_code         | customer group [delete](https://adobe-commerce.redoc.ly/2.4.6-admin/tag/customerGroupsid#operation/DeleteV1CustomerGroupsId)                                                                                                                                                                                                                                                                                                                |
| Order          | observer.sales_order_save_commit_after                 | created_at, updated_at      | order update ([hold](https://adobe-commerce.redoc.ly/2.4.6-admin/tag/ordersidhold#operation/PostV1OrdersIdHold), [unhold](https://adobe-commerce.redoc.ly/2.4.6-admin/tag/ordersidunhold#operation/PostV1OrdersIdUnhold), [cancel](https://adobe-commerce.redoc.ly/2.4.6-admin/tag/ordersidcancel#operation/PostV1OrdersIdCancel), [emails](https://adobe-commerce.redoc.ly/2.4.6-admin/tag/ordersidemails#operation/PostV1OrdersIdEmails)) |
| Stock          | observer.cataloginventory_stock_item_save_commit_after | product_id                  | product [stock update](https://adobe-commerce.redoc.ly/2.4.6-admin/tag/productsproductSkustockItemsitemId/#operation/PutV1ProductsProductSkuStockItemsItemId)                                                                                                                                                                                                                                                                               |

### Automating the execution of onboarding and event subscription
App builder defines lifecycle event hooks that make possible to automatically execute custom code when a particular application lifecycle event happens.
To learn more these hooks navigate to [App Builder application tooling lifecycle event hooks](https://developer.adobe.com/app-builder/docs/guides/app-hooks/).

The following code snapshot in the `app.config.yaml` file shows how to define a hook that will execute the onboarding and event subscription scripts after the application has been deployed:

```yaml
application:
  hooks:
    post-app-deploy: ./hooks/post-app-deploy.js

For convenience, the hook configuration is commented out in the app.config.yaml file. To enable the hook, uncomment the hook configuration.

If you plan to add more hooks to the application, you can define them in the hooks folder and reference them in the app.config.yaml file.

Development

Project source code structure

The starter kit provides boilerplate code for the synchronization across systems of the following entities:

The synchronization is bidirectional by default: changes in Commerce are propagated to the external back-office application. application and the other way around.

The source code is organized following the file structure of a typical App Builder application, where the actions folder contains the source code for all the serverless actions.

actions folder structure

The actions folder contains:

entity folder structure

Each `entity folder follows a similar structure, and it contains folders named after each system being integrated, namely:

commerce and external folders structure

The commerce and external folders follow a similar structure:

Individual action folder structure

Each individual action folder contains the following files:

Pass env params to an action

You can pass values from the environment to the actionparams object following: Add your parameter to .env file:

HERE_YOUR_PARAM=any value

Pass the required parameters to the action by configuring them in the actions/{entity}/../actions.config.yaml under {action name} -> inputs as follows:

{action name}:
  function: commerce/{action name}/index.js
  web: 'no'
  runtime: nodejs:20
  inputs:
    LOG_LEVEL: debug
    HERE_YOUR_PARAM: $HERE_YOUR_PARAM_ENV
  annotations:
    require-adobe-auth: true
    final: true

This parameter should be accessible on the params object

async function main(params) {
  params.HERE_YOUR_PARAM
}

Different types of actions included in the starter kit

consumer and event handler actions are the two main types of actions defined by the starter kit to implement the business logic needed to synchronize data between the different systems being integrated.

Additionally, boilerplate code and samples for event ingestion and synchronous webhook actions are provided.

consumer action

This action is subscribed to a subset of events (typically all of them belonging to the same entity, e.g. product, although there are examples where it receives events from various entities belonging to the same “domain", e.g. order and shipment). When the event provider it is attached to receives an event, this runtime action will be automatically activated.

The main purpose of this action is to route the event received to the event handler action. Normally, this routing is determined by the name of the event received.

The response returned by a consumer action is expected to be consistent with the response received from the activation of the subsequent event handler action. For example, if the event handler action returns an HTTP/400 status, the consumer action is expected to respond with the same status.

When it receives an event that it does not know how to route, it is expected to return HTTP/400 status. This will prevent the event handling from being retried.

By default, the response of the consumer actions is the following:

event handler action

This action implements the business logic to manage an individual event notifying about a change in one of the systems being integrated. Typically, its business logic includes an API call to propagate the changes to the other system being integrated.

The consumer action activates these event handler actions to delegate the handling of a particular event. This activation is done in a synchronous way.

The response returned by an event handler action is expected to include a statusCode attribute. This attribute allows the consumer action to propagate the response HTTP status code upstream so it properly reflects on the event registration Debug Tracing tab on the Adobe Developer Console.

By default, the response of the event handler actions is the following:

event ingestion action

The source code for this action can be found at ./actions/ingestion.

This runtime action is provided as an alternative approach to deliver events to the integration if the 3rd-party back-office application cannot fulfill the Events Publishing API requirements.

Additional details can be found at this README

To get the URL of the webhook, run the following command:

aio runtime action get ingestion/webhook --url

By default, the response of the event ingestion actions is the following:

synchronous webhook actions

The source code for these actions can be found at ./actions/webhook.

These runtime actions are meant to expose a webhook that can be invoked synchronously from Commerce in order to affect the behavior of a particular business flow.

The ./actions/webhook/check-stock folder provides a sample implementation of a synchronous webhook action. Additional details can be found at this README

To get the URL of the webhook, run the following command:

aio runtime action get webhook/check-stock --url

By default, the response of the synchronous webhook actions is the following:

Remember, these responses are adapted to Commerce webhook module; in case you want to use a different approach, you can change the response implementation in the code as you need.

starter kit info action

Warning
Please DO NOT DELETE this action; future functionalities planned for upcoming starter kit releases may stop working.

The source code for this action can be found at ./actions/starter-kit-info.

This runtime action, when invoked, returns information about the starter-kit used to develop the project, such as

To get the URL of the webhook, run the following command:

aio runtime action get starter-kit/info --url

By default, the response of the starter kit info action is the following:

Log management and forwarding

Application logs allow developers to debug an application in development as well as monitor it in production.

By default, the starter kit uses the AIO SDK to store logs in Adobe I/O Runtime. You can find additional details on this topic in Managing Application Logs.

The application logs can alternatively be forwarded to a customer-owned log management solution (such as Splunk, Azure, or New Relic). Use the comparison in When to use Log Forwarding to decide when to store logs in Adobe I/O Runtime and when to forward them to a log management platform.

If you are running your Adobe Commerce instance in the cloud, you already have a New Relic instance provisioned for you. The Forwarding Logs to New Relic page describes the steps to set up the starter kit to forward logs to New Relic.

Prevent secrets from leaking in logs.

The stringParameters in the ./actions/utils.js file can be used to avoid secrets leaking when logging the parameters received by a runtime action. It will replace

The default parameters to be hidden are:

const hidden = [
  'secret',
  'token'
]

Adjust these values to hide secrets passed as params to your runtime actions if needed.

Testing

The starter kit provides unit tests for most of the runtime actions it includes. These tests can be located in the ./test/actions folder.

Additionally, unit tests for the onboarding script can be found in the .test/onboarding folder.

The coverage report could be found in the .test/test-coverage folder.

You can find more details about unit testing and an example in Lesson 3: Testing a Serverless Action.

How to subscribe to a new event

The starter kit comes with predefined events for each entity. Sometimes, you may need to add a new event to an entity, e.g., a customer. To do this, follow the next steps:

With these steps, you can consume the new event you added to the project. If you want to change an existing event, make the changes in the same places:

Included actions documentation

External back-office ingestion webhook

Product entity

Commerce to third party

Third party to Commerce

Customer entity

Commerce to third party

Third party to Commerce

Third party to Commerce

Stock entity

Commerce to third party

Third party to Commerce

References

Contributing

Contributions are welcomed! Read the Contributing Guide for more information.