public async Task <bool> ShopperHasPurchasedProduct(string shopperId, string productId) { bool hasPurchased = false; try { VtexOrderList vtexOrderList = await _productReviewRepository.ListOrders($"q={shopperId}"); var orderIds = vtexOrderList.List.Select(o => o.OrderId); foreach (string orderId in orderIds) { VtexOrder vtexOrder = await _productReviewRepository.GetOrderInformation(orderId); var productIds = vtexOrder.Items.Select(i => i.ProductId); hasPurchased = productIds.Contains(productId); if (hasPurchased) { break; } } } catch (Exception ex) { _context.Vtex.Logger.Error("ShopperHasPurchasedProduct", null, "Request Error", ex); } return(hasPurchased); }
public async Task <IActionResult> BuildEvent(string orderId, string eventType) { Console.WriteLine($"[Build Event]"); VtexOrder vtexOrder = await _orderFeedAPI.GetOrderInformation(orderId); bool success = await _treasureDataAPI.BuildAndSendEvent(vtexOrder, eventType); return(Json(success)); }
public async Task <VtexOrder> GetOrderInformation(string orderId) { //Console.WriteLine("------- Headers -------"); //foreach (var header in this._httpContextAccessor.HttpContext.Request.Headers) //{ // Console.WriteLine($"{header.Key}: {header.Value}"); //} //Console.WriteLine($"http://{this._httpContextAccessor.HttpContext.Request.Headers[Constants.VTEX_ACCOUNT_HEADER_NAME]}.{Constants.ENVIRONMENT}.com.br/api/checkout/pvt/orders/{orderId}"); VtexOrder vtexOrder = null; try { var request = new HttpRequestMessage { Method = HttpMethod.Get, RequestUri = new Uri($"http://{this._httpContextAccessor.HttpContext.Request.Headers[Constants.VTEX_ACCOUNT_HEADER_NAME]}.{Constants.ENVIRONMENT}.com.br/api/checkout/pvt/orders/{orderId}") }; //request.Headers.Add(Constants.ACCEPT, Constants.APPLICATION_JSON); //request.Headers.Add(Constants.CONTENT_TYPE, Constants.APPLICATION_JSON); string authToken = this._httpContextAccessor.HttpContext.Request.Headers[Constants.HEADER_VTEX_CREDENTIAL]; //Console.WriteLine($"Token = '{authToken}'"); if (authToken != null) { request.Headers.Add(Constants.AUTHORIZATION_HEADER_NAME, authToken); request.Headers.Add(Constants.VTEX_ID_HEADER_NAME, authToken); request.Headers.Add(Constants.PROXY_AUTHORIZATION_HEADER_NAME, authToken); } //StringBuilder sb = new StringBuilder(); var client = _clientFactory.CreateClient(); var response = await client.SendAsync(request); string responseContent = await response.Content.ReadAsStringAsync(); if (response.IsSuccessStatusCode) { vtexOrder = JsonConvert.DeserializeObject <VtexOrder>(responseContent); Console.WriteLine($"GetOrderInformation: [{response.StatusCode}] "); } else { Console.WriteLine($"GetOrderInformation: [{response.StatusCode}] '{responseContent}'"); _context.Vtex.Logger.Info("GetOrderInformation", null, $"Order# {orderId} [{response.StatusCode}] '{responseContent}'"); } } catch (Exception ex) { Console.WriteLine($"GetOrderInformation Error: {ex.Message}"); _context.Vtex.Logger.Error("GetOrderInformation", null, $"Order# {orderId} Error", ex); } return(vtexOrder); }
public async Task <IActionResult> BuildEvent(string orderId, string eventType) { Console.WriteLine($"[Build Event]"); DateTimeOffset dateTimeOffset = new DateTimeOffset(DateTime.Now); VtexOrder vtexOrder = await _orderFeedAPI.GetOrderInformation(orderId); KlaviyoEvent klaviyoEvent = await _klaviyoAPI.BuildEvent(vtexOrder, eventType, dateTimeOffset); return(Json(klaviyoEvent)); }
public async Task <bool> ProcessNotification(HookNotification hookNotification) { bool success = false; switch (hookNotification.Domain) { case StorePickUpConstants.Domain.Fulfillment: switch (hookNotification.State) { case StorePickUpConstants.Status.ReadyForHandling: VtexOrder vtexOrder = await this.GetOrderInformation(hookNotification.OrderId); if (vtexOrder != null && vtexOrder.ShippingData != null && vtexOrder.ShippingData.LogisticsInfo != null) { List <LogisticsInfo> pickUpItems = vtexOrder.ShippingData.LogisticsInfo.Where(i => i.Slas.Any(s => s.PickupStoreInfo.IsPickupStore)).ToList(); if (pickUpItems != null && pickUpItems.Count > 0) { Console.WriteLine($"{pickUpItems.Count} Items for pickup."); success = await this.SendEmail(StorePickUpConstants.MailTemplateType.ReadyForPacking, vtexOrder); if (success) { success = await this.AddOrderComment(StorePickUpConstants.OrderCommentText.ReadyForPacking, vtexOrder.OrderId); } } else { Console.WriteLine("No items for pickup."); success = true; } } break; default: Console.WriteLine($"State {hookNotification.State} not implemeted."); _context.Vtex.Logger.Info("ProcessNotification", null, $"State {hookNotification.State} not implemeted."); break; } break; case StorePickUpConstants.Domain.Marketplace: break; default: Console.WriteLine($"Domain {hookNotification.Domain} not implemeted."); _context.Vtex.Logger.Info("ProcessNotification", null, $"Domain {hookNotification.Domain} not implemeted."); break; } return(success); }
//public async Task<bool> ProcessNotification(AllStatesNotification allStatesNotification) //{ // bool success = true; // // Use our server - side Track API for the following: // // Placed Order - When an order successfully processes on your system // // Ordered Product - An event for each item in a processed order // // Fulfilled Order - When an order is sent to the customer // // Cancelled Order - When a customer cancels their order // // Refunded Order - When a customer’s order is refunded // string orderId = allStatesNotification.OrderId; // TreasureDataEvent treasureDataEvent; // VtexOrder vtexOrder = await _orderFeedAPI.GetOrderInformation(orderId); // switch (allStatesNotification.Domain) // { // case Constants.Domain.Fulfillment: // switch (allStatesNotification.CurrentState) // { // case Constants.Status.ReadyForHandling: // treasureDataEvent = await BuildEvent(vtexOrder, Constants.Events.PlacedOrder); // if (treasureDataEvent != null) // { // success = await SendEvent(treasureDataEvent); // // Send each item as a separate event // foreach (Item item in vtexOrder.Items) // { // VtexOrder order = vtexOrder; // order.Items = new List<Item> { item }; // treasureDataEvent = await BuildEvent(vtexOrder, Constants.Events.OrderedProduct); // success = success && await SendEvent(treasureDataEvent); // } // } // break; // case Constants.Status.Invoiced: // treasureDataEvent = await BuildEvent(vtexOrder, Constants.Events.FulfilledOrder); // if (treasureDataEvent != null) // { // success = await SendEvent(treasureDataEvent); // } // break; // //case Constants.Status.Canceled: // // break; // default: // Console.WriteLine($"State {allStatesNotification.CurrentState} not implemeted."); // _context.Vtex.Logger.Info("ProcessNotification", null, $"State {allStatesNotification.CurrentState} not implemeted."); // break; // } // break; // case Constants.Domain.Marketplace: // break; // default: // Console.WriteLine($"Domain {allStatesNotification.Domain} not implemeted."); // _context.Vtex.Logger.Info("ProcessNotification", null, $"Domain {allStatesNotification.Domain} not implemeted."); // break; // } // return success; //} public async Task <bool> ProcessNotification(AllStatesNotification allStatesNotification) { bool success = true; // Use our server - side Track API for the following: // Placed Order - When an order successfully processes on your system // Ordered Product - An event for each item in a processed order // Fulfilled Order - When an order is sent to the customer // Cancelled Order - When a customer cancels their order // Refunded Order - When a customer’s order is refunded string orderId = allStatesNotification.OrderId; VtexOrder vtexOrder = await _orderFeedAPI.GetOrderInformation(orderId); switch (allStatesNotification.Domain) { case Constants.Domain.Fulfillment: switch (allStatesNotification.CurrentState) { case Constants.Status.ReadyForHandling: success = await this.BuildAndSendEvent(vtexOrder, Constants.Events.PlacedOrder); break; case Constants.Status.Invoiced: success = await this.BuildAndSendEvent(vtexOrder, Constants.Events.FulfilledOrder); break; case Constants.Status.Canceled: success = await this.BuildAndSendEvent(vtexOrder, Constants.Events.CanceledOrder); break; default: Console.WriteLine($"State {allStatesNotification.CurrentState} not implemeted."); _context.Vtex.Logger.Info("ProcessNotification", null, $"State {allStatesNotification.CurrentState} not implemeted."); break; } break; case Constants.Domain.Marketplace: break; default: Console.WriteLine($"Domain {allStatesNotification.Domain} not implemeted."); _context.Vtex.Logger.Info("ProcessNotification", null, $"Domain {allStatesNotification.Domain} not implemeted."); break; } return(success); }
public async Task <VtexOrder> GetOrderInformation(string orderId) { VtexOrder vtexOrder = null; try { var request = new HttpRequestMessage { Method = HttpMethod.Get, RequestUri = new Uri($"http://{this._httpContextAccessor.HttpContext.Request.Headers[StorePickUpConstants.VTEX_ACCOUNT_HEADER_NAME]}.{StorePickUpConstants.ENVIRONMENT}.com.br/api/checkout/pvt/orders/{orderId}") }; request.Headers.Add(StorePickUpConstants.USE_HTTPS_HEADER_NAME, "true"); string authToken = this._httpContextAccessor.HttpContext.Request.Headers[StorePickUpConstants.HEADER_VTEX_CREDENTIAL]; if (authToken != null) { request.Headers.Add(StorePickUpConstants.AUTHORIZATION_HEADER_NAME, authToken); request.Headers.Add(StorePickUpConstants.VTEX_ID_HEADER_NAME, authToken); request.Headers.Add(StorePickUpConstants.PROXY_AUTHORIZATION_HEADER_NAME, authToken); } var client = _clientFactory.CreateClient(); var response = await client.SendAsync(request); string responseContent = await response.Content.ReadAsStringAsync(); if (response.IsSuccessStatusCode) { vtexOrder = JsonConvert.DeserializeObject <VtexOrder>(responseContent); Console.WriteLine($"GetOrderInformation: [{response.StatusCode}] "); } else { Console.WriteLine($"GetOrderInformation: [{response.StatusCode}] '{responseContent}'"); _context.Vtex.Logger.Info("GetOrderInformation", null, $"Order# {orderId} [{response.StatusCode}] '{responseContent}'"); } } catch (Exception ex) { Console.WriteLine($"GetOrderInformation Error: {ex.Message}"); _context.Vtex.Logger.Error("GetOrderInformation", null, $"Order# {orderId} Error", ex); } return(vtexOrder); }
public async Task <VtexOrder> GetOrderInformation(string orderId) { VtexOrder vtexOrder = null; try { var request = new HttpRequestMessage { Method = HttpMethod.Get, RequestUri = new Uri($"http://{this._httpContextAccessor.HttpContext.Request.Headers[VTEX_ACCOUNT_HEADER_NAME]}.{ENVIRONMENT}.com.br/api/oms/pvt/orders/{orderId}") }; request.Headers.Add(USE_HTTPS_HEADER_NAME, "true"); string authToken = this._httpContextAccessor.HttpContext.Request.Headers[HEADER_VTEX_CREDENTIAL]; if (authToken != null) { request.Headers.Add(AUTHORIZATION_HEADER_NAME, authToken); request.Headers.Add(VTEX_ID_HEADER_NAME, authToken); request.Headers.Add(PROXY_AUTHORIZATION_HEADER_NAME, authToken); } var client = _clientFactory.CreateClient(); var response = await client.SendAsync(request); string responseContent = await response.Content.ReadAsStringAsync(); //_context.Vtex.Logger.Info("GetOrderInformation", null, $"[{response.StatusCode}] {responseContent}"); if (response.IsSuccessStatusCode) { vtexOrder = JsonConvert.DeserializeObject <VtexOrder>(responseContent); } } catch (Exception ex) { _context.Vtex.Logger.Error("GetOrderInformation", null, "Request Error", ex); } return(vtexOrder); }
public async Task <string> ProcessLink(string action, string id) { string baseUrl = this._httpContextAccessor.HttpContext.Request.Headers[StorePickUpConstants.FORWARDED_HOST]; string returnUrl = $"https://{baseUrl}/{StorePickUpConstants.AppName}/"; try { string argsText = _cryptoService.DecryptString(action, id, _context.Vtex.Account); string[] args = argsText.Split('|'); string email = args[0]; string orderId = _cryptoService.DecryptString(email, args[1], _context.Vtex.Account); Console.WriteLine($"{email} {orderId}"); _context.Vtex.Logger.Info("ProcessLink", null, $"{action} {email} {orderId}"); VtexOrder order = await this.GetOrderInformation(orderId); bool mailSent = false; switch (action) { case StorePickUpConstants.MailTemplates.ReadyForPacking: await this.AddOrderComment(StorePickUpConstants.OrderCommentText.ReadyForPacking, orderId); await this.SendEmail(StorePickUpConstants.MailTemplateType.ReadyForPacking, order); break; case StorePickUpConstants.MailTemplates.PackageReady: await this.AddOrderComment(StorePickUpConstants.OrderCommentText.PackageReady, orderId); await this.SendEmail(StorePickUpConstants.MailTemplateType.PackageReady, order); returnUrl = $"{returnUrl}{StorePickUpConstants.RedirectPage.Notified}"; break; case StorePickUpConstants.MailTemplates.AtLocation: await this.AddOrderComment(StorePickUpConstants.OrderCommentText.AtLocation, orderId); await this.SendEmail(StorePickUpConstants.MailTemplateType.AtLocation, order); returnUrl = $"{returnUrl}{StorePickUpConstants.RedirectPage.ThankYou}"; break; case StorePickUpConstants.MailTemplates.PickedUp: await this.AddOrderComment(StorePickUpConstants.OrderCommentText.PickedUp, orderId); returnUrl = $"{returnUrl}{StorePickUpConstants.RedirectPage.Handover}"; break; default: Console.WriteLine($"ProcessLink {action} not implemented."); _context.Vtex.Logger.Info("ProcessLink", null, $"Link action '{action}' not implemented."); break; } } catch (Exception ex) { Console.WriteLine($"ProcessLink Error {ex.Message}"); returnUrl = $"https://{baseUrl}/{StorePickUpConstants.AppName}/{StorePickUpConstants.RedirectPage.Error}"; } Console.WriteLine($"returnUrl [{returnUrl}]"); return(returnUrl); }
public async Task <bool> SendEmail(StorePickUpConstants.MailTemplateType templateType, VtexOrder order) { bool success = false; MerchantSettings merchantSettings = await _storePickupRepository.GetMerchantSettings(); if (string.IsNullOrEmpty(merchantSettings.AppKey) || string.IsNullOrEmpty(merchantSettings.AppToken)) { Console.WriteLine("App Settings missing."); } string responseText = string.Empty; string templateName = string.Empty; string subjectText = string.Empty; string toEmail = string.Empty; string nextAction = string.Empty; string shopperEmail = order.ClientProfileData.Email; List <LogisticsInfo> pickUpItems = order.ShippingData.LogisticsInfo.Where(i => i.Slas.Any(s => s.PickupStoreInfo.IsPickupStore)).ToList(); string storeEmail = string.Empty; // TODO: Divide notifications by store location. Send separate email to each. foreach (LogisticsInfo logisticsInfo in pickUpItems) { string selectedSla = logisticsInfo.SelectedSla; Sla sla = logisticsInfo.Slas.Where(s => s.Id.Equals(selectedSla)).FirstOrDefault(); storeEmail = sla.PickupStoreInfo.Address.Complement; if (!string.IsNullOrEmpty(storeEmail)) { break; } } Console.WriteLine($"Store Email = {storeEmail}"); switch (templateType) { case StorePickUpConstants.MailTemplateType.AtLocation: templateName = StorePickUpConstants.MailTemplates.AtLocation; subjectText = StorePickUpConstants.TemplateSubject.AtLocation; toEmail = storeEmail; nextAction = StorePickUpConstants.MailTemplates.PickedUp; break; case StorePickUpConstants.MailTemplateType.PackageReady: templateName = StorePickUpConstants.MailTemplates.PackageReady; subjectText = StorePickUpConstants.TemplateSubject.PackageReady; toEmail = shopperEmail; nextAction = StorePickUpConstants.MailTemplates.AtLocation; break; case StorePickUpConstants.MailTemplateType.ReadyForPacking: templateName = StorePickUpConstants.MailTemplates.ReadyForPacking; subjectText = StorePickUpConstants.TemplateSubject.ReadyForPacking; toEmail = storeEmail; nextAction = StorePickUpConstants.MailTemplates.PackageReady; break; case StorePickUpConstants.MailTemplateType.PickedUp: templateName = StorePickUpConstants.MailTemplates.PickedUp; subjectText = StorePickUpConstants.TemplateSubject.PickedUp; toEmail = shopperEmail; break; } //templateName = "test1"; string encryptedOrderId = _cryptoService.EncryptString(order.ClientProfileData.Email, order.OrderId, _context.Vtex.Account); string queryText = $"{order.ClientProfileData.Email}|{encryptedOrderId}"; string queryArgs = Uri.EscapeDataString(_cryptoService.EncryptString(nextAction, queryText, _context.Vtex.Account)); string cancelOrderQueryArgs = Uri.EscapeDataString(_cryptoService.EncryptString(StorePickUpConstants.MailTemplates.CancelOrder, queryText, _context.Vtex.Account)); // https://sandboxusdev.myvtex.com/_v/pickup/notification/package-ready/{{queryArgs}} string actionLink = $"https://{_context.Vtex.Host}/_v/curbside-pickup/notification/{nextAction}/{queryArgs}"; string cancelLink = $"https://{_context.Vtex.Host}/_v/curbside-pickup/notification/{StorePickUpConstants.MailTemplates.CancelOrder}/{cancelOrderQueryArgs}"; EmailMessage emailMessage = new EmailMessage { templateName = templateName, providerName = StorePickUpConstants.Acquirer, jsonData = new JsonData { order = order, curbsidePickup = new CurbsidePickup { actionLink = actionLink, cancelLink = cancelLink, encryptedOrderId = encryptedOrderId, toEmail = toEmail, queryArgs = queryArgs } } }; string accountName = _httpContextAccessor.HttpContext.Request.Headers[StorePickUpConstants.VTEX_ACCOUNT_HEADER_NAME].ToString(); string message = JsonConvert.SerializeObject(emailMessage); var request = new HttpRequestMessage { Method = HttpMethod.Post, RequestUri = new Uri($"{StorePickUpConstants.MailService}?an={accountName}"), Content = new StringContent(message, Encoding.UTF8, StorePickUpConstants.APPLICATION_JSON) }; request.Headers.Add(StorePickUpConstants.USE_HTTPS_HEADER_NAME, "true"); string authToken = this._httpContextAccessor.HttpContext.Request.Headers[StorePickUpConstants.HEADER_VTEX_CREDENTIAL]; if (authToken != null) { request.Headers.Add(StorePickUpConstants.AUTHORIZATION_HEADER_NAME, authToken); request.Headers.Add(StorePickUpConstants.PROXY_AUTHORIZATION_HEADER_NAME, authToken); } request.Headers.Add(StorePickUpConstants.AppKey, merchantSettings.AppKey); request.Headers.Add(StorePickUpConstants.AppToken, merchantSettings.AppToken); HttpClient client = _clientFactory.CreateClient(); try { HttpResponseMessage responseMessage = await client.SendAsync(request); string responseContent = await responseMessage.Content.ReadAsStringAsync(); responseText = $"[-] SendEmail [{responseMessage.StatusCode}] {responseContent}"; _context.Vtex.Logger.Info("SendEmail", null, $"{toEmail} [{responseMessage.StatusCode}] {responseContent}"); success = responseMessage.IsSuccessStatusCode; if (responseMessage.StatusCode.Equals(HttpStatusCode.NotFound)) { _context.Vtex.Logger.Error("SendEmail", null, $"Template {templateName} not found."); } } catch (Exception ex) { responseText = $"[-] SendEmail Failure [{ex.Message}]"; _context.Vtex.Logger.Error("SendEmail", null, "Failure", ex); success = false; //jic } Console.WriteLine(responseText); return(success); }
public async Task <bool> SendEmail(StorePickUpConstants.MailTemplateType templateType, VtexOrder order) { bool success = false; MerchantSettings merchantSettings = await _storePickupRepository.GetMerchantSettings(); if (string.IsNullOrEmpty(merchantSettings.AppKey) || string.IsNullOrEmpty(merchantSettings.AppToken)) { _context.Vtex.Logger.Error("SendEmail", null, "App Settings Missing."); return(success); } string templateName = string.Empty; string subjectText = string.Empty; string toEmail = string.Empty; string nextAction = string.Empty; string shopperEmail = order.ClientProfileData.Email; List <LogisticsInfo> pickUpItems = order.ShippingData.LogisticsInfo.Where(i => i.Slas.Any(s => s.PickupStoreInfo.IsPickupStore)).ToList(); string storeEmail = string.Empty; if (pickUpItems != null && pickUpItems.Count > 0) { try { // TODO: Divide notifications by store location. Send separate email to each. foreach (LogisticsInfo logisticsInfo in pickUpItems) { string selectedSla = logisticsInfo.SelectedSla; Sla sla = logisticsInfo.Slas.FirstOrDefault(s => s.Id.Equals(selectedSla)); if (sla.PickupStoreInfo.Address != null && !string.IsNullOrEmpty(sla.PickupStoreInfo.Address.Complement)) { storeEmail = sla.PickupStoreInfo.Address.Complement; } } } catch (Exception ex) { _context.Vtex.Logger.Error("SendEmail", null, $"Pickup Store Info Missing. Order Id {order.OrderId}", ex); return(success); } } else { _context.Vtex.Logger.Error("SendEmail", null, $"Pickup Store Info Missing. Order Id {order.OrderId}"); return(success); } // Store email fallback if (string.IsNullOrWhiteSpace(storeEmail)) { try { foreach (LogisticsInfo logisticsInfo in pickUpItems) { string selectedSla = logisticsInfo.SelectedSla; Sla sla = logisticsInfo.Slas.FirstOrDefault(s => s.Id.Equals(selectedSla)); if (sla.PickupStoreInfo.Address != null && !string.IsNullOrEmpty(sla.PickupStoreInfo.AdditionalInfo)) { string emailToVerify = sla.PickupStoreInfo.AdditionalInfo.Trim(); if (this.IsValidEmail(emailToVerify)) { storeEmail = emailToVerify; _context.Vtex.Logger.Info("SendEmail", null, "Using email from AdditionalInfo."); } } } } catch (Exception ex) { _context.Vtex.Logger.Warn("SendEmail", null, $"Pickup Store Info Missing. Order Id {order.OrderId}"); return(success); } } switch (templateType) { case StorePickUpConstants.MailTemplateType.AtLocation: templateName = StorePickUpConstants.MailTemplates.AtLocation; subjectText = StorePickUpConstants.TemplateSubject.AtLocation; toEmail = storeEmail; nextAction = StorePickUpConstants.MailTemplates.PickedUp; break; case StorePickUpConstants.MailTemplateType.PackageReady: templateName = StorePickUpConstants.MailTemplates.PackageReady; subjectText = StorePickUpConstants.TemplateSubject.PackageReady; toEmail = shopperEmail; nextAction = StorePickUpConstants.MailTemplates.AtLocation; break; case StorePickUpConstants.MailTemplateType.ReadyForPacking: templateName = StorePickUpConstants.MailTemplates.ReadyForPacking; subjectText = StorePickUpConstants.TemplateSubject.ReadyForPacking; toEmail = storeEmail; nextAction = StorePickUpConstants.MailTemplates.PackageReady; break; case StorePickUpConstants.MailTemplateType.PickedUp: templateName = StorePickUpConstants.MailTemplates.PickedUp; subjectText = StorePickUpConstants.TemplateSubject.PickedUp; toEmail = shopperEmail; break; } if (string.IsNullOrWhiteSpace(toEmail)) { // log the missing email address, but allow the mail to send in the event that the to address is in the template _context.Vtex.Logger.Error("SendEmail", null, "'To' email address missing.", null, new[] { ("templateType", templateType.ToString()), ("order", JsonConvert.SerializeObject(order)) });
public async Task <bool> BuildAndSendEvent(VtexOrder vtexOrder, string eventType) { bool sent = true; if (vtexOrder != null) { MerchantSettings merchantSettings = await _orderFeedAPI.GetMerchantSettings(); TreasureDataHeader treasureDataHeader = new TreasureDataHeader { // td_format=pixel // &td_write_key=XXXYYYZZZZ // &td_global_id=td_global_id // &td_ip=td_ip // &td_ua=td_ua Format = "pixel", GlobalId = "td_global_id", IpAddress = "td_ip", UserAgent = "ua" }; TreasureDataEvent treasureDataEvent = new TreasureDataEvent { OrderId = vtexOrder.OrderId, Country = vtexOrder.ShippingData.Address.Country, EventType = eventType, Value = ToDollar(vtexOrder.Value) }; TreasureDataEventPrefix treasureDataEventPrefix = new TreasureDataEventPrefix { Address1 = vtexOrder.ShippingData.Address.Street, Address2 = vtexOrder.ShippingData.Address.Complement, City = vtexOrder.ShippingData.Address.City, Email = vtexOrder.ClientProfileData.Email, FirstName = vtexOrder.ClientProfileData.FirstName, LastName = vtexOrder.ClientProfileData.LastName, PhoneNumber = vtexOrder.ClientProfileData.Phone, Zip = vtexOrder.ShippingData.Address.PostalCode, ConsentKey = null // TODO: ready consent status from orderform }; Dictionary <string, string> tdRecordBase = new Dictionary <string, string>(); Dictionary <string, string> tdHeader = ToDictionary(treasureDataHeader); Dictionary <string, string> tdEvent = ToDictionary(treasureDataEvent); Dictionary <string, string> tdEventPrefix = AddPrefix(ToDictionary(treasureDataEventPrefix), merchantSettings.FieldPrefix); tdRecordBase = AddToDictionary(tdRecordBase, tdHeader); tdRecordBase = AddToDictionary(tdRecordBase, tdEvent); tdRecordBase = AddToDictionary(tdRecordBase, tdEventPrefix); if (merchantSettings.CustomFields != null) { Dictionary <string, string> customFields = new Dictionary <string, string>(); foreach (CustomField setting in merchantSettings.CustomFields) { customFields.Add(setting.ColumnName, setting.ColumnValue); } tdRecordBase = AddToDictionary(tdRecordBase, customFields); } foreach (Item item in vtexOrder.Items) { TreasureDataItem treasureDataItem = new TreasureDataItem { ItemProductname = item.Name, ItemQuantity = item.Quantity, ItemSku = item.SellerSku, TtemProductid = item.ProductId }; Dictionary <string, string> tdItem = ToDictionary(treasureDataItem); Dictionary <string, string> treasureDataEventRecord = AddToDictionary(tdRecordBase, tdItem); sent &= await this.SendEvent(treasureDataEventRecord); } } else { Console.WriteLine($"Could not load order {vtexOrder.OrderId}"); _context.Vtex.Logger.Info("BuildEvent", null, $"Could not load order {vtexOrder.OrderId}"); } return(sent); }
public async Task <bool> ProcessNotification(HookNotification hookNotification) { bool success = false; // Use our server - side Track API for the following: // Placed Order - When an order successfully processes on your system // Ordered Product - An event for each item in a processed order // Fulfilled Order - When an order is sent to the customer // Cancelled Order - When a customer cancels their order // Refunded Order - When a customer’s order is refunded string orderId = hookNotification.OrderId; DateTimeOffset lastChange = hookNotification.LastChange; KlaviyoEvent klaviyoEvent; VtexOrder vtexOrder = await _orderFeedAPI.GetOrderInformation(orderId); switch (hookNotification.Domain) { case Constants.Domain.Fulfillment: switch (hookNotification.State) { case Constants.Status.ReadyForHandling: klaviyoEvent = await BuildEvent(vtexOrder, Constants.Events.PlacedOrder, lastChange); if (klaviyoEvent != null) { success = await SendEvent(klaviyoEvent); // Send each item as a separate event foreach (Item item in vtexOrder.Items) { VtexOrder order = vtexOrder; order.Items = new List <Item> { item }; klaviyoEvent = await BuildEvent(vtexOrder, Constants.Events.OrderedProduct, lastChange); success = success && await SendEvent(klaviyoEvent); } } break; case Constants.Status.Invoiced: klaviyoEvent = await BuildEvent(vtexOrder, Constants.Events.FulfilledOrder, lastChange); if (klaviyoEvent != null) { success = await SendEvent(klaviyoEvent); } break; //case Constants.Status.Canceled: // break; default: Console.WriteLine($"State {hookNotification.State} not implemeted."); _context.Vtex.Logger.Info("ProcessNotification", null, $"State {hookNotification.State} not implemeted."); break; } break; case Constants.Domain.Marketplace: break; default: Console.WriteLine($"Domain {hookNotification.Domain} not implemeted."); _context.Vtex.Logger.Info("ProcessNotification", null, $"Domain {hookNotification.Domain} not implemeted."); break; } return(success); }
public async Task <KlaviyoEvent> BuildEvent(VtexOrder vtexOrder, string eventType, DateTimeOffset lastChange) { KlaviyoEvent klaviyoEvent = null; if (vtexOrder != null) { MerchantSettings merchantSettings = await _orderFeedAPI.GetMerchantSettings(); klaviyoEvent = new KlaviyoEvent { CustomerProperties = new CustomerProperties { Address1 = vtexOrder.ShippingData.Address.Street, Address2 = vtexOrder.ShippingData.Address.Number, City = vtexOrder.ShippingData.Address.City, Country = vtexOrder.ShippingData.Address.Country, Email = vtexOrder.ClientProfileData.Email, FirstName = vtexOrder.ClientProfileData.FirstName, //vtexOrder.ShippingData.Address.FirstName, LastName = vtexOrder.ClientProfileData.LastName, //vtexOrder.ShippingData.Address.LastName, PhoneNumber = vtexOrder.ClientProfileData.Phone, //vtexOrder.ShippingData.Address.Phone, Region = vtexOrder.ShippingData.Address.State, Zip = vtexOrder.ShippingData.Address.PostalCode }, Event = eventType, Properties = new Properties { Brands = vtexOrder.Items.Select(i => i.AdditionalInfo.BrandName).ToList(), Categories = vtexOrder.Items.Select(i => i.AdditionalInfo.CategoriesIds.Replace(@"\", string.Empty)).ToList(), DiscountCode = string.Join(',', vtexOrder.RatesAndBenefitsData.RateAndBenefitsIdentifiers.Select(r => r.Name).ToList()), DiscountValue = vtexOrder.Totals.Where(t => t.Name == "Discounts").Select(d => d.Value).FirstOrDefault(), EventId = vtexOrder.OrderId, ItemNames = vtexOrder.Items.Select(i => i.Name).ToList(), Items = new List <KlaviyoItem>(), Value = ToDollar(vtexOrder.Totals.Sum(t => t.Value)) }, //Time = lastChange.UtcTicks, Token = merchantSettings.AppId }; foreach (Item item in vtexOrder.Items) { KlaviyoItem klaviyoItem = new KlaviyoItem { BillingAddress = new Address { Address1 = vtexOrder.ShippingData.Address.Street, Address2 = vtexOrder.ShippingData.Address.Number, City = vtexOrder.ShippingData.Address.City, Country = vtexOrder.ShippingData.Address.Country, FirstName = vtexOrder.ClientProfileData.FirstName, //vtexOrder.ShippingData.Address.FirstName, LastName = vtexOrder.ClientProfileData.LastName, //vtexOrder.ShippingData.Address.LastName, Region = vtexOrder.ShippingData.Address.State, Zip = vtexOrder.ShippingData.Address.PostalCode, Company = null, CountryCode = vtexOrder.ShippingData.Address.Country, Phone = vtexOrder.ClientProfileData.Phone, RegionCode = vtexOrder.ShippingData.Address.State }, Brand = item.AdditionalInfo.BrandName, Categories = new Dictionary <string, string>(), ImageUrl = item.ImageUrl.AbsoluteUri, ItemPrice = ToDollar(item.Price), ProductId = item.ProductId, ProductName = item.Name, ProductUrl = $"{merchantSettings.ProductRootUrl}{item.DetailUrl}", Quantity = item.Quantity, RowTotal = ToDollar(item.Price * item.Quantity), ShippingAddress = new Address { Address1 = vtexOrder.ShippingData.Address.Street, Address2 = vtexOrder.ShippingData.Address.Number, City = vtexOrder.ShippingData.Address.City, Country = vtexOrder.ShippingData.Address.Country, FirstName = vtexOrder.ClientProfileData.FirstName, //vtexOrder.ShippingData.Address.FirstName, LastName = vtexOrder.ClientProfileData.LastName, //vtexOrder.ShippingData.Address.LastName, Region = vtexOrder.ShippingData.Address.State, Zip = vtexOrder.ShippingData.Address.PostalCode, Company = null, CountryCode = vtexOrder.ShippingData.Address.Country, Phone = vtexOrder.ClientProfileData.Phone, RegionCode = vtexOrder.ShippingData.Address.State }, Sku = item.SellerSku }; klaviyoItem.Categories.Add("001", item.AdditionalInfo.CategoriesIds.ToString().Replace(@"\", string.Empty)); klaviyoItem.Categories.Add("002", item.AdditionalInfo.CategoriesIds.ToString().Replace(@"\", string.Empty)); klaviyoEvent.Properties.Items.Add(klaviyoItem); } _context.Vtex.Logger.Info("BuildEvent", null, JsonConvert.SerializeObject(klaviyoEvent)); } else { Console.WriteLine($"Could not load order {vtexOrder.OrderId}"); _context.Vtex.Logger.Info("BuildEvent", null, $"Could not load order {vtexOrder.OrderId}"); } return(klaviyoEvent); }
public async Task <KlaviyoEvent> BuildEvent(VtexOrder vtexOrder, string eventType, DateTimeOffset lastChange) { KlaviyoEvent klaviyoEvent = null; if (vtexOrder != null) { MerchantSettings merchantSettings = await _orderFeedAPI.GetMerchantSettings(); if (eventType.Equals(Constants.Events.PlacedOrder) || eventType.Equals(Constants.Events.Canceled) || eventType.Equals(Constants.Events.FulfilledOrder)) { List <string> categoryNames = new List <string>(); List <string> rawCategoryIds = vtexOrder.Items.Select(i => i.AdditionalInfo.CategoriesIds).ToList(); List <string> categoryIds = new List <string>(); foreach (string rawCategoryId in rawCategoryIds) { Console.WriteLine($" --- rawCategoryId = {rawCategoryId}"); List <string> parsedIds = rawCategoryId.Split('/').ToList(); categoryIds.AddRange(parsedIds); } foreach (string categoryId in categoryIds) { Console.WriteLine($" --- categoryId = {categoryId}"); if (!string.IsNullOrEmpty(categoryId)) { CategoryResponse categoryResponse = await _orderFeedAPI.GetCategoryById(categoryId); if (categoryResponse != null) { categoryNames.Add(categoryResponse.Name); } } } klaviyoEvent = new KlaviyoEvent { CustomerProperties = new CustomerProperties { //Address1 = vtexOrder.ShippingData.Address.Street, //Address2 = vtexOrder.ShippingData.Address.Number, //City = vtexOrder.ShippingData.Address.City, //Country = vtexOrder.ShippingData.Address.Country, Email = vtexOrder.ClientProfileData.Email, FirstName = vtexOrder.ClientProfileData.FirstName, //vtexOrder.ShippingData.Address.FirstName, LastName = vtexOrder.ClientProfileData.LastName, //vtexOrder.ShippingData.Address.LastName, PhoneNumber = vtexOrder.ClientProfileData.Phone, //vtexOrder.ShippingData.Address.Phone, //Region = vtexOrder.ShippingData.Address.State, //Zip = vtexOrder.ShippingData.Address.PostalCode }, Event = eventType, Properties = new Properties { Brands = vtexOrder.Items.Select(i => i.AdditionalInfo.BrandName).ToList(), Categories = categoryNames, DiscountCode = string.Join(',', vtexOrder.RatesAndBenefitsData.RateAndBenefitsIdentifiers.Select(r => r.Name).ToList()), DiscountValue = vtexOrder.Totals.Where(t => t.Name == "Discounts").Select(d => d.Value).FirstOrDefault(), EventId = vtexOrder.OrderId, ItemNames = vtexOrder.Items.Select(i => i.Name).ToList(), Items = new List <KlaviyoItem>(), Value = ToDollar(vtexOrder.Totals.Sum(t => t.Value)), BillingAddress = new Address { //Address1 = vtexOrder.ShippingData.Address.Street, //Address2 = vtexOrder.ShippingData.Address.Number, //City = vtexOrder.ShippingData.Address.City, //Country = vtexOrder.ShippingData.Address.Country, FirstName = vtexOrder.ClientProfileData.FirstName, //vtexOrder.ShippingData.Address.FirstName, LastName = vtexOrder.ClientProfileData.LastName, //vtexOrder.ShippingData.Address.LastName, //Region = vtexOrder.ShippingData.Address.State, //Zip = vtexOrder.ShippingData.Address.PostalCode, Company = null, //CountryCode = vtexOrder.ShippingData.Address.Country, Phone = vtexOrder.ClientProfileData.Phone, //RegionCode = vtexOrder.ShippingData.Address.State }, ShippingAddress = new Address { Address1 = vtexOrder.ShippingData.Address.Street, Address2 = vtexOrder.ShippingData.Address.Number, City = vtexOrder.ShippingData.Address.City, Country = vtexOrder.ShippingData.Address.Country, //FirstName = vtexOrder.ClientProfileData.FirstName, //vtexOrder.ShippingData.Address.FirstName, //LastName = vtexOrder.ClientProfileData.LastName, //vtexOrder.ShippingData.Address.LastName, Region = vtexOrder.ShippingData.Address.State, Zip = vtexOrder.ShippingData.Address.PostalCode, Company = null, CountryCode = vtexOrder.ShippingData.Address.Country, Phone = vtexOrder.ClientProfileData.Phone, RegionCode = vtexOrder.ShippingData.Address.State } }, //Time = lastChange.UtcTicks, Token = merchantSettings.AppId }; foreach (Item item in vtexOrder.Items) { KlaviyoItem klaviyoItem = new KlaviyoItem { Brand = item.AdditionalInfo.BrandName, Categories = new List <string>(), ImageUrl = item.ImageUrl.AbsoluteUri, ItemPrice = ToDollar(item.Price), ProductId = item.ProductId, ProductName = item.Name, ProductUrl = $"{merchantSettings.ProductRootUrl}{item.DetailUrl}", Quantity = item.Quantity, RowTotal = ToDollar(item.Price * item.Quantity), Sku = item.SellerSku }; List <string> itemCategoryIds = item.AdditionalInfo.CategoriesIds.Split('/').ToList(); foreach (string itemCategoryId in itemCategoryIds) { if (!string.IsNullOrEmpty(itemCategoryId)) { CategoryResponse categoryResponse = await _orderFeedAPI.GetCategoryById(itemCategoryId); if (categoryResponse != null && !string.IsNullOrEmpty(categoryResponse.Name)) { klaviyoItem.Categories.Add(categoryResponse.Name); } } } klaviyoEvent.Properties.Items.Add(klaviyoItem); } if (eventType.Equals(Constants.Events.Canceled)) { klaviyoEvent.Properties.Reason = vtexOrder.CancelReason; } } else if (eventType.Equals(Constants.Events.OrderedProduct)) { klaviyoEvent = new KlaviyoEvent { Token = merchantSettings.AppId, Event = eventType, CustomerProperties = new CustomerProperties { Email = vtexOrder.ClientProfileData.Email, FirstName = vtexOrder.ClientProfileData.FirstName, LastName = vtexOrder.ClientProfileData.LastName }, Properties = new Properties { EventId = vtexOrder.OrderId, Value = ToDollar(vtexOrder.Items[0].Price), //ToDollar(vtexOrder.Items[0].Price * vtexOrder.Items[0].Quantity), OrderId = vtexOrder.OrderId, ProductId = vtexOrder.Items[0].ProductId, Sku = vtexOrder.Items[0].SellerSku, ProductName = vtexOrder.Items[0].Name, Quantity = vtexOrder.Items[0].Quantity, ProductUrl = $"{merchantSettings.ProductRootUrl}{vtexOrder.Items[0].DetailUrl}", ImageUrl = vtexOrder.Items[0].ImageUrl.AbsoluteUri, Categories = new List <string>(), ProductBrand = vtexOrder.Items[0].AdditionalInfo.BrandName }, //Time = }; List <string> itemCategoryIds = vtexOrder.Items[0].AdditionalInfo.CategoriesIds.Split('/').ToList(); foreach (string itemCategoryId in itemCategoryIds) { if (!string.IsNullOrEmpty(itemCategoryId)) { CategoryResponse categoryResponse = await _orderFeedAPI.GetCategoryById(itemCategoryId); if (categoryResponse != null && !string.IsNullOrEmpty(categoryResponse.Name)) { klaviyoEvent.Properties.Categories.Add(categoryResponse.Name); } } } } _context.Vtex.Logger.Debug("BuildEvent", eventType, JsonConvert.SerializeObject(klaviyoEvent)); } else { Console.WriteLine($"Could not load order {vtexOrder.OrderId}"); _context.Vtex.Logger.Warn("BuildEvent", null, $"Could not load order {vtexOrder.OrderId}"); } return(klaviyoEvent); }