/// <summary>
        /// Creates a single discount in Shopify
        /// </summary>
        public static void CreateDiscount(AuthInfo authInfo, Discount discount)
        {
            try
            {
                Console.Write("Creating {0}: ", discount.Code);

                string discountsUrl = String.Format(_discountsUrl, authInfo.StoreName,"");
                HttpWebRequest request = HttpWebRequest.Create(discountsUrl) as HttpWebRequest;

                // Set required HTTP headers
                request.Accept = "*/*";
                request.Headers["Accept-Language"] = "en-US";
                request.Headers["Accept-Charset"] = "utf-8";
                request.Headers["X-Requested-With"] = "XMLHttpRequest";
                request.Headers["X-Prototype-Version"] = "1.7";
                request.Headers["Cookie"] = String.Format("_secure_session_id={0}", authInfo.SessionId);
                request.Headers["X-CSRF-Token"] = authInfo.CsrfToken;

                // POST the create discount form
                IDictionary<string, string> postData = new Dictionary<string, string>();
                postData["authenticity_token"] = authInfo.CsrfToken;
                postData["discount[code]"] = discount.Code;
                postData["type"] = discount.Type;
                postData["discount[value]"] = discount.Value;
                postData["discount[applies_to_type]"] = discount.AppliesToType;
                postData["discount[minimum_order_amount]"] = discount.MinimumOrderAmount;
                postData["discount[applies_to_id]"] = discount.AppliesToId;
                postData["discount[starts_at]"] = discount.StartsAt;
                postData["discount[ends_at]"] = discount.EndsAt;
                postData["discount[usage_limit]"] = discount.UsageLimit;
                HttpWebResponse response = request.Post(postData);

                // Read response in.
                string responseText = response.GetResponseText();

                // Check for application level errors
                if (responseText.Contains("Messenger.error(\""))
                {
                    string errorMessage = responseText.GetFirstDelimitedValue("Messenger.error(\"", "\");");
                    throw new Exception(errorMessage);
                }

                // Check for success
                string successNotice = String.Format("Messenger.notice(\"Successfully created the discount {0}\\u0026hellip;\");", discount.Code);
                if (!responseText.Contains(successNotice))
                {
                    throw new Exception("Sanity check failed");
                }

                Console.WriteLine("OK");

            }
            catch (Exception ex)
            {
                Console.WriteLine("ERROR");

                string errorMessage = String.Format("Error Creating Discount ({0})", ( discount == null ? "" : discount.Code) );
                throw new Exception(errorMessage, ex);
            }
        }
Example #2
0
        /// <summary>
        /// Posts the Shopify store login page and populates the authInfo object with the
        /// session and CSRF tokens parsed from the reponse.
        /// </summary>
        public static void Authenticate(AuthInfo authInfo)
        {
            string loginUrl = null;
            try
            {
                loginUrl = String.Format(_loginUrl, authInfo.StoreName);
                HttpWebRequest request = HttpWebRequest.Create(loginUrl) as HttpWebRequest;
                request.CookieContainer = new CookieContainer();

                // POST the login form
                IDictionary<string, string> postData = new Dictionary<string, string>();
                postData["login"] = authInfo.Username;
                postData["password"] = authInfo.Password;
                HttpWebResponse response = request.Post(postData);

                // Get the session cookie
                Cookie sessionIdCookie = request.CookieContainer.GetCookies(new Uri(loginUrl))["_secure_session_id"];
                authInfo.SessionId = sessionIdCookie.Value;

                // Read response in
                HtmlDocument html = response.GetResponseHtml();

                // Do a quick sanity check to make sure that we are logged in.
                // (If there is a logout link, its a safe bet to assume that we are logged in)
                HtmlNode logoutLink = html.DocumentNode.SelectSingleNode("//a[@href=\"/admin/auth/logout\"]");
                if (logoutLink == null)
                {
                    throw new Exception("Login Failed");
                }

                // Pluck out the csrf token.
                HtmlNode hiddenCsrfInput = html.DocumentNode.SelectSingleNode("//meta[@name=\"csrf-token\"]");
                authInfo.CsrfToken = WebUtility.HtmlDecode(hiddenCsrfInput.Attributes["content"].Value);

            }
            catch (Exception ex)
            {
                throw new Exception("Error logging into shopify", ex);
            }
        }
 /// <summary>
 /// Creates multiple discounts in Shopify
 /// </summary>
 public static void CreateDiscounts(AuthInfo authInfo, IEnumerable<Discount> discounts)
 {
     bool errors = false;
     foreach (Discount discount in discounts)
     {
         // Log errors and continue. We rethrow later.
         try
         {
             DiscountsWrapper.CreateDiscount(authInfo, discount);
         }
         catch (Exception ex)
         {
             errors = true;
             _log.Error(ex);
         }
     }
     if(errors)
     {
         throw new Exception("One or more errors occurred while creating discounts");
     }
 }
        /// <summary>
        /// Reads all discounts from Shopify
        /// </summary>
        public static void ReadDiscounts(AuthInfo authInfo, IList<Discount> discounts)
        {
            bool errors = false;

            for (int pageNumber = 1; true; pageNumber++)
            {
                try
                {
                    Console.WriteLine("Processing Page {0}", pageNumber);

                    string marketingUrl = String.Format(_marketingUrl, authInfo.StoreName, pageNumber);
                    HttpWebRequest request = HttpWebRequest.Create(marketingUrl) as HttpWebRequest;

                    // Set required HTTP headers
                    request.Accept = "*/*";
                    request.Headers["Accept-Language"] = "en-US";
                    request.Headers["Accept-Charset"] = "utf-8";
                    request.Headers["Cookie"] = String.Format("_secure_session_id={0}", authInfo.SessionId);
                    request.Headers["X-CSRF-Token"] = authInfo.CsrfToken;

                    // Read response
                    HttpWebResponse response = (HttpWebResponse)request.GetResponse();
                    HtmlDocument html = response.GetResponseHtml();

                    // Parse out the discounts rows from the Coupons table
                    HtmlNodeCollection discountRows = html.DocumentNode.SelectNodes("//table[@id=\"coupons\"]/tbody/tr");

                    // If the first row does not have 4 columns, we no discounts for this page.
                    if (discountRows[0].SelectNodes("td").Count != 4)
                    {
                        break;
                    }

                    // Each row is a discount.
                    foreach (HtmlNode discountRow in discountRows)
                    {
                        // Log errors and continue. We rethrow later.
                        try
                        {
                            Discount discount = ParseDiscount(discountRow);
                            discounts.Add(discount);
                        }
                        catch (Exception ex)
                        {
                            errors = true;
                            _log.Error(ex);
                        }
                    }
                }
                catch (Exception ex)
                {
                    string errorMessage = String.Format("Error Processing Page {0}", pageNumber);
                    throw new Exception(errorMessage, ex);
                }
            }

            if (errors)
            {
                throw new Exception("One or more errors occurred while reading discounts");
            }
        }
