예제 #1
0
        public List<ShopifyProduct> GetAllProducts(ShopifyStoreAuth storeAuth)
        {
            var returnList = new List<ShopifyProduct>(250);
            int pageNumber = 1;

            while (true)
            {
                List<ShopifyProduct> tempList = GetPageOfProducts(storeAuth, 250, pageNumber++);
                if (tempList != null)
                {
                    returnList = returnList.Union(tempList).ToList();
                    if (tempList.Count < 250)
                    {
                        break;
                    }
                }
            }

            return returnList;
        }
예제 #2
0
        public List<ShopifyOrder> GetListAllOrders(ShopifyStoreAuth storeAuth)
        {
            List<ShopifyOrder> returnList = null;
            XmlDocument responseDoc = ShopifyGet((_protocol + storeAuth.StoreSubDomain + _domain + "/admin/orders.xml"),
                                                 HashString(_appAuth.Secret + storeAuth.StoreAuthToken));

            if (responseDoc != null)
            {
                XmlNodeList errors = responseDoc.SelectNodes("//errors/error");
                if (errors != null)
                    if (errors.Count != 0)
                    {
                        var sw = new StringWriter();
                        var xw = new XmlTextWriter(sw);
                        responseDoc.WriteTo(xw);

                        Logger.ErrorFormat("ShopifyCommunicator::GetAllOrders(): Shopify returned errors: {0}",
                                           sw);
                        //for now we fall through and take whatever orders we can.
                    }

                XmlNodeList orders = responseDoc.SelectNodes("//orders/order");

                if (orders != null)
                {
                    returnList = new List<ShopifyOrder>(orders.Count);

                    foreach (XmlNode order in orders)
                    {
                        var orderDoc = new XmlDocument();
                        orderDoc.AppendChild(orderDoc.ImportNode(order, true));
                        var serializedResponse = new ShopifyResponse<ShopifyOrder>(orderDoc);

                        if (serializedResponse.State == ResponseState.OK)
                        {
                            returnList.Add(serializedResponse.ResponseObject);
                        }
                        else
                        {
                            XmlNodeList orderId = responseDoc.SelectNodes("//order/id");
                            if (orderId != null)
                            {
                                string id = orderId.Count > 0 ? orderId[0].InnerText : "unknown";
                                Logger.ErrorFormat(
                                    "ShopifyCommunicator()::GetListAllOrders(): Error deserializing order id={0}.", id);
                            }
                        }
                    }
                }
            }
            return returnList;
        }
예제 #3
0
        public ShopifyResponse<ShopifyProduct> CreateProduct(ShopifyStoreAuth storeAuth, IShopifyProduct sP)
        {
            //We serialize the ShopifyProduct into and XMLDocument, then POST it to shopify.
            var xS = new XmlSerializer(typeof (ShopifyProduct));

            var memStream = new MemoryStream();
            var xDoc = new XmlDocument();

            xS.Serialize(memStream, sP);
            memStream.Seek(0, SeekOrigin.Begin);
            xDoc.Load(memStream);
            memStream.Close();
            return
                new ShopifyResponse<ShopifyProduct>(
                    ShopifyPutPost((_protocol + storeAuth.StoreSubDomain + _domain + "/admin/products.xml"),
                                   HashString(_appAuth.Secret + storeAuth.StoreAuthToken), xDoc, "POST"));
        }
예제 #4
0
        public bool DeleteProduct(ShopifyStoreAuth storeAuth, int? productId)
        {
            if (productId == null)
            {
                Logger.WarnFormat("ShopifyCommunicator::DeleteProduct(): Argument productId is null.");
                return true;
            }

            XmlDocument errorDocument =
                ShopifyDelete(
                    _protocol + storeAuth.StoreSubDomain + _domain + "/admin/products/" + productId + ".xml",
                    HashString(_appAuth.Secret + storeAuth.StoreAuthToken));
            if (errorDocument == null) // null == No Errors
            {
                return true;
            }

            ApiLogger.ErrorFormat("ShopifyCommunicator::DeleteProduct(): Shopify returned errors: {0}",
                                  errorDocument.InnerText);
            return false;
        }
