diff --git a/starter-kit/README.md b/starter-kit/README.md new file mode 100644 index 0000000..13aa5fe --- /dev/null +++ b/starter-kit/README.md @@ -0,0 +1,36 @@ +# Adobe Commerce integration starter kit samples + +This section contains a collection of samples that show how the [Adobe Commerce integration starter kit](https://github.com/adobe/commerce-integration-starter-kit) can be customized to meet your business needs. +Each folder serves as a practical example of a particular customization. + +## Overview + +Use the Adobe Commerce integration starter kit to enrich customer shopping experiences and to support multichannel, global commerce for B2B, B2C, and hybrid businesses. + +## Directory Structure + +- `add-ingestion-scheduler`: Contains sample code of how to create an scheduled ingestion action. +- `customize-ingestion-webhook`: Contains sample code of how to customize the ingestion webhook. +- `customize-registrations-and-events`: Contains sample code of how to customize the registrations and events used by an integration built on top of the starter kit. + +## Getting Started + +To get started with these samples, follow these steps: + +1. Clone the [Adobe Commerce integration starter kit](https://github.com/adobe/commerce-integration-starter-kit) repository. + ```bash + git clone git@github.com:adobe/commerce-integration-starter-kit.git + ``` +2. Navigate to the cloned directory. + ```bash + cd commerce-integration-starter-kit + ``` +3. Override the `commerce-integration-starter-kit` files with the files from the sample you want to use. + ```bash + cp -r /* . + ``` +4. Install and deploy the starter kit following the instructions in the [README](https://github.com/adobe/commerce-integration-starter-kit/blob/main/README.md) + +## More information + +To learn more about Adobe Commerce integration starter kit visit the [Developer docs](https://developer.adobe.com/commerce/extensibility/starter-kit/). diff --git a/starter-kit/add-ingestion-scheduler/README.md b/starter-kit/add-ingestion-scheduler/README.md new file mode 100644 index 0000000..4639732 --- /dev/null +++ b/starter-kit/add-ingestion-scheduler/README.md @@ -0,0 +1,12 @@ +# Scheduled Ingestion Action + +This sample code shows how to create a scheduled ingestion action using the Adobe Commerce integration starter kit. +It provides an alternative to the event [ingestion webhook](https://developer.adobe.com/commerce/extensibility/starter-kit/events/#ingestion-webhook), practical when the third-party system cannot push events to the starter kit, and a pull mechanism from an event storage has to be used instead. + +## Usage + +After installation and configuration, the scheduled ingestion action will be triggered at the specified time. + +## More information + +To learn more about Adobe Commerce integration starter kit visit the [Developer docs](https://developer.adobe.com/commerce/extensibility/starter-kit/). \ No newline at end of file diff --git a/starter-kit/add-ingestion-scheduler/actions/customer/external/created/schema.json b/starter-kit/add-ingestion-scheduler/actions/customer/external/created/schema.json new file mode 100644 index 0000000..c050fc8 --- /dev/null +++ b/starter-kit/add-ingestion-scheduler/actions/customer/external/created/schema.json @@ -0,0 +1,10 @@ +{ + "type": "object", + "properties": { + "PersonFirstName": { "type": "string" }, + "PersonLastName": {"type": "string"}, + "PrimaryContactEmail": {"type": "string"} + }, + "required": ["PersonFirstName", "PersonLastName", "PrimaryContactEmail"], + "additionalProperties": true +} diff --git a/starter-kit/add-ingestion-scheduler/actions/customer/external/created/transformer.js b/starter-kit/add-ingestion-scheduler/actions/customer/external/created/transformer.js new file mode 100644 index 0000000..ce490f6 --- /dev/null +++ b/starter-kit/add-ingestion-scheduler/actions/customer/external/created/transformer.js @@ -0,0 +1,31 @@ +/* +Copyright 2022 Adobe. All rights reserved. +This file is licensed to you under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. You may obtain a copy +of the License at http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under +the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS +OF ANY KIND, either express or implied. See the License for the specific language +governing permissions and limitations under the License. +*/ + +/** + * This function transform the received customer data from external back-office application to Adobe commerce + * + * @param {object} params - Data received from Adobe commerce + * @returns {object} - Returns transformed data object + */ +function transformData (params) { + return { + customer: { + email: params.data.PrimaryContactEmail, + firstname: params.data.PersonFirstName, + lastname: params.data.PersonLastName + } + } +} + +module.exports = { + transformData +} diff --git a/starter-kit/add-ingestion-scheduler/actions/ingestion/actions.config.yaml b/starter-kit/add-ingestion-scheduler/actions/ingestion/actions.config.yaml new file mode 100644 index 0000000..521566c --- /dev/null +++ b/starter-kit/add-ingestion-scheduler/actions/ingestion/actions.config.yaml @@ -0,0 +1,38 @@ +#webhook: +# function: ./webhook/index.js +# web: 'yes' +# runtime: nodejs:20 +# inputs: +# LOG_LEVEL: debug +# OAUTH_ORG_ID: $OAUTH_ORG_ID +# OAUTH_CLIENT_ID: $OAUTH_CLIENT_ID +# OAUTH_CLIENT_SECRET: $OAUTH_CLIENT_SECRET +# OAUTH_TECHNICAL_ACCOUNT_ID: $OAUTH_TECHNICAL_ACCOUNT_ID +# OAUTH_TECHNICAL_ACCOUNT_EMAIL: $OAUTH_TECHNICAL_ACCOUNT_EMAIL +# IO_MANAGEMENT_BASE_URL: $IO_MANAGEMENT_BASE_URL +# IO_CONSUMER_ID: $IO_CONSUMER_ID +# IO_PROJECT_ID: $IO_PROJECT_ID +# IO_WORKSPACE_ID: $IO_WORKSPACE_ID +# AIO_runtime_namespace: $AIO_RUNTIME_NAMESPACE +# annotations: +# require-adobe-auth: false +# final: true +scheduler: + function: ./scheduler/index.js + web: 'no' + runtime: nodejs:20 + inputs: + LOG_LEVEL: debug + OAUTH_ORG_ID: $OAUTH_ORG_ID + OAUTH_CLIENT_ID: $OAUTH_CLIENT_ID + OAUTH_CLIENT_SECRET: $OAUTH_CLIENT_SECRET + OAUTH_TECHNICAL_ACCOUNT_ID: $OAUTH_TECHNICAL_ACCOUNT_ID + OAUTH_TECHNICAL_ACCOUNT_EMAIL: $OAUTH_TECHNICAL_ACCOUNT_EMAIL + IO_MANAGEMENT_BASE_URL: $IO_MANAGEMENT_BASE_URL + IO_CONSUMER_ID: $IO_CONSUMER_ID + IO_PROJECT_ID: $IO_PROJECT_ID + IO_WORKSPACE_ID: $IO_WORKSPACE_ID + AIO_runtime_namespace: $AIO_RUNTIME_NAMESPACE + annotations: + require-adobe-auth: true + final: true diff --git a/starter-kit/add-ingestion-scheduler/actions/ingestion/scheduler/event-mapping.json b/starter-kit/add-ingestion-scheduler/actions/ingestion/scheduler/event-mapping.json new file mode 100644 index 0000000..3aba38c --- /dev/null +++ b/starter-kit/add-ingestion-scheduler/actions/ingestion/scheduler/event-mapping.json @@ -0,0 +1,3 @@ +{ + "external_provider.customer_created.v1.0": "be-observer.customer_create" +} diff --git a/starter-kit/add-ingestion-scheduler/actions/ingestion/scheduler/index.js b/starter-kit/add-ingestion-scheduler/actions/ingestion/scheduler/index.js new file mode 100644 index 0000000..439d4e2 --- /dev/null +++ b/starter-kit/add-ingestion-scheduler/actions/ingestion/scheduler/index.js @@ -0,0 +1,121 @@ +/* +Copyright 2022 Adobe. All rights reserved. +This file is licensed to you under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. You may obtain a copy +of the License at http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under +the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS +OF ANY KIND, either express or implied. See the License for the specific language +governing permissions and limitations under the License. +*/ + +const { Core, Events } = require('@adobe/aio-sdk') +const { stringParameters } = require('../../../actions/utils') +const { CloudEvent } = require('cloudevents') +const uuid = require('uuid') +const { HTTP_OK, HTTP_INTERNAL_ERROR, BACKOFFICE_PROVIDER_KEY} = require('../../../actions/constants') +const { getAdobeAccessToken } = require('../../../utils/adobe-auth') +const { getProviderByKey } = require('../../../utils/adobe-events-api') +const { errorResponse, successResponse } = require('../../responses') +const eventMappings = require("./event-mapping.json"); +const {transformData} = require("./payload-transform"); + +/** + * This web action allow external back-office application publish event to IO event using custom authentication mechanism. + * + * @param {object} params - method params includes environment and request data + * @returns {object} - response with success status and result + */ +async function main (params) { + const logger = Core.Logger('ingestion-scheduler', { level: params.LOG_LEVEL || 'info' }) + try { + logger.info('Start processing request') + logger.debug(`Scheduler main params: ${stringParameters(params)}`) + + // Faking the reading the events from STFP, S3, etc + const externalEventPayload = { + data: { + uid: `${uuid.v4()}`, + event: 'external_provider.customer_created.v1.0', + value: { + PersonFirstName: 'Test', + PersonLastName: 'Customer', + PersonMiddleName: 'AC', + PrimaryContactEmail: `${uuid.v4()}@sample.com.au`, + CustomerGroupId: '30', + SalesCurrencyCode: 'USD', + PrimaryContactPhone: '555-555-1234', + PartyType: 'Person', + AddressStreet: '1 Test Street', + AddressCountryRegionISOCode: 'US', + AddressZipCode: '00210', + AddressCity: 'Portsmouth', + AddressState: 'NH', + AddressLocationRoles: 'Invoice', + AddressDescription: 'Test Billing', + DeliveryAddressStreet: '2 Test Avenue', + DeliveryAddressCountryRegionISOCode: 'US', + DeliveryAddressZipCode: '00210', + DeliveryAddressCity: 'Portsmouth', + DeliveryAddressState: 'NH', + DeliveryAddressDescription: 'Test Deliver' + } + } + } + + // validate data - add here your validation if needed + + // map event name + const eventType = eventMappings[externalEventPayload.data?.event] + + // trim event payload + const transformedEventData = transformData(externalEventPayload) + + // send event + logger.debug('Generate Adobe access token') + const accessToken = await getAdobeAccessToken(params) + + logger.debug('Get existing registrations') + const provider = await getProviderByKey(params, accessToken, BACKOFFICE_PROVIDER_KEY) + + if (!provider) { + const errorMessage = 'Could not find any external backoffice provider' + logger.error(`${errorMessage}`) + return errorResponse(HTTP_INTERNAL_ERROR, errorMessage) + } + + logger.debug('Initiate events client') + const eventsClient = await Events.init( + params.OAUTH_ORG_ID, + params.OAUTH_CLIENT_ID, + accessToken) + + logger.info('Process event data') + logger.debug( + `Process event ${eventType}`) + + const cloudEvent = new CloudEvent({ + source: 'urn:uuid:' + provider.id, + type: eventType, + datacontenttype: 'application/json', + data: transformedEventData, + id: uuid.v4() + }) + + logger.debug(`Publish event ${eventType} to provider ${provider.label}`) + await eventsClient.publishEvent(cloudEvent) + + logger.info(`Successful request: ${HTTP_OK}`) + + return successResponse(eventType, { + success: true, + message: 'Event published successfully' + }) + } catch (error) { + logger.error(`Server error: ${error.message}`) + return errorResponse(HTTP_INTERNAL_ERROR, error.message) + } +} + +exports.main = main diff --git a/starter-kit/add-ingestion-scheduler/actions/ingestion/scheduler/payload-transform.js b/starter-kit/add-ingestion-scheduler/actions/ingestion/scheduler/payload-transform.js new file mode 100644 index 0000000..1b4c66d --- /dev/null +++ b/starter-kit/add-ingestion-scheduler/actions/ingestion/scheduler/payload-transform.js @@ -0,0 +1,34 @@ +/* +Copyright 2022 Adobe. All rights reserved. +This file is licensed to you under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. You may obtain a copy +of the License at http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under +the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS +OF ANY KIND, either express or implied. See the License for the specific language +governing permissions and limitations under the License. +*/ + +/** + * This function transform the received customer data from external back-office application to Adobe commerce + * + * @param {object} params - Data received from Adobe commerce + * @returns {object} - Returns transformed data object + */ +function transformData (params) { + switch (params.data.event) { + case 'external_provider.customer_created.v1.0': + return { + PersonFirstName: params.data.value.PersonFirstName, + PersonLastName: params.data.value.PersonLastName, + PrimaryContactEmail: params.data.value.PrimaryContactEmail, + } + default: + return params.data + } +} + +module.exports = { + transformData +} diff --git a/starter-kit/add-ingestion-scheduler/app.config.yaml b/starter-kit/add-ingestion-scheduler/app.config.yaml new file mode 100644 index 0000000..5c4e187 --- /dev/null +++ b/starter-kit/add-ingestion-scheduler/app.config.yaml @@ -0,0 +1,70 @@ +application: +# hooks: +# post-app-deploy: ./hooks/post-app-deploy.js + runtimeManifest: + packages: + starter-kit: + license: Apache-2.0 + actions: + # Please DO NOT DELETE this action; future functionalities planned for upcoming starter kit releases may stop working. + info: + function: actions/starter-kit-info/index.js + web: 'yes' + runtime: nodejs:20 + inputs: + LOG_LEVEL: debug + annotations: + require-adobe-auth: true + final: true + ingestion: + license: Apache-2.0 + actions: + $include: ./actions/ingestion/actions.config.yaml + triggers: + everyTwoMin: + feed: /whisk.system/alarms/interval + inputs: + minutes: 2 + rules: + everyTwoMinRule: + trigger: everyTwoMin + action: scheduler + webhook: + license: Apache-2.0 + actions: + $include: ./actions/webhook/actions.config.yaml + 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 + order-commerce: + license: Apache-2.0 + actions: + $include: ./actions/order/commerce/actions.config.yaml + order-backoffice: + license: Apache-2.0 + actions: + $include: ./actions/order/external/actions.config.yaml + stock-commerce: + license: Apache-2.0 + actions: + $include: ./actions/stock/commerce/actions.config.yaml + stock-backoffice: + license: Apache-2.0 + actions: + $include: ./actions/stock/external/actions.config.yaml +productDependencies: + - code: COMMC + minVersion: 2.4.4 diff --git a/starter-kit/customize-ingestion-webhook/README.md b/starter-kit/customize-ingestion-webhook/README.md new file mode 100644 index 0000000..24ec4fc --- /dev/null +++ b/starter-kit/customize-ingestion-webhook/README.md @@ -0,0 +1,48 @@ +# Customize Event Ingestion Webhook + +This sample code shows how to customize the event [ingestion webhook](https://developer.adobe.com/commerce/extensibility/starter-kit/events/#ingestion-webhook) provided by the Adobe Commerce integration starter kit. +The customizations implemented in the sample code include: +- mapping the incoming event name to the event name configured in the external event provider +- trimming the incoming event data to match the data expected by the external event + +## Usage + +After installation and configuration, activate the event ingestion webhook by running the following command in a terminal. +```bash +curl --request POST \ + --url https://${PROJECT_NAMESPACE}.adobeioruntime.net/api/v1/web/ingestion/webhook \ + --header 'Content-Type: application/json' \ + --data '{ + "data": { + "uid": "${UUID}", + "event": "external_provider.customer_created.v1.0", + "value": { + "PersonFirstName": "Test", + "PersonLastName": "Customer", + "PersonMiddleName": "AC", + "PrimaryContactEmail": "${UNIQUE_EMAIL_ADDRESS}", + "CustomerGroupId": "30", + "SalesCurrencyCode": "USD", + "PrimaryContactPhone": "555-555-1234", + "PartyType": "Person", + "AddressStreet": "1 Test Street", + "AddressCountryRegionISOCode": "US", + "AddressZipCode": "00210", + "AddressCity": "Portsmouth", + "AddressState": "NH", + "AddressLocationRoles": "Invoice", + "AddressDescription": "Test Billing", + "DeliveryAddressStreet": "2 Test Avenue", + "DeliveryAddressCountryRegionISOCode": "US", + "DeliveryAddressZipCode": "00210", + "DeliveryAddressCity": "Portsmouth", + "DeliveryAddressState": "NH", + "DeliveryAddressDescription": "Test Delivery" + } + } +}' +``` + +## More information + +To learn more about Adobe Commerce integration starter kit visit the [Developer docs](https://developer.adobe.com/commerce/extensibility/starter-kit/). diff --git a/starter-kit/customize-ingestion-webhook/actions/customer/external/created/schema.json b/starter-kit/customize-ingestion-webhook/actions/customer/external/created/schema.json new file mode 100644 index 0000000..c050fc8 --- /dev/null +++ b/starter-kit/customize-ingestion-webhook/actions/customer/external/created/schema.json @@ -0,0 +1,10 @@ +{ + "type": "object", + "properties": { + "PersonFirstName": { "type": "string" }, + "PersonLastName": {"type": "string"}, + "PrimaryContactEmail": {"type": "string"} + }, + "required": ["PersonFirstName", "PersonLastName", "PrimaryContactEmail"], + "additionalProperties": true +} diff --git a/starter-kit/customize-ingestion-webhook/actions/customer/external/created/transformer.js b/starter-kit/customize-ingestion-webhook/actions/customer/external/created/transformer.js new file mode 100644 index 0000000..7d45346 --- /dev/null +++ b/starter-kit/customize-ingestion-webhook/actions/customer/external/created/transformer.js @@ -0,0 +1,33 @@ +/* +Copyright 2022 Adobe. All rights reserved. +This file is licensed to you under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. You may obtain a copy +of the License at http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under +the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS +OF ANY KIND, either express or implied. See the License for the specific language +governing permissions and limitations under the License. +*/ + +/** + * This function transform the received customer data from external back-office application to Adobe commerce + * + * @param {object} params - Data received from Adobe commerce + * @returns {object} - Returns transformed data object + */ +function transformData (params) { + // @TODO This is a sample implementation. Please adapt based on your needs + // @TODO Notice that the attribute_set_id may need to be changed + return { + customer: { + email: params.data.PrimaryContactEmail, + firstname: params.data.PersonFirstName, + lastname: params.data.PersonLastName + } + } +} + +module.exports = { + transformData +} diff --git a/starter-kit/customize-ingestion-webhook/actions/ingestion/actions.config.yaml b/starter-kit/customize-ingestion-webhook/actions/ingestion/actions.config.yaml new file mode 100644 index 0000000..66fc181 --- /dev/null +++ b/starter-kit/customize-ingestion-webhook/actions/ingestion/actions.config.yaml @@ -0,0 +1,19 @@ +webhook: + function: ./webhook/index.js + web: 'yes' + runtime: nodejs:20 + inputs: + LOG_LEVEL: debug + OAUTH_ORG_ID: $OAUTH_ORG_ID + OAUTH_CLIENT_ID: $OAUTH_CLIENT_ID + OAUTH_CLIENT_SECRET: $OAUTH_CLIENT_SECRET + OAUTH_TECHNICAL_ACCOUNT_ID: $OAUTH_TECHNICAL_ACCOUNT_ID + OAUTH_TECHNICAL_ACCOUNT_EMAIL: $OAUTH_TECHNICAL_ACCOUNT_EMAIL + IO_MANAGEMENT_BASE_URL: $IO_MANAGEMENT_BASE_URL + IO_CONSUMER_ID: $IO_CONSUMER_ID + IO_PROJECT_ID: $IO_PROJECT_ID + IO_WORKSPACE_ID: $IO_WORKSPACE_ID + AIO_runtime_namespace: $AIO_RUNTIME_NAMESPACE + annotations: + require-adobe-auth: false + final: true diff --git a/starter-kit/customize-ingestion-webhook/actions/ingestion/webhook/event-mapping.json b/starter-kit/customize-ingestion-webhook/actions/ingestion/webhook/event-mapping.json new file mode 100644 index 0000000..3aba38c --- /dev/null +++ b/starter-kit/customize-ingestion-webhook/actions/ingestion/webhook/event-mapping.json @@ -0,0 +1,3 @@ +{ + "external_provider.customer_created.v1.0": "be-observer.customer_create" +} diff --git a/starter-kit/customize-ingestion-webhook/actions/ingestion/webhook/index.js b/starter-kit/customize-ingestion-webhook/actions/ingestion/webhook/index.js new file mode 100644 index 0000000..a6b3105 --- /dev/null +++ b/starter-kit/customize-ingestion-webhook/actions/ingestion/webhook/index.js @@ -0,0 +1,107 @@ +/* +Copyright 2022 Adobe. All rights reserved. +This file is licensed to you under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. You may obtain a copy +of the License at http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under +the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS +OF ANY KIND, either express or implied. See the License for the specific language +governing permissions and limitations under the License. +*/ + +const { Core, Events } = require('@adobe/aio-sdk') +const { stringParameters } = require('../../../actions/utils') +const { CloudEvent } = require('cloudevents') +const uuid = require('uuid') +const { + HTTP_BAD_REQUEST, HTTP_OK, HTTP_INTERNAL_ERROR, HTTP_UNAUTHORIZED, + BACKOFFICE_PROVIDER_KEY, PUBLISH_EVENT_SUCCESS +} = require('../../../actions/constants') +const { getAdobeAccessToken } = require('../../../utils/adobe-auth') +const { getProviderByKey } = require('../../../utils/adobe-events-api') +const { validateData } = require('./validator') +const { checkAuthentication } = require('./auth') +const { errorResponse, successResponse } = require('../../responses') +const eventMappings = require('./event-mapping.json') +const { transformData } = require("./payload-transform"); + +/** + * This web action allow external back-office application publish event to IO event using custom authentication mechanism. + * + * @param {object} params - method params includes environment and request data + * @returns {object} - response with success status and result + */ +async function main (params) { + const logger = Core.Logger('ingestion-webhook', { level: params.LOG_LEVEL || 'info' }) + try { + logger.info('Start processing request') + logger.debug(`Webhook main params: ${stringParameters(params)}`) + + const authentication = await checkAuthentication(params) + if (!authentication.success) { + logger.error(`Authentication failed with error: ${authentication.message}`) + return errorResponse(HTTP_UNAUTHORIZED, authentication.message) + } + + // map event name + const mappedEventType = eventMappings[params.data?.event] + + // trim the event payload + const transformedEventData = transformData(params) + + const validationResult = validateData(params) + if (!validationResult.success) { + logger.error(`Validation failed with error: ${validationResult.message}`) + return errorResponse(HTTP_BAD_REQUEST, validationResult.message) + } + + logger.debug('Generate Adobe access token') + const accessToken = await getAdobeAccessToken(params) + + logger.debug('Get existing registrations') + const provider = await getProviderByKey(params, accessToken, BACKOFFICE_PROVIDER_KEY) + + if (!provider) { + const errorMessage = 'Could not find any external backoffice provider' + logger.error(`${errorMessage}`) + return errorResponse(HTTP_INTERNAL_ERROR, errorMessage) + } + + logger.debug('Initiate events client') + const eventsClient = await Events.init( + params.OAUTH_ORG_ID, + params.OAUTH_CLIENT_ID, + accessToken) + + const eventType = mappedEventType ? mappedEventType: params.data.event + logger.info(`Process event data ${eventType}`) + const cloudEvent = new CloudEvent({ + source: 'urn:uuid:' + provider.id, + type: eventType, + datacontenttype: 'application/json', + data: transformedEventData, + id: uuid.v4() + }) + + logger.debug(`Publish event ${eventType} to provider ${provider.label}`) + const publishEventResult = await eventsClient.publishEvent(cloudEvent) + logger.debug(`Publish event result: ${publishEventResult}`) + if (publishEventResult !== PUBLISH_EVENT_SUCCESS) { + logger.error(`Unable to publish event ${eventType}: Unknown event type`) + return errorResponse(HTTP_BAD_REQUEST, `Unable to publish event ${eventType}: Unknown event type`) + } + + logger.info(`Successful request: ${HTTP_OK}`) + + return successResponse(eventType, { + success: true, + message: 'Event published successfully' + }) + } catch (error) { + logger.error(`Server error: ${error.message}`) + return errorResponse(HTTP_INTERNAL_ERROR, error.message) + } +} + +exports.main = main diff --git a/starter-kit/customize-ingestion-webhook/actions/ingestion/webhook/payload-transform.js b/starter-kit/customize-ingestion-webhook/actions/ingestion/webhook/payload-transform.js new file mode 100644 index 0000000..1b4c66d --- /dev/null +++ b/starter-kit/customize-ingestion-webhook/actions/ingestion/webhook/payload-transform.js @@ -0,0 +1,34 @@ +/* +Copyright 2022 Adobe. All rights reserved. +This file is licensed to you under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. You may obtain a copy +of the License at http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under +the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS +OF ANY KIND, either express or implied. See the License for the specific language +governing permissions and limitations under the License. +*/ + +/** + * This function transform the received customer data from external back-office application to Adobe commerce + * + * @param {object} params - Data received from Adobe commerce + * @returns {object} - Returns transformed data object + */ +function transformData (params) { + switch (params.data.event) { + case 'external_provider.customer_created.v1.0': + return { + PersonFirstName: params.data.value.PersonFirstName, + PersonLastName: params.data.value.PersonLastName, + PrimaryContactEmail: params.data.value.PrimaryContactEmail, + } + default: + return params.data + } +} + +module.exports = { + transformData +} diff --git a/starter-kit/customize-registrations-and-events/README.md b/starter-kit/customize-registrations-and-events/README.md new file mode 100644 index 0000000..da03aff --- /dev/null +++ b/starter-kit/customize-registrations-and-events/README.md @@ -0,0 +1,30 @@ +# Customize Registrations and Events + +This sample code shows how to customize the registrations and events predefined in the Adobe Commerce integration starter kit, to match the requirements of the integration you are building. + +## Usage + +The customizations implemented in the sample code include: +- Registering only to the events relevant to the integration you are building. For example, the following `scripts/onboarding/config/starter-kit-registrations.json` indicate that your integration is only concerned about + ```json + { + "product": ["commerce"], + "customer": ["commerce", "backoffice"], + "order": ["commerce"], + "stock": [] + } + ``` + - `product` and `order` events originating from Commerce + - `customer` events originating from both systems + - no `stock` events +- Subscribing Commerce to propagate to App Builder only the events of interest to your integration. + +[Complete the configuration](https://developer.adobe.com/commerce/extensibility/starter-kit/create-integration/#complete-the-configuration) provides additional information about setting up your integration. + +After installation, configuration and deployment +- Only the runtime actions relevant to the integration you are building will be deployed, and +- Only the event registrations relevant to the integration you are building will be active. + +## More information + +To learn more about Adobe Commerce integration starter kit visit the [Developer docs](https://developer.adobe.com/commerce/extensibility/starter-kit/). diff --git a/starter-kit/customize-registrations-and-events/app.config.yaml b/starter-kit/customize-registrations-and-events/app.config.yaml new file mode 100644 index 0000000..f029416 --- /dev/null +++ b/starter-kit/customize-registrations-and-events/app.config.yaml @@ -0,0 +1,61 @@ +application: +# hooks: +# post-app-deploy: ./hooks/post-app-deploy.js + runtimeManifest: + packages: + starter-kit: + license: Apache-2.0 + actions: + # Please DO NOT DELETE this action; future functionalities planned for upcoming starter kit releases may stop working. + info: + function: actions/starter-kit-info/index.js + web: 'yes' + runtime: nodejs:20 + inputs: + LOG_LEVEL: debug + annotations: + require-adobe-auth: true + final: true + # ingestion: + # license: Apache-2.0 + # actions: + # $include: ./actions/ingestion/actions.config.yaml + webhook: + license: Apache-2.0 + actions: + $include: ./actions/webhook/actions.config.yaml + 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 + order-commerce: + license: Apache-2.0 + actions: + $include: ./actions/order/commerce/actions.config.yaml +# order-backoffice: +# license: Apache-2.0 +# actions: +# $include: ./actions/order/external/actions.config.yaml +# stock-commerce: +# license: Apache-2.0 +# actions: +# $include: ./actions/stock/commerce/actions.config.yaml +# stock-backoffice: +# license: Apache-2.0 +# actions: +# $include: ./actions/stock/external/actions.config.yaml +productDependencies: + - code: COMMC + minVersion: 2.4.4 diff --git a/starter-kit/customize-registrations-and-events/scripts/commerce-event-subscribe/config/commerce-event-subscribe.json b/starter-kit/customize-registrations-and-events/scripts/commerce-event-subscribe/config/commerce-event-subscribe.json new file mode 100644 index 0000000..7441162 --- /dev/null +++ b/starter-kit/customize-registrations-and-events/scripts/commerce-event-subscribe/config/commerce-event-subscribe.json @@ -0,0 +1,138 @@ +[ + { + "event": { + "name": "observer.catalog_product_delete_commit_after", + "fields": [ + { + "name": "id" + }, + { + "name": "sku" + }, + { + "name": "name" + }, + { + "name": "created_at" + }, + { + "name": "updated_at" + }, + { + "name": "description" + } + ] + } + }, + { + "event": { + "name": "observer.catalog_product_save_commit_after", + "fields": [ + { + "name": "id" + }, + { + "name": "sku'" + }, + { + "name": "name" + }, + { + "name": "price" + }, + { + "name": "created_at" + }, + { + "name": "updated_at" + }, + { + "name": "description" + } + ] + } + }, + { + "event": { + "name": "observer.customer_save_commit_after", + "fields": [ + { + "name": "id" + }, + { + "name": "email" + }, + { + "name": "firstname" + }, + { + "name": "lastname" + }, + { + "name": "created_at" + }, + { + "name": "updated_at" + } + ] + } + }, + { + "event": { + "name": "observer.customer_delete_commit_after", + "fields": [ + { + "name": "id" + }, + { + "name": "email" + }, + { + "name": "firstname" + }, + { + "name": "lastname" + } + ] + } + }, + { + "event": { + "name": "observer.customer_group_save_commit_after", + "fields": [ + { + "name": "*" + } + ] + } + }, + { + "event": { + "name": "observer.customer_group_delete_commit_after", + "fields": [ + { + "name": "*" + } + ] + } + }, + { + "event": { + "name": "observer.sales_order_save_commit_after", + "fields": [ + { + "name": "id" + }, + { + "name": "increment_id" + }, + { + "name": "created_at" + }, + { + "name": "updated_at" + } + ] + } + } +] diff --git a/starter-kit/customize-registrations-and-events/scripts/onboarding/config/events.json b/starter-kit/customize-registrations-and-events/scripts/onboarding/config/events.json new file mode 100644 index 0000000..c73b65a --- /dev/null +++ b/starter-kit/customize-registrations-and-events/scripts/onboarding/config/events.json @@ -0,0 +1,29 @@ +{ + "product": { + "commerce": [ + "com.adobe.commerce.observer.catalog_product_delete_commit_after", + "com.adobe.commerce.observer.catalog_product_save_commit_after" + ] + }, + "customer": { + "commerce": [ + "com.adobe.commerce.observer.customer_save_commit_after", + "com.adobe.commerce.observer.customer_delete_commit_after", + "com.adobe.commerce.observer.customer_group_save_commit_after", + "com.adobe.commerce.observer.customer_group_delete_commit_after" + ], + "backoffice": [ + "be-observer.customer_create", + "be-observer.customer_update", + "be-observer.customer_delete", + "be-observer.customer_group_create", + "be-observer.customer_group_update", + "be-observer.customer_group_delete" + ] + }, + "order": { + "commerce": [ + "com.adobe.commerce.observer.sales_order_save_commit_after" + ] + } +} diff --git a/starter-kit/customize-registrations-and-events/scripts/onboarding/config/starter-kit-registrations.json b/starter-kit/customize-registrations-and-events/scripts/onboarding/config/starter-kit-registrations.json new file mode 100644 index 0000000..8736c2f --- /dev/null +++ b/starter-kit/customize-registrations-and-events/scripts/onboarding/config/starter-kit-registrations.json @@ -0,0 +1,6 @@ +{ + "product": ["commerce"], + "customer": ["commerce", "backoffice"], + "order": ["commerce"], + "stock": [] +}