Example #5
0
        /// <summary>
        /// Main program entry point
        /// </summary>
        public static void Main(string[] args)
        {
            try
            {
                // Ignore Certificate validation failures (aka untrusted certificate + certificate chains) so we can debug https in Fiddler
                //ServicePointManager.ServerCertificateValidationCallback = ((sender2, certificate, chain, sslPolicyErrors) => true);

                string helpText = String.Empty;
                helpText += "\r\n";
                helpText += "EZSD.EXE storename username password [/CREATE | /READ | /DELETE] csvfile\r\n";
                helpText += "  storename Specifies the Shopify store name\r\n";
                helpText += "  username  Specifies the user name used to _log into Shopify\r\n";
                helpText += "  password  Specifies the password used to _log into Shopify\r\n";
                helpText += "  /CREATE   Causes discounts to be created in Shopify\r\n";
                helpText += "  /READ     Causes discounts to be read from Shopify\r\n";
                helpText += "  /DELETE   Causes discounts to be deleted in Shopify\r\n";
                helpText += "  csvfile   Specifies the CSV csvFile to be read from or written to\r\n";
                helpText += "\r\n";

                // Validate Arguments Length
                if (args.Length != 5)
                {
                    Console.WriteLine(helpText);
                    return;
                }

                // Validate StoreName, Username, and Password
                if (args[0].Length < 1 || args[1].Length < 1 || args[2].Length < 1)
                {
                    Console.WriteLine(helpText);
                    return;
                }

                // Validate Action
                string action = args[3].ToUpper();
                if (action != "/CREATE" && action != "/READ" && action != "/DELETE")
                {
                    Console.WriteLine(helpText);
                    return;
                }

                // Validate Filename
                string csvFile = null;
                try
                {
                    csvFile = Path.GetFullPath(args[4]);
                }
                catch(Exception) {
                    Console.WriteLine(helpText);
                    return;
                }

                // Authenticate with shopify
                AuthInfo authInfo = new AuthInfo() { StoreName = args[0], Username = args[1], Password = args[2] };
                Console.WriteLine("Authenticating...");
                AuthWrapper.Authenticate(authInfo);

                switch (action)
                {
                    case "/CREATE":
                        Console.WriteLine("Creating Discounts...");
                        CreateDiscounts(authInfo, csvFile);
                        break;
                    case "/READ":
                        Console.WriteLine("Reading Discounts...");
                        ReadDiscounts(authInfo, csvFile);
                        break;
                    case "/DELETE":
                        Console.WriteLine("Deleting Discounts...");
                        DeleteDiscounts(authInfo, csvFile);
                        break;
                }
                Console.WriteLine("Done!");

            }
            catch (Exception ex)
            {
                _log.Error(ex);
                Console.WriteLine("Done, but with errors. Check ezsd.log.txt for details.");
            }
        }
Example #6
0
        /// <summary>
        /// Helper method to read discounts
        /// </summary>
        private static void ReadDiscounts(AuthInfo authInfo, string csvFile)
        {
            List<Discount> discounts = new List<Discount>();
            DiscountsWrapper.ReadDiscounts(authInfo, discounts);

            Console.WriteLine("Writing Discounts to file...");
            using (TextWriter writer = new StreamWriter(csvFile))
            {
                // Write file header
                writer.WriteLine(Discount.CsvFileHeader);

                // Write discounts
                FileHelperEngine fileHelper = new FileHelperEngine(typeof(Discount));
                fileHelper.WriteStream(writer, discounts);
            }
        }
Example #7
0
        /// <summary>
        /// Helper method to delete discounts
        /// </summary>
        private static void DeleteDiscounts(AuthInfo authInfo, string csvFile)
        {
            // Read in discount codes from csvFile
            FileHelperEngine fileHelper = new FileHelperEngine(typeof(Discount));
            Discount[] discounts = fileHelper.ReadFile(csvFile) as Discount[];

            // Add discount codes for csvFile
            DiscountsWrapper.DeleteDiscounts(authInfo, discounts);
        }