Skip to content

About

Sample code for QuoteConnector and ErpConnector

Resources

Stars

1 star

Watchers

4 watching

Forks

Repository files navigation

Connectors

This project is created as a sample for how to set up a QuoteConnector and ERPConnector.

Prerequisites

The solution uses the XML-based solution format (Connectors.slnx), which requires:

  • Visual Studio 2022 version 17.14 or newer (or another IDE with .slnx support)
  • .NET SDK 9.0.200 or newer when building from the command line

The projects themselves still target .NET 8 (net8.0) and .NET Standard 2.0.

Architecture

An overview of the architecture can be seen in Architecture.dsl. To view the diagram, you can use the free tool structurizr, or you can use vscode with the c4-dsl-extension.

ConnectorService

This project is the wrapper which exposes the services for the QuoteConnector and ERPConnector.

Since .net Core does not natively support WCF, this projects makes use of the community-driven project coreWCF to add this support. CoreWCF has been picked up by microsoft and is now part of their support policy, but SuperOffice does not have anything to do with this support directly.

EPPLUS

The service uses the EPPLUS for reading from and writing to excelfiles. This is a licensed product, and since this project is a sample (and not to be used in production), the license is set to be NonCommercial.

For production use, you need to acquire a license from EPPLUS (or make sure you adhere to their licensing terms).

QuoteConnectorWS

Service-endpoint: https://HOSTNAME/Services/QuoteConnectorWS.svc

This is the WCF service that is exposed to SuperOffice. It is a simple wrapper around the QuoteConnector, and is responsible for handling the incoming requests and returning the responses.

Note: The service requires a special snippet to check if the incoming request comes from SuperOffice Online. The snippet can be found in RefactorConnectionConfigFields() in QuoteConnectorWS.cs. This snippet is not mandatory for all connectors, but the implementation for the connector expects the fileName to be in the first position of the connectionConfigFields dictionary. This filename is used to load data from Excel in ReadInData() This workaround is necessary to support both onsite and online versions of SuperOffice.

ERPConnectorWS

Service-endpoint: https://HOSTNAME/Services/ErpConnectorWS.svc

This is the WCF service that is exposed to SuperOffice. It is a simple wrapper around the ErpConnector, and is responsible for handling the incoming requests and returning the responses.

Authentication

When SuperOffice Online calls Authenticate on QuoteConnectorWS or ERPConnectorWS, it sends a signed token. The service:

  1. Validates the token with SuperOfficeJwksTokenValidator, using the public signing keys SuperOffice publishes for each environment (sod, qaonline and online). One deployment can therefore serve all three environments without any certificate configuration. The keys are loaded at startup and refreshed automatically.
  2. Signs the token's nonce with the application's private key (ConnectorService:PrivateKeyFile) and returns it, which proves to SuperOffice that the response comes from your application.

Both services share this logic in IntegrationServiceAuthentication.cs. The service needs outbound HTTPS access to sod.superoffice.com, qaonline.superoffice.com and online.superoffice.com to fetch the keys.

Minimalistic API

The ConnectorService project contains a minimalistic API for handling reading from and writing to the ExcelFiles. It also enables the user to upload a new Excel-file to the service, or download the template-excelfile.

All endpoints configured for this sample can be found in ExcelHandlerEndpoints.cs.

To easily get access to use/test these endpoints the projects uses Swagger. All endpoints require the X-Api-Key header (ConnectorService:ApiKey); use the Authorize button in Swagger to set it.

GET /signing-keys lists the SuperOffice signing keys the service has currently loaded (key ID, certificate subject and validity). Use it after deploying to check that keys for all three environments were loaded.

QuoteConnector

Contains the implementation of the QuoteConnector, using a locally stored Excel file as the data source. This implementation is not intended for production use, but as a sample for how to implement a QuoteConnector.

ERPConnector

Contains the implementation of the ERPConnector, using a locally stored text file as the data source. This implementation is not intended for production use, but as a sample for how to implement an ERPConnector.

Quickstart

