-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #26 from adobe/rojo-add_order_bidirectional_integr…
…ation_sample Add order bidirectional integration sample used in the Adobe Developer's Integration Starter Kit for Adobe Commerce session
- Loading branch information
Showing
154 changed files
with
34,323 additions
and
0 deletions.
There are no files selected for viewing
161 changes: 161 additions & 0 deletions
161
starter-kit/order-bidirectional-integration-sample-prj/README.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,161 @@ | ||
# Order Bidirectional Integration Sample Project | ||
|
||
Sample code for a starter kit based project that demonstrates how to integrate Adobe Commerce with a mock third-party back-office system. | ||
|
||
The project includes the following features: | ||
- Integration of the order entity between Adobe Commerce and a mock third-party back-office system. | ||
- Integration of an email notification system to send an email when an order is created in Adobe Commerce. | ||
|
||
The code was used in this Adobe Developer's Integration Starter Kit for Adobe Commerce session: | ||
|
||
[![Integration Starter Kit for Adobe Commerce](https://img.youtube.com/vi/PQvdt7DrO7I/0.jpg)](https://www.youtube.com/watch?v=PQvdt7DrO7I) | ||
|
||
The starter kit public documentation can be found at [Adobe Developer Starter Kit docs](https://developer.adobe.com/commerce/extensibility/starter-kit/). | ||
|
||
* [Prerequisites](#prerequisites) | ||
* [Starter Kit first deploy & onboarding](#starter-kit-first-deploy--onboarding) | ||
* [Development](#development) | ||
* [References](#references) | ||
|
||
## Prerequisites | ||
|
||
### Create App Builder project | ||
Go to the [Adobe developer console](https://developer.adobe.com/console) portal | ||
- Click on `Create a new project from template` | ||
- Select `App Builder` | ||
- Chose a name and title | ||
- Select stage workspace or create a new one | ||
- Add the following API services (select default Oauth server to server) | ||
- I/0 events | ||
- Adobe I/O Events for Adobe Commerce | ||
- I/O management API | ||
- Download the [workspace configuration JSON](https://developer.adobe.com/commerce/extensibility/events/project-setup/#download-the-workspace-configuration-file) file and save it as `workspace.json` in the `./scripts/onboarding/config` starter kit folder because you will use it to configure Adobe IO Events in commerce afterward. | ||
|
||
### 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: | ||
- In the Commerce Admin, navigate to System > Extensions > Integrations. | ||
- Click the `Add New Integration` button. | ||
- Give the integration a name. The rest of the fields can be left blank. | ||
- Select API on the left and grant access to all the resources. | ||
- Click Save. | ||
- In the list of integrations, activate your integration. | ||
- To configure the starter kit, you will need the integration details (consumer key, consumer secret, access token, and access token secret). | ||
|
||
### 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](https://developer.adobe.com/commerce/extensibility/events/installation/) | ||
|
||
> **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 | ||
- Download and unzip the project | ||
- Copy the env file `cp env.dist .env` | ||
- Fill in the values following the comments on the env file. | ||
|
||
### Configure the project | ||
Install the npm dependencies using the command: | ||
```bash | ||
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: | ||
```bash | ||
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: | ||
```bash | ||
aio app use | ||
# Choose the option 'm' (merge) | ||
``` | ||
|
||
### Deploy | ||
Run the following command to deploy the project; this will deploy the runtime actions needed for the onboarding step: | ||
```bash | ||
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. | ||
|
||
### Onboarding | ||
|
||
#### 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: | ||
```bash | ||
npm run onboard | ||
``` | ||
|
||
The console will return the provider's IDs and save this information: | ||
- You will need the commerce instance ID and provider ID to configure your commerce instance later. | ||
- You will need the backoffice provider id to send the events to the App builder project. | ||
e.g., of output: | ||
```bash | ||
Process of On-Boarding done successfully: [ | ||
{ | ||
key: 'commerce', | ||
id: 'THIS IS THE ID OF COMMERCE PROVIDER', | ||
instanceId: 'THIS IS THE INSTANCE ID OF COMMERCE PROVIDER', | ||
label: 'Commerce Provider' | ||
}, | ||
{ | ||
key: 'backoffice', | ||
id: 'THIS IS THE ID OF BACKOFFICE PROVIDER', | ||
instanceId: 'THIS IS THE INSTANCE ID OF BACKOFFICE PROVIDER', | ||
label: 'Backoffice Provider' | ||
}, | ||
{ | ||
key: 'email', | ||
id: 'THIS IS THE ID OF EMAIL PROVIDER', | ||
instanceId: 'THIS IS THE INSTANCE ID OF EMAIL PROVIDER', | ||
label: 'Email Provider' | ||
} | ||
] | ||
|
||
``` | ||
Check your App developer console to confirm the creation of the 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 | ||
- 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). |
31 changes: 31 additions & 0 deletions
31
starter-kit/order-bidirectional-integration-sample-prj/actions/constants.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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. | ||
*/ | ||
|
||
const HTTP_OK = 200 | ||
const HTTP_BAD_REQUEST = 400 | ||
const HTTP_UNAUTHORIZED = 401 | ||
const HTTP_NOT_FOUND = 404 | ||
const HTTP_INTERNAL_ERROR = 500 | ||
|
||
const BACKOFFICE_PROVIDER_KEY = 'backoffice' | ||
|
||
const PUBLISH_EVENT_SUCCESS = 'OK' | ||
|
||
module.exports = { | ||
HTTP_OK, | ||
HTTP_BAD_REQUEST, | ||
HTTP_UNAUTHORIZED, | ||
HTTP_NOT_FOUND, | ||
HTTP_INTERNAL_ERROR, | ||
BACKOFFICE_PROVIDER_KEY, | ||
PUBLISH_EVENT_SUCCESS | ||
} |
157 changes: 157 additions & 0 deletions
157
starter-kit/order-bidirectional-integration-sample-prj/actions/oauth1a.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,157 @@ | ||
/* | ||
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 Oauth1a = require('oauth-1.0a') | ||
const crypto = require('crypto') | ||
const got = require('got') | ||
|
||
/** | ||
* This function return the Adobe commerce OAuth client | ||
* | ||
* @returns {object} - The Oauth client | ||
* @param {object} options - include the information to configure oauth | ||
* @param {object} logger - Logger | ||
*/ | ||
function getOauthClient (options, logger) { | ||
const instance = {} | ||
|
||
// Remove trailing slash if any | ||
const serverUrl = options.url | ||
const apiVersion = options.version | ||
const oauth = Oauth1a({ | ||
consumer: { | ||
key: options.consumerKey, | ||
secret: options.consumerSecret | ||
}, | ||
signature_method: 'HMAC-SHA256', | ||
hash_function: hashFunctionSha256 | ||
}) | ||
const token = { | ||
key: options.accessToken, | ||
secret: options.accessTokenSecret | ||
} | ||
|
||
/** | ||
* This function create the sha 256 hash | ||
* | ||
* @returns {string} - returns generated hash | ||
* @param {string} baseString - base string | ||
* @param {string} key - key to encrypt | ||
*/ | ||
function hashFunctionSha256 (baseString, key) { | ||
return crypto.createHmac('sha256', key).update(baseString).digest('base64') | ||
} | ||
|
||
/** | ||
* This function make the call to the api | ||
* | ||
* @returns {object} - returns the call response | ||
* @param {object} requestData - include the request data | ||
* @param {string} requestToken - access token | ||
* @param {object} customHeaders - include custom headers | ||
*/ | ||
async function apiCall (requestData, requestToken = '', customHeaders = {}) { | ||
try { | ||
logger.debug('Fetching URL: ' + requestData.url + ' with method: ' + requestData.method) | ||
|
||
const headers = { | ||
...(requestToken | ||
? { Authorization: 'Bearer ' + requestToken } | ||
: oauth.toHeader(oauth.authorize(requestData, token))), | ||
...customHeaders | ||
} | ||
|
||
return await got(requestData.url, { | ||
http2: true, | ||
method: requestData.method, | ||
headers, | ||
body: requestData.body, | ||
responseType: 'json' | ||
}).json() | ||
} catch (error) { | ||
logger.error(`Error fetching URL ${requestData.url}: ${error}`) | ||
throw error | ||
} | ||
} | ||
|
||
instance.consumerToken = async function (loginData) { | ||
return apiCall({ | ||
url: createUrl('integration/customer/token'), | ||
method: 'POST', | ||
body: loginData | ||
}) | ||
} | ||
|
||
instance.get = async function (resourceUrl, requestToken = '') { | ||
const requestData = { | ||
url: createUrl(resourceUrl), | ||
method: 'GET' | ||
} | ||
return apiCall(requestData, requestToken) | ||
} | ||
|
||
/** | ||
* This function create the full url | ||
* | ||
* @returns {string} - generated url | ||
* @param {string} resourceUrl - Adobe commerce rest API resource url | ||
*/ | ||
function createUrl (resourceUrl) { | ||
return serverUrl + apiVersion + '/' + resourceUrl | ||
} | ||
|
||
instance.post = async function (resourceUrl, data, requestToken = '', customHeaders = {}) { | ||
const requestData = { | ||
url: createUrl(resourceUrl), | ||
method: 'POST', | ||
body: data | ||
} | ||
return apiCall(requestData, requestToken, customHeaders) | ||
} | ||
|
||
instance.put = async function (resourceUrl, data, requestToken = '', customHeaders = {}) { | ||
const requestData = { | ||
url: createUrl(resourceUrl), | ||
method: 'PUT', | ||
body: data | ||
} | ||
return apiCall(requestData, requestToken, customHeaders) | ||
} | ||
|
||
instance.delete = async function (resourceUrl, requestToken = '') { | ||
const requestData = { | ||
url: createUrl(resourceUrl), | ||
method: 'DELETE' | ||
} | ||
return apiCall(requestData, requestToken) | ||
} | ||
|
||
return instance | ||
} | ||
|
||
/** | ||
* This function create the oauth client to use for calling adobe commerce api | ||
* | ||
* @returns {object} - returns the oauth client | ||
* @param {object} options - define the options for the client | ||
* @param {object} logger - define the Logger | ||
*/ | ||
function getCommerceOauthClient (options, logger) { | ||
options.version = 'V1' | ||
options.url = options.url + 'rest/' | ||
return getOauthClient(options, logger) | ||
} | ||
|
||
module.exports = { | ||
getOauthClient, | ||
getCommerceOauthClient | ||
} |
33 changes: 33 additions & 0 deletions
33
starter-kit/order-bidirectional-integration-sample-prj/actions/openwhisk.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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. | ||
*/ | ||
|
||
const openwhisk = require('openwhisk') | ||
|
||
class Openwhisk { | ||
#openwhiskClient | ||
|
||
constructor (host, apiKey) { | ||
this.#openwhiskClient = openwhisk({ apihost: host, api_key: apiKey }) | ||
} | ||
|
||
async invokeAction (action, data) { | ||
return await this.#openwhiskClient.actions.invoke({ | ||
name: action, | ||
blocking: true, | ||
params: { | ||
data | ||
} | ||
}) | ||
} | ||
} | ||
|
||
module.exports = Openwhisk |
Oops, something went wrong.