Introduction

Below are the steps to develop and publish any standard apps in the platform.

The steps briefly involved are as follows:

Initial Set Up

Set Up for Serverless App

  • Node.js 18
  • Any IDE, for example, Visual Studio Code
  • Access to the cloud account to host the app.

Instructions

  1. Install the Serverless Framework.
  2. Configure your cloud credentials, for example, for AWS as the cloud provider.
  3. Install the necessary dependencies based on the package.json file.

App Development

Prerequisites

  1. Identify the list of extensions enabled for the Tax app integrations. Refer to the list of tax extensions and other extensions on the Equinox platform.
  2. Develop and host an app (HTTPS endpoint function) that accepts webhook extensions with a POST method.

App Functions

Overview

  1. CalculateTaxAPIFunction: This function is invoked at runtime during the user checkout journey in the storefront with the Equinox event payload for calculateTax to retrieve tax from the third-party provider.
  2. ValidateAPIFunction: This validation function is used in App Admin to validate the configuration parameters entered during the app installation flow.
  3. ParameterStoreAPIFunction: This util function is used at the app side to store the app secret created on app creation and used for signature validation.

CalculateTaxAPIFunction

  • Validates the signature of the event using the received signature and the API secret.
  • Validates the merchant details received in the event of a null check.
  • Constructs the payload to call the third-party API, receives the response from the 3rd party, and converts the response to Equinox for calculating the tax extension.

Extension: taxservice/tax/calculatetax

Microservice Extension Webhook Name Description Request & Response Payload
Tax CalculateTax taxservice/tax/calculatetax During the tax calculation for the items in the cart, the tax calculation request body is sent to the registered app, and the response would be the tax-calculated value by the third-party tax providers. Request

JavaDoc: TaxRequest.html

Response

JavaDoc: TaxResponse.html

CalculateTaxAPIFunctionValidate signature

It fetches the app secret stored for the app and uses it to generate the signature for the payload received:

  1. Fetch the App secret for the app ID included in the payload.
  2. Generate the signature using the calculateHMACSHA256 function. It takes the event payload and app secret as parameters.
  3. The verifySignature function validates the signature received in the payload header against the generated signature.
  4. If there is a mismatch, it returns an authentication failure response.

ValidateAPIFunction

  • Validates the signature of the event using the received signature and the API secret.
  • Validates the merchant details received in the event for a null check.
  • Constructs a static payload, calls the third-party API, and sends the success or failure response for the Equinox validator extension.

Event Payload: Validate.txt

Response

Success:

{
  “responseMessage”: “Product Validated Successfully”,
  “status”: 200
}

Error:

{
  “responseCode”: “”,
  “responseMessage”: “”,
  “timeStamp”: “2024-05-08T09:36:52.188Z”,
  “status”: 409
}

ParameterStoreAPIFunction

It receives the API secret key and then writes the secret key to the parameter store.

Webhook configuration in the app template.

{
  “entity”: “app”,
  “url”: “https://eq-pdn-apps.equinox.shop/avalara/payments/v1/updateSecretKey”,
  “webhookType”: “ASYNC”,
  “priority”: “Normal”,
  “events”: [
  “appmarketplaceservices/generateapikeyandsecret/create”
  ]
}

Event Payload

Sample Response

{
  “responseCode”: “SECRET_KEY_UPDATION_SUCCESS”,
  “responseMessage”: “Parameter Value Updated Successfully for Parameter Key – /APP/App-Klarna/uat/HMAC_KEY”,
  “timeStamp”: “2024-05-15T08:17:03.377Z”,
  “status”: 200
}

App Deployment

  • Serverless deploy command based on the staging environment: serverless deploy –stage <stage-name>
  • Validate if the functions deployed are fine.

