/// <summary> /// Calls Facebook Api batch endpoint. /// </summary> /// <param name="container"></param> private void FacebookShopProductBatch(FacebookShopRequestContainer container) { if (container.Requests.Count == 0) { Logger.Debug(T("No products in request container.").Text); } else { var jsonBody = container.ToJson(); string url = _fsssp.ApiBaseUrl + (_fsssp.ApiBaseUrl.EndsWith("/") ? _fsssp.CatalogId : "/" + _fsssp.CatalogId); url = string.Format(url + "/batch?access_token={0}", _fsssp.AccessToken); HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest; try { byte[] bodyData = Encoding.UTF8.GetBytes(jsonBody); request.Method = WebRequestMethods.Http.Post; request.ContentType = "application/json"; using (Stream reqStream = request.GetRequestStream()) { reqStream.Write(bodyData, 0, bodyData.Length); } using (HttpWebResponse response = request.GetResponse() as HttpWebResponse) { if (response.StatusCode == HttpStatusCode.OK) { using (var reader = new StreamReader(response.GetResponseStream())) { string respJson = reader.ReadToEnd(); var json = JObject.Parse(respJson); // Facebook handles are managed after a while (we can't read errors immediately after the product batch call). // For this reason, I need to schedule the CheckFacebookHandles call. // First I need to create a FacebookShopHandleRecord. if (json["handles"] != null) { var handleId = CreateFacebookShopHandleRecord(json["handles"].First.ToString(), jsonBody); _taskManager.CreateTask(FacebookShopProductSynchronizationTaskHandler.CHECKHANDLE_TASK + "_" + handleId.ToString(), _clock.UtcNow.AddMinutes(1), null); } // If I'm here, product/s should be on Facebook Shop. if (container.Requests.Count == 1) { Logger.Debug(T("Product {0} synchronized on Facebook Shop.", container.Requests[0].RetailerId).Text); } else { Logger.Debug(T("{0} products synchronized on Facebook Shop.", container.Requests.Count.ToString()).Text); } } } else { Logger.Debug(T("Invalid Facebook api response. Product is not synchronized on Facebook Shop.").Text); } } } catch (Exception ex) { Logger.Debug(ex, T("Invalid Facebook api response. Product is not synchronized on Facebook Shop.").Text); } } }
public FacebookShopRequestContainer SyncProduct(ContentItem product) { var productPart = product.As <ProductPart>(); try { var facebookPart = product.As <FacebookShopProductPart>(); if (productPart != null && facebookPart != null && facebookPart.SynchronizeFacebookShop) { var jsonTemplate = facebookPart.Settings.GetModel <FacebookShopProductPartSettings>().JsonForProductUpdate; _fsssp = _workContext.GetContext().CurrentSite.As <FacebookShopSiteSettingsPart>(); if (string.IsNullOrWhiteSpace(jsonTemplate)) { // Fallback to FacebookShopSiteSettingsPart jsonTemplate = _fsssp.DefaultJsonForProductUpdate; } if (!string.IsNullOrWhiteSpace(jsonTemplate)) { // jsonTemplate typically begins with a double '{' and ends with a double '}' (to make tokens work). // For this reason, before deserialization, I need to replace tokens and replace double parenthesis. string jsonBody = _tokenizer.Replace(jsonTemplate, product); jsonBody = jsonBody.Replace("{{", "{").Replace("}}", "}"); var jsonContext = FacebookShopProductUpdateRequest.From(jsonBody); CheckCompliance(jsonContext, product); if (jsonContext != null && jsonContext.Valid) { return(SyncProduct(jsonContext)); } else if (jsonContext != null) { // I need to tell it was impossible to synchronize the product on Facebook Shop. Logger.Debug(T("Product {0} can't be synchronized on Facebook catalog.", productPart.Sku).Text); Logger.Debug(jsonContext.Message.Text); var returnValue = new FacebookShopRequestContainer(); returnValue.Requests.Add(jsonContext); return(returnValue); } } } } catch (Exception ex) { // I need to tell it was impossible to synchronize the product on Facebook Shop. if (productPart != null) { Logger.Debug(ex, T("Product {0} can't be synchronized on Facebook catalog.", productPart.Sku).Text); } else { Logger.Debug(ex, T("Product part or Facebook part are not valid.").Text); } return(null); } return(null); }
/// <summary> /// Calls Facebook Api batch endpoint. /// </summary> /// <param name="container"></param> private void FacebookShopProductBatch(FacebookShopRequestContainer container) { if (container.Requests.Count == 0) { Logger.Debug(T("No products in request container.").Text); } else { var jsonBody = container.ToJson(); string url = _fsssp.ApiBaseUrl + (_fsssp.ApiBaseUrl.EndsWith("/") ? _fsssp.CatalogId : "/" + _fsssp.CatalogId); url = string.Format(url + "/batch?access_token={0}", _fsssp.AccessToken); HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest; try { byte[] bodyData = Encoding.UTF8.GetBytes(jsonBody); request.Method = WebRequestMethods.Http.Post; request.ContentType = "application/json"; using (Stream reqStream = request.GetRequestStream()) { reqStream.Write(bodyData, 0, bodyData.Length); } using (HttpWebResponse response = request.GetResponse() as HttpWebResponse) { if (response.StatusCode == HttpStatusCode.OK) { using (var reader = new StreamReader(response.GetResponseStream())) { string respJson = reader.ReadToEnd(); var json = JObject.Parse(respJson); // If I'm here, product/s should be on Facebook Shop. if (container.Requests.Count == 1) { Logger.Debug(T("Product {0} synchronized on Facebook Shop.", container.Requests[0].RetailerId).Text); } else { Logger.Debug(T("{0} products synchronized on Facebook Shop.", container.Requests.Count.ToString()).Text); } } } else { Logger.Debug(T("Invalid Facebook api response. Product is not synchronized on Facebook Shop.").Text); } } } catch (Exception ex) { Logger.Debug(ex, T("Invalid Facebook api response. Product is not synchronized on Facebook Shop.").Text); } } }
public void SyncProducts() { // Facebook Shop Site Settings: I need url, catalog id and access token. _fsssp = _workContext.GetContext().CurrentSite.As <FacebookShopSiteSettingsPart>(); FacebookShopServiceContext ctx = new FacebookShopServiceContext() { ApiBaseUrl = _fsssp.ApiBaseUrl, BusinessId = _fsssp.BusinessId, CatalogId = _fsssp.CatalogId, AccessToken = _fsssp.AccessToken }; // Query on published products, to send them all in a single request to Facebook api. // Every call to Facebook api sends the update of 20 products. int step = 20; // I look for the FacebookShopPart because I may have some products I don't need to synchronize on Facebook Shop (without the FacebookShopProductPart or with the SynchronizeFacebookShopFlag disabled). var query = _contentManager.Query <FacebookShopProductPart, FacebookShopProductPartRecord>(VersionOptions.Published) .Where(fp => fp.SynchronizeFacebookShop == true); for (int count = 0; count < query.Count(); count += step) { var facebookParts = _contentManager.Query <FacebookShopProductPart, FacebookShopProductPartRecord>(VersionOptions.Published) .Where(fp => fp.SynchronizeFacebookShop == true) .Slice(count, step); // I build a container for each slice of the query results. FacebookShopRequestContainer requestContainer = new FacebookShopRequestContainer(); foreach (var facebookPart in facebookParts) { var jsonContext = GetJsonContext(facebookPart.ContentItem); if (jsonContext != null && jsonContext.Valid) { requestContainer.Requests.Add(jsonContext); } else if (jsonContext != null) { Logger.Error(T("Product {0} can't be synchronized on Facebook catalog.", jsonContext.RetailerId).Text); Logger.Error(jsonContext.Message.Text); } } // I can now send the request to Facebook api. // This call contains every valid product in the slice from the query. FacebookShopProductBatch(requestContainer); } }
public FacebookShopRequestContainer RemoveProduct(FacebookShopProductDeleteRequest context) { FacebookShopRequestContainer requestContainer = new FacebookShopRequestContainer(); requestContainer.Requests.Add(context); // Facebook Shop Site Settings: I need url, catalog id and access token. _fsssp = _workContext.GetContext().CurrentSite.As <FacebookShopSiteSettingsPart>(); FacebookShopServiceContext ctx = new FacebookShopServiceContext() { ApiBaseUrl = _fsssp.ApiBaseUrl, BusinessId = _fsssp.BusinessId, CatalogId = _fsssp.CatalogId, AccessToken = _fsssp.AccessToken }; FacebookShopProductBatch(requestContainer); return(requestContainer); }