ProductService
ProductService is found in Poq.Shopify.Services namespace. ProductService service uses only Shopify Storefront API to obtain data and can be used for feedless implementation of BFC. It requires two dependencies to be used in your backend. All required dependencies should be registered using IoC:
services.AddScoped<IShopifyProductClient, ShopifyProductClient>();services.AddScoped<IProductMapper, ProductMapper>();services.AddScoped<IProductService, ProductService>();Explanation of services
IShopifyProductClientis available as part of Poq Shopify nuget package. No further action is required than properly registering the service.IProductServicewith implementationProductServiceProduct Service searches for products by their ids using Shopify Storefront Api. Service functionality and products mapping can be modified by providing custom implementation of
IProductMapper.ProducServicehas generic overloads that allow customization of Graphql query and contract.IProductMapperwith implementationProductMapperis responsible of mapping product listings, filters and pagination. It is used to map filters to shopify contract.
Here in an example of overriding default handling in IProductMapper.
services.AddScoped<IProductMapper, MyProductMapper>();
public class MyProductMapper : IProductMapper{ private readonly string _onlineStoreBaseUrl;
public ProductMapper(string onlineStoreBaseUrl) { _onlineStoreBaseUrl = onlineStoreBaseUrl; }
public Product MapProduct(string appIdentifier, ProductListing productListing) { return new Product( appIdentifier, productListing.Id, MapProductDetails(productListing), productListing.Variants.Variants.Select(v => MapVariant(productListing, v.ListingVariant)), MapForms(productListing) ) { Meta = new ProductMeta() { ClientId = productListing.Id, DefaultVariantId = productListing.Variants.Variants.FirstOrDefault()?.ListingVariant.Id, WebUrl = $"{_onlineStoreBaseUrl}/products/{productListing.Handle}", }, Promotion = new Promotion(), Review = new Review(), }; }
protected virtual IEnumerable<Form>? MapForms(ProductListing productListing) { var result = new List<Form>(); foreach (var option in productListing.Options) { result.Add(new Form() { Name = MapFormName(option.Name), Variations = option.Values.Select(optionValue => new FormVariant() { Id = $"{MapFormName(option.Name)}{optionValue}", Value = optionValue }).ToArray(), }); }
return result; }
protected virtual ProductVariant MapVariant(ProductListing productListing, ProductListingVariant variant) { var images = new List<string>() { variant.Image.Src }; images.AddRange(productListing.ImageEdges?.ImageEdges?.Select(i => i.Image.Url) ?? new List<string>()); images = images.Distinct().ToList();
return new ProductVariant() { Id = variant.Id, ListingId = productListing.Id, Images = new Images(images), Meta = new VariantMeta() { Barcode = string.IsNullOrWhiteSpace(variant.Barcode) ? null : variant.Barcode, DefaultCurrency = variant.Price.CurrencyCode }, Name = productListing.Title, Prices = new Dictionary<string, Price>() { { variant.Price.CurrencyCode, new Price(variant.Price.Amount ?? 0) { Was = variant.CompareAtPrice?.Amount } } }, Forms = MapVariantForms(variant), Stock = new Stock() { Available = variant.AvailableForSale, MaxOrderableQuantity = variant.QuantityAvailable, LowOnStock = variant.QuantityAvailable < 5, Quantity = variant.QuantityAvailable, } }; }
...}Methods
GetProductsAsyncobtains products from Shopify storefront API by provided productIds. This method is used to obtain products bylistingIdsince Shopify SDK considers productId and listingId to be the same.GetProductsByVariantIdsAsyncobtains products from Shopify storefront API by provided variantIds.