예제 #5
0
        public ShopifyResponse<ShopifyProduct> UpdateProduct(ShopifyStoreAuth storeAuth, ShopifyProduct shopifyProduct)
        {
            if (shopifyProduct == null || shopifyProduct.Id == null)
            {
                throw new ArgumentNullException(
                    "shopifyProduct");
            }

            var xS = new XmlSerializer(typeof (ShopifyProduct));

            var memStream = new MemoryStream();
            var xDoc = new XmlDocument();

            xS.Serialize(memStream, shopifyProduct);
            memStream.Seek(0, SeekOrigin.Begin);
            xDoc.Load(memStream);
            memStream.Close();

            XmlDocument productResponse =
                ShopifyPutPost(
                    (_protocol + storeAuth.StoreSubDomain + _domain + "/admin/products/" + shopifyProduct.Id + ".xml"),
                    HashString(_appAuth.Secret + storeAuth.StoreAuthToken), xDoc, "PUT");

            return new ShopifyResponse<ShopifyProduct>(productResponse);
        }
        private bool DeleteProductAndDeleteMap(ShopifyStoreAuth shopifyAuth, ConnectsterProductMap productMap,
                                               ConnectsterProduct item)
        {
            //Attempt to delete the shopsterItem from shopify
            if (!_shopifyComm.DeleteProduct(shopifyAuth, item.DestinationId))
            {
                //maybe a communication error, try next time around
                //todo: error, logs
                return false;
            }

            //Delete the Mapping
            return (productMap.DeleteMapping(item));
        }
예제 #7
0
            public ShopifyResponse<ShopifyCollection> GetCollectionByName(ShopifyStoreAuth storeAuth, string name)
            {
            if (storeAuth == null || string.IsNullOrEmpty(name))
            {
                Logger.Error(
                    "ShopifyCommunicator::GetCollectionByName(): storeAuth and name cannot be null. name cannot be empty");
                return null;
            }

            return
                new ShopifyResponse<ShopifyCollection>(
                    ShopifyGet(
                        (_protocol + storeAuth.StoreSubDomain + _domain + "/admin/custom_collections.xml?name=" +
                         HttpUtility.UrlEncode(name)),
                        HashString(_appAuth.Secret + storeAuth.StoreAuthToken)));
            }
예제 #8
0
        public ShopifyResponse<ShopifyProduct> GetProduct(ShopifyStoreAuth storeAuth, int productId)
        {
            if (productId < 0)
            {
                Logger.ErrorFormat(
                    "ShopifyCommunicator::GetProduct() was passed a negative productId ({0}), returning null.",
                    productId);
                return null;
            }

            XmlDocument xDoc =
                ShopifyGet(
                    (_protocol + storeAuth.StoreSubDomain + _domain + "/admin/products/" + productId + ".xml"),
                    HashString(_appAuth.Secret + storeAuth.StoreAuthToken));

            return new ShopifyResponse<ShopifyProduct>(xDoc);
        }
        //TODO : Make shopsterify user contain apiContext and shopifyAuth objects, then code that takes both a ApiContext and ShopifyStoreAuth can just take a shopsterifyUser
        private bool CreateProductAndMap(ApiContext apiContext, ShopifyStoreAuth shopifyAuth,
                                         InventoryItemType shopsterItem, ShopifyMetafieldMap shopifyMapping)
        {
            //Steps are: Upload Item to Shopify, Create metafield, Update map according to new productId

            //Upload to shopify
            List<InventoryCategoryType> categories =
                (shopsterItem.Categories == null || shopsterItem.Categories.Count < 1)
                    ? new List<InventoryCategoryType>(1)
                    : new List<InventoryCategoryType>(shopsterItem.Categories.Count);
            if (shopsterItem.Categories != null)
                categories.AddRange(shopsterItem.Categories.Select(categoryId => _shopsterComm.GetCategory(apiContext, categoryId)));

            //get the categories for this item

            ShopifyResponse<ShopifyProduct> response = _shopifyComm.CreateProduct(shopifyAuth,
                                                                                 ShopsterifyConverter.convertItem(
                                                                                     shopsterItem, categories));
            if (response.State == ResponseState.OK)
            {
                _metaFieldShopsterProductId.Value = shopsterItem.ItemId;
                if (response.ResponseObject.Id != null)
                {
                    if (response.ResponseObject.Created != null)
                    {
                        ShopifyMetafieldMapping newMap =
                            ShopifyMetafieldMapping.CreateMetafieldMapping((int) response.ResponseObject.Id,
                                                                           (DateTime) response.ResponseObject.Created,
                                                                           _metaFieldShopsterProductId);

                        //Update map (add mapping will create/update the ShopifyMetafield on shopify)
                        if (shopifyMapping.AddMapping(newMap))
                        {
            #if DEBUG
                            logger.DebugFormat(
                                "ConnectsterController::CreateProductAndMap(): CreatedProduct({0}) and mapping on Shopify.",
                                response.ResponseObject.Id);
            #endif
                            return true;
                        }
                    }
                }
            }
            #if DEBUG
            logger.DebugFormat(
                "ConnectsterController::CreateProductAndMap(): attempted to create mapping and failed. ShopsterToken({0}), ShopifySubdomain({1}, shopsterItemId({2})",
                apiContext.AccessToken, shopifyAuth.StoreSubDomain, shopsterItem.ItemId);
            #endif
            return false;
        }
