diff --git a/Nop.Plugin.Api.Client/App.config b/Nop.Plugin.Api.Client/App.config
new file mode 100644
index 0000000..62c8f44
--- /dev/null
+++ b/Nop.Plugin.Api.Client/App.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/Nop.Plugin.Api.Client/Clients/BaseRestClient.cs b/Nop.Plugin.Api.Client/Clients/BaseRestClient.cs
new file mode 100644
index 0000000..eba5b18
--- /dev/null
+++ b/Nop.Plugin.Api.Client/Clients/BaseRestClient.cs
@@ -0,0 +1,217 @@
+using System;
+using System.Globalization;
+using System.Net;
+using System.Text;
+using Nop.Plugin.Api.Client.Exceptions;
+using Nop.Plugin.Api.Client.Security;
+using Nop.Plugin.Api.Client.Serialization;
+using Polly;
+using RestSharp;
+using RestSharp.Authenticators;
+using RestSharp.Deserializers;
+using RestSharp.Extensions;
+using RestSharp.Serializers;
+
+namespace Nop.Plugin.Api.Client.Clients
+{
+ public abstract class BaseRestClient
+ {
+ private readonly NopApiClient _parent;
+
+ private const int DefaultRetryAttempts = 10;
+
+ private const int DefaultDelayBetweenRetryAttemptsInMs = 250;
+
+ private Token _currentToken;
+
+ private IDeserializer _deserializer;
+
+ private ISerializer _serializer;
+
+
+ protected BaseRestClient(NopApiClient parent)
+ {
+ _parent = parent;
+ }
+
+ protected RestRequest GetRequest(string resource, Method method = Method.GET)
+ {
+ return new RestRequest(resource, method) { RequestFormat = DataFormat.Json };
+ }
+
+ protected IRestResponse Execute(
+ IRestRequest request,
+ bool throwIfError = true,
+ int retryAttempts = DefaultRetryAttempts,
+ int waitTimeBetweenAttempts = DefaultDelayBetweenRetryAttemptsInMs)
+ where T : new()
+ {
+ InitRequest(request);
+
+ var policy = GetPolicy>(retryAttempts, waitTimeBetweenAttempts);
+
+ return policy.Execute(
+ () =>
+ {
+ var response = GetClient().Execute(request);
+
+ if (throwIfError)
+ {
+ Process(request, response);
+ }
+
+ return response;
+ });
+ }
+
+ protected ISerializer Serializer
+ {
+ get => _serializer ?? (_serializer = new NewtonsoftSerializer());
+
+ set => _serializer = value;
+ }
+
+ protected IDeserializer Deserializer
+ {
+ get => _deserializer ?? (_deserializer = new NewtonsoftSerializer());
+
+ set => _deserializer = value;
+ }
+
+ private void Process(IRestRequest request, IRestResponse response)
+ {
+ if (response.ResponseStatus == ResponseStatus.Error && response.ErrorException != null)
+ {
+ // This is likely a transport issue such as the underlying connection was closed
+ throw new NopApiClientException(
+ $"Request to {request.Method}:{response.ResponseUri} {response.StatusCode} failed with exception",
+ true);
+ }
+
+ if (response.ResponseStatus == ResponseStatus.Error)
+ {
+ throw new NopApiClientException(
+ $"Failed to connect to REST API {request.Resource}, status: {response.StatusCode}",
+ true);
+ }
+
+ ThrowErrorIfAny(response);
+ }
+
+ protected bool HasError(IRestResponse response)
+ {
+ if (response?.Request == null)
+ {
+ return false;
+ }
+
+ return response.StatusCode != HttpStatusCode.OK && response.StatusCode != HttpStatusCode.Accepted
+ && response.StatusCode != HttpStatusCode.Created
+ && response.StatusCode != HttpStatusCode.Continue
+ && response.StatusCode != HttpStatusCode.NoContent;
+ }
+
+ protected void ThrowErrorIfAny(IRestResponse response, string message = null)
+ {
+ if (response?.Request == null)
+ {
+ throw new NopApiClientException("null response");
+ }
+
+ if (HasError(response))
+ {
+ NopApiClientExceptionDetails exceptionDetails = null;
+
+ if (response.Request.RequestFormat == DataFormat.Json)
+ {
+ if (!JsonSerializationUtility.TryDeserialize(response.Content, out exceptionDetails))
+ {
+ if (exceptionDetails == null && response.ErrorException != null)
+ {
+ exceptionDetails = new NopApiClientExceptionDetails
+ {
+ Message = response.ErrorException.Message,
+ ExceptionType = response.ErrorException.GetType().Name,
+ //ExceptionMessage = response.ErrorException.Message,
+ StackTrace = response.ErrorException.StackTrace
+ };
+ }
+ }
+ }
+
+ throw new NopApiClientException(
+ response.StatusCode,
+ response.ResponseUri != null ? response.ResponseUri.ToString() : string.Empty,
+ response.Request.Method.ToString(),
+ message,
+ exceptionDetails);
+ }
+
+ if (response.ErrorException != null)
+ {
+ throw new NopApiClientException(
+ response.StatusCode,
+ response.ResponseUri != null ? response.ResponseUri.ToString() : string.Empty,
+ response.Request.Method.ToString(),
+ response.ErrorException);
+ }
+ }
+
+ private RestClient GetClient()
+ {
+ var client = new RestClient(_parent.ServerUrl);
+
+ ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11;
+
+ // Override with Newtonsoft JSON Handler
+ client.AddHandler("application/json", Deserializer);
+ client.AddHandler("text/json", Deserializer);
+ client.AddHandler("text/x-json", Deserializer);
+ client.AddHandler("text/javascript", Deserializer);
+ client.AddHandler("*+json", Deserializer);
+
+ client.Authenticator = new OAuth2AuthorizationRequestHeaderAuthenticator(
+ CurrentToken.AccessToken,
+ CurrentToken.TokenType);
+
+ return client;
+ }
+
+ protected Token CurrentToken => _currentToken ?? (_currentToken = GetToken());
+
+ private Token GetToken()
+ {
+ var client = new TokenClient(new Uri(_parent.ServerUrl));
+
+ return client.GetToken(_parent.ClientId, _parent.Secret);
+ }
+
+ private void InitRequest(IRestRequest request)
+ {
+ request.OnBeforeDeserialization = resp =>
+ {
+ // for individual resources when there's an error to make
+ // sure that RestException props are populated
+ if ((int)resp.StatusCode >= 400)
+ {
+ // have to read the bytes so .Content doesn't get populated
+ const string restException = "{{ \"RestException\" : {0} }}";
+ var content = resp.RawBytes.AsString(); //get the response content
+ var newJson = string.Format(restException, content);
+
+ resp.Content = null;
+ resp.RawBytes = Encoding.UTF8.GetBytes(newJson.ToString(CultureInfo.InvariantCulture));
+ }
+ };
+ }
+
+ private static Policy GetPolicy(int retryAttempts, int waitTimeBetweenAttempts)
+ {
+ return Policy.Handle(ex => ex.CanRetry).WaitAndRetry(
+ retryAttempts,
+ attempt => TimeSpan.FromMilliseconds(waitTimeBetweenAttempts));
+ }
+ }
+}
+
+
diff --git a/Nop.Plugin.Api.Client/Clients/OrdersClient.cs b/Nop.Plugin.Api.Client/Clients/OrdersClient.cs
new file mode 100644
index 0000000..cd36db5
--- /dev/null
+++ b/Nop.Plugin.Api.Client/Clients/OrdersClient.cs
@@ -0,0 +1,73 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) Lindell Technologies All Rights Reserved.
+// Information Contained Herein is Proprietary and Confidential.
+//
+// -----------------------------------------------------------------------
+
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using Nop.Plugin.Api.Client.DTOs.Orders;
+
+namespace Nop.Plugin.Api.Client.Clients
+{
+ public class OrdersClient : BaseRestClient
+ {
+ internal OrdersClient(NopApiClient parent) : base(parent)
+ {
+ }
+
+ public IList GetOrders(int sinceId = 0, DateTime? createdAtMin = null, DateTime? createdAtMax = null, int? customerId = null, int page = 1, int limit = 50)
+ {
+ var request = GetRequest("api/orders");
+
+
+ if (sinceId > 0)
+ {
+ request.AddQueryParameter("sinceId", sinceId.ToString());
+ }
+
+ if (createdAtMin.HasValue)
+ {
+ request.AddQueryParameter("createdAtMin", createdAtMin.Value.ToString(CultureInfo.InvariantCulture));
+ }
+
+ if (createdAtMax.HasValue)
+ {
+ request.AddQueryParameter("createdAtMax", createdAtMax.Value.ToString(CultureInfo.InvariantCulture));
+ }
+
+ if (customerId.GetValueOrDefault() > 0)
+ {
+ request.AddQueryParameter("customerId", customerId.GetValueOrDefault().ToString());
+ }
+
+ if (page > 0)
+ {
+ request.AddQueryParameter("page", page.ToString());
+ }
+
+ if (limit > 0)
+ {
+ request.AddQueryParameter("limit", Math.Min(250, limit).ToString());
+ }
+
+
+ return Execute(request).Data.Orders;
+ }
+
+ public IList GetOrders(IEnumerable ids)
+ {
+ var request = GetRequest("api/orders");
+
+ if (ids != null)
+ {
+ request.AddQueryParameter("ids", string.Join(",", ids.Select(s => s.ToString())));
+ }
+
+ return Execute(request).Data.Orders;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Nop.Plugin.Api.Client/DTOs/AddressDto.cs b/Nop.Plugin.Api.Client/DTOs/AddressDto.cs
new file mode 100644
index 0000000..1fb8600
--- /dev/null
+++ b/Nop.Plugin.Api.Client/DTOs/AddressDto.cs
@@ -0,0 +1,80 @@
+using Newtonsoft.Json;
+
+namespace Nop.Plugin.Api.Client.DTOs
+{
+ [JsonObject(Title = "address")]
+ public class AddressDto
+ {
+ ///
+ /// Gets or sets the first name
+ ///
+ [JsonProperty("first_name")]
+ public string FirstName { get; set; }
+
+ ///
+ /// Gets or sets the last name
+ ///
+ [JsonProperty("last_name")]
+ public string LastName { get; set; }
+
+ ///
+ /// Gets or sets the email
+ ///
+ [JsonProperty("email")]
+ public string Email { get; set; }
+
+ ///
+ /// Gets or sets the company
+ ///
+ [JsonProperty("company")]
+ public string Company { get; set; }
+
+ ///
+ /// Gets or sets the country name
+ ///
+ [JsonProperty("country")]
+ public string CountryName { get; set; }
+
+ ///
+ /// Gets or sets the city
+ ///
+ [JsonProperty("city")]
+ public string City { get; set; }
+
+ ///
+ /// Gets or sets the address 1
+ ///
+ [JsonProperty("address1")]
+ public string Address1 { get; set; }
+
+ ///
+ /// Gets or sets the address 2
+ ///
+ [JsonProperty("address2")]
+ public string Address2 { get; set; }
+
+ ///
+ /// Gets or sets the zip/postal code
+ ///
+ [JsonProperty("zip_postal_code")]
+ public string ZipPostalCode { get; set; }
+
+ ///
+ /// Gets or sets the phone number
+ ///
+ [JsonProperty("phone_number")]
+ public string PhoneNumber { get; set; }
+
+ ///
+ /// Gets or sets the fax number
+ ///
+ [JsonProperty("fax_number")]
+ public string FaxNumber { get; set; }
+
+ ///
+ /// Gets or sets the state/province
+ ///
+ [JsonProperty("province")]
+ public string StateProvinceName { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/Nop.Plugin.Api.Client/DTOs/Categories/CategoriesCountRootObject.cs b/Nop.Plugin.Api.Client/DTOs/Categories/CategoriesCountRootObject.cs
new file mode 100644
index 0000000..408053e
--- /dev/null
+++ b/Nop.Plugin.Api.Client/DTOs/Categories/CategoriesCountRootObject.cs
@@ -0,0 +1,10 @@
+using Newtonsoft.Json;
+
+namespace Nop.Plugin.Api.Client.DTOs.Categories
+{
+ public class CategoriesCountRootObject
+ {
+ [JsonProperty("count")]
+ public int Count { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/Nop.Plugin.Api.Client/DTOs/Categories/CategoriesRootObject.cs b/Nop.Plugin.Api.Client/DTOs/Categories/CategoriesRootObject.cs
new file mode 100644
index 0000000..ddd4ba8
--- /dev/null
+++ b/Nop.Plugin.Api.Client/DTOs/Categories/CategoriesRootObject.cs
@@ -0,0 +1,17 @@
+using System.Collections.Generic;
+using Newtonsoft.Json;
+
+namespace Nop.Plugin.Api.Client.DTOs.Categories
+{
+ public class CategoriesRootObject
+ {
+ public CategoriesRootObject()
+ {
+ Categories = new List();
+ }
+
+ [JsonProperty("categories")]
+ public IList Categories { get; set; }
+
+ }
+}
\ No newline at end of file
diff --git a/Nop.Plugin.Api.Client/DTOs/Categories/CategoryDto.cs b/Nop.Plugin.Api.Client/DTOs/Categories/CategoryDto.cs
new file mode 100644
index 0000000..6bae5df
--- /dev/null
+++ b/Nop.Plugin.Api.Client/DTOs/Categories/CategoryDto.cs
@@ -0,0 +1,145 @@
+using System;
+using System.Collections.Generic;
+using Newtonsoft.Json;
+using Nop.Plugin.Api.Client.DTOs.Images;
+using Nop.Plugin.Api.Client.DTOs.Languages;
+
+namespace Nop.Plugin.Api.Client.DTOs.Categories
+{
+ [JsonObject(Title = "category")]
+ public class CategoryDto
+ {
+ [JsonProperty("id")]
+ public string Id { get; set; }
+
+ [JsonProperty("name")]
+ public string Name { get; set; }
+
+ ///
+ /// Gets or sets the localized names
+ ///
+ [JsonProperty("localized_names")]
+ public List LocalizedNames { get; set; }
+
+ ///
+ /// Gets or sets the description
+ ///
+ [JsonProperty("description")]
+ public string Description { get; set; }
+
+ ///
+ /// Gets or sets a value of used category template identifier
+ ///
+ [JsonProperty("category_template_id")]
+ public int? CategoryTemplateId { get; set; }
+
+ ///
+ /// Gets or sets the meta keywords
+ ///
+ [JsonProperty("meta_keywords")]
+ public string MetaKeywords { get; set; }
+
+ ///
+ /// Gets or sets the meta description
+ ///
+ [JsonProperty("meta_description")]
+ public string MetaDescription { get; set; }
+
+ ///
+ /// Gets or sets the meta title
+ ///
+ [JsonProperty("meta_title")]
+ public string MetaTitle { get; set; }
+
+ ///
+ /// Gets or sets the parent category identifier
+ ///
+ [JsonProperty("parent_category_id")]
+ public int? ParentCategoryId { get; set; }
+
+ ///
+ /// Gets or sets the page size
+ ///
+ [JsonProperty("page_size")]
+ public int? PageSize { get; set; }
+
+ ///
+ /// Gets or sets the available customer selectable page size options
+ ///
+ [JsonProperty("page_size_options")]
+ public string PageSizeOptions { get; set; }
+
+ ///
+ /// Gets or sets the available price ranges
+ ///
+ [JsonProperty("price_ranges")]
+ public string PriceRanges { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether to show the category on home page
+ ///
+ [JsonProperty("show_on_home_page")]
+ public bool? ShowOnHomePage { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether to include this category in the top menu
+ ///
+ [JsonProperty("include_in_top_menu")]
+ public bool? IncludeInTopMenu { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether this category has discounts applied
+ /// The same as if we run category.AppliedDiscounts.Count > 0
+ /// We use this property for performance optimization:
+ /// if this property is set to false, then we do not need to load Applied Discounts navigation property
+ ///
+ ///
+ [JsonProperty("has_discounts_applied")]
+ public bool? HasDiscountsApplied { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether the entity is published
+ ///
+ [JsonProperty("published")]
+ public bool? Published { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether the entity has been deleted
+ ///
+ [JsonProperty("deleted")]
+ public bool? Deleted { get; set; }
+
+ ///
+ /// Gets or sets the display order
+ ///
+ [JsonProperty("display_order")]
+ public int? DisplayOrder { get; set; }
+
+ ///
+ /// Gets or sets the date and time of instance creation
+ ///
+ [JsonProperty("created_on_utc")]
+ public DateTime? CreatedOnUtc { get; set; }
+
+ ///
+ /// Gets or sets the date and time of instance update
+ ///
+ [JsonProperty("updated_on_utc")]
+ public DateTime? UpdatedOnUtc { get; set; }
+
+ [JsonProperty("role_ids")]
+ public List RoleIds { get; set; }
+
+ [JsonProperty("discount_ids")]
+ public List DiscountIds { get; set; }
+
+ [JsonProperty("store_ids")]
+ public List StoreIds { get; set; }
+
+ [JsonProperty("image")]
+ public ImageDto Image { get; set; }
+
+ [JsonProperty("se_name")]
+ public string SeName { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/Nop.Plugin.Api.Client/DTOs/CustomerRoles/CustomerRoleDto.cs b/Nop.Plugin.Api.Client/DTOs/CustomerRoles/CustomerRoleDto.cs
new file mode 100644
index 0000000..d1670aa
--- /dev/null
+++ b/Nop.Plugin.Api.Client/DTOs/CustomerRoles/CustomerRoleDto.cs
@@ -0,0 +1,64 @@
+using Newtonsoft.Json;
+
+namespace Nop.Plugin.Api.Client.DTOs.CustomerRoles
+{
+ [JsonObject(Title = "customer_role")]
+ public class CustomerRoleDto
+ {
+ ///
+ /// Gets or sets the store ID
+ ///
+ [JsonProperty("id")]
+ public string Id { get; set; }
+
+ ///
+ /// Gets or sets the customer role name
+ ///
+ [JsonProperty("name")]
+ public string Name { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether the customer role is marked as free shiping
+ ///
+ [JsonProperty("free_shipping")]
+ public bool? FreeShipping { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether the customer role is marked as tax exempt
+ ///
+ [JsonProperty("tax_exempt")]
+
+ public bool? TaxExempt { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether the customer role is active
+ ///
+ [JsonProperty("active")]
+ public bool? Active { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether the customer role is system
+ ///
+ [JsonProperty("is_system_role")]
+ public bool? IsSystemRole { get; set; }
+
+ ///
+ /// Gets or sets the customer role system name
+ ///
+ [JsonProperty("system_name")]
+ public string SystemName { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether the customers must change passwords after a specified time
+ ///
+ [JsonProperty("enable_password_lifetime")]
+ public bool? EnablePasswordLifetime { get; set; }
+
+ ///
+ /// Gets or sets a product identifier that is required by this customer role.
+ /// A customer is added to this customer role once a specified product is purchased.
+ ///
+ [JsonProperty("purchased_with_product_id")]
+ public int? PurchasedWithProductId { get; set; }
+ }
+}
diff --git a/Nop.Plugin.Api.Client/DTOs/CustomerRoles/CustomerRolesRootObject.cs b/Nop.Plugin.Api.Client/DTOs/CustomerRoles/CustomerRolesRootObject.cs
new file mode 100644
index 0000000..5f2c46f
--- /dev/null
+++ b/Nop.Plugin.Api.Client/DTOs/CustomerRoles/CustomerRolesRootObject.cs
@@ -0,0 +1,17 @@
+using System.Collections.Generic;
+using Newtonsoft.Json;
+
+namespace Nop.Plugin.Api.Client.DTOs.CustomerRoles
+{
+ public class CustomerRolesRootObject
+ {
+ public CustomerRolesRootObject()
+ {
+ CustomerRoles = new List();
+ }
+
+ [JsonProperty("customer_roles")]
+ public IList CustomerRoles { get; set; }
+
+ }
+}
diff --git a/Nop.Plugin.Api.Client/DTOs/Customers/BaseCustomerDto.cs b/Nop.Plugin.Api.Client/DTOs/Customers/BaseCustomerDto.cs
new file mode 100644
index 0000000..81bd9b3
--- /dev/null
+++ b/Nop.Plugin.Api.Client/DTOs/Customers/BaseCustomerDto.cs
@@ -0,0 +1,127 @@
+using System;
+using System.Collections.Generic;
+using Newtonsoft.Json;
+
+namespace Nop.Plugin.Api.Client.DTOs.Customers
+{
+ public class BaseCustomerDto
+ {
+ private List _roleIds;
+
+ [JsonProperty("id")]
+ public string Id { get; set; }
+
+ [JsonProperty("username")]
+ public string Username { get; set; }
+ ///
+ /// Gets or sets the email
+ ///
+ [JsonProperty("email")]
+ public string Email { get; set; }
+
+ [JsonProperty("first_name")]
+ public string FirstName { get; set; }
+
+ [JsonProperty("last_name")]
+ public string LastName { get; set; }
+
+ [JsonProperty("language_id")]
+ public string LanguageId { get; set; }
+
+ [JsonProperty("date_of_birth")]
+ public DateTime? DateOfBirth { get; set; }
+
+ [JsonProperty("gender")]
+ public string Gender { get; set; }
+
+ ///
+ /// Gets or sets the admin comment
+ ///
+ [JsonProperty("admin_comment")]
+ public string AdminComment { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether the customer is tax exempt
+ ///
+ [JsonProperty("is_tax_exempt")]
+ public bool? IsTaxExempt { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether this customer has some products in the shopping cart
+ /// The same as if we run this.ShoppingCartItems.Count > 0
+ /// We use this property for performance optimization:
+ /// if this property is set to false, then we do not need to load "ShoppingCartItems" navigation property for each page load
+ /// It's used only in a couple of places in the presentation layer
+ ///
+ ///
+ [JsonProperty("has_shopping_cart_items")]
+ public bool? HasShoppingCartItems { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether the customer is active
+ ///
+ [JsonProperty("active")]
+ public bool? Active { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether the customer has been deleted
+ ///
+ [JsonProperty("deleted")]
+ public bool? Deleted { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether the customer account is system
+ ///
+ [JsonProperty("is_system_account")]
+ public bool? IsSystemAccount { get; set; }
+
+ ///
+ /// Gets or sets the customer system name
+ ///
+ [JsonProperty("system_name")]
+ public string SystemName { get; set; }
+
+ ///
+ /// Gets or sets the last IP address
+ ///
+ [JsonProperty("last_ip_address")]
+ public string LastIpAddress { get; set; }
+
+ ///
+ /// Gets or sets the date and time of entity creation
+ ///
+ [JsonProperty("created_on_utc")]
+ public DateTime? CreatedOnUtc { get; set; }
+
+ ///
+ /// Gets or sets the date and time of last login
+ ///
+ [JsonProperty("last_login_date_utc")]
+ public DateTime? LastLoginDateUtc { get; set; }
+
+ ///
+ /// Gets or sets the date and time of last activity
+ ///
+ [JsonProperty("last_activity_date_utc")]
+ public DateTime? LastActivityDateUtc { get; set; }
+
+ ///
+ /// Gets or sets the store identifier in which customer registered
+ ///
+ [JsonProperty("registered_in_store_id")]
+ public int? RegisteredInStoreId { get; set; }
+
+ ///
+ /// Gets or sets the subscribed to newsletter property
+ ///
+ [JsonProperty("subscribed_to_newsletter")]
+ public bool SubscribedToNewsletter { get; set; }
+
+ [JsonProperty("role_ids")]
+ public List RoleIds
+ {
+ get => _roleIds ?? (_roleIds = new List());
+ set => _roleIds = value;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Nop.Plugin.Api.Client/DTOs/Customers/CustomerDto.cs b/Nop.Plugin.Api.Client/DTOs/Customers/CustomerDto.cs
new file mode 100644
index 0000000..de7bf1f
--- /dev/null
+++ b/Nop.Plugin.Api.Client/DTOs/Customers/CustomerDto.cs
@@ -0,0 +1,60 @@
+using System.Collections.Generic;
+using Newtonsoft.Json;
+using Nop.Plugin.Api.Client.DTOs.ShoppingCarts;
+
+namespace Nop.Plugin.Api.Client.DTOs.Customers
+{
+ [JsonObject(Title = "customer")]
+ public class CustomerDto : BaseCustomerDto
+ {
+ private ICollection _shoppingCartItems;
+ private ICollection _addresses;
+
+ [JsonIgnore]
+ [JsonProperty("password")]
+ public string Password { get; set; }
+
+ #region Navigation properties
+
+ ///
+ /// Gets or sets shopping cart items
+ ///
+ [JsonProperty("shopping_cart_items")]
+ public ICollection ShoppingCartItems
+ {
+ get => _shoppingCartItems ?? (_shoppingCartItems = new List());
+ set => _shoppingCartItems = value;
+ }
+
+ ///
+ /// Default billing address
+ ///
+ [JsonProperty("billing_address")]
+ public AddressDto BillingAddress { get; set; }
+
+ ///
+ /// Default shipping address
+ ///
+ [JsonProperty("shipping_address")]
+ public AddressDto ShippingAddress { get; set; }
+
+ ///
+ /// Gets or sets customer addresses
+ ///
+ [JsonProperty("addresses")]
+ public ICollection CustomerAddresses
+ {
+ get
+ {
+ if (_addresses == null)
+ {
+ _addresses = new List();
+ }
+
+ return _addresses;
+ }
+ set => _addresses = value;
+ }
+ #endregion
+ }
+}
diff --git a/Nop.Plugin.Api.Client/DTOs/Customers/CustomerForShoppingCartItemDto.cs b/Nop.Plugin.Api.Client/DTOs/Customers/CustomerForShoppingCartItemDto.cs
new file mode 100644
index 0000000..f37275a
--- /dev/null
+++ b/Nop.Plugin.Api.Client/DTOs/Customers/CustomerForShoppingCartItemDto.cs
@@ -0,0 +1,32 @@
+using System.Collections.Generic;
+using Newtonsoft.Json;
+
+namespace Nop.Plugin.Api.Client.DTOs.Customers
+{
+ // We need this DTO object to avoid loop in the entity to dto mappings. The difference is the missing ShoppingCartItems collection.
+ [JsonObject(Title = "customers")]
+ public class CustomerForShoppingCartItemDto : BaseCustomerDto
+ {
+ #region Navigation properties
+
+ ///
+ /// Default billing address
+ ///
+ [JsonProperty("billing_address")]
+ public AddressDto BillingAddress { get; set; }
+
+ ///
+ /// Default shipping address
+ ///
+ [JsonProperty("shipping_address")]
+ public AddressDto ShippingAddress { get; set; }
+
+ ///
+ /// Gets or sets customer addresses
+ ///
+ [JsonProperty("addresses")]
+ public ICollection Addresses { get; set; }
+
+ #endregion
+ }
+}
diff --git a/Nop.Plugin.Api.Client/DTOs/Customers/CustomersCountRootObject.cs b/Nop.Plugin.Api.Client/DTOs/Customers/CustomersCountRootObject.cs
new file mode 100644
index 0000000..3e027a9
--- /dev/null
+++ b/Nop.Plugin.Api.Client/DTOs/Customers/CustomersCountRootObject.cs
@@ -0,0 +1,10 @@
+using Newtonsoft.Json;
+
+namespace Nop.Plugin.Api.Client.DTOs.Customers
+{
+ public class CustomersCountRootObject
+ {
+ [JsonProperty("count")]
+ public int Count { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/Nop.Plugin.Api.Client/DTOs/Customers/CustomersRootObject.cs b/Nop.Plugin.Api.Client/DTOs/Customers/CustomersRootObject.cs
new file mode 100644
index 0000000..7ba6248
--- /dev/null
+++ b/Nop.Plugin.Api.Client/DTOs/Customers/CustomersRootObject.cs
@@ -0,0 +1,17 @@
+using System.Collections.Generic;
+using Newtonsoft.Json;
+
+namespace Nop.Plugin.Api.Client.DTOs.Customers
+{
+ public class CustomersRootObject
+ {
+ public CustomersRootObject()
+ {
+ Customers = new List();
+ }
+
+ [JsonProperty("customers")]
+ public IList Customers { get; set; }
+
+ }
+}
\ No newline at end of file
diff --git a/Nop.Plugin.Api.Client/DTOs/Customers/OrderCustomerDto.cs b/Nop.Plugin.Api.Client/DTOs/Customers/OrderCustomerDto.cs
new file mode 100644
index 0000000..246ee9a
--- /dev/null
+++ b/Nop.Plugin.Api.Client/DTOs/Customers/OrderCustomerDto.cs
@@ -0,0 +1,7 @@
+namespace Nop.Plugin.Api.Client.DTOs.Customers
+{
+ public class OrderCustomerDto : BaseCustomerDto
+ {
+
+ }
+}
\ No newline at end of file
diff --git a/Nop.Plugin.Api.Client/DTOs/Errors/ErrorsRootObject.cs b/Nop.Plugin.Api.Client/DTOs/Errors/ErrorsRootObject.cs
new file mode 100644
index 0000000..93e66da
--- /dev/null
+++ b/Nop.Plugin.Api.Client/DTOs/Errors/ErrorsRootObject.cs
@@ -0,0 +1,12 @@
+using System.Collections.Generic;
+using Newtonsoft.Json;
+
+namespace Nop.Plugin.Api.Client.DTOs.Errors
+{
+ public class ErrorsRootObject
+ {
+ [JsonProperty("errors")]
+ public Dictionary> Errors { get; set; }
+
+ }
+}
\ No newline at end of file
diff --git a/Nop.Plugin.Api.Client/DTOs/Images/ImageDto.cs b/Nop.Plugin.Api.Client/DTOs/Images/ImageDto.cs
new file mode 100644
index 0000000..4a1ac68
--- /dev/null
+++ b/Nop.Plugin.Api.Client/DTOs/Images/ImageDto.cs
@@ -0,0 +1,19 @@
+using Newtonsoft.Json;
+
+namespace Nop.Plugin.Api.Client.DTOs.Images
+{
+ public class ImageDto
+ {
+ [JsonProperty("src")]
+ public string Src { get; set; }
+
+ [JsonProperty("attachment")]
+ public string Attachment { get; set; }
+
+ [JsonIgnore]
+ public byte[] Binary { get; set; }
+
+ [JsonIgnore]
+ public string MimeType { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/Nop.Plugin.Api.Client/DTOs/Images/ImageMappingDto.cs b/Nop.Plugin.Api.Client/DTOs/Images/ImageMappingDto.cs
new file mode 100644
index 0000000..48c74b6
--- /dev/null
+++ b/Nop.Plugin.Api.Client/DTOs/Images/ImageMappingDto.cs
@@ -0,0 +1,13 @@
+using Newtonsoft.Json;
+
+namespace Nop.Plugin.Api.Client.DTOs.Images
+{
+ public class ImageMappingDto : ImageDto
+ {
+ [JsonProperty("id")]
+ public int Id { get; set; }
+
+ [JsonProperty("position")]
+ public int Position { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/Nop.Plugin.Api.Client/DTOs/Languages/LanguageDto.cs b/Nop.Plugin.Api.Client/DTOs/Languages/LanguageDto.cs
new file mode 100644
index 0000000..982d2b9
--- /dev/null
+++ b/Nop.Plugin.Api.Client/DTOs/Languages/LanguageDto.cs
@@ -0,0 +1,75 @@
+using System.Collections.Generic;
+using Newtonsoft.Json;
+
+namespace Nop.Plugin.Api.Client.DTOs.Languages
+{
+ [JsonObject(Title = "language")]
+ public class LanguageDto
+ {
+ ///
+ /// Gets or sets the store ID
+ ///
+ [JsonProperty("id")]
+ public string Id { get; set; }
+
+ ///
+ /// Gets or sets the name
+ ///
+ [JsonProperty("name")]
+ public string Name { get; set; }
+
+ ///
+ /// Gets or sets the language culture
+ ///
+ [JsonProperty("language_culture")]
+ public string LanguageCulture { get; set; }
+
+ ///
+ /// Gets or sets the unique SEO code
+ ///
+ [JsonProperty("unique_seo_code")]
+ public string UniqueSeoCode { get; set; }
+
+ ///
+ /// Gets or sets the flag image file name
+ ///
+ [JsonProperty("flag_image_file_name")]
+ public string FlagImageFileName { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether the language supports "Right-to-left"
+ ///
+ [JsonProperty("rtl")]
+ public bool? Rtl { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether the entity is limited/restricted to certain stores
+ ///
+ [JsonProperty("limited_to_stores")]
+ public bool? LimitedToStores { get; set; }
+
+ ///
+ /// Gets or sets the identifier of the default currency for this language; 0 is set when we use the default currency display order
+ ///
+ [JsonProperty("default_currency_id")]
+ public int? DefaultCurrencyId { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether the language is published
+ ///
+ [JsonProperty("published")]
+ public bool? Published { get; set; }
+
+ ///
+ /// Gets or sets the display order
+ ///
+ [JsonProperty("display_order")]
+ public int? DisplayOrder { get; set; }
+
+ ///
+ /// Gets or sets the store ids in which the language is enabled
+ ///
+ [JsonProperty("store_ids")]
+ public List StoreIds { get; set; }
+ }
+}
diff --git a/Nop.Plugin.Api.Client/DTOs/Languages/LanguagesRootObject.cs b/Nop.Plugin.Api.Client/DTOs/Languages/LanguagesRootObject.cs
new file mode 100644
index 0000000..09109ca
--- /dev/null
+++ b/Nop.Plugin.Api.Client/DTOs/Languages/LanguagesRootObject.cs
@@ -0,0 +1,17 @@
+using System.Collections.Generic;
+using Newtonsoft.Json;
+
+namespace Nop.Plugin.Api.Client.DTOs.Languages
+{
+ public class LanguagesRootObject
+ {
+ public LanguagesRootObject()
+ {
+ Languages = new List();
+ }
+
+ [JsonProperty("languages")]
+ public IList Languages { get; set; }
+
+ }
+}
diff --git a/Nop.Plugin.Api.Client/DTOs/Languages/LocalizedNameDto.cs b/Nop.Plugin.Api.Client/DTOs/Languages/LocalizedNameDto.cs
new file mode 100644
index 0000000..9ad7e22
--- /dev/null
+++ b/Nop.Plugin.Api.Client/DTOs/Languages/LocalizedNameDto.cs
@@ -0,0 +1,19 @@
+using Newtonsoft.Json;
+
+namespace Nop.Plugin.Api.Client.DTOs.Languages
+{
+ public class LocalizedNameDto
+ {
+ ///
+ /// Gets or sets the language identifier
+ ///
+ [JsonProperty("language_id")]
+ public int? LanguageId { get; set; }
+
+ ///
+ /// Gets or sets the localized name
+ ///
+ [JsonProperty("localized_name")]
+ public string LocalizedName { get; set; }
+ }
+}
diff --git a/Nop.Plugin.Api.Client/DTOs/NewsLetterSubscriptions/NewsLetterSubscriptionDto.cs b/Nop.Plugin.Api.Client/DTOs/NewsLetterSubscriptions/NewsLetterSubscriptionDto.cs
new file mode 100644
index 0000000..1a5710b
--- /dev/null
+++ b/Nop.Plugin.Api.Client/DTOs/NewsLetterSubscriptions/NewsLetterSubscriptionDto.cs
@@ -0,0 +1,39 @@
+using System;
+using Newtonsoft.Json;
+
+namespace Nop.Plugin.Api.Client.DTOs.NewsLetterSubscriptions
+{
+ [JsonObject(Title = "news_letter_subscription")]
+ public class NewsLetterSubscriptionDto
+ {
+ ///
+ /// Gets or sets the id
+ ///
+ [JsonProperty("id")]
+ public string Id { get; set; }
+
+ ///
+ /// Gets or sets the email
+ ///
+ [JsonProperty("email")]
+ public string Email { get; set; }
+
+ ///
+ /// Gets or sets whether the subscription is active
+ ///
+ [JsonProperty("active")]
+ public bool Active { get; set; }
+
+ ///
+ /// Gets or sets whether the subscription is active
+ ///
+ [JsonProperty("store_id")]
+ public int StoreId { get; set; }
+
+ ///
+ /// Gets or sets created on utc date
+ ///
+ [JsonProperty("created_on_utc")]
+ public DateTime? CreatedOnUtc { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/Nop.Plugin.Api.Client/DTOs/NewsLetterSubscriptions/NewsLetterSubscriptionsRootObject.cs b/Nop.Plugin.Api.Client/DTOs/NewsLetterSubscriptions/NewsLetterSubscriptionsRootObject.cs
new file mode 100644
index 0000000..eba36fb
--- /dev/null
+++ b/Nop.Plugin.Api.Client/DTOs/NewsLetterSubscriptions/NewsLetterSubscriptionsRootObject.cs
@@ -0,0 +1,17 @@
+using System.Collections.Generic;
+using Newtonsoft.Json;
+
+namespace Nop.Plugin.Api.Client.DTOs.NewsLetterSubscriptions
+{
+ public class NewsLetterSubscriptionsRootObject
+ {
+ public NewsLetterSubscriptionsRootObject()
+ {
+ NewsLetterSubscriptions = new List();
+ }
+
+ [JsonProperty("news_letter_subscriptions")]
+ public IList NewsLetterSubscriptions { get; set; }
+
+ }
+}
\ No newline at end of file
diff --git a/Nop.Plugin.Api.Client/DTOs/OrderItems/OrderItemDto.cs b/Nop.Plugin.Api.Client/DTOs/OrderItems/OrderItemDto.cs
new file mode 100644
index 0000000..bccad1f
--- /dev/null
+++ b/Nop.Plugin.Api.Client/DTOs/OrderItems/OrderItemDto.cs
@@ -0,0 +1,123 @@
+using System;
+using System.Collections.Generic;
+using Newtonsoft.Json;
+using Nop.Plugin.Api.Client.DTOs.Products;
+
+namespace Nop.Plugin.Api.Client.DTOs.OrderItems
+{
+ [JsonObject(Title = "order_item")]
+ public class OrderItemDto
+ {
+ ///
+ /// Gets or sets the id
+ ///
+ [JsonProperty("id")]
+ public string Id { get; set; }
+
+ ///
+ /// Gets or sets the selected attributes
+ ///
+ [JsonProperty("product_attributes")]
+ public List Attributes { get; set; }
+
+ ///
+ /// Gets or sets the quantity
+ ///
+ [JsonProperty("quantity")]
+ public int? Quantity { get; set; }
+
+ ///
+ /// Gets or sets the unit price in primary store currency (incl tax)
+ ///
+ [JsonProperty("unit_price_incl_tax")]
+ public decimal? UnitPriceInclTax { get; set; }
+
+ ///
+ /// Gets or sets the unit price in primary store currency (excl tax)
+ ///
+ [JsonProperty("unit_price_excl_tax")]
+ public decimal? UnitPriceExclTax { get; set; }
+
+ ///
+ /// Gets or sets the price in primary store currency (incl tax)
+ ///
+ [JsonProperty("price_incl_tax")]
+ public decimal? PriceInclTax { get; set; }
+
+ ///
+ /// Gets or sets the price in primary store currency (excl tax)
+ ///
+ [JsonProperty("price_excl_tax")]
+ public decimal? PriceExclTax { get; set; }
+
+ ///
+ /// Gets or sets the discount amount (incl tax)
+ ///
+ [JsonProperty("discount_amount_incl_tax")]
+ public decimal? DiscountAmountInclTax { get; set; }
+
+ ///
+ /// Gets or sets the discount amount (excl tax)
+ ///
+ [JsonProperty("discount_amount_excl_tax")]
+ public decimal? DiscountAmountExclTax { get; set; }
+
+ ///
+ /// Gets or sets the original cost of this order item (when an order was placed), qty 1
+ ///
+ [JsonProperty("original_product_cost")]
+ public decimal? OriginalProductCost { get; set; }
+
+ ///
+ /// Gets or sets the attribute description
+ ///
+ [JsonProperty("attribute_description")]
+ public string AttributeDescription { get; set; }
+
+ ///
+ /// Gets or sets the download count
+ ///
+ [JsonProperty("download_count")]
+ public int? DownloadCount { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether download is activated
+ ///
+ [JsonProperty("isDownload_activated")]
+ public bool? IsDownloadActivated { get; set; }
+
+ ///
+ /// Gets or sets a license download identifier (in case this is a downloadable product)
+ ///
+ [JsonProperty("license_download_id")]
+ public int? LicenseDownloadId { get; set; }
+
+ ///
+ /// Gets or sets the total weight of one item
+ /// It's nullable for compatibility with the previous version of nopCommerce where was no such property
+ ///
+ [JsonProperty("item_weight")]
+ public decimal? ItemWeight { get; set; }
+
+ ///
+ /// Gets or sets the rental product start date (null if it's not a rental product)
+ ///
+ [JsonProperty("rental_start_date_utc")]
+ public DateTime? RentalStartDateUtc { get; set; }
+
+ ///
+ /// Gets or sets the rental product end date (null if it's not a rental product)
+ ///
+ [JsonProperty("rental_end_date_utc")]
+ public DateTime? RentalEndDateUtc { get; set; }
+
+ ///
+ /// Gets the product
+ ///
+ [JsonProperty("product")]
+ public ProductDto Product { get; set; }
+
+ [JsonProperty("product_id")]
+ public int? ProductId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/Nop.Plugin.Api.Client/DTOs/OrderItems/OrderItemsCountRootObject.cs b/Nop.Plugin.Api.Client/DTOs/OrderItems/OrderItemsCountRootObject.cs
new file mode 100644
index 0000000..e949562
--- /dev/null
+++ b/Nop.Plugin.Api.Client/DTOs/OrderItems/OrderItemsCountRootObject.cs
@@ -0,0 +1,10 @@
+using Newtonsoft.Json;
+
+namespace Nop.Plugin.Api.Client.DTOs.OrderItems
+{
+ public class OrderItemsCountRootObject
+ {
+ [JsonProperty("count")]
+ public int Count { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/Nop.Plugin.Api.Client/DTOs/OrderItems/OrderItemsRootObject.cs b/Nop.Plugin.Api.Client/DTOs/OrderItems/OrderItemsRootObject.cs
new file mode 100644
index 0000000..eab7835
--- /dev/null
+++ b/Nop.Plugin.Api.Client/DTOs/OrderItems/OrderItemsRootObject.cs
@@ -0,0 +1,17 @@
+using System.Collections.Generic;
+using Newtonsoft.Json;
+
+namespace Nop.Plugin.Api.Client.DTOs.OrderItems
+{
+ public class OrderItemsRootObject
+ {
+ public OrderItemsRootObject()
+ {
+ OrderItems = new List();
+ }
+
+ [JsonProperty("order_items")]
+ public IList OrderItems { get; set; }
+
+ }
+}
\ No newline at end of file
diff --git a/Nop.Plugin.Api.Client/DTOs/Orders/OrderDto.cs b/Nop.Plugin.Api.Client/DTOs/Orders/OrderDto.cs
new file mode 100644
index 0000000..7ee014d
--- /dev/null
+++ b/Nop.Plugin.Api.Client/DTOs/Orders/OrderDto.cs
@@ -0,0 +1,281 @@
+using System;
+using System.Collections.Generic;
+using Newtonsoft.Json;
+using Nop.Plugin.Api.Client.DTOs.Customers;
+using Nop.Plugin.Api.Client.DTOs.OrderItems;
+
+namespace Nop.Plugin.Api.Client.DTOs.Orders
+{
+ [JsonObject(Title = "order")]
+ public class OrderDto
+ {
+ ///
+ /// Gets or sets a value indicating the order id
+ ///
+ [JsonProperty("id")]
+ public string Id { get; set; }
+
+ [JsonProperty("store_id")]
+ public int? StoreId { get; set; }
+
+ ///
+ /// Gets or sets the payment method system name
+ ///
+ [JsonProperty("payment_method_system_name")]
+ public string PaymentMethodSystemName { get; set; }
+
+ ///
+ /// Gets or sets the customer currency code (at the moment of order placing)
+ ///
+ [JsonProperty("customer_currency_code")]
+ public string CustomerCurrencyCode { get; set; }
+
+ ///
+ /// Gets or sets the currency rate
+ ///
+ [JsonProperty("currency_rate")]
+ public decimal? CurrencyRate { get; set; }
+
+ ///
+ /// Gets or sets the customer tax display type identifier
+ ///
+ [JsonProperty("customer_tax_display_type_id")]
+ public int? CustomerTaxDisplayTypeId { get; set; }
+
+ ///
+ /// Gets or sets the VAT number (the European Union Value Added Tax)
+ ///
+ [JsonProperty("vat_number")]
+ public string VatNumber { get; set; }
+
+ ///
+ /// Gets or sets the order subtotal (incl tax)
+ ///
+ [JsonProperty("order_subtotal_incl_tax")]
+ public decimal? OrderSubtotalInclTax { get; set; }
+
+ ///
+ /// Gets or sets the order subtotal (excl tax)
+ ///
+ [JsonProperty("order_subtotal_excl_tax")]
+ public decimal? OrderSubtotalExclTax { get; set; }
+
+ ///
+ /// Gets or sets the order subtotal discount (incl tax)
+ ///
+ [JsonProperty("order_sub_total_discount_incl_tax")]
+ public decimal? OrderSubTotalDiscountInclTax { get; set; }
+
+ ///
+ /// Gets or sets the order subtotal discount (excl tax)
+ ///
+ [JsonProperty("order_sub_total_discount_excl_tax")]
+ public decimal? OrderSubTotalDiscountExclTax { get; set; }
+
+ ///
+ /// Gets or sets the order shipping (incl tax)
+ ///
+ [JsonProperty("order_shipping_incl_tax")]
+ public decimal? OrderShippingInclTax { get; set; }
+
+ ///
+ /// Gets or sets the order shipping (excl tax)
+ ///
+ [JsonProperty("order_shipping_excl_tax")]
+ public decimal? OrderShippingExclTax { get; set; }
+
+ ///
+ /// Gets or sets the payment method additional fee (incl tax)
+ ///
+ [JsonProperty("payment_method_additional_fee_incl_tax")]
+ public decimal? PaymentMethodAdditionalFeeInclTax { get; set; }
+
+ ///
+ /// Gets or sets the payment method additional fee (excl tax)
+ ///
+ [JsonProperty("payment_method_additional_fee_excl_tax")]
+ public decimal? PaymentMethodAdditionalFeeExclTax { get; set; }
+
+ ///
+ /// Gets or sets the tax rates
+ ///
+ [JsonProperty("tax_rates")]
+ public string TaxRates { get; set; }
+
+ ///
+ /// Gets or sets the order tax
+ ///
+ [JsonProperty("order_tax")]
+ public decimal? OrderTax { get; set; }
+
+ ///
+ /// Gets or sets the order discount (applied to order total)
+ ///
+ [JsonProperty("order_discount")]
+ public decimal? OrderDiscount { get; set; }
+
+ ///
+ /// Gets or sets the order total
+ ///
+ [JsonProperty("order_total")]
+ public decimal? OrderTotal { get; set; }
+
+ ///
+ /// Gets or sets the refunded amount
+ ///
+ [JsonProperty("refunded_amount")]
+ public decimal? RefundedAmount { get; set; }
+
+ ///
+ /// Gets or sets the value indicating whether reward points were earned for this order
+ ///
+ [JsonProperty("reward_points_were_added")]
+ public bool? RewardPointsWereAdded { get; set; }
+
+ ///
+ /// Gets or sets the checkout attribute description
+ ///
+ [JsonProperty("checkout_attribute_description")]
+ public string CheckoutAttributeDescription { get; set; }
+
+ ///
+ /// Gets or sets the customer language identifier
+ ///
+ [JsonProperty("customer_language_id")]
+ public int? CustomerLanguageId { get; set; }
+
+ ///
+ /// Gets or sets the affiliate identifier
+ ///
+ [JsonProperty("affiliate_id")]
+ public int? AffiliateId { get; set; }
+
+ ///
+ /// Gets or sets the customer IP address
+ ///
+ [JsonProperty("customer_ip")]
+ public string CustomerIp { get; set; }
+
+ ///
+ /// Gets or sets the authorization transaction identifier
+ ///
+ [JsonProperty("authorization_transaction_id")]
+ public string AuthorizationTransactionId { get; set; }
+
+ ///
+ /// Gets or sets the authorization transaction code
+ ///
+ [JsonProperty("authorization_transaction_code")]
+ public string AuthorizationTransactionCode { get; set; }
+
+ ///
+ /// Gets or sets the authorization transaction result
+ ///
+ [JsonProperty("authorization_transaction_result")]
+ public string AuthorizationTransactionResult { get; set; }
+
+ ///
+ /// Gets or sets the capture transaction identifier
+ ///
+ [JsonProperty("capture_transaction_id")]
+ public string CaptureTransactionId { get; set; }
+
+ ///
+ /// Gets or sets the capture transaction result
+ ///
+ [JsonProperty("capture_transaction_result")]
+ public string CaptureTransactionResult { get; set; }
+
+ ///
+ /// Gets or sets the subscription transaction identifier
+ ///
+ [JsonProperty("subscription_transaction_id")]
+ public string SubscriptionTransactionId { get; set; }
+
+ ///
+ /// Gets or sets the paid date and time
+ ///
+ [JsonProperty("paid_date_utc")]
+ public DateTime? PaidDateUtc { get; set; }
+
+ ///
+ /// Gets or sets the shipping method
+ ///
+ [JsonProperty("shipping_method")]
+ public string ShippingMethod { get; set; }
+
+ ///
+ /// Gets or sets the shipping rate computation method identifier
+ ///
+ [JsonProperty("shipping_rate_computation_method_system_name")]
+ public string ShippingRateComputationMethodSystemName { get; set; }
+
+ ///
+ /// Gets or sets the serialized CustomValues (values from ProcessPaymentRequest)
+ ///
+ [JsonProperty("custom_values_xml")]
+ public string CustomValuesXml { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether the entity has been deleted
+ ///
+ [JsonProperty("deleted")]
+ public bool? Deleted { get; set; }
+
+ ///
+ /// Gets or sets the date and time of order creation
+ ///
+ [JsonProperty("created_on_utc")]
+ public DateTime? CreatedOnUtc { get; set; }
+
+ ///
+ /// Gets or sets the customer
+ ///
+ [JsonProperty("customer")]
+ public OrderCustomerDto Customer { get; set; }
+
+ [JsonProperty("customer_id")]
+ public int? CustomerId { get; set; }
+
+ ///
+ /// Gets or sets the billing address
+ ///
+ [JsonProperty("billing_address")]
+ public AddressDto BillingAddress { get; set; }
+
+ ///
+ /// Gets or sets the shipping address
+ ///
+ [JsonProperty("shipping_address")]
+ public AddressDto ShippingAddress { get; set; }
+
+ ///
+ /// Gets or sets order items
+ ///
+ [JsonProperty("order_items")]
+ public ICollection OrderItemDtos { get; set; }
+
+ ///
+ /// Gets or sets the order status
+ ///
+ [JsonProperty("order_status")]
+ public string OrderStatus { get; set; }
+
+ ///
+ /// Gets or sets the payment status
+ ///
+ [JsonProperty("payment_status")]
+ public string PaymentStatus { get; set; }
+
+ ///
+ /// Gets or sets the shipping status
+ ///
+ [JsonProperty("shipping_status")]
+ public string ShippingStatus { get; set; }
+ ///
+ /// Gets or sets the customer tax display type
+ ///
+ [JsonProperty("customer_tax_display_type")]
+ public string CustomerTaxDisplayType { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/Nop.Plugin.Api.Client/DTOs/Orders/OrdersCountRootObject.cs b/Nop.Plugin.Api.Client/DTOs/Orders/OrdersCountRootObject.cs
new file mode 100644
index 0000000..ebfea1b
--- /dev/null
+++ b/Nop.Plugin.Api.Client/DTOs/Orders/OrdersCountRootObject.cs
@@ -0,0 +1,10 @@
+using Newtonsoft.Json;
+
+namespace Nop.Plugin.Api.Client.DTOs.Orders
+{
+ public class OrdersCountRootObject
+ {
+ [JsonProperty("count")]
+ public int Count { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/Nop.Plugin.Api.Client/DTOs/Orders/OrdersRootObject.cs b/Nop.Plugin.Api.Client/DTOs/Orders/OrdersRootObject.cs
new file mode 100644
index 0000000..01e806f
--- /dev/null
+++ b/Nop.Plugin.Api.Client/DTOs/Orders/OrdersRootObject.cs
@@ -0,0 +1,17 @@
+using System.Collections.Generic;
+using Newtonsoft.Json;
+
+namespace Nop.Plugin.Api.Client.DTOs.Orders
+{
+ public class OrdersRootObject
+ {
+ public OrdersRootObject()
+ {
+ Orders = new List();
+ }
+
+ [JsonProperty("orders")]
+ public List Orders { get; set; }
+
+ }
+}
\ No newline at end of file
diff --git a/Nop.Plugin.Api.Client/DTOs/Orders/SingleOrderRootObject.cs b/Nop.Plugin.Api.Client/DTOs/Orders/SingleOrderRootObject.cs
new file mode 100644
index 0000000..f930edb
--- /dev/null
+++ b/Nop.Plugin.Api.Client/DTOs/Orders/SingleOrderRootObject.cs
@@ -0,0 +1,10 @@
+using Newtonsoft.Json;
+
+namespace Nop.Plugin.Api.Client.DTOs.Orders
+{
+ public class SingleOrderRootObject
+ {
+ [JsonProperty("order")]
+ public OrderDto Order { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/Nop.Plugin.Api.Client/DTOs/ProductAttributes/ProductAttributeDto.cs b/Nop.Plugin.Api.Client/DTOs/ProductAttributes/ProductAttributeDto.cs
new file mode 100644
index 0000000..b30269b
--- /dev/null
+++ b/Nop.Plugin.Api.Client/DTOs/ProductAttributes/ProductAttributeDto.cs
@@ -0,0 +1,26 @@
+using Newtonsoft.Json;
+
+namespace Nop.Plugin.Api.Client.DTOs.ProductAttributes
+{
+ [JsonObject(Title = "product_attribute")]
+ public class ProductAttributeDto
+ {
+ ///
+ /// Gets or sets the product attribute id
+ ///
+ [JsonProperty("id")]
+ public string Id { get; set; }
+
+ ///
+ /// Gets or sets the name
+ ///
+ [JsonProperty("name")]
+ public string Name { get; set; }
+
+ ///
+ /// Gets or sets the description
+ ///
+ [JsonProperty("description")]
+ public string Description { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/Nop.Plugin.Api.Client/DTOs/ProductAttributes/ProductAttributesCountRootObject.cs b/Nop.Plugin.Api.Client/DTOs/ProductAttributes/ProductAttributesCountRootObject.cs
new file mode 100644
index 0000000..871b67c
--- /dev/null
+++ b/Nop.Plugin.Api.Client/DTOs/ProductAttributes/ProductAttributesCountRootObject.cs
@@ -0,0 +1,10 @@
+using Newtonsoft.Json;
+
+namespace Nop.Plugin.Api.Client.DTOs.ProductAttributes
+{
+ public class ProductAttributesCountRootObject
+ {
+ [JsonProperty("count")]
+ public int Count { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/Nop.Plugin.Api.Client/DTOs/ProductAttributes/ProductAttributesRootObjectDto.cs b/Nop.Plugin.Api.Client/DTOs/ProductAttributes/ProductAttributesRootObjectDto.cs
new file mode 100644
index 0000000..eb303da
--- /dev/null
+++ b/Nop.Plugin.Api.Client/DTOs/ProductAttributes/ProductAttributesRootObjectDto.cs
@@ -0,0 +1,17 @@
+using System.Collections.Generic;
+using Newtonsoft.Json;
+
+namespace Nop.Plugin.Api.Client.DTOs.ProductAttributes
+{
+ public class ProductAttributesRootObjectDto
+ {
+ public ProductAttributesRootObjectDto()
+ {
+ ProductAttributes = new List();
+ }
+
+ [JsonProperty("product_attributes")]
+ public IList ProductAttributes { get; set; }
+
+ }
+}
\ No newline at end of file
diff --git a/Nop.Plugin.Api.Client/DTOs/ProductCategoryMappings/ProductCategoryMappingsCountRootObject.cs b/Nop.Plugin.Api.Client/DTOs/ProductCategoryMappings/ProductCategoryMappingsCountRootObject.cs
new file mode 100644
index 0000000..c6b76e6
--- /dev/null
+++ b/Nop.Plugin.Api.Client/DTOs/ProductCategoryMappings/ProductCategoryMappingsCountRootObject.cs
@@ -0,0 +1,10 @@
+using Newtonsoft.Json;
+
+namespace Nop.Plugin.Api.Client.DTOs.ProductCategoryMappings
+{
+ public class ProductCategoryMappingsCountRootObject
+ {
+ [JsonProperty("count")]
+ public int Count { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/Nop.Plugin.Api.Client/DTOs/ProductCategoryMappings/ProductCategoryMappingsDto.cs b/Nop.Plugin.Api.Client/DTOs/ProductCategoryMappings/ProductCategoryMappingsDto.cs
new file mode 100644
index 0000000..4dd54b6
--- /dev/null
+++ b/Nop.Plugin.Api.Client/DTOs/ProductCategoryMappings/ProductCategoryMappingsDto.cs
@@ -0,0 +1,35 @@
+using Newtonsoft.Json;
+
+namespace Nop.Plugin.Api.Client.DTOs.ProductCategoryMappings
+{
+ [JsonObject(Title = "product_category_mapping")]
+ public class ProductCategoryMappingDto
+ {
+ [JsonProperty("id")]
+ public int Id { get; set; }
+
+ ///
+ /// Gets or sets the product identifier
+ ///
+ [JsonProperty("product_id")]
+ public int? ProductId { get; set; }
+
+ ///
+ /// Gets or sets the category identifier
+ ///
+ [JsonProperty("category_id")]
+ public int? CategoryId { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether the product is featured
+ ///
+ [JsonProperty("is_featured_product")]
+ public bool? IsFeaturedProduct { get; set; }
+
+ ///
+ /// Gets or sets the display order
+ ///
+ [JsonProperty("display_order")]
+ public int? DisplayOrder { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/Nop.Plugin.Api.Client/DTOs/ProductCategoryMappings/ProductCategoryMappingsRootObject.cs b/Nop.Plugin.Api.Client/DTOs/ProductCategoryMappings/ProductCategoryMappingsRootObject.cs
new file mode 100644
index 0000000..e017c4e
--- /dev/null
+++ b/Nop.Plugin.Api.Client/DTOs/ProductCategoryMappings/ProductCategoryMappingsRootObject.cs
@@ -0,0 +1,17 @@
+using System.Collections.Generic;
+using Newtonsoft.Json;
+
+namespace Nop.Plugin.Api.Client.DTOs.ProductCategoryMappings
+{
+ public class ProductCategoryMappingsRootObject
+ {
+ public ProductCategoryMappingsRootObject()
+ {
+ ProductCategoryMappingDtos = new List();
+ }
+
+ [JsonProperty("product_category_mappings")]
+ public IList ProductCategoryMappingDtos { get; set; }
+
+ }
+}
\ No newline at end of file
diff --git a/Nop.Plugin.Api.Client/DTOs/ProductItemAttributeDto.cs b/Nop.Plugin.Api.Client/DTOs/ProductItemAttributeDto.cs
new file mode 100644
index 0000000..90520b6
--- /dev/null
+++ b/Nop.Plugin.Api.Client/DTOs/ProductItemAttributeDto.cs
@@ -0,0 +1,14 @@
+using Newtonsoft.Json;
+
+namespace Nop.Plugin.Api.Client.DTOs
+{
+ [JsonObject(Title = "attribute")]
+ public class ProductItemAttributeDto
+ {
+ [JsonProperty("id")]
+ public int Id { get; set; }
+
+ [JsonProperty("value")]
+ public string Value { get; set; }
+ }
+}
diff --git a/Nop.Plugin.Api.Client/DTOs/Products/ProductAttributeMappingDto.cs b/Nop.Plugin.Api.Client/DTOs/Products/ProductAttributeMappingDto.cs
new file mode 100644
index 0000000..b79be42
--- /dev/null
+++ b/Nop.Plugin.Api.Client/DTOs/Products/ProductAttributeMappingDto.cs
@@ -0,0 +1,67 @@
+using System.Collections.Generic;
+using Newtonsoft.Json;
+
+namespace Nop.Plugin.Api.Client.DTOs.Products
+{
+ [JsonObject(Title = "attribute")]
+ public class ProductAttributeMappingDto
+ {
+ ///
+ /// Gets or sets the product attribute identifier
+ ///
+ [JsonProperty("id")]
+ public int Id { get; set; }
+
+ ///
+ /// Gets or sets the product attribute identifier
+ ///
+ [JsonProperty("product_attribute_id")]
+ public int ProductAttributeId { get; set; }
+
+ [JsonProperty("product_attribute_name")]
+ public string ProductAttributeName { get; set; }
+
+ ///
+ /// Gets or sets a value a text prompt
+ ///
+ [JsonProperty("text_prompt")]
+ public string TextPrompt { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether the entity is required
+ ///
+ [JsonProperty("is_required")]
+ public bool IsRequired { get; set; }
+
+ ///
+ /// Gets or sets the attribute control type identifier
+ ///
+ [JsonProperty("attribute_control_type_id")]
+ public int AttributeControlTypeId { get; set; }
+
+ ///
+ /// Gets or sets the display order
+ ///
+ [JsonProperty("display_order")]
+ public int DisplayOrder { get; set; }
+
+ ///
+ /// Gets or sets the default value (for textbox and multiline textbox)
+ ///
+ [JsonProperty("default_value")]
+ public string DefaultValue { get; set; }
+
+ ///
+ /// Gets the attribute control type
+ ///
+ [JsonProperty("attribute_control_type_name")]
+ public string AttributeControlType { get; set; }
+
+
+ ///
+ /// Gets the product attribute values
+ ///
+ [JsonProperty("attribute_values")]
+ public List ProductAttributeValues { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/Nop.Plugin.Api.Client/DTOs/Products/ProductAttributeValueDto.cs b/Nop.Plugin.Api.Client/DTOs/Products/ProductAttributeValueDto.cs
new file mode 100644
index 0000000..a7af63a
--- /dev/null
+++ b/Nop.Plugin.Api.Client/DTOs/Products/ProductAttributeValueDto.cs
@@ -0,0 +1,96 @@
+using Newtonsoft.Json;
+using Nop.Plugin.Api.Client.DTOs.Images;
+
+namespace Nop.Plugin.Api.Client.DTOs.Products
+{
+ [JsonObject(Title = "attribute_value")]
+ public class ProductAttributeValueDto
+ {
+ ///
+ /// Gets or sets the product attribute value id
+ ///
+ [JsonProperty("id")]
+ public int Id { get; set; }
+
+ ///
+ /// Gets or sets the attribute value type identifier
+ ///
+ [JsonProperty("type_id")]
+ public int? AttributeValueTypeId { get; set; }
+
+ ///
+ /// Gets or sets the associated product identifier (used only with AttributeValueType.AssociatedToProduct)
+ ///
+ [JsonProperty("associated_product_id")]
+ public int? AssociatedProductId { get; set; }
+
+ ///
+ /// Gets or sets the product attribute name
+ ///
+ [JsonProperty("name")]
+ public string Name { get; set; }
+
+ ///
+ /// Gets or sets the color RGB value (used with "Color squares" attribute type)
+ ///
+ [JsonProperty("color_squares_rgb")]
+ public string ColorSquaresRgb { get; set; }
+
+ ///
+ /// Gets or sets the picture ID for image square (used with "Image squares" attribute type)
+ ///
+ [JsonProperty("image_squares_image")]
+ public ImageDto ImageSquaresImage { get; set; }
+
+ ///
+ /// Gets or sets the price adjustment (used only with AttributeValueType.Simple)
+ ///
+ [JsonProperty("price_adjustment")]
+ public decimal? PriceAdjustment { get; set; }
+
+ ///
+ /// Gets or sets the weight adjustment (used only with AttributeValueType.Simple)
+ ///
+ [JsonProperty("weight_adjustment")]
+ public decimal? WeightAdjustment { get; set; }
+
+ ///
+ /// Gets or sets the attibute value cost (used only with AttributeValueType.Simple)
+ ///
+ [JsonProperty("cost")]
+ public decimal? Cost { get; set; }
+
+ ///
+ /// Gets or sets the quantity of associated product (used only with AttributeValueType.AssociatedToProduct)
+ ///
+ [JsonProperty("quantity")]
+ public int? Quantity { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether the value is pre-selected
+ ///
+ [JsonProperty("is_pre_selected")]
+ public bool? IsPreSelected { get; set; }
+
+ ///
+ /// Gets or sets the display order
+ ///
+ [JsonProperty("display_order")]
+ public int? DisplayOrder { get; set; }
+
+ ///
+ /// Gets or sets the picture (identifier) associated with this value. This picture should replace a product main picture once clicked (selected).
+ ///
+ [JsonIgnore]
+ public int? PictureId { get; set; }
+
+ [JsonProperty("product_image_id")]
+ public int? ProductPictureId { get; set; }
+
+ ///
+ /// Gets or sets the attribute value type
+ ///
+ [JsonProperty("type")]
+ public string AttributeValueType { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/Nop.Plugin.Api.Client/DTOs/Products/ProductDto.cs b/Nop.Plugin.Api.Client/DTOs/Products/ProductDto.cs
new file mode 100644
index 0000000..657e118
--- /dev/null
+++ b/Nop.Plugin.Api.Client/DTOs/Products/ProductDto.cs
@@ -0,0 +1,502 @@
+using System;
+using System.Collections.Generic;
+using Newtonsoft.Json;
+using Nop.Plugin.Api.Client.DTOs.Images;
+using Nop.Plugin.Api.Client.DTOs.Languages;
+
+namespace Nop.Plugin.Api.Client.DTOs.Products
+{
+ [JsonObject(Title = "product")]
+ public class ProductDto
+ {
+ ///
+ /// Gets or sets the product id
+ ///
+ [JsonProperty("id")]
+ public string Id { get; set; }
+
+ ///
+ /// Gets or sets the values indicating whether this product is visible in catalog or search results.
+ /// It's used when this product is associated to some "grouped" one
+ /// This way associated products could be accessed/added/etc only from a grouped product details page
+ ///
+ [JsonProperty("visible_individually")]
+ public bool? VisibleIndividually { get; set; }
+
+ ///
+ /// Gets or sets the name
+ ///
+ [JsonProperty("name")]
+ public string Name { get; set; }
+
+ ///
+ /// Gets or sets the localized names
+ ///
+ [JsonProperty("localized_names")]
+ public List LocalizedNames { get; set; }
+
+ ///
+ /// Gets or sets the short description
+ ///
+ [JsonProperty("short_description")]
+ public string ShortDescription { get; set; }
+ ///
+ /// Gets or sets the full description
+ ///
+ [JsonProperty("full_description")]
+ public string FullDescription { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether to show the product on home page
+ ///
+ [JsonProperty("show_on_home_page")]
+ public bool? ShowOnHomePage { get; set; }
+
+ ///
+ /// Gets or sets the meta keywords
+ ///
+ [JsonProperty("meta_keywords")]
+ public string MetaKeywords { get; set; }
+ ///
+ /// Gets or sets the meta description
+ ///
+ [JsonProperty("meta_description")]
+ public string MetaDescription { get; set; }
+ ///
+ /// Gets or sets the meta title
+ ///
+ [JsonProperty("meta_title")]
+ public string MetaTitle { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether the product allows customer reviews
+ ///
+ [JsonProperty("allow_customer_reviews")]
+ public bool? AllowCustomerReviews { get; set; }
+ ///
+ /// Gets or sets the rating sum (approved reviews)
+ ///
+ [JsonProperty("approved_rating_sum")]
+ public int? ApprovedRatingSum { get; set; }
+ ///
+ /// Gets or sets the rating sum (not approved reviews)
+ ///
+ [JsonProperty("not_approved_rating_sum")]
+ public int? NotApprovedRatingSum { get; set; }
+ ///
+ /// Gets or sets the total rating votes (approved reviews)
+ ///
+ [JsonProperty("approved_total_reviews")]
+ public int? ApprovedTotalReviews { get; set; }
+ ///
+ /// Gets or sets the total rating votes (not approved reviews)
+ ///
+ [JsonProperty("not_approved_total_reviews")]
+ public int? NotApprovedTotalReviews { get; set; }
+
+ ///
+ /// Gets or sets the SKU
+ ///
+ [JsonProperty("sku")]
+ public string Sku { get; set; }
+ ///
+ /// Gets or sets the manufacturer part number
+ ///
+ [JsonProperty("manufacturer_part_number")]
+ public string ManufacturerPartNumber { get; set; }
+ ///
+ /// Gets or sets the Global Trade Item Number (GTIN). These identifiers include UPC (in North America), EAN (in Europe), JAN (in Japan), and ISBN (for books).
+ ///
+ [JsonProperty("gtin")]
+ public string Gtin { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether the product is gift card
+ ///
+ [JsonProperty("is_gift_card")]
+ public bool? IsGiftCard { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether the product requires that other products are added to the cart (Product X requires Product Y)
+ ///
+ [JsonProperty("require_other_products")]
+ public bool? RequireOtherProducts { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether required products are automatically added to the cart
+ ///
+ [JsonProperty("automatically_add_required_products")]
+ public bool? AutomaticallyAddRequiredProducts { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether the product is download
+ ///
+ [JsonProperty("is_download")]
+ public bool? IsDownload { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether this downloadable product can be downloaded unlimited number of times
+ ///
+ [JsonProperty("unlimited_downloads")]
+ public bool? UnlimitedDownloads { get; set; }
+ ///
+ /// Gets or sets the maximum number of downloads
+ ///
+ [JsonProperty("max_number_of_downloads")]
+ public int? MaxNumberOfDownloads { get; set; }
+ ///
+ /// Gets or sets the number of days during customers keeps access to the file.
+ ///
+ [JsonProperty("download_expiration_days")]
+ public int? DownloadExpirationDays { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether the product has a sample download file
+ ///
+ [JsonProperty("has_sample_download")]
+ public bool? HasSampleDownload { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether the product has user agreement
+ ///
+ [JsonProperty("has_user_agreement")]
+ public bool? HasUserAgreement { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether the product is recurring
+ ///
+ [JsonProperty("is_recurring")]
+ public bool? IsRecurring { get; set; }
+ ///
+ /// Gets or sets the cycle length
+ ///
+ [JsonProperty("recurring_cycle_length")]
+ public int? RecurringCycleLength { get; set; }
+
+ ///
+ /// Gets or sets the total cycles
+ ///
+ [JsonProperty("recurring_total_cycles")]
+ public int? RecurringTotalCycles { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether the product is rental
+ ///
+ [JsonProperty("is_rental")]
+ public bool? IsRental { get; set; }
+ ///
+ /// Gets or sets the rental length for some period (price for this period)
+ ///
+ [JsonProperty("rental_price_length")]
+ public int? RentalPriceLength { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether the entity is ship enabled
+ ///
+ [JsonProperty("is_ship_enabled")]
+ public bool? IsShipEnabled { get; set; }
+ ///
+ /// Gets or sets a value indicating whether the entity is free shipping
+ ///
+ [JsonProperty("is_free_shipping")]
+ public bool? IsFreeShipping { get; set; }
+ ///
+ /// Gets or sets a value this product should be shipped separately (each item)
+ ///
+ [JsonProperty("ship_separately")]
+ public bool? ShipSeparately { get; set; }
+ ///
+ /// Gets or sets the additional shipping charge
+ ///
+ [JsonProperty("additional_shipping_charge")]
+ public decimal? AdditionalShippingCharge { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether the product is marked as tax exempt
+ ///
+ [JsonProperty("is_tax_exempt")]
+ public bool? IsTaxExempt { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether the product is telecommunications or broadcasting or electronic services
+ ///
+ [JsonProperty("is_telecommunications_or_broadcasting_or_electronic_services")]
+ public bool? IsTelecommunicationsOrBroadcastingOrElectronicServices { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether multiple warehouses are used for this product
+ ///
+ [JsonProperty("use_multiple_warehouses")]
+ public bool? UseMultipleWarehouses { get; set; }
+
+ ///
+ /// Gets or sets a value indicating how to manage inventory.
+ /// 0 - do not track inventory
+ /// 1 - track inventory
+ /// 2 - track invetory by attributes
+ ///
+ [JsonProperty("manage_inventory_method_id")]
+ public int? ManageInventoryMethodId { get; set; }
+
+ ///
+ /// Gets or sets the stock quantity
+ ///
+ [JsonProperty("stock_quantity")]
+ public int? StockQuantity { get; set; }
+ ///
+ /// Gets or sets a value indicating whether to display stock availability
+ ///
+ [JsonProperty("display_stock_availability")]
+ public bool? DisplayStockAvailability { get; set; }
+ ///
+ /// Gets or sets a value indicating whether to display stock quantity
+ ///
+ [JsonProperty("display_stock_quantity")]
+ public bool? DisplayStockQuantity { get; set; }
+ ///
+ /// Gets or sets the minimum stock quantity
+ ///
+ [JsonProperty("min_stock_quantity")]
+ public int? MinStockQuantity { get; set; }
+
+ ///
+ /// Gets or sets the quantity when admin should be notified
+ ///
+ [JsonProperty("notify_admin_for_quantity_below")]
+ public int? NotifyAdminForQuantityBelow { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether to back in stock subscriptions are allowed
+ ///
+ [JsonProperty("allow_back_in_stock_subscriptions")]
+ public bool? AllowBackInStockSubscriptions { get; set; }
+ ///
+ /// Gets or sets the order minimum quantity
+ ///
+ [JsonProperty("order_minimum_quantity")]
+ public int? OrderMinimumQuantity { get; set; }
+ ///
+ /// Gets or sets the order maximum quantity
+ ///
+ [JsonProperty("order_maximum_quantity")]
+ public int? OrderMaximumQuantity { get; set; }
+ ///
+ /// Gets or sets the comma seperated list of allowed quantities. null or empty if any quantity is allowed
+ ///
+ [JsonProperty("allowed_quantities")]
+ public string AllowedQuantities { get; set; }
+ ///
+ /// Gets or sets a value indicating whether we allow adding to the cart/wishlist only attribute combinations that exist and have stock greater than zero.
+ /// This option is used only when we have "manage inventory" set to "track inventory by product attributes"
+ ///
+ [JsonProperty("allow_adding_only_existing_attribute_combinations")]
+ public bool? AllowAddingOnlyExistingAttributeCombinations { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether to disable buy (Add to cart) button
+ ///
+ [JsonProperty("disable_buy_button")]
+ public bool? DisableBuyButton { get; set; }
+ ///
+ /// Gets or sets a value indicating whether to disable "Add to wishlist" button
+ ///
+ [JsonProperty("disable_wishlist_button")]
+ public bool? DisableWishlistButton { get; set; }
+ ///
+ /// Gets or sets a value indicating whether this item is available for Pre-Order
+ ///
+ [JsonProperty("available_for_pre_order")]
+ public bool? AvailableForPreOrder { get; set; }
+ ///
+ /// Gets or sets the start date and time of the product availability (for pre-order products)
+ ///
+ [JsonProperty("pre_order_availability_start_date_time_utc")]
+ public DateTime? PreOrderAvailabilityStartDateTimeUtc { get; set; }
+ ///
+ /// Gets or sets a value indicating whether to show "Call for Pricing" or "Call for quote" instead of price
+ ///
+ [JsonProperty("call_for_price")]
+ public bool? CallForPrice { get; set; }
+ ///
+ /// Gets or sets the price
+ ///
+ [JsonProperty("price")]
+ public decimal? Price { get; set; }
+ ///
+ /// Gets or sets the old price
+ ///
+ [JsonProperty("old_price")]
+ public decimal? OldPrice { get; set; }
+ ///
+ /// Gets or sets the product cost
+ ///
+ [JsonProperty("product_cost")]
+ public decimal? ProductCost { get; set; }
+ ///
+ /// Gets or sets the product special price
+ ///
+ [JsonProperty("special_price")]
+ public decimal? SpecialPrice { get; set; }
+ ///
+ /// Gets or sets the start date and time of the special price
+ ///
+ [JsonProperty("special_price_start_date_time_utc")]
+ public DateTime? SpecialPriceStartDateTimeUtc { get; set; }
+ ///
+ /// Gets or sets the end date and time of the special price
+ ///
+ [JsonProperty("special_price_end_date_time_utc")]
+ public DateTime? SpecialPriceEndDateTimeUtc { get; set; }
+ ///
+ /// Gets or sets a value indicating whether a customer enters price
+ ///
+ [JsonProperty("customer_enters_price")]
+ public bool? CustomerEntersPrice { get; set; }
+ ///
+ /// Gets or sets the minimum price entered by a customer
+ ///
+ [JsonProperty("minimum_customer_entered_price")]
+ public decimal? MinimumCustomerEnteredPrice { get; set; }
+ ///
+ /// Gets or sets the maximum price entered by a customer
+ ///
+ [JsonProperty("maximum_customer_entered_price")]
+ public decimal? MaximumCustomerEnteredPrice { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether base price (PAngV) is enabled. Used by German users.
+ ///
+ [JsonProperty("baseprice_enabled")]
+ public bool? BasePriceEnabled { get; set; }
+ ///
+ /// Gets or sets an amount in product for PAngV
+ ///
+ [JsonProperty("baseprice_amount")]
+ public decimal? BasePriceAmount { get; set; }
+
+ ///
+ /// Gets or sets a reference amount for PAngV
+ ///
+ [JsonProperty("baseprice_base_amount")]
+ public decimal? BasePriceBaseAmount { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether this product has tier prices configured
+ /// The same as if we run this.TierPrices.Count > 0
+ /// We use this property for performance optimization:
+ /// if this property is set to false, then we do not need to load tier prices navigation property
+ ///
+ ///
+ [JsonProperty("has_tier_prices")]
+ public bool? HasTierPrices { get; set; }
+ ///
+ /// Gets or sets a value indicating whether this product has discounts applied
+ /// The same as if we run this.AppliedDiscounts.Count > 0
+ /// We use this property for performance optimization:
+ /// if this property is set to false, then we do not need to load Applied Discounts navigation property
+ ///
+ ///
+ [JsonProperty("has_discounts_applied")]
+ public bool? HasDiscountsApplied { get; set; }
+
+ ///
+ /// Gets or sets the weight
+ ///
+ [JsonProperty("weight")]
+ public decimal? Weight { get; set; }
+ ///
+ /// Gets or sets the length
+ ///
+ [JsonProperty("length")]
+ public decimal? Length { get; set; }
+ ///
+ /// Gets or sets the width
+ ///
+ [JsonProperty("width")]
+ public decimal? Width { get; set; }
+ ///
+ /// Gets or sets the height
+ ///
+ [JsonProperty("height")]
+ public decimal? Height { get; set; }
+
+ ///
+ /// Gets or sets the available start date and time
+ ///
+ [JsonProperty("available_start_date_time_utc")]
+ public DateTime? AvailableStartDateTimeUtc { get; set; }
+ ///
+ /// Gets or sets the available end date and time
+ ///
+ [JsonProperty("available_end_date_time_utc")]
+ public DateTime? AvailableEndDateTimeUtc { get; set; }
+
+ ///
+ /// Gets or sets a display order.
+ /// This value is used when sorting associated products (used with "grouped" products)
+ /// This value is used when sorting home page products
+ ///
+ [JsonProperty("display_order")]
+ public int? DisplayOrder { get; set; }
+ ///
+ /// Gets or sets a value indicating whether the entity is published
+ ///
+ [JsonProperty("published")]
+ public bool? Published { get; set; }
+ ///
+ /// Gets or sets a value indicating whether the entity has been deleted
+ ///
+ [JsonProperty("deleted")]
+ public bool? Deleted { get; set; }
+
+ ///
+ /// Gets or sets the date and time of product creation
+ ///
+ [JsonProperty("created_on_utc")]
+ public DateTime? CreatedOnUtc { get; set; }
+ ///
+ /// Gets or sets the date and time of product update
+ ///
+ [JsonProperty("updated_on_utc")]
+ public DateTime? UpdatedOnUtc { get; set; }
+
+ ///
+ /// Gets or sets the product type
+ ///
+ [JsonProperty("product_type")]
+ public string ProductType { get; set; }
+
+ [JsonProperty("parent_grouped_product_id")]
+ public int? ParentGroupedProductId { get; set; }
+
+ [JsonProperty("role_ids")]
+ public List RoleIds { get; set; }
+
+ [JsonProperty("discount_ids")]
+ public List DiscountIds { get; set; }
+
+ [JsonProperty("store_ids")]
+ public List StoreIds { get; set; }
+
+ [JsonProperty("manufacturer_ids")]
+ public List ManufacturerIds { get; set; }
+
+ [JsonProperty("images")]
+ public List Images { get; set; }
+
+ [JsonProperty("attributes")]
+ public List ProductAttributeMappings { get; set; }
+
+ [JsonProperty("associated_product_ids")]
+ public List AssociatedProductIds { get; set; }
+
+ [JsonProperty("tags")]
+ public List Tags { get; set; }
+
+ [JsonProperty("vendor_id")]
+ public int? VendorId { get; set; }
+
+ [JsonProperty("se_name")]
+ public string SeName { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/Nop.Plugin.Api.Client/DTOs/Products/ProductsCountRootObject.cs b/Nop.Plugin.Api.Client/DTOs/Products/ProductsCountRootObject.cs
new file mode 100644
index 0000000..30e8e9c
--- /dev/null
+++ b/Nop.Plugin.Api.Client/DTOs/Products/ProductsCountRootObject.cs
@@ -0,0 +1,10 @@
+using Newtonsoft.Json;
+
+namespace Nop.Plugin.Api.Client.DTOs.Products
+{
+ public class ProductsCountRootObject
+ {
+ [JsonProperty("count")]
+ public int Count { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/Nop.Plugin.Api.Client/DTOs/Products/ProductsRootObjectDto.cs b/Nop.Plugin.Api.Client/DTOs/Products/ProductsRootObjectDto.cs
new file mode 100644
index 0000000..5a8a360
--- /dev/null
+++ b/Nop.Plugin.Api.Client/DTOs/Products/ProductsRootObjectDto.cs
@@ -0,0 +1,17 @@
+using System.Collections.Generic;
+using Newtonsoft.Json;
+
+namespace Nop.Plugin.Api.Client.DTOs.Products
+{
+ public class ProductsRootObjectDto
+ {
+ public ProductsRootObjectDto()
+ {
+ Products = new List();
+ }
+
+ [JsonProperty("products")]
+ public IList Products { get; set; }
+
+ }
+}
\ No newline at end of file
diff --git a/Nop.Plugin.Api.Client/DTOs/ShoppingCarts/ShoppingCartItemDto.cs b/Nop.Plugin.Api.Client/DTOs/ShoppingCarts/ShoppingCartItemDto.cs
new file mode 100644
index 0000000..597b293
--- /dev/null
+++ b/Nop.Plugin.Api.Client/DTOs/ShoppingCarts/ShoppingCartItemDto.cs
@@ -0,0 +1,85 @@
+using System;
+using System.Collections.Generic;
+using Newtonsoft.Json;
+using Nop.Plugin.Api.Client.DTOs.Customers;
+using Nop.Plugin.Api.Client.DTOs.Products;
+
+namespace Nop.Plugin.Api.Client.DTOs.ShoppingCarts
+{
+ [JsonObject(Title = "shopping_cart_item")]
+ public class ShoppingCartItemDto
+ {
+ ///
+ /// Gets or sets the id
+ ///
+ [JsonProperty("id")]
+ public string Id { get; set; }
+
+ ///
+ /// Gets or sets the selected attributes
+ ///
+ [JsonProperty("product_attributes")]
+ public List Attributes { get; set; }
+
+ ///
+ /// Gets or sets the price enter by a customer
+ ///
+ [JsonProperty("customer_entered_price")]
+ public decimal? CustomerEnteredPrice { get; set; }
+
+ ///
+ /// Gets or sets the quantity
+ ///
+ [JsonProperty("quantity")]
+ public int? Quantity { get; set; }
+
+ ///
+ /// Gets or sets the rental product start date (null if it's not a rental product)
+ ///
+ [JsonProperty("rental_start_date_utc")]
+ public DateTime? RentalStartDateUtc { get; set; }
+
+ ///
+ /// Gets or sets the rental product end date (null if it's not a rental product)
+ ///
+ [JsonProperty("rental_end_date_utc")]
+ public DateTime? RentalEndDateUtc { get; set; }
+
+ ///
+ /// Gets or sets the date and time of instance creation
+ ///
+ [JsonProperty("created_on_utc")]
+ public DateTime? CreatedOnUtc { get; set; }
+
+ ///
+ /// Gets or sets the date and time of instance update
+ ///
+ [JsonProperty("updated_on_utc")]
+ public DateTime? UpdatedOnUtc { get; set; }
+
+ ///
+ /// Gets the log type
+ ///
+ [JsonProperty("shopping_cart_type")]
+ public string ShoppingCartType { get; set; }
+
+
+ [JsonProperty("product_id")]
+ public int? ProductId { get; set; }
+
+ ///
+ /// Gets or sets the product
+ ///
+ [JsonProperty("product")]
+ public ProductDto ProductDto { get; set; }
+
+ [JsonProperty("customer_id")]
+ public int? CustomerId { get; set; }
+
+ ///
+ /// Gets or sets the customer
+ ///
+ [JsonProperty("customer")]
+ public CustomerForShoppingCartItemDto CustomerDto { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/Nop.Plugin.Api.Client/DTOs/ShoppingCarts/ShoppingCartItemsRootObject.cs b/Nop.Plugin.Api.Client/DTOs/ShoppingCarts/ShoppingCartItemsRootObject.cs
new file mode 100644
index 0000000..673a627
--- /dev/null
+++ b/Nop.Plugin.Api.Client/DTOs/ShoppingCarts/ShoppingCartItemsRootObject.cs
@@ -0,0 +1,17 @@
+using System.Collections.Generic;
+using Newtonsoft.Json;
+
+namespace Nop.Plugin.Api.Client.DTOs.ShoppingCarts
+{
+ public class ShoppingCartItemsRootObject
+ {
+ public ShoppingCartItemsRootObject()
+ {
+ ShoppingCartItems = new List();
+ }
+
+ [JsonProperty("shopping_carts")]
+ public IList ShoppingCartItems { get; set; }
+
+ }
+}
\ No newline at end of file
diff --git a/Nop.Plugin.Api.Client/DTOs/Stores/StoreDto.cs b/Nop.Plugin.Api.Client/DTOs/Stores/StoreDto.cs
new file mode 100644
index 0000000..1551d73
--- /dev/null
+++ b/Nop.Plugin.Api.Client/DTOs/Stores/StoreDto.cs
@@ -0,0 +1,93 @@
+using System.Collections.Generic;
+using Newtonsoft.Json;
+
+namespace Nop.Plugin.Api.Client.DTOs.Stores
+{
+ [JsonObject(Title = "store")]
+ public class StoreDto
+ {
+ ///
+ /// Gets or sets the store ID
+ ///
+ [JsonProperty("id")]
+ public string Id { get; set; }
+
+ ///
+ /// Gets or sets the store name
+ ///
+ [JsonProperty("name")]
+ public string Name { get; set; }
+
+ ///
+ /// Gets or sets the store URL
+ ///
+ [JsonProperty("url")]
+ public string Url { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether SSL is enabled
+ ///
+ [JsonProperty("ssl_enabled")]
+ public bool? SslEnabled { get; set; }
+
+ ///
+ /// Gets or sets the store secure URL (HTTPS)
+ ///
+ [JsonProperty("secure_url")]
+ public string SecureUrl { get; set; }
+
+ ///
+ /// Gets or sets the comma separated list of possible HTTP_HOST values
+ ///
+ [JsonProperty("hosts")]
+ public string Hosts { get; set; }
+
+ ///
+ /// Gets or sets the identifier of the default language for this store; 0 is set when we use the default language display order
+ ///
+ [JsonProperty("default_language_id")]
+ public int? DefaultLanguageId { get; set; }
+
+ ///
+ /// Gets or sets the identifier of the language IDs for this store
+ ///
+ [JsonProperty("language_ids")]
+ public List LanguageIds { get; set; }
+
+ ///
+ /// Gets or sets the display order
+ ///
+ [JsonProperty("display_order")]
+ public int? DisplayOrder { get; set; }
+
+ ///
+ /// Gets or sets the company name
+ ///
+ [JsonProperty("company_name")]
+ public string CompanyName { get; set; }
+
+ ///
+ /// Gets or sets the company address
+ ///
+ [JsonProperty("company_address")]
+ public string CompanyAddress { get; set; }
+
+ ///
+ /// Gets or sets the store phone number
+ ///
+ [JsonProperty("company_phone_number")]
+ public string CompanyPhoneNumber { get; set; }
+
+ ///
+ /// Gets or sets the company VAT (used in Europe Union countries)
+ ///
+ [JsonProperty("company_vat")]
+ public string CompanyVat { get; set; }
+
+ ///
+ /// Get or set the currency format
+ ///
+ [JsonProperty("primary_currency_display_locale")]
+ public string PrimaryCurrencyDisplayLocale { get; set; }
+ }
+}
diff --git a/Nop.Plugin.Api.Client/DTOs/Stores/StoresRootObject.cs b/Nop.Plugin.Api.Client/DTOs/Stores/StoresRootObject.cs
new file mode 100644
index 0000000..cff9698
--- /dev/null
+++ b/Nop.Plugin.Api.Client/DTOs/Stores/StoresRootObject.cs
@@ -0,0 +1,17 @@
+using System.Collections.Generic;
+using Newtonsoft.Json;
+
+namespace Nop.Plugin.Api.Client.DTOs.Stores
+{
+ public class StoresRootObject
+ {
+ public StoresRootObject()
+ {
+ Stores = new List();
+ }
+
+ [JsonProperty("stores")]
+ public IList Stores { get; set; }
+
+ }
+}
diff --git a/Nop.Plugin.Api.Client/Exceptions/NopApiClientException.cs b/Nop.Plugin.Api.Client/Exceptions/NopApiClientException.cs
new file mode 100644
index 0000000..7b110d4
--- /dev/null
+++ b/Nop.Plugin.Api.Client/Exceptions/NopApiClientException.cs
@@ -0,0 +1,94 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) Lindell Technologies All Rights Reserved.
+// Information Contained Herein is Proprietary and Confidential.
+//
+// -----------------------------------------------------------------------
+
+using System;
+using System.Net;
+using System.Runtime.Serialization;
+using System.Security.Permissions;
+
+namespace Nop.Plugin.Api.Client.Exceptions
+{
+ public class NopApiClientException : ApplicationException
+ {
+ public NopApiClientException()
+ : this(null, null)
+ {
+ }
+
+ public NopApiClientException(string message, bool canRetry = false)
+ : this(HttpStatusCode.BadRequest, null, null, message, canRetry)
+ {
+ }
+
+ public NopApiClientException(string resourceUrl, string method, bool canRetry = false)
+ : this(HttpStatusCode.ServiceUnavailable, resourceUrl, method, "No Response", canRetry)
+ {
+ }
+
+ public NopApiClientException(
+ HttpStatusCode statusCode,
+ string resourceUrl,
+ string method,
+ string message,
+ bool canRetry = false)
+ : this(statusCode, resourceUrl, method, message, null, canRetry)
+ {
+ }
+
+ public NopApiClientException(
+ HttpStatusCode statusCode,
+ string resourceUrl,
+ string method,
+ string message,
+ NopApiClientExceptionDetails exceptionDetails,
+ bool canRetry = false)
+ : base(message ?? (exceptionDetails != null ? exceptionDetails.Message : statusCode.ToString()))
+ {
+ ResourceUrl = resourceUrl;
+ StatusCode = statusCode;
+ Method = method;
+ ExceptionDetails = exceptionDetails;
+ CanRetry = canRetry;
+ }
+
+ public NopApiClientException(
+ HttpStatusCode statusCode,
+ string resourceUrl,
+ string method,
+ Exception exception,
+ bool canRetry = false)
+ : base(exception.Message, exception)
+ {
+ ResourceUrl = resourceUrl;
+ StatusCode = statusCode;
+ Method = method;
+ CanRetry = canRetry;
+ }
+
+ public bool CanRetry { get; }
+
+ public string ResourceUrl { get; }
+
+ public HttpStatusCode StatusCode { get; }
+
+ public string Method { get; }
+
+ public NopApiClientExceptionDetails ExceptionDetails { get; }
+
+ public override string Message =>
+ $"{Method} request for '{ResourceUrl}' returned [{StatusCode}] {base.Message} ";
+
+ [SecurityPermission(
+ SecurityAction.Demand,
+ Flags = SecurityPermissionFlag.SerializationFormatter,
+ SerializationFormatter = true)]
+ public override void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ base.GetObjectData(info, context);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Nop.Plugin.Api.Client/Exceptions/NopApiClientExceptionDetails.cs b/Nop.Plugin.Api.Client/Exceptions/NopApiClientExceptionDetails.cs
new file mode 100644
index 0000000..7259876
--- /dev/null
+++ b/Nop.Plugin.Api.Client/Exceptions/NopApiClientExceptionDetails.cs
@@ -0,0 +1,22 @@
+using Newtonsoft.Json;
+
+namespace Nop.Plugin.Api.Client.Exceptions
+{
+ public class NopApiClientExceptionDetails
+ {
+ public string Content { get; set; }
+
+ public string Message { get; set; }
+
+ [JsonProperty("errors")] public dynamic Errors { get; set; }
+
+ public string ExceptionType { get; set; }
+
+ public string StackTrace { get; set; }
+
+ public override string ToString()
+ {
+ return Message;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Nop.Plugin.Api.Client/Nop.Plugin.Api.Client.csproj b/Nop.Plugin.Api.Client/Nop.Plugin.Api.Client.csproj
new file mode 100644
index 0000000..f5d6dbe
--- /dev/null
+++ b/Nop.Plugin.Api.Client/Nop.Plugin.Api.Client.csproj
@@ -0,0 +1,120 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {42CDBA4C-A9B0-4C9E-A1E5-932D6025D768}
+ Exe
+ Nop.Plugin.Api.Client
+ ApiClient
+ v4.7.1
+ 512
+ true
+ SAK
+ SAK
+ SAK
+ SAK
+
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ ..\..\packages\Newtonsoft.Json.11.0.2\lib\net45\Newtonsoft.Json.dll
+
+
+ ..\..\packages\Polly.6.1.0\lib\netstandard2.0\Polly.dll
+
+
+ ..\..\packages\RestSharp.106.3.1\lib\net452\RestSharp.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Nop.Plugin.Api.Client/NopApiClient.cs b/Nop.Plugin.Api.Client/NopApiClient.cs
new file mode 100644
index 0000000..4e6c672
--- /dev/null
+++ b/Nop.Plugin.Api.Client/NopApiClient.cs
@@ -0,0 +1,32 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) Lindell Technologies All Rights Reserved.
+// Information Contained Herein is Proprietary and Confidential.
+//
+// -----------------------------------------------------------------------
+
+
+using Nop.Plugin.Api.Client.Clients;
+
+namespace Nop.Plugin.Api.Client
+{
+ public class NopApiClient
+ {
+ private OrdersClient _ordersClient;
+
+ public NopApiClient(string serverUrl, string clientId, string secret)
+ {
+ ServerUrl = serverUrl;
+ ClientId = clientId;
+ Secret = secret;
+ }
+
+ public string ServerUrl { get; }
+
+ public string ClientId { get; }
+
+ public string Secret { get; }
+
+ public OrdersClient Orders => _ordersClient ?? (_ordersClient = new OrdersClient(this));
+ }
+}
\ No newline at end of file
diff --git a/Nop.Plugin.Api.Client/Program.cs b/Nop.Plugin.Api.Client/Program.cs
new file mode 100644
index 0000000..b6ba3dd
--- /dev/null
+++ b/Nop.Plugin.Api.Client/Program.cs
@@ -0,0 +1,54 @@
+using System;
+using System.Linq;
+
+
+namespace Nop.Plugin.Api.Client
+{
+ class Program
+ {
+ static void Main(string[] args)
+ {
+
+ // TODO: Change to match your environment
+ var url = "http://localhost:15536";
+ var clientId = "ea0204cd-5bbd-49ae-9810-d24735581f43";
+ var clientSecret = "80a14949-8549-4d60-9d3a-864473b7a93a";
+
+
+
+ var client = new NopApiClient(url, clientId, clientSecret);
+
+ Console.Write("Fetching Orders...");
+ var orders = client.Orders.GetOrders();
+
+ Console.WriteLine($"received {orders.Count} orders.");
+
+
+ ///////////////////////////////////////////
+ // Example of how to go through each order
+ ///////////////////////////////////////////
+
+ var start = 0;
+
+ while (true)
+ {
+ orders = client.Orders.GetOrders(start, limit: 1);
+
+ var order = orders.LastOrDefault();
+ if (order == null)
+ {
+ break;
+ }
+
+ start = int.Parse(order.Id);
+ }
+
+ // now at this point we should store the 'start' variable
+
+
+ Console.WriteLine("Hit any key to continue...");
+ Console.ReadKey();
+
+ }
+ }
+}
diff --git a/Nop.Plugin.Api.Client/Properties/AssemblyInfo.cs b/Nop.Plugin.Api.Client/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..382ea70
--- /dev/null
+++ b/Nop.Plugin.Api.Client/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Nop.Plugin.Api.Client")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Nop.Plugin.Api.Client")]
+[assembly: AssemblyCopyright("Copyright © 2018")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("42cdba4c-a9b0-4c9e-a1e5-932d6025d768")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Nop.Plugin.Api.Client/Security/Token.cs b/Nop.Plugin.Api.Client/Security/Token.cs
new file mode 100644
index 0000000..76d039a
--- /dev/null
+++ b/Nop.Plugin.Api.Client/Security/Token.cs
@@ -0,0 +1,33 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) Lindell Technologies All Rights Reserved.
+// Information Contained Herein is Proprietary and Confidential.
+//
+// -----------------------------------------------------------------------
+
+using Newtonsoft.Json;
+
+namespace Nop.Plugin.Api.Client.Security
+{
+ public class Token
+ {
+ [JsonProperty("access_token")]
+ public string AccessToken { get; set; }
+
+ [JsonProperty("expires_in")]
+ public int ExpiresIn { get; set; }
+
+ [JsonProperty("token_type")]
+ public string TokenType { get; set; }
+
+ [JsonProperty("refresh_token")]
+ public string RefreshToken { get; set; }
+
+ ///
+ public override string ToString()
+ {
+ return AccessToken;
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/Nop.Plugin.Api.Client/Security/TokenClient.cs b/Nop.Plugin.Api.Client/Security/TokenClient.cs
new file mode 100644
index 0000000..c2ee1e2
--- /dev/null
+++ b/Nop.Plugin.Api.Client/Security/TokenClient.cs
@@ -0,0 +1,68 @@
+using System;
+using Nop.Plugin.Api.Client.Exceptions;
+using RestSharp;
+
+namespace Nop.Plugin.Api.Client.Security
+{
+ public class TokenClient
+ {
+ private readonly Uri _serverUrl;
+
+ public TokenClient(Uri serverUrl)
+ {
+ _serverUrl = serverUrl;
+ }
+
+ public Token GetToken(string clientId, string secret)
+ {
+ return GetTokenInternal(clientId, secret, GetAuthCode(clientId));
+ }
+
+ private string GetAuthCode(string clientId)
+ {
+ var restClient = new RestClient(_serverUrl.ToString());
+ var request = new RestRequest("oauth/authorize") { Method = Method.GET };
+ request.AddHeader("Accept", "application/json");
+ request.AddHeader("Content-Type", "application/x-www-form-urlencoded");
+ request.AddParameter("client_id", clientId);
+ request.AddParameter("redirect_uri", $"{_serverUrl}token");
+ request.AddParameter("response_type", "code");
+
+ var response = restClient.Execute(request);
+ if (response.ResponseUri != null)
+ {
+ var parameters = response.ResponseUri.Query.Replace("?", "").Split(new[] {'&'}, StringSplitOptions.RemoveEmptyEntries);
+ foreach (var p in parameters)
+ {
+ var parts = p.Split('=');
+ if (parts.Length == 2)
+ {
+ if (parts[0].ToLower() == "code")
+ {
+ return parts[1];
+ }
+ }
+ }
+ }
+
+ throw new NopApiClientException("Could not fetch auth code.");
+ }
+
+ private Token GetTokenInternal(string clientId, string secret, string code)
+ {
+ var restClient = new RestClient(_serverUrl.ToString());
+ var request = new RestRequest("connect/token") { Method = Method.POST };
+ request.AddHeader("Accept", "application/json");
+ request.AddHeader("Content-Type", "application/x-www-form-urlencoded");
+ request.AddParameter("client_id", clientId);
+ request.AddParameter("client_secret", secret);
+ request.AddParameter("code", code);
+ request.AddParameter("grant_type", "authorization_code");
+ request.AddParameter("redirect_uri", $"{_serverUrl}token");
+
+ var tokenResponse = restClient.Execute(request);
+
+ return tokenResponse.Data;
+ }
+ }
+}
diff --git a/Nop.Plugin.Api.Client/Serialization/JsonSeriailzationUtility.cs b/Nop.Plugin.Api.Client/Serialization/JsonSeriailzationUtility.cs
new file mode 100644
index 0000000..864d4ee
--- /dev/null
+++ b/Nop.Plugin.Api.Client/Serialization/JsonSeriailzationUtility.cs
@@ -0,0 +1,55 @@
+using System;
+using System.IO;
+using System.Text;
+using Newtonsoft.Json;
+
+namespace Nop.Plugin.Api.Client.Serialization
+{
+ public static class JsonSerializationUtility
+ {
+ public static bool TryDeserialize(string json, out T result)
+ {
+ try
+ {
+ result = Deserialize(json);
+ return true;
+ }
+ catch
+ {
+ result = default(T);
+ }
+
+ return false;
+ }
+
+ public static T Deserialize(string json)
+ {
+ return JsonConvert.DeserializeObject(json);
+ }
+
+ public static object Deserialize(string json, Type objectType)
+ {
+ return JsonConvert.DeserializeObject(json, objectType);
+ }
+
+ public static string Serialize(T obj, bool indent = false, JsonConverter converter = null)
+ {
+ var sb = new StringBuilder();
+ var settings = new JsonSerializerSettings();
+
+ if (indent)
+ {
+ settings.Formatting = Formatting.Indented;
+ }
+
+ if (converter != null)
+ {
+ settings.Converters.Add(converter);
+ }
+
+ JsonSerializer.CreateDefault(settings).Serialize(new JsonTextWriter(new StringWriter(sb)), obj);
+
+ return sb.ToString();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Nop.Plugin.Api.Client/Serialization/NewtonsoftSerializer.cs b/Nop.Plugin.Api.Client/Serialization/NewtonsoftSerializer.cs
new file mode 100644
index 0000000..0deede6
--- /dev/null
+++ b/Nop.Plugin.Api.Client/Serialization/NewtonsoftSerializer.cs
@@ -0,0 +1,140 @@
+using System.IO;
+using System.Text;
+using System.Threading.Tasks;
+using Newtonsoft.Json;
+using RestSharp;
+using RestSharp.Deserializers;
+using RestSharp.Serializers;
+using JsonSerializer = Newtonsoft.Json.JsonSerializer;
+
+namespace Nop.Plugin.Api.Client.Serialization
+{
+ public class NewtonsoftSerializer : ISerializer, IDeserializer
+ {
+ ///
+ /// Encoding to use to convert string to byte[] and the other way around.
+ ///
+ ///
+ /// StackExchange.Redis uses Encoding.UTF8 to convert strings to bytes,
+ /// hence we do same here.
+ ///
+ private static readonly Encoding s_encoding = Encoding.UTF8;
+
+ private readonly JsonSerializer _serializer;
+
+ private readonly JsonSerializerSettings _settings;
+
+ public NewtonsoftSerializer()
+ {
+ _serializer = new JsonSerializer
+ {
+ MissingMemberHandling = MissingMemberHandling.Ignore,
+ NullValueHandling = NullValueHandling.Ignore,
+ DefaultValueHandling = DefaultValueHandling.Include
+ };
+
+ _settings = new JsonSerializerSettings
+ {
+ MissingMemberHandling = MissingMemberHandling.Ignore,
+ NullValueHandling = NullValueHandling.Ignore,
+ DefaultValueHandling = DefaultValueHandling.Include
+ };
+ }
+
+ public NewtonsoftSerializer(JsonSerializer serializer, JsonSerializerSettings settings)
+ {
+ _serializer = serializer;
+ _settings = settings;
+ }
+
+ public T Deserialize(IRestResponse response)
+ {
+ var content = response.Content;
+
+ using (var stringReader = new StringReader(content))
+ {
+ using (var jsonTextReader = new JsonTextReader(stringReader))
+ {
+ return _serializer.Deserialize(jsonTextReader);
+ }
+ }
+ }
+
+ public byte[] Serialize(object item)
+ {
+ var jsonString = JsonConvert.SerializeObject(item, _settings);
+ return s_encoding.GetBytes(jsonString);
+ }
+
+ public async Task SerializeAsync(object item)
+ {
+ var jsonString = await Task.Factory.StartNew(() => JsonConvert.SerializeObject(item, _settings));
+
+ return s_encoding.GetBytes(jsonString);
+ }
+
+ public object Deserialize(byte[] serializedObject)
+ {
+ var jsonString = s_encoding.GetString(serializedObject);
+ return JsonConvert.DeserializeObject(jsonString, typeof(object), _settings);
+ }
+
+ public Task