Sitecore Commerce - Web project notification regarding order completion
on17. August 2020.in categorySitecore
When order is completed in the engine project we wanted it to be followed by some business logic in a web project. Order undergoes status like pending, released, problem, completed, the intention was to catch it when order is completed and payment settled in the engine project and to alert the web project as the result. Order is completed after Release Minion is finished and after the block MoveReleasedOrderBlock, when order changes status from released to completed. So we created new plugin on engine project and added our custom block NotifyOrderCompletedBlock after that one:
public class ConfigureSitecore : IConfigureSitecore
{
public void ConfigureServices(IServiceCollection services)
{
var assembly = Assembly.GetExecutingAssembly();
services.RegisterAllPipelineBlocks(assembly);
services.Sitecore().Pipelines(config => config
.ConfigurePipeline<IReleasedOrdersMinionPipeline>(c => c.Add<Pipelines.Blocks.NotifyOrderCompletedBlock>().After<MoveReleasedOrderBlock>())
);
services.RegisterAllCommands(assembly);
}
}
NotifyOrderCompletedBlock is a simple http request to a web project where we are sending order as a json object. We used IHttpClientFactory.
Next step is implementing observer pattern in the web project. When changes happen to a class that we are tracking(subject), it alerts all other classes which are subscribed to it and business logic happens in subscribers. Interface and the class we are tracking:
public interface INotifyOrderCompletedObservable : IObservable<EntryClass>
{
void Changed(EntryClass entryClass);
}
public class NotifyOrderCompletedObservable : INotifyOrderCompletedObservable
{
List<IObserver<EntryClass>> observers = new List<IObserver<EntryClass>>();
public IDisposable Subscribe(IObserver<EntryClass> observer)
{
observers.Add(observer);
return new Unsubscriber(observers, observer);
}
public void Changed(EntryClass entryClass)
{
//create some object, that can be send onNext, classOnNext
foreach (var item in observers)
{
item.OnNext(classOnNext);
}
}
private class Unsubscriber : IDisposable
{
private List<IObserver<EntryClass>> _observers;
private IObserver<EntryClass> _observer;
public Unsubscriber(List<IObserver<EntryClass>> observers, IObserver<EntryClass> observer)
{
this._observers = observers;
this._observer = observer;
}
public void Dispose()
{
if (_observer != null && _observers.Contains(_observer))
_observers.Remove(_observer);
}
}
}
Subscriber class:
public class OrderCompletedObserver : IObserver<EntryClass>
{
public void OnError(Exception error)
{
//dont need this, but must be implemented
throw new NotImplementedException();
}
public void OnCompleted() { }
public void OnNext(ClassOnNext)
{
//business logic goes here
}
}
We also need to register container for dependency injection:
public class RegisterContainer : IServicesConfigurator
{
public void Configure(IServiceCollection serviceCollection
{
serviceCollection.AddSingleton<INotifyOrderCompletedObservable,NotifyOrderCompletedObservable>();
}
}
Endpoint for web project is:
public ActionResult NotifyOrderCompleted([FromBody] EntryClass entryClass){
_subject.Changed(entryClass);
}
We wanted to subscribe class when application starts. In Foundation/Commerce/code/Pipelines we added CommerceInitializeProcessor.cs file:
public class CommerceInitializeProcessor
{
private INotifyOrderCompletedObservable _subject;
public CommerceInitializeProcessor(INotifyOrderCompletedObservable subject)
{
_subject = subject;
}
public void Process(PipelineArgs args)
{
var observer = new OrderCompletedObserver();
_subject.Subscribe(observer);
}
}
And in Foundation\Commerce\code\App_config\Include\Foundation\Commerce\ we added z.Foundation.Commerce.CommerceInitializeProcessor.config:
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
<sitecore>
<pipelines>
<initialize>
<processor type="NameOfTheProject.Foundation.Commerce.Pipelines.CommerceInitializeProcessor, NameOfTheProject.Foundation.Commerce" resolve="true"/>
</initialize>
</pipelines>
</sitecore>
</configuration>