예제 #10
0
            public ShopifyResponse<ShopifyCollection> CreateCollection(ShopifyStoreAuth storeAuth,
                                                                   ShopifyCollection collection)
            {
            if (storeAuth == null || collection == null)
            {
                Logger.Error("ShopifyCommunicator::CreateCollection(): storeAuth and collection cannot be null.");
                return null;
            }

            var xS = new XmlSerializer(typeof (ShopifyCollection));
            var memStream = new MemoryStream();
            var xDoc = new XmlDocument();

            xS.Serialize(memStream, collection);
            memStream.Seek(0, SeekOrigin.Begin);
            xDoc.Load(memStream);
            memStream.Close();

            return
                new ShopifyResponse<ShopifyCollection>(
                    ShopifyPutPost((_protocol + storeAuth.StoreSubDomain + _domain + "/admin/custom_collections.xml"),
                                   HashString(_appAuth.Secret + storeAuth.StoreAuthToken), xDoc, "POST"));
            }
예제 #11
0
 public ConnectsterUser GetUser(ApiContext apiContext, ShopifyStoreAuth shopifyAuth)
 {
     return _database.SelectConnectsterUser(apiContext, shopifyAuth);
 }
예제 #12
0
        /// <summary>
        /// Pushes all shopster products to shopify. Deals with all error states with an existing shopster Item. Deals with cases 1357, all ending in case7's state (see wiki).
        /// </summary>
        /// <param name="shopsterItems"></param>
        /// <param name="productMap"></param>
        /// <param name="shopifyMap"></param>
        /// <param name="shopifyIds"></param>
        /// <param name="shopifyItems"></param>
        /// <param name="storeAuth"></param>
        /// <param name="apiContext"></param>
        /// <returns>A count of how many products were fixed/changed.</returns>
        private int PushProductToShopify(IEnumerable<InventoryItemType> shopsterItems, ConnectsterProductMap productMap,
                                         ShopifyMetafieldMap shopifyMap, IList<int> shopifyIds,
                                         List<ShopifyProduct> shopifyItems, ShopifyStoreAuth storeAuth,
                                         ApiContext apiContext)
        {
            if (shopifyItems == null) throw new ArgumentNullException("shopifyItems");
            int returnCount = 0;
            //All of these are ending up in a Case7 (All good) state.
            foreach (InventoryItemType shopsterItem in shopsterItems)
            {
                InventoryItemType inventoryItem = shopsterItem;
                IList<ConnectsterProduct> mappings = productMap.GetMappedItems()
                    .Where(p => p.SourceId == Convert.ToInt32(inventoryItem.ItemId)).Select(p => p).ToList();
                if (mappings.Count > 0) //Cases 3,7
                {
                    foreach (ConnectsterProduct mapping in mappings)
                    {
                        if (!shopifyIds.Contains(mapping.DestinationId)) //If we have a broken mapping. (Case3)
                        {
                            //if the metafields have a mapping, fix the mapping
                            if (shopifyMap.GetDestinationIds().Contains(Convert.ToInt32(shopsterItem.ItemId)))
                            {
                                //There is a shopifyItem that wants to be linked to this shopsterItem
                                if (shopifyItems.Count > 0)
                                {
                                    ShopifyProduct shopifyItem = shopifyItems
                                        .Where(item => item.Id ==
                                                       shopifyMap.GetSourcesForDestiation(
                                                           Convert.ToInt32(shopsterItem.ItemId)).Take(1).First())
                                        .Select(item => item).First();
                                    if (shopifyItem.Id != null) mapping.DestinationId = (int) shopifyItem.Id;
                                    productMap.AddMapping(mapping); //Add mapping will update if it is already there.
                                    return returnCount;
                                }

                            }
                            else
                            {
                                //upload the product

                                List<InventoryCategoryType> categories =
                                    (shopsterItem.Categories == null || shopsterItem.Categories.Count < 1)
                                        ? new List<InventoryCategoryType>(1)
                                        : new List<InventoryCategoryType>(shopsterItem.Categories.Count);

                                if (shopsterItem.Categories != null)
                                    categories.AddRange(shopsterItem.Categories.Select(categoryId => _shopsterComm.GetCategory(apiContext, categoryId)));

                                ShopifyProduct sP = ShopsterifyConverter.convertItem(shopsterItem, categories);
                                ShopifyResponse<ShopifyProduct> response = _shopifyComm.CreateProduct(storeAuth, sP);
                                if (response.State == ResponseState.OK)
                                {
                                    _metaFieldShopsterProductId.Value = Convert.ToInt32(shopsterItem.ItemId).ToString();
                                    ShopifyResponse<ShopifyMetafield> responseMetafield =
                                        _shopifyComm.CreateMetafield(storeAuth, _metaFieldShopsterProductId,
                                                                    response.ResponseObject.Id);
                                    if (responseMetafield == null) throw new NotImplementedException();

                                    mapping.DestinationId = response.ResponseObject.Id != null
                                                                ? (int) response.ResponseObject.Id
                                                                : 0;
                                    productMap.AddMapping(mapping); //Add mapping will update if it is already there.
                                    returnCount++;
                                }
                            }
                        }
                        else //Case7 update and ensure metafield map is correct.
                        {
                            //Todo enable the below comparison of Sourcedate and DestinationDate
                            //if (mapping.SourceDate > mapping.DestinationDate)

                            if (mapping.DestinationDate < DateTime.UtcNow.AddMinutes(-5))
                            {
                                List<InventoryCategoryType> categories =
                                    (shopsterItem.Categories == null || shopsterItem.Categories.Count < 1)
                                        ? new List<InventoryCategoryType>(1)
                                        : new List<InventoryCategoryType>(shopsterItem.Categories.Count);
                                if (shopsterItem.Categories != null)
                                    categories.AddRange(shopsterItem.Categories.Select(categoryId => _shopsterComm.GetCategory(apiContext, categoryId)));

                                ShopifyProduct shopifyProduct = ShopsterifyConverter.convertItem(shopsterItem,
                                                                                                 categories);

                                shopifyProduct.Id = productMap.GetProductTable()[Convert.ToInt32(shopsterItem.ItemId)];
                                ShopifyVariant[] shopifyVars =
                                    shopifyItems.Where(item => item.Id == shopifyProduct.Id).Select(
                                        item => item.Variants).FirstOrDefault();

                                foreach (ShopifyVariant sV in shopifyProduct.Variants)
                                {
                                    sV.ProductId = shopifyProduct.Id;
                                    if (shopifyVars != null) sV.Id = shopifyVars[0].Id;
                                }

                                ShopifyResponse<ShopifyProduct> response = _shopifyComm.UpdateProduct(storeAuth,
                                                                                                     shopifyProduct);
                                if (response.State == ResponseState.OK)
                                {
                                    //Todo add debug logging that this item was updated correctly
                                    returnCount++;
                                    logger.InfoFormat(
                                        "ConnectsterController:: Updated shopify item({0}) successfully.",
                                        shopifyProduct.Id);

                                    _database.UpdateShopifyProductTimeStamp(response.ResponseObject, DateTime.UtcNow);
                                }
                            }
                            else
                            {
                                logger.InfoFormat("ConnectsterController:: Skipped update due to timestamps.");
                            }
                        }
                    }
                }
                else //Cases 1, 5 -- Product exists, no mappings found, maybe on shopify
                {
                    InventoryItemType inventoryItemType = shopsterItem;
                    IList<ShopifyMetafieldMapping> metaFieldMappings = shopifyMap.GetMappedItems()
                        .Where(map => map.DestinationId == Convert.ToInt32(inventoryItemType.ItemId))
                        .Select(map => map).ToList();

                    if (metaFieldMappings.Count > 0)
                        //There are products on shopify that think they belong to this shopsteritem
                    {
                        //Case 5
                        foreach (ShopifyMetafieldMapping metaFieldMapping in metaFieldMappings)
                        {
                            //rebuild the mapping, this call pushes through to the db.
                            ShopifyMetafieldMapping mapping = metaFieldMapping;
                            InventoryItemType item1 = shopsterItem;
                            productMap.AddMapping(new ConnectsterProduct(shopsterItem, shopifyItems
                                                                                           .Where(
                                                                                               item =>
                                                                                               (item.Id ==
                                                                                                mapping.
                                                                                                    SourceId) &&
                                                                                               (mapping.
                                                                                                    DestinationId ==
                                                                                                Convert.ToInt32(
                                                                                                    item1.ItemId)))
                                                                                           .Select(item => item).Take(1)
                                                                                           .ToList()[0]));
                            returnCount++;
                        }
                    }
                    else //There aren't any products on shopify that belong to this shopsterItem
                    {
                        //Case 1
                        //upload the product
                        List<InventoryCategoryType> categories =
                            (shopsterItem.Categories == null || shopsterItem.Categories.Count < 1)
                                ? new List<InventoryCategoryType>(1)
                                : new List<InventoryCategoryType>(shopsterItem.Categories.Count);

                        if (shopsterItem.Categories != null)
                            categories.AddRange(shopsterItem.Categories.Select(categoryId => _shopsterComm.GetCategory(apiContext, categoryId)));

                        ShopifyProduct sP = ShopsterifyConverter.convertItem(shopsterItem, categories);
                        ShopifyResponse<ShopifyProduct> response = _shopifyComm.CreateProduct(storeAuth, sP);
                        if (response.State == ResponseState.OK)
                        {
                            _metaFieldShopsterProductId.Value = Convert.ToInt32(shopsterItem.ItemId).ToString();
                            ShopifyResponse<ShopifyMetafield> responseMetafield = _shopifyComm.CreateMetafield(
                                storeAuth, _metaFieldShopsterProductId, response.ResponseObject.Id);
                            if (responseMetafield.State == ResponseState.OK)
                            {
                                //create the mapping

                                var mapping = new ConnectsterProduct(shopsterItem, response.ResponseObject);
                                productMap.AddMapping(mapping);
                            }

                            returnCount++;
                        }
                    }
                }
            }

            return returnCount;
        }
