/// <summary> /// Creates a new <see cref="ShopifyCollect"/> on the store. Map product to collection /// </summary> /// <param name="collect">A new <see cref="ShopifyCollect"/>. Id should be set to null.</param> /// <returns>The new <see cref="ShopifyCollect"/>.</returns> public virtual async Task <ShopifyCollect> CreateAsync(ShopifyCollect collect) { IRestRequest req = RequestEngine.CreateRequest("collects.json", RestSharp.Method.POST, "collect"); Dictionary <string, object> body = new Dictionary <string, object>() { { "collect", collect } }; req.AddJsonBody(body); return(await RequestEngine.ExecuteRequestAsync <ShopifyCollect>(_RestClient, req)); }
/// <summary> /// Creates a new <see cref="ShopifyFulfillment"/> on the store. /// </summary> /// <param name="orderId">The order id to which the fulfillments belong.</param> /// <param name="fulfillment">A new <see cref="ShopifyFulfillment"/>. Id should be set to null.</param> /// <param name="notifyCustomer">Whether the customer should be notified that the fulfillment /// has been created.</param> /// <returns>The new <see cref="ShopifyFulfillment"/>.</returns> public async Task <ShopifyFulfillment> CreateAsync(long orderId, ShopifyFulfillment fulfillment, bool notifyCustomer) { var req = RequestEngine.CreateRequest($"orders/{orderId}/fulfillments.json", Method.POST, "fulfillment"); //Convert the fulfillment to a dictionary and add the notifyCustomer prop var body = fulfillment.ToDictionary(); body.Add("notify_customer", notifyCustomer); req.AddJsonBody(new { fulfillment = body }); return(await RequestEngine.ExecuteRequestAsync <ShopifyFulfillment>(_RestClient, req)); }
/// <summary> /// Gets a count of all of the collects (product-collection mappings). /// </summary> /// <returns>The count of all collects for the shop.</returns> public virtual async Task <int> CountAsync(ShopifyCollectFilter filter = null) { IRestRequest req = RequestEngine.CreateRequest("collects/count.json", Method.GET, "count"); if (filter != null) { req.Parameters.AddRange(filter.ToParameters(ParameterType.GetOrPost)); } JToken responseObject = await RequestEngine.ExecuteRequestAsync(_RestClient, req); return(responseObject.Value <int>("count")); }
/// <summary> /// Gets a count of all of the custom collections /// </summary> /// <returns>The count of all collects for the shop.</returns> public async Task <int> CountAsync(ShopifyCustomCollectionFilter options = null) { IRestRequest req = RequestEngine.CreateRequest("custom_collections/count.json", Method.GET, "count"); if (options != null) { req.Parameters.AddRange(options.ToParameters(ParameterType.GetOrPost)); } JToken responseObject = await RequestEngine.ExecuteRequestAsync(_RestClient, req); return(responseObject.Value <int>("count")); }
/// <summary> /// Retrieves the <see cref="ShopifyAsset"/> with the given id. /// </summary> /// <param name="themeId">The id of the theme that the asset belongs to. Assets themselves do not have ids.</param> /// <param name="key">The key value of the asset, e.g. 'templates/index.liquid' or 'assets/bg-body.gif'.</param> /// <param name="fields">A comma-separated list of fields to return.</param> /// <returns>The <see cref="ShopifyAsset"/>.</returns> public async Task <ShopifyAsset> GetAsync(long themeId, string key, string fields = null) { IRestRequest req = RequestEngine.CreateRequest("themes/{0}/assets.json".FormatWith(themeId), Method.GET, "asset"); //Add the proper asset querystring req = SetAssetQuerystring(req, key, themeId); if (string.IsNullOrEmpty(fields) == false) { req.AddParameter("fields", fields); } return(await RequestEngine.ExecuteRequestAsync <ShopifyAsset>(_RestClient, req)); }
/// <summary> /// Creates a new <see cref="ShopifyScriptTag"/> on the store. /// </summary> /// <param name="tag">A new <see cref="ShopifyScriptTag"/>. Id should be set to null.</param> /// <returns>The new <see cref="ShopifyScriptTag"/>.</returns> public async Task <ShopifyScriptTag> CreateAsync(ShopifyScriptTag tag) { IRestRequest req = RequestEngine.CreateRequest("script_tags.json", Method.POST, "script_tag"); //Build the request body var body = new Dictionary <string, object>() { { "script_tag", tag } }; req.AddJsonBody(body); return(await RequestEngine.ExecuteRequestAsync <ShopifyScriptTag>(_RestClient, req)); }
/// <summary> /// Updates the given <see cref="ShopifyCustomCollection"/>. Id must not be null. /// </summary> /// <param name="customCollection">The <see cref="ShopifyCustomCollection"/> to update.</param> /// <returns>The updated <see cref="ShopifyCustomCollection"/>.</returns> public virtual async Task <ShopifyCustomCollection> UpdateAsync(ShopifyCustomCollection customCollection) { IRestRequest req = RequestEngine.CreateRequest($"custom_collections/{customCollection.Id.Value}.json", Method.PUT, "custom_collection"); //Build the request body Dictionary <string, object> body = new Dictionary <string, object>() { { "custom_collection", customCollection } }; req.AddJsonBody(body); return(await RequestEngine.ExecuteRequestAsync <ShopifyCustomCollection>(_RestClient, req)); }
/// <summary> /// Authorizes an application installation, generating an access token for the given shop. /// </summary> /// <param name="code">The authorization code generated by Shopify, which should be a parameter named 'code' on the request querystring.</param> /// <param name="myShopifyUrl">The store's *.myshopify.com URL, which should be a paramter named 'shop' on the request querystring.</param> /// <param name="shopifyApiKey">Your app's public API key.</param> /// <param name="shopifySecretKey">Your app's secret key.</param> /// <returns>The shop access token.</returns> public static async Task <string> Authorize(string code, string myShopifyUrl, string shopifyApiKey, string shopifySecretKey) { Uri shopUri = RequestEngine.BuildShopUri(myShopifyUrl); RestClient client = RequestEngine.CreateClient(shopUri); IRestRequest req = RequestEngine.CreateRequest("oauth/access_token", Method.POST); JToken response; //Build request body req.AddJsonBody(new { client_id = shopifyApiKey, client_secret = shopifySecretKey, code }); response = await RequestEngine.ExecuteRequestAsync(client, req); return(response.Value <string>("access_token")); }
/// <summary> /// Creates a new <see cref="ShopifyOrder"/> on the store. /// </summary> /// <param name="order">A new <see cref="ShopifyOrder"/>. Id should be set to null.</param> /// <param name="options">Options for creating the order.</param> /// <returns>The new <see cref="ShopifyOrder"/>.</returns> public async Task <ShopifyOrder> CreateAsync(ShopifyOrder order, ShopifyOrderCreateOptions options = null) { IRestRequest req = RequestEngine.CreateRequest("orders.json", Method.POST, "order"); //Build the request body Dictionary <string, object> body = new Dictionary <string, object>(options?.ToDictionary() ?? new Dictionary <string, object>()) { { "order", order } }; req.AddJsonBody(body); return(await RequestEngine.ExecuteRequestAsync <ShopifyOrder>(_RestClient, req)); }
/// <summary> /// Gets a count of all of the shop's ProductImages. /// </summary> /// <param name="productId">The id of the product that counted images belong to.</param> /// <param name="filter">An optional filter that restricts the results.</param> /// <returns>The count of all ProductImages for the shop.</returns> public virtual async Task <int> CountAsync(long productId, ShopifyPublishableCountFilter filter = null) { var req = RequestEngine.CreateRequest($"products/{productId}/images/count.json", Method.GET); if (filter != null) { req.Parameters.AddRange(filter.ToParameters(ParameterType.GetOrPost)); } JToken responseObject = await RequestEngine.ExecuteRequestAsync(_RestClient, req); //Response looks like { "count" : 123 }. Does not warrant its own class. return(responseObject.Value <int>("count")); }
/// <summary> /// Creates a new <see cref="ShopifyPage"/> on the store. /// </summary> /// <param name="page">A new <see cref="ShopifyPage"/>. Id should be set to null.</param> /// <param name="options">Options for creating the page.</param> /// <returns>The new <see cref="ShopifyPage"/>.</returns> public virtual async Task <ShopifyPage> CreateAsync(ShopifyPage page, ShopifyPageCreateOptions options = null) { IRestRequest req = RequestEngine.CreateRequest("pages.json", Method.POST, "page"); //Build the request body Dictionary <string, object> body = new Dictionary <string, object>(options?.ToDictionary() ?? new Dictionary <string, object>()) { { "page", page } }; req.AddJsonBody(body); return(await RequestEngine.ExecuteRequestAsync <ShopifyPage>(_RestClient, req)); }
/// <summary> /// Unpublishes an published <see cref="ShopifyProduct"/>. /// </summary> /// <param name="id">The product's id.</param> /// <returns>The unpublished <see cref="ShopifyProduct"/></returns> public virtual async Task <ShopifyProduct> UnpublishAsync(long id) { IRestRequest req = RequestEngine.CreateRequest($"products/{id}.json", Method.PUT, "product"); req.AddJsonBody(new { product = new { id = id, published = false } }); return(await RequestEngine.ExecuteRequestAsync <ShopifyProduct>(_RestClient, req)); }
/// <summary> /// Gets a count of all of the shop's <see cref="ShopifyScriptTag"/>s. /// </summary> /// <param name="src">Optionally filters the count to only those <see cref="ShopifyScriptTag"/>s with the /// given <see cref="ShopifyScriptTag.Src"/> value.</param> /// <returns>The count.</returns> public async Task <int> CountAsync(string src = null) { IRestRequest req = RequestEngine.CreateRequest("script_tags/count.json", Method.GET); //Filter the count where necessary. if (string.IsNullOrEmpty(src) == false) { req.AddQueryParameter("src", src); } JToken responseObject = await RequestEngine.ExecuteRequestAsync(_RestClient, req); //Response looks like { "count" : 123 }. Does not warrant its own class. return(responseObject.Value <int>("count")); }
/// <summary> /// Gets a count of all of the shop's orders. /// </summary> /// <param name="filter">Options for filtering the count.</param> /// <returns>The count of all orders for the shop.</returns> public async Task <int> CountAsync(ShopifyOrderFilter filter = null) { IRestRequest req = RequestEngine.CreateRequest("orders/count.json", Method.GET); //Add optional parameters to request if (filter != null) { req.Parameters.AddRange(filter.ToParameters(ParameterType.GetOrPost)); } JToken responseObject = await RequestEngine.ExecuteRequestAsync(_RestClient, req); //Response looks like { "count" : 123 }. Does not warrant its own class. return(responseObject.Value <int>("count")); }
/// <summary> /// Gets a count of all of the shop's fulfillments. /// </summary> /// <param name="orderId">The order id to which the fulfillments belong.</param> /// <param name="options">Options for filtering the count.</param> /// <returns>The count of all fulfillments for the shop.</returns> public async Task <int> CountAsync(long orderId, ShopifyCountFilter options = null) { var req = RequestEngine.CreateRequest($"orders/{orderId}/fulfillments/count.json", Method.GET); //Add optional parameters to request if (options != null) { req.Parameters.AddRange(options.ToParameters(ParameterType.GetOrPost)); } var responseObject = await RequestEngine.ExecuteRequestAsync(_RestClient, req); //Response looks like { "count" : 123 }. Does not warrant its own class. return(responseObject.Value <int>("count")); }
/// <summary> /// Retrieves a list of all past and present <see cref="ShopifyCharge"/> objects. /// </summary> /// <param name="sinceId">Restricts results to any charge after the given id.</param> /// <param name="fields">A comma-separated list of fields to return.</param> /// <returns>The list of <see cref="ShopifyCharge"/> objects.</returns> public async Task <IEnumerable <ShopifyCharge> > ListAsync(long?sinceId = null, string fields = null) { IRestRequest req = RequestEngine.CreateRequest("application_charges.json", Method.GET, "application_charges"); if (string.IsNullOrEmpty(fields) == false) { req.AddParameter("fields", fields); } if (sinceId.HasValue) { req.AddParameter("since_id", sinceId); } return(await RequestEngine.ExecuteRequestAsync <List <ShopifyCharge> >(_RestClient, req)); }
/// <summary> /// Gets a list of all article tags for the given blog. /// </summary> /// <param name="blogId">The blog that the tags belong to.</param> /// <param name="limit">The number of tags to return</param> /// <param name="popular">A flag to indicate only to a certain number of the most popular tags.</param> public async Task <IEnumerable <string> > ListTagsForBlogAsync(long blogId, int?popular = null, int?limit = null) { var req = RequestEngine.CreateRequest($"blogs/{blogId}/articles/tags.json", Method.GET, "tags"); if (popular.HasValue) { req.AddQueryParameter("popular", popular.Value.ToString()); } if (limit.HasValue) { req.AddQueryParameter("limit", limit.Value.ToString()); } return(await RequestEngine.ExecuteRequestAsync <List <string> >(_RestClient, req)); }
/// <summary> /// Creates a new <see cref="ShopifyCustomCollection"/> Custom Collection /// </summary> /// <param name="customCollection">A new <see cref="ShopifyCustomCollection"/>. Id should be set to null.</param> /// <returns>The new <see cref="ShopifyCustomCollection"/>.</returns> public virtual async Task <ShopifyCustomCollection> CreateAsync(ShopifyCustomCollection customCollection) { string reqPath = "custom_collections.json"; IRestRequest req = RequestEngine.CreateRequest(reqPath, Method.POST, "custom_collection"); //Build the request body Dictionary <string, object> body = new Dictionary <string, object>() { { "custom_collection", customCollection } }; req.AddJsonBody(body); return(await RequestEngine.ExecuteRequestAsync <ShopifyCustomCollection>(_RestClient, req)); }
/// <summary> /// Creates a new <see cref="ShopifyTheme"/> on the store. The theme always starts out with a role of /// "unpublished." If the theme has a different role, it will be assigned that only after all of its /// files have been extracted and stored by Shopify (which might take a couple of minutes). /// </summary> /// <param name="theme">The new <see cref="ShopifyTheme"/>.</param> /// <param name="sourceUrl">A URL that points to the .zip file containing the theme's source files.</param> /// <returns>The new <see cref="ShopifyTheme"/>.</returns> public async Task <ShopifyTheme> CreateAsync(ShopifyTheme theme, string sourceUrl) { IRestRequest req = RequestEngine.CreateRequest("themes.json", Method.POST, "theme"); //Convert the theme to a dictionary, which will let us add the src URL to the request. var body = theme.ToDictionary(); if (string.IsNullOrEmpty(sourceUrl) == false) { body["src"] = sourceUrl; } req.AddJsonBody(new { theme = body }); return(await RequestEngine.ExecuteRequestAsync <ShopifyTheme>(_RestClient, req)); }
/// <summary> /// Creates a new article on the given blog. /// </summary> /// <param name="blogId">The blog that the article will belong to.</param> /// <param name="article">The article being created. Id should be null.</param> /// <param name="metafields">Optional metafield data that can be returned by the <see cref="ShopifyMetaFieldService"/>.</param> public async Task <ShopifyArticle> CreateAsync(long blogId, ShopifyArticle article, IEnumerable <ShopifyMetaField> metafields = null) { var req = RequestEngine.CreateRequest($"blogs/{blogId}/articles.json", Method.POST, "article"); var body = article.ToDictionary(); if (metafields != null) { body.Add("metafields", metafields); } req.AddJsonBody(new { article = body }); return(await RequestEngine.ExecuteRequestAsync <ShopifyArticle>(_RestClient, req)); }
/// <summary> /// Updates a blog. /// </summary> /// <param name="blog">The updated blog. Id should not be null.</param> /// <param name="metafields">Optional metafield data that can be returned by the <see cref="ShopifyMetaFieldService"/>.</param> public async Task <ShopifyBlog> UpdateAsync(ShopifyBlog blog, IEnumerable <ShopifyMetaField> metafields = null) { var request = RequestEngine.CreateRequest($"blogs/{blog.Id.Value}.json", RestSharp.Method.PUT, "blog"); var body = blog.ToDictionary(); if (metafields != null && metafields.Count() >= 1) { body.Add("metafields", metafields); } request.AddJsonBody(new { blog = body }); return(await RequestEngine.ExecuteRequestAsync <ShopifyBlog>(_RestClient, request)); }
/// <summary> /// Gets a list of up to 250 of the shop's transactions. /// </summary> /// <param name="orderId">The order id to which the fulfillments belong.</param> /// <param name="sinceId">Filters the results to after the specified id.</param> /// <returns>The list of transactions.</returns> public virtual async Task <IEnumerable <ShopifyTransaction> > ListAsync(long orderId, long?sinceId = null) { var req = RequestEngine.CreateRequest($"orders/{orderId}/transactions.json", Method.GET, "transactions"); //Add optional parameters to request if (sinceId != null) { req.Parameters.Add(new Parameter() { Name = "since_id", Value = sinceId, Type = ParameterType.GetOrPost }); } return(await RequestEngine.ExecuteRequestAsync <List <ShopifyTransaction> >(_RestClient, req)); }
/// <summary> /// Searches through a shop's customers for the given search query. /// </summary> /// <param name="query">The search query, in format of 'Bob country:United States', which would search for customers in the United States with a name like 'Bob'.</param> /// <param name="order">An optional string to order the results, in format of 'field_name DESC'. Default is 'last_order_date DESC'.</param> /// <param name="options">Options for filtering the results.</param> /// <returns>A list of matching customers.</returns> public async Task <IEnumerable <ShopifyCustomer> > SearchAsync(string query, string order = null, ShopifyFilterOptions options = null) { IRestRequest req = RequestEngine.CreateRequest("customers/search.json", Method.GET, "customers"); req.AddQueryParameter("query", query); if (string.IsNullOrEmpty(order) == false) { req.AddQueryParameter("order", order); } if (options != null) { req.Parameters.AddRange(options.ToParameters(ParameterType.QueryString)); } return(await RequestEngine.ExecuteRequestAsync <List <ShopifyCustomer> >(_RestClient, req)); }
/// <summary> /// Updates the given <see cref="ShopifyPage"/>. Id must not be null. /// </summary> /// <param name="pageId">The <see cref="ShopifyPage"/> pageId to update.</param> /// <param name="metafield">The <see cref="ShopifyMetaField"/> to update.</param> /// <returns>The updated <see cref="ShopifyMetaField"/>.</returns> public virtual async Task <ShopifyMetaField> UpdateMetafieldAsync(long pageId, ShopifyMetaField metafield) { var requestPath = $"pages/{pageId}/metafields.json"; var method = Method.POST; if (metafield.Id.HasValue) { requestPath = $"pages/{pageId}/metafields/{metafield.Id.Value}.json"; method = Method.PUT; } IRestRequest req = RequestEngine.CreateRequest(requestPath, method, "metafield"); req.AddJsonBody(new { metafield }); return(await RequestEngine.ExecuteRequestAsync <ShopifyMetaField>(_RestClient, req)); }
/// <summary> /// Gets a list of up to 250 of the shop's ProductImages. /// </summary> /// <param name="productId">The id of the product that counted images belong to.</param> /// <param name="fields"> /// An optional, comma-separated list of fields to include in the response. /// </param> /// <param name="sinceId"> /// Restricts results to after the specified id. /// </param> /// <returns>The list of <see cref="ShopifyProductImage"/>.</returns> /// <remarks> /// Unlike most list commands, this one only accepts the since_id and fields filters. /// </remarks> public virtual async Task <IEnumerable <ShopifyProductImage> > ListAsync(long productId, long?sinceId = null, string fields = null) { var req = RequestEngine.CreateRequest($"products/{productId}/images.json", Method.GET, "images"); //Add optional parameters to request if (sinceId.HasValue) { req.AddParameter("since_id", sinceId.Value); } if (string.IsNullOrEmpty(fields) == false) { req.AddParameter("fields", fields); } return(await RequestEngine.ExecuteRequestAsync <List <ShopifyProductImage> >(_RestClient, req)); }
/// <summary> /// Gets a list of up to 250 of the customer's orders. /// </summary> /// <param name="customerId">The id of the customer to list orders for.</param> /// <param name="options">Options for filtering the list.</param> /// <returns>The list of orders matching the filter.</returns> public async Task <IEnumerable <ShopifyOrder> > ListForCustomerAsync(long customerId, ShopifyOrderFilter options = null) { IRestRequest req = RequestEngine.CreateRequest("orders.json", Method.GET, "orders"); //Add the customer id to the filter req.Parameters.Add(new Parameter() { Name = "customer_id", Value = customerId, Type = ParameterType.GetOrPost }); //Add optional parameters to request if (options != null) { req.Parameters.AddRange(options.ToParameters(ParameterType.GetOrPost)); } return(await RequestEngine.ExecuteRequestAsync <List <ShopifyOrder> >(_RestClient, req)); }
/// <summary> /// Returns a list of events for the given subject and subject type. A full list of supported subject types can be found at https://help.shopify.com/api/reference/event /// </summary> /// <param name="options">Options for filtering the result.</param> /// <param name="subjectId">Restricts results to just one subject item, e.g. all changes on a product.</param> /// <param name="subjectType">The subject's type, e.g. 'Order' or 'Product'. Known subject types are 'Articles', 'Blogs', 'Custom_Collections', 'Comments', 'Orders', 'Pages', 'Products' and 'Smart_Collections'. A current list of subject types can be found at https://help.shopify.com/api/reference/event </param> public async Task <IEnumerable <ShopifyEvent> > ListAsync(long subjectId, string subjectType, ShopifyEventListFilter options = null) { // Ensure the subject type is plural if (!subjectType.Substring(subjectType.Length - 1).Equals("s", System.StringComparison.OrdinalIgnoreCase)) { subjectType = subjectType + "s"; } var req = RequestEngine.CreateRequest($"{subjectType?.ToLower()}/{subjectId}/events.json", Method.GET, "events"); //Add optional parameters to request if (options != null) { req.Parameters.AddRange(options.ToParameters(ParameterType.GetOrPost)); } return(await RequestEngine.ExecuteRequestAsync <List <ShopifyEvent> >(_RestClient, req)); }
/// <summary> /// Gets a list of the metafields for a specified resource. Leave both resourceType and resourceId null for shop metafields. /// </summary> /// <param name="resourceType">The type of shopify resource to obtain metafields for. This could be variants, products, orders, customers, custom_collections.</param> /// <param name="resourceId">The Id for the resource type.</param> /// <param name="options">The <see cref="ShopifyMetaFieldFilter"/> used to filter results</param> /// <returns></returns> public async Task <IEnumerable <ShopifyMetaField> > ListAsync(long?resourceId, string resourceType = null, ShopifyMetaFieldFilter options = null) { string reqPath = "metafields.json"; if (resourceType != null && resourceId != null) { reqPath = $"{resourceType}/{resourceId}/metafields.json"; } IRestRequest req = RequestEngine.CreateRequest(reqPath, Method.GET, "metafields"); //Add optional parameters to request if (options != null) { req.Parameters.AddRange(options.ToParameters(ParameterType.GetOrPost)); } return(await RequestEngine.ExecuteRequestAsync <List <ShopifyMetaField> >(_RestClient, req)); }
/// <summary> /// Gets a count of all of the shop's webhooks. /// </summary> /// <param name="address">An optional filter for the address property. When used, this method will only count webhooks with the given address.</param> /// <param name="topic">An optional filter for the topic property. When used, this method will only count webhooks with the given topic. A full list of topics can be found at https://help.shopify.com/api/reference/webhook. </param> /// <returns>The count of all webhooks for the shop.</returns> public virtual async Task <int> CountAsync(string address = null, string topic = null) { IRestRequest req = RequestEngine.CreateRequest("webhooks/count.json", Method.GET); //Add optional parameters to request if (string.IsNullOrEmpty(address) == false) { req.AddParameter("address", address); } if (!string.IsNullOrEmpty(topic)) { req.AddParameter("topic", topic); } JToken responseObject = await RequestEngine.ExecuteRequestAsync(_RestClient, req); //Response looks like { "count" : 123 }. Does not warrant its own class. return(responseObject.Value <int>("count")); }
/// <summary> /// Gets a count of all of the shop's redirects. /// </summary> /// <param name="path">An optional parameter that filters the result to redirects with the given path.</param> /// <param name="target">An optional parameter that filters the result to redirects with the given target.</param> /// <returns>The count of all redirects for the shop.</returns> public async Task <int> CountAsync(string path = null, string target = null) { IRestRequest req = RequestEngine.CreateRequest("redirects/count.json", Method.GET); //Add optional parameters to request if (string.IsNullOrEmpty(path) == false) { req.AddParameter("path", path); } if (string.IsNullOrEmpty(target) == false) { req.AddParameter("target", target); } JToken responseObject = await RequestEngine.ExecuteRequestAsync(_RestClient, req); //Response looks like { "count" : 123 }. Does not warrant its own class. return(responseObject.Value <int>("count")); }