Connector Class

The connector class is the main class of a connector for an e-commerce system.

The connector class performs the following functions:
  • Provides the settings for connection with the external system
  • Implements navigation to external records
  • Performs the synchronization of records of the external system and MYOB Acumatica
  • Implements real-time subscription and processing

Base Class and Interface

The connector class implements the PX.Commerce.Core.IConnector interface and derives from the PX.Commerce.Core.BCConnectorBase<TConnector> base abstract class. The BCConnectorBase<TConnector> class is a graph. Therefore, the connector class is a graph as well.

Properties and Methods of the Connector Class

In the ConnectorType property of the connector class, you define a string identifier of the connector type; this identifier can be no more than three characters long. In the ConnectorName property of this class, you define the name of the connector, which is displayed on MYOB Acumatica forms. For example, the value is displayed in the Connector box on the Entities (BC202000) form.

For details about the methods of the connector class, see PX.Commerce.Core.IConnector.

Example

The following code shows an example of the connector class implementation.

Tip: You can see this code on GitHub.
using Newtonsoft.Json;
using System;
using PX.Commerce.BigCommerce.API.REST;
using PX.Commerce.Core.REST;
using PX.Commerce.Core;
using CommonServiceLocator;
using PX.Data.BQL;
using System.Collections.Generic;
using PX.Common;
using System.Linq;
using PX.Data;
using System.Threading.Tasks;
using System.Threading;

namespace WooCommerceTest
{
    public class WooCommerceConnector: BCConnectorBase<WooCommerceConnector>, 
        IConnector
    {
        public const string TYPE = "WOO";
        public const string NAME = "WooCommerce";

        public class WCConnectorType : BqlString.Constant<WCConnectorType>
        {
            public WCConnectorType() : base(TYPE) { }
        }

        public override string ConnectorType { get => TYPE; }
        public override string ConnectorName { get => NAME; }

        public void NavigateExtern(ISyncStatus status, ISyncDetail detail = null)
        {
            if (status?.ExternID == null) return;

            EntityInfo info = GetEntities().FirstOrDefault(e => e.EntityType == 
                status.EntityType);
            BCBindingWooCommerce bCBindingBigCommerce = 
                BCBindingWooCommerce.PK.Find(this, status.BindingID);

            if (string.IsNullOrEmpty(bCBindingBigCommerce?.StoreAdminUrl) || 
                string.IsNullOrEmpty(info.URL)) return;

            string[] parts = status.ExternID.Split(new char[] { ';' });
            string url = string.Format(info.URL, parts.Length > 2 ? 
                parts.Take(2).ToArray() : parts);
            string redirectUrl = bCBindingBigCommerce.StoreAdminUrl.TrimEnd('/') + 
                "/" + url;

            throw new PXRedirectToUrlException(redirectUrl, 
                PXBaseRedirectException.WindowMode.New, string.Empty);
        }

        //Create an instance of the processor graph that corresponds to the entity 
        //and run its Process method.
        public virtual async Task<ConnectorOperationResult> Process(
            ConnectorOperation operation, int?[] syncIDs = null, 
            CancellationToken cancellationToken = default)
        {
            LogInfo(operation.LogScope(), BCMessages.LogConnectorStarted, NAME);

            EntityInfo info = GetEntities().FirstOrDefault(e => 
                e.EntityType == operation.EntityType);
            using (IProcessor graph = (IProcessor)CreateInstance(info.ProcessorType))
            {
                graph.Initialise(this, operation);
                return await graph.Process(syncIDs, cancellationToken);
            }
        }

        public DateTime GetSyncTime(ConnectorOperation operation)
        {
            BCBindingWooCommerce binding = BCBindingWooCommerce.PK.Find(this, 
                operation.Binding);
            //Acumatica Time
            PXDatabase.SelectDate(out DateTime dtLocal, out DateTime dtUtc);
            dtLocal = PX.Common.PXTimeZoneInfo.ConvertTimeFromUtc(dtUtc, 
                PX.Common.LocaleInfo.GetTimeZone());


            return dtLocal;
        }

        public override void StartWebHook(string baseUrl, BCWebHook hook)
        {
            throw new NotImplementedException();
        }

        public virtual async Task ProcessHook(IEnumerable<BCExternQueueMessage> messages,
            CancellationToken cancellationToken = default)
        {
            throw new NotImplementedException();
        }

        public override void StopWebHook(string baseUrl, BCWebHook hook)
        {
            throw new NotImplementedException();
        }

        public static WooRestClient GetRestClient(BCBindingWooCommerce binding)
        {
            return GetRestClient(binding.StoreBaseUrl, binding.StoreXAuthClient, 
            binding.StoreXAuthToken);
        }

        public static WooRestClient GetRestClient(String url, String clientID, 
            String token)
        {
            RestOptions options = new RestOptions
            {
                BaseUri = url,
                XAuthClient = clientID,
                XAuthTocken = token
            };
            JsonSerializer serializer = new JsonSerializer
            {
                MissingMemberHandling = MissingMemberHandling.Ignore,
                NullValueHandling = NullValueHandling.Ignore,
                DefaultValueHandling = DefaultValueHandling.Include,
                DateFormatHandling = DateFormatHandling.IsoDateFormat,
                DateTimeZoneHandling = DateTimeZoneHandling.Unspecified,
                ContractResolver = new GetOnlyContractResolver()
            };
            RestJsonSerializer restSerializer = new RestJsonSerializer(serializer);
            WooRestClient client = new WooRestClient(restSerializer, restSerializer, 
                options,
                ServiceLocator.Current.GetInstance<Serilog.ILogger>());

            return client;
        }

        public List<Tuple<string, string, string>> GetExternalFields(
            string type, int? binding, string entity)
        {
            List<Tuple<string, string, string>> fieldsList = 
                new List<Tuple<string, string, string>>();
            if (entity != BCEntitiesAttribute.Customer && 
                entity != BCEntitiesAttribute.Address) return fieldsList;

            return fieldsList;
        }
    }
}