예제 #13
0
        //End of PushProductToShopify
        /// <summary>
        /// Deals with any orphaned cases with a Mapped remaining. Attempts to clean up any shopify Items in the process.
        /// </summary>
        /// <param name="shopsterIds"></param>
        /// <param name="productMap"></param>
        /// <param name="shopifyMapping"></param>
        /// <param name="shopifyIds"></param>
        /// <param name="shopifyAuth"></param>
        /// <returns>Number of "items" affected</returns>
        private int FixOrphanedMappings(IList<int> shopsterIds, ConnectsterProductMap productMap,
                                        ShopifyMetafieldMap shopifyMapping, IList<int> shopifyIds,
                                        ShopifyStoreAuth shopifyAuth)
        {
            int returnCount = 0;

            //Foreach productMap for which there is no corresponding shopsterItem.
            // Delete the map, and if applicable delete the shopifyItem.
            foreach (ConnectsterProduct shopsterifyProduct in productMap.GetMappedItems()
                .Where(p => !shopsterIds.Contains(p.SourceId)).Select(p => p).ToList())
            {
                //case 2
                if (!shopifyIds.Contains(shopsterifyProduct.DestinationId))
                {
                    productMap.DeleteMapping(shopsterifyProduct);
                    returnCount++;
                }
                else //case 6
                {
                    if (DeleteProductAndDeleteMap(shopifyAuth, productMap, shopsterifyProduct))
                    {
                        shopifyIds.Remove(shopsterifyProduct.DestinationId);
                        ConnectsterProduct product = shopsterifyProduct;
                        ShopifyMetafieldMapping toRemove =
                            shopifyMapping.GetMappedItems().Where(
                                map => map.SourceId == product.DestinationId).Select(map => map).
                                FirstOrDefault();
                        shopifyMapping.GetMappedItems().Remove(toRemove);
                        returnCount++;
                    }
                }
            }
            return returnCount;
        }