To set up a new QuoteConnector the following steps needs to be completed:

  1. Create a quote connector
  2. Register an app (shared by the ERPConnector and QuoteConnector)
  3. Configure the application with service endpoints
  4. Host the application
  5. Create a new Quote Connector in SuperOffice Admin

Note: The ERPConnector and QuoteConnector share one application (ConnectorService:ClientId).

Hosting

SuperOffice does not require the service to be hosted in a specific way, but it needs to be accessible externally. One way to host the service is to use Azure App Services, but any hosting provider that supports .Net Core should work.

Alternatively it can be run directly from Visual Studio by using the launchSettings.json for https: Vs Hosting

Ngrok

For local development you can use ngrok to expose your local service to the internet. This is useful for testing the service with SuperOffice Online.

Through Ngrok.exe you can run this command to create a tunnel for a locally running SSL secure endpoint:

ngrok http https://localhost:7128 --url=YOURDOMAIN.ngrok-free.app

Adjust port 7128 to be the port for the internally running application, and YOURDOMAIN to be what ngrok gives you when setting it up through ngrok.com

Appsettings.json

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*",
  "Application": {
    "EnableHttpsEndpoints": true,
    "Host": "HOSTNAME",
    "ResourcesPath": "Resources"
  },
  "ConnectorService": {
    "ConnectorAssemblies": [
      "ErpConnector.dll"
    ]
  },
  "VaultUri": ""
}

In addition, the service needs these secrets, which are not stored in appsettings.json:

Setting Value
ConnectorService:ClientId The application identifier (client_id) of your app.
ConnectorService:PrivateKeyFile The application's private key as XML (the <RSAKeyValue>...</RSAKeyValue> content itself, not a file path).
ConnectorService:ApiKey The key clients must send in the X-Api-Key header to use the Minimalistic API.

If VaultUri is set, the secrets are read from that Azure Key Vault using DefaultAzureCredential. Key Vault uses -- as the section separator, so the secret names are ConnectorService--ClientId, ConnectorService--PrivateKeyFile and ConnectorService--ApiKey.

If VaultUri is empty, Key Vault is skipped. When running locally you can then set the secrets with user secrets:

dotnet user-secrets set "ConnectorService:ClientId" "<client_id>" --project Source/ConnectorService
dotnet user-secrets set "ConnectorService:PrivateKeyFile" "<RSAKeyValue>...</RSAKeyValue>" --project Source/ConnectorService
dotnet user-secrets set "ConnectorService:ApiKey" "<api-key>" --project Source/ConnectorService

Environment variables work too, for example ConnectorService__ApiKey.

Alternatively, add ClientId, PrivateKeyFile and ApiKey under ConnectorService in appsettings.Development.json. This file is gitignored, and VaultUri must be empty for its values to be used. The private key XML must be on a single line.

If the service is hosted in Azure, the Application.Host should be set to the hostname of the Azure App Service. All of these settings can be found in Azure portal, and settings defined in the portal directly will override the settings defined in appsettings.json. Please refer to Microsoft documentation for how to configure your application.

If you are running this application locally, on localhost, you can set the hostname to be localhost.

The reasoning for setting Application.Host specifically can be seen in this discussion on github. For a project running locally/outside of an App Service this setting can probably be omitted, but it is included in this POC for completeness.

Where are the data used by the Connectors?

The data provided by the connectors are all located in Resources.

  • ERP_Connections.txt - Used by ErpConnector to store information about a connection that has been created.
  • ErpClient.xlsm - Used by the ErpConnector to provide data back to SuperOffice.
  • ExcelConnectorWithCapabilities.xlsx - Used by the ExcelQuoteConnector to provide data back to SuperOffice.

Editing these files will reflect the data seen inside of SuperOffice, and in SuperOffice Admin it is necessary to point to the correct file to get the data. It is also possible to upload your own files, through the Minimalistic API, or download one of the existing 'templates' above and re-upload new versions.

In a real-world scenario, the data would be fetched from an external system, and not stored in the project itself.

Questions and feedback

If you have any questions or feedback, please create an issue in this repository.

About

Sample code for QuoteConnector and ErpConnector

Resources

Stars

1 star

Watchers

4 watching

Forks

Releases

Packages

Contributors

Languages