Publishing App in Equinox App Microservice

  • Refer to the sample app template JSON file Avalara Tax App_CLOUD_V1.json used for the Avalara app.
    {
        "createAppRequest": {
            "appName": "Avalara",
            "appVersion": "1.0.0",
            "appKey": "avalarauat",
            "appShortDescription": "The Avalara app in Equinox connects your business with Avalara AvaTax to calculate SALES tax accurately and dynamically.",
            "appSummary": "The Avalara app in Equinox connects your business with Avalara AvaTax to calculate SALES tax accurately and dynamically.The sales tax also gets calculated based on the appropriate tax codes.",
            "appCategory": "Tax",
            "pricingType": "FREE",
            "appDisplayType": "DESKTOP",
            "visibilityType": "PUBLIC",
            "developerOrg": "EquinoxAppTeam",
            "appGoal": "",
            "tags": [
                "string"
            ],
            "appSupport": {
                "email": "appmsuser@gmail.com",
                "phoneNumber": ""
            },
            "appImages": [
                {
                    "type": "image",
                    "url": "https://d6o25ylad6893.cloudfront.net/smbadminorchestration/1d353bba-e7dd-4e1f-9329-83abefc7fb77/Avalara.png",
                    "remarks": "AppImage"
                }
            ],
            "properties": [
                {
                    "locale": "en_US",
                    "name": "",
                    "value": ""
                }
            ]
        },
        "appConfigurationRequest": {
            "createAppDescription": {
                "appDescriptionList": {
                    "en_US": {
                        "ataGlance": "The Avalara app in Equinox is designed to calculate sales tax rates for all 13,000+ jurisdictions in the United States, providing comprehensive coverage by connecting with Avalara Avatax..",
                        "readMoreDescription": {
                            "section1": "Access state and local tax rates, regularly updated based on the latest laws, exemptions, and jurisdiction boundaries.",
                            "section2": "Verify tax rates based on address, rather than relying on less accurate ZIP code rates.",
                            "section3": "Use advanced rules to more easily apply standardized tax codes to products sold or purchased.",
                            "section4": ""
                        },
                        "characteristics": {
                            "category": "Tax",
                            "goal": "To calculate SALES TAX",
                            "helpCenterUrl": "https://infosys.equinox.com",
                            "developedBy": "Equinox"
                        }
                    }
                }
            },
            "createAppConfig": {
                "apiConfig": [
                    {
                        "action": "baseUrl",
                        "apiUrl": "https://eq-uat-apps-apps.equinox.shop/avalara/tax/v1/"
                    }
                ],
                "appScopes": [
                    {
                        "role": "ROLE_TAX_ADMIN",
                        "services": [
                            "tax"
                        ]
                    }
                ],
                "properties": [
                    {
                        "name": "",
                        "value": ""
                    }
                ],
                "webhooksConfig": [
                    {
                        "url": "https://eq-pdn-apps.equinox.shop/avalara/tax/v1/calculatetax",
                        "webhookType": "SYNC",
                        "priority": "Normal",
                        "events": [
                            "taxservice/tax/calculatetax"
                        ]
                    },
    				{
                        "entity": "app",
                        "url": "https://eq-pdn-apps.equinox.shop/avalara/payments/v1/updateSecretKey",
                        "webhookType": "ASYNC",
                        "priority": "Normal",
                        "events": [
                            "appmarketplaceservices/generateapikeyandsecret/create"
                        ]
                    },
                    {
                        "entity": "app",
                        "url": "https://eq-pdn-apps.equinox.shop/avalara/tax/v1/validate",
                        "webhookType": "SYNC",
                        "priority": "Normal",
                        "events": [
                            "appmarketplaceservices/validator/merchantdetails"
                        ]
                    }
                ]
            },
            "appActivationInputData": {
                "uiSchema": {
                    "title": "Configure AvaTax for your Merchant account",
                    "elements": [
    					{
                            "uiElement": "textbox",
                            "label": "Company Code",
                            "required": "true",
                            "default": "DEFAULT",
                            "minLength": 1,
                            "pattern": "^[^ ]{1,}$",
                            "key": "companyCode"
                        },
                        {
                            "uiElement": "textbox",
                            "label": "Account/Username",
                            "required": "true",
                            "default": "",
                            "minLength": 1,
                            "pattern": "^[^ ]{1,}$",
                            "key": "merchantId"
                        },
                        {
                            "uiElement": "textbox",
                            "label": "Key/Password",
                            "required": "true",
                            "default": "",
                            "minLength": 1,
                            "pattern": "^[^ ]{1,}$",
                            "key": "privateKey"
                        },
                        {
                            "uiElement": "textbox",
                            "label": "Warehouse Address Line1",
                            "required": "true",
                            "default": "",
                            "minLength": 1,
                            "pattern": "",
                            "key": "addressLine1"
                        },
                        {
                            "uiElement": "textbox",
                            "label": "City",
                            "required": "true",
                            "default": "",
                            "minLength": 1,
                            "pattern": "",
                            "key": "city"
                        },
                        {
                            "uiElement": "textbox",
                            "label": "State",
                            "required": "true",
                            "default": "",
                            "minLength": 2,
                            "pattern": "",
                            "key": "state"
                        },
                        {
                            "uiElement": "textbox",
                            "label": "Country",
                            "required": "true",
                            "default": "",
                            "minLength": 2,
                            "pattern": "",
                            "key": "country"
                        },
                        {
                            "uiElement": "textbox",
                            "label": "Postal Code",
                            "required": "true",
                            "default": "",
                            "minLength": 4,
                            "pattern": "",
                            "key": "postalCode"
                        },
    					{
                            "uiElement": "checkbox",
                            "label": "Sandbox Mode",
                            "required": "true",
                            "default": "true",
                            "key": "isSandbox"
                        },
    					{
                            "uiElement": "checkbox",
                            "label": "Enable Tax For Shipping Charge",
                            "required": "false",
                            "default": "false",
                            "key": "enableTaxForShippingCharge"
                        }
                    ]
                }
            }
        }
    }
  • Refer to the link to update the app metadata.
  • Refer to the link to configure the extensions.
  • Refer to the admin guide to register the app in the Infosys Equinox App Marketplace.

Validate App in Test Store

To validate the app in the test store

  1. Once the app is registered or created, navigate to the App Marketplace Admin console from the StoreOps page.
    The app will be available on the Unpublished Apps page.
  2. Install the app to the store.
  3. Validate the app to check all the functionalities.

App Approval Workflow

  • App marketplace has workflow enabled for the apps to be published.
  • Submit the app for approval.
  • App Marketplace admin user can approve or reject an app as a marketplace admin.
  • If the app is approved, the developer can publish the app to Apps Manager.

References

Here is the sample postman collection of the Avalara app: Avalara Enterprise.postman_collection

 

Revision History

2024-05-20 | JP – Page created and content added for release 8.17.4.