예제 #14
0
        public ShopifyResponse<ShopifyOrder> GetOrder(ShopifyStoreAuth storeAuth, int orderId)
        {
            //Ensure the orderID makes sense
            if (orderId < 0)
            {
                Logger.Warn("ShopifyCommunicator::GetOrder(): Was passed orderId<0, returning null");
                return null;
            }

            //Retrieve the order from shopify
            XmlDocument retrievedOrder =
                ShopifyGet(
                    (_protocol + storeAuth.StoreSubDomain + _domain + "/admin/orders/" + orderId + ".xml"),
                    HashString(_appAuth.Secret + storeAuth.StoreAuthToken));

            //Create e responseObject out of the response.
            return new ShopifyResponse<ShopifyOrder>(retrievedOrder);
        }
예제 #15
0
            public ShopifyResponse<ShopifyCollection> GetCollection(ShopifyStoreAuth storeAuth, int collectionId)
            {
            if (storeAuth == null || collectionId <= 0)
            {
                Logger.Error(
                    "ShopifyCommunicator::GetCollection(): storeAuth cannot be null and collectionId must be >0");
                return null;
            }

            return
                new ShopifyResponse<ShopifyCollection>(
                    ShopifyGet(
                        (string.Format("{0}{1}{2}/admin/custom_collections/{3}.xml", _protocol, storeAuth.StoreSubDomain,
                                       _domain, collectionId)),
                        HashString(_appAuth.Secret + storeAuth.StoreAuthToken)));
            }
