Last active
May 27, 2021 10:59
-
-
Save davidknipe/51003f9084c85d82dc08f75be2b4a41f to your computer and use it in GitHub Desktop.
Starter code to send order confirmation events to Optimizely Data Platform
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
using System; | |
using System.Collections.Generic; | |
using System.Net.Http; | |
using System.Text; | |
using System.Web; | |
using EPiServer.Commerce.Order; | |
using EPiServer.Framework; | |
using EPiServer.Framework.Initialization; | |
using EPiServer.ServiceLocation; | |
// Note all in a single gist for convienience | |
namespace Foundation.Features.OdpOrderConfirmation | |
{ | |
[InitializableModule] | |
[ModuleDependency(typeof(EPiServer.Web.InitializationModule))] | |
public class OdpOrderConfirmationTrackingInit : IInitializableModule | |
{ | |
private static readonly HttpClient httpClient = new HttpClient(); | |
private static OdpConfigOptions _configOptions; | |
public void Initialize(InitializationEngine context) | |
{ | |
_configOptions = context.Locate.Advanced.GetInstance<OdpConfigOptions>(); | |
var orderEvents = context.Locate.Advanced.GetInstance<IOrderEvents>(); | |
orderEvents.SavingOrder += OrderEvents_SavingOrder; | |
orderEvents.SavedOrder += OrderEvents_SavedOrder; | |
} | |
private void OrderEvents_SavingOrder(object sender, OrderEventArgs e) | |
{ | |
var orderType = e.OrderLink.OrderType.Name; | |
HttpContext.Current.Items["orderType"] = orderType; | |
} | |
private void OrderEvents_SavedOrder(object sender, OrderEventArgs e) | |
{ | |
var orderType = e.OrderLink.OrderType.Name; | |
// The order group has become PO so assume we are transitioning from basket to PO | |
if (HttpContext.Current != null && | |
HttpContext.Current.Items["orderType"].ToString() != orderType && | |
orderType == "PurchaseOrder") | |
{ | |
PostOrderConfirm(e.OrderGroup); | |
} | |
} | |
public void Uninitialize(InitializationEngine context) | |
{ | |
var orderEvents = context.Locate.Advanced.GetInstance<IOrderEvents>(); | |
orderEvents.SavingOrder -= OrderEvents_SavingOrder; | |
orderEvents.SavedOrder -= OrderEvents_SavedOrder; | |
} | |
private bool PostOrderConfirm(IOrderGroup orderGroup) | |
{ | |
// Use the id stored in the vuid cookie to identify the visitor | |
var customerId = HttpContext.Current.Request.Cookies["vuid"]?.Value.Split('%')[0].Replace("-", string.Empty); | |
var orderNo = ((Mediachase.Commerce.Orders.PurchaseOrder)orderGroup).TrackingNumber; | |
var orderTotal = orderGroup.GetTotal().ToString("0.00"); | |
var orderSubtotal = orderGroup.GetSubTotal().ToString("0.00"); | |
var orderTax = orderGroup.GetTaxTotal().ToString("0.00"); | |
var orderShipping = orderGroup.GetShippingTotal().ToString("0.00"); | |
var orderDiscount = orderGroup.GetOrderDiscountTotal().ToString("0.00"); | |
var payload = new Payload() | |
{ | |
type = "order", | |
action = "purchase", | |
identifiers = new Identifiers() | |
{ | |
vuid = customerId | |
}, | |
data = new Data() | |
{ | |
order = new Order() | |
{ | |
order_id = orderNo, | |
total = orderTotal, | |
coupon_code = null, | |
discount = orderDiscount, | |
shipping = orderShipping, | |
subtotal = orderSubtotal, | |
tax = orderTax, | |
items = new List<Item>() | |
} | |
} | |
}; | |
foreach (var lineItem in orderGroup.GetAllLineItems()) | |
{ | |
var lineItemProductId = lineItem.Code; | |
var lineItemPrice = lineItem.PlacedPrice.ToString("0.00"); | |
var lineItemQuantity = Convert.ToInt32(lineItem.Quantity); | |
var lineItemDiscount = lineItem.GetEntryDiscount().ToString("0.00"); | |
var lineItemSubtotal = ( | |
(lineItem.PlacedPrice * lineItem.Quantity) - lineItem.GetEntryDiscount()).ToString("0.00"); | |
payload.data.order.items.Add(new Item() | |
{ | |
discount = lineItemDiscount, | |
price = lineItemPrice, | |
product_id = lineItemProductId, | |
quantity = lineItemQuantity, | |
subtotal = lineItemSubtotal | |
} | |
); | |
} | |
string payloadJson = Mediachase.Web.Console.Common.JsonSerializer.Serialize(payload); | |
var content = new StringContent(payloadJson, Encoding.UTF8, "application/json"); | |
content.Headers.ContentType.MediaType = "application/json"; | |
content.Headers.Add("x-api-key", _configOptions.EventsApiKey); | |
var response = httpClient.PostAsync(_configOptions.EventsApiUrl, content).Result; | |
return response.IsSuccessStatusCode; | |
} | |
} | |
/// <summary> | |
/// Optimizely Data Platform config options | |
/// </summary> | |
/// <remarks> | |
/// Using an [Options] class means these values can be set through code or config. To see how to set through | |
/// config see this: https://world.episerver.com/documentation/Release-Notes/ReleaseNote/?releaseNoteId=CMS-15875 | |
/// </remarks> | |
[Options] | |
public class OdpConfigOptions | |
{ | |
public string EventsApiUrl { get; set; } | |
public string EventsApiKey { get; set; } | |
public OdpConfigOptions() | |
{ | |
EventsApiUrl = "https://api.zaius.com/v3/events"; | |
EventsApiKey = "[ODP API KEY LIVES HERE]"; | |
} | |
} | |
public class Data | |
{ | |
public Order order { get; set; } | |
} | |
public class Identifiers | |
{ | |
public string vuid { get; set; } | |
} | |
public class Item | |
{ | |
public string product_id { get; set; } | |
public string price { get; set; } | |
public int quantity { get; set; } | |
public string discount { get; set; } | |
public string subtotal { get; set; } | |
} | |
public class Order | |
{ | |
public string order_id { get; set; } | |
public string total { get; set; } | |
public string discount { get; set; } | |
public string subtotal { get; set; } | |
public string tax { get; set; } | |
public string shipping { get; set; } | |
public string coupon_code { get; set; } | |
public List<Item> items { get; set; } | |
} | |
public class Payload | |
{ | |
public string type { get; set; } | |
public string action { get; set; } | |
public Identifiers identifiers { get; set; } | |
public Data data { get; set; } | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment