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));
        }
Esempio n. 3
0
        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);
        }
Esempio n. 4
0
        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);
        }
Esempio n. 6
0
        //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)) });
Esempio n. 12
0
        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);
        }
Esempio n. 13
0
        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);
        }
Esempio n. 14
0
        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);
        }
Esempio n. 15
0
        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);
        }