예제 #16
0
        public List<ShopifyProduct> GetPageOfProducts(ShopifyStoreAuth storeAuth, int numWanted, int pageNumber)
        {
            if (storeAuth == null)
            {
                Logger.Warn("ShopifyCommunicator::GetPageOfProducts: storeAuth cannot be null");
                return null;
            }

            if (!(numWanted > 0 && numWanted < 251 && pageNumber > 0))
            {
                Logger.WarnFormat(
                    "ShopifyCommunicator::GetPageOfProducts(): numWanted({0}) must be between 0 and 251, pageNumber({1}) must be >0.",
                    numWanted, pageNumber);
                return null;
            }

            var url = new StringBuilder();
            url.Append(_protocol);
            url.Append(storeAuth.StoreSubDomain);
            url.Append(_domain);
            url.Append("/admin/products.xml?");

            url.Append("limit=" + numWanted);
            url.Append("&page=" + pageNumber);

            XmlDocument xDoc = ShopifyGet(url.ToString(), HashString(_appAuth.Secret + storeAuth.StoreAuthToken));
            //Now the fun part of parsing this xml.
            if (xDoc == null)
            {
                return null;
            }

            XmlNodeList productNodeList = xDoc.SelectNodes("//products/product");

            var returnList = new List<ShopifyProduct>();
            //			Foreach product found, serialize and add to return list
            if (productNodeList != null)
                foreach (XmlNode productNode in productNodeList)
                {
                    var productDoc = new XmlDocument();
                    productDoc.AppendChild(productDoc.ImportNode(productNode, true));
                    var serializedResponse = new ShopifyResponse<ShopifyProduct>(productDoc);

                    if (serializedResponse.State == ResponseState.OK)
                    {
                        returnList.Add(serializedResponse.ResponseObject);
                    }
                    else
                    {
                        XmlNodeList idNode = productNode.SelectNodes("//id");
                        if (idNode != null)
                        {
                            string productId = idNode.Count > 0 ? idNode[0].InnerText : "null";
                            Logger.ErrorFormat(
                                "ShopifyCommunicator()::GetPageOfProducts(): Couldn't parse product ({0}) returned in page of product.",
                                productId);
                        }
                    }
                }

            return returnList;
        }
예제 #17
0
            /// <summary>
            ///
            /// </summary>
            /// <param name="storeAuth"></param>
            /// <param name="limit"></param>
            /// <param name="createdMin"></param>
            /// <param name="createdMax"></param>
            /// <param name="updatedMin"></param>
            /// <param name="updatedMax"></param>
            /// <param name="fieldNamespace"></param>
            /// <param name="key"></param>
            /// <param name="valueType"></param>
            /// <param name="productId">If productId is >0 get all metafields for that product, if null get metafields tagged to the shop. </param>
            /// <exception cref="ArgumentNullException"></exception>
            /// <returns></returns>
            public List<ShopifyMetafield> GetAllMetafields(ShopifyStoreAuth storeAuth, int? limit,
                                                       DateTime? createdMin, DateTime? createdMax, DateTime? updatedMin,
                                                       DateTime? updatedMax,
                                                       string fieldNamespace, string key, string valueType,
                                                       int? productId)
            {
            //Todo: Should we make this take a "dictionary" and then simply do "foreach key in dictionary"
            if (!(valueType == "string" || valueType == "integer"))
            {
                throw new ArgumentException("valueType can only be 'string' or 'integer'");
            }
            if (limit > 250 || limit < 0)
            {
                throw new ArgumentException("limit must be between 1 and 250 inclusive");
            }
            if (storeAuth == null)
            {
                throw new ArgumentNullException("storeAuth");
            }
            if (productId == null && productId < 1)
            {
                throw new ArgumentException("productId must be >0");
            }

            List<ShopifyMetafield> returnList = limit != null
                                                    ? new List<ShopifyMetafield>((int) limit)
                                                    : new List<ShopifyMetafield>();

            var sbUrl = new StringBuilder();
            sbUrl.Append(_protocol + storeAuth.StoreSubDomain + _domain + "/admin/");

            if (productId != null)
            {
                sbUrl.Append("products/" + productId + "/");
            }
            sbUrl.Append("metafields.xml?");
            //Append each of the filter terms.
            if (limit != null)
            {
                sbUrl.Append("limit=" + limit);
            }
            if (createdMin != null)
            {
                sbUrl.Append("&created_at_min=" + HttpUtility.UrlEncode(DateTimeToShopifyString((DateTime) createdMin)));
            }
            if (createdMax != null)
            {
                sbUrl.Append("&created_at_max=" + HttpUtility.UrlEncode(DateTimeToShopifyString((DateTime) createdMax)));
            }
            if (updatedMin != null)
            {
                sbUrl.Append("&updated_at_min=" + HttpUtility.UrlEncode(DateTimeToShopifyString((DateTime) updatedMin)));
            }
            if (updatedMax != null)
            {
                sbUrl.Append("&updated_at_max=" + HttpUtility.UrlEncode(DateTimeToShopifyString((DateTime) updatedMax)));
            }
            if (!string.IsNullOrEmpty(key))
            {
                sbUrl.Append("&key=" + HttpUtility.UrlEncode(key));
            }
            if (!string.IsNullOrEmpty(fieldNamespace))
            {
                sbUrl.Append("&namespace=" + HttpUtility.UrlEncode(fieldNamespace));
            }
            if (valueType != string.Empty)
            {
                sbUrl.Append("&value_type=" + HttpUtility.UrlEncode(valueType));
            }

            XmlDocument xDoc = ShopifyGet(sbUrl.ToString().Replace("?&", "?"),
                                          HashString(_appAuth.Secret + storeAuth.StoreAuthToken));

            if (xDoc == null)
            {
                //ShopifyGet should be logging/reporting the error
                return null;
            }
            XmlNodeList metaFields = xDoc.SelectNodes("//metafields/metafield");

            if (metaFields != null)
                foreach (XmlNode metaField in metaFields)
                {
                    var metaFieldDoc = new XmlDocument();
                    metaFieldDoc.AppendChild(metaFieldDoc.ImportNode(metaField, true));
                    var serializedResponse =
                        new ShopifyResponse<ShopifyMetafield>(metaFieldDoc);

                    if (serializedResponse.State == ResponseState.OK)
                    {
                        returnList.Add(serializedResponse.ResponseObject);
                    }
                    else
                    {
                        //Log this error, ignore this metafield and continue with call so we can return the properly formatted metafields
                        XmlNodeList idNode = metaField.SelectNodes("//id");
                        if (idNode != null)
                        {
                            string metafieldId = idNode.Count > 0 ? idNode[0].InnerText : "null";
                            Logger.ErrorFormat(
                                "ShopifyCommunicator()::GetAllMetafields(): Couldn't parse metafield ({0}) returned in page of metafields.",
                                metafieldId);
                        }
                    }
                }
            return returnList;
        }
예제 #18
0
        public ShopifyResponse<ShopifyShop> GetShopInformation(ShopifyStoreAuth storeAuth)
        {
            XmlDocument retrievedShop = ShopifyGet((_protocol + storeAuth.StoreSubDomain + _domain + "/admin/shop.xml"),
                                                   HashString(_appAuth.Secret + storeAuth.StoreAuthToken));

            return new ShopifyResponse<ShopifyShop>(retrievedShop);
        }
예제 #19
0
        public ShopifyResponse<ShopifyMetafield> CreateMetafield(ShopifyStoreAuth storeAuth, ShopifyMetafield metaField,
                                                                 int? productId)
        {
            if (storeAuth == null || metaField == null)
            {
                Logger.WarnFormat("ShopifyCommunicator::CreateMetafield():storeAuth and metaField cannot be null");
                return null;
            }
            if (productId != null && productId < 1)
                //Product ID can be null if the metafield is tagged to the store itself (vs. tagged to a product).
            {
                Logger.ErrorFormat("ShopifyCommunicator::CreateMetafield(): productId must be >=1 if non-null.");
                return null;
            }

            //Build our url depending on if this metafield will apply to e product or e shop
            var url = new StringBuilder();
            url.Append(_protocol + storeAuth.StoreSubDomain + _domain + "/admin/");

            if (productId != null)
            {
                url.Append("products/" + productId + "/");
            }
            url.Append("metafields.xml");

            var xS = new XmlSerializer(typeof (ShopifyMetafield));

            var memStream = new MemoryStream();
            var xDoc = new XmlDocument();

            xS.Serialize(memStream, metaField);
            memStream.Seek(0, SeekOrigin.Begin);
            xDoc.Load(memStream);
            memStream.Close();

            return new ShopifyResponse<ShopifyMetafield>(ShopifyPutPost(url.ToString(),
                                                                        HashString(_appAuth.Secret +
                                                                                   storeAuth.StoreAuthToken), xDoc,
                                                                        "POST"));
        }
예제 #20
0
        public ConnectsterUser SelectConnectsterUser(ApiContext apiContext, ShopifyStoreAuth shopifyAuth)
        {
            if (apiContext == null || shopifyAuth == null)
            {
                Logger.ErrorFormat("SelectConnectsterUser(): Was given null apiContext or ShopifyAuth");
                throw new ArgumentException("Neither arguments can be null");
            }

            string query = String.Format(
                @" SELECT shopsterU.id as ShopsterUserId, shopifyU.subdomain as ShopifyUserId, smap.sleepUntil
                FROM shopifyUser shopifyU JOIN connectsterusermap smap ON shopifyU.subdomain = smap.ShopifySubdomain
                JOIN shopsteruser shopsterU ON shopsterU.id = smap.ShopsterUserId
                WHERE  shopsterU.AuthToken = '{0}' AND
                shopsterU.AuthSecret = '{1}' AND
                shopifyU.subDomain = '{2}' AND
                shopifyU.AuthToken = '{3}' LIMIT 1;",
                apiContext.AccessToken,
                apiContext.AccessTokenSecret,
                shopifyAuth.StoreSubDomain,
                shopifyAuth.StoreAuthToken);

            var sqlCommand = new MySqlCommand(query, _dbConn);

            using (var sqlResult = sqlCommand.ExecuteReader())
            {
                while (sqlResult.Read()) //We return the first read.
                {
                    try //Try to do Convert.ToInt32
                    {
                        return new ConnectsterUser(Convert.ToInt32(sqlResult[0]), (string) sqlResult[1]);
                    }
                    catch (FormatException e)
                    {
                        Logger.DebugFormat(
                            "SelectConnectsterUser(): FormatException for returned userId({0}). Exception Message is {1}",
                            sqlResult[0], e.Message);
                        continue; //Just abandon this user and move on.
                    }
                    catch (OverflowException e)
                    {
                        Logger.DebugFormat(
                            "SelectConnectsterUser(): OverflowException for returned userId({0}). Exception Message is {1}",
                            sqlResult[0], e.Message);
                        continue;
                    }
                }
            }

            //User not found.
            return null;
        }
예제 #21
0
        /// <summary>
        /// Deletes completely orphaned ShopifyProducts (one's which are tagged) but not related to an existing shopsteritem or a mapping.
        /// </summary>
        /// <param name="shopsterItems"></param>
        /// <param name="productMap"></param>
        /// <param name="shopifyMapping"></param>
        /// <param name="shopifyAuth"></param>
        /// <returns></returns>
        private int DeleteOrphanedShopifyProducts(IEnumerable<InventoryItemType> shopsterItems,
                                                  ConnectsterProductMap productMap, ShopifyMetafieldMap shopifyMapping,
                                                  ShopifyStoreAuth shopifyAuth)
        {
            //DeleteOrphanedShopifyProducts(productMap, shopifyMapping, user, shopifyAuth)
            List<ShopifyMetafieldMapping> notMappedProductsList = shopifyMapping.GetMappedItems()
                .Where(item => (!productMap.GetDestinationIds().Contains(item.SourceId))).Select(item => item).ToList();

            return notMappedProductsList.Where(notMappedProduct => shopsterItems.Where(item => Convert.ToInt32(item.ItemId) == notMappedProduct.DestinationId).Count() == 0).Count(notMappedProduct => _shopifyComm.DeleteProduct(shopifyAuth, notMappedProduct.SourceId));
        }