mirror of
https://github.com/stokebob/bnhtrade.git
synced 2026-05-18 19:48:23 +00:00
Migration from Amazon MWS to Selling Partner API
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
using bnhtrade.Core.Data.Amazon.SellingPartnerAPI;
|
||||
using FikaAmazonAPI;
|
||||
using FikaAmazonAPI.Parameter.FbaInventory;
|
||||
using FikaAmazonAPI.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace bnhtrade.Core.Data.Amazon.FbaInventory
|
||||
{
|
||||
public class GetFbaInventoryInfo
|
||||
{
|
||||
private AmazonConnection amznConn = new SpApiConnection().Connection;
|
||||
|
||||
public List<string> MarketPlaceIds { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// True to return inventory summaries with additional summarized inventory details and quantities.
|
||||
/// Otherwise, returns inventory summaries only (the default value).
|
||||
/// </summary>
|
||||
public bool WithDetails { get; set; }
|
||||
|
||||
public GetFbaInventoryInfo()
|
||||
{
|
||||
}
|
||||
|
||||
public Dictionary<string, string> GetFnsku(List<string> skuList)
|
||||
{
|
||||
var returnList = new Dictionary<string, string>();
|
||||
var result = GetInventorySummaries(skuList);
|
||||
|
||||
foreach (var list in result)
|
||||
{
|
||||
foreach(var item in list)
|
||||
{
|
||||
returnList.Add(item.SellerSku, item.FnSku);
|
||||
}
|
||||
}
|
||||
|
||||
return returnList;
|
||||
}
|
||||
|
||||
private List<FikaAmazonAPI.AmazonSpApiSDK.Models.FbaInventory.InventorySummaries> GetInventorySummaries(List<string> skuList, DateTime? startDateTime = null)
|
||||
{
|
||||
var returnList = new List<FikaAmazonAPI.AmazonSpApiSDK.Models.FbaInventory.InventorySummaries>();
|
||||
|
||||
// max of 50 sku in one call
|
||||
int i = 0;
|
||||
int total = skuList.Count;
|
||||
var skuRequestList = new List<string>();
|
||||
foreach (string sku in skuList)
|
||||
{
|
||||
i++;
|
||||
skuRequestList.Add(sku);
|
||||
|
||||
if (i == total || i % 50 == 0)
|
||||
{
|
||||
var parameters = new ParameterGetInventorySummaries();
|
||||
//parameters.details = WithDetails;
|
||||
parameters.granularityType = FikaAmazonAPI.AmazonSpApiSDK.Models.FbaInventory.Granularity.GranularityTypeEnum.Marketplace;
|
||||
parameters.granularityId = new Data.Amazon.SellingPartnerAPI.Defaults().MarketPlaceIdAsString();
|
||||
parameters.marketplaceIds = MarketPlaceIds;
|
||||
//parameters.startDateTime = startDateTime;
|
||||
parameters.sellerSkus = skuRequestList;
|
||||
|
||||
var lkdsjflds = amznConn.FbaInventory.GetInventorySummaries(parameters);
|
||||
returnList.AddRange(lkdsjflds);
|
||||
|
||||
skuRequestList = new List<string>();
|
||||
}
|
||||
}
|
||||
|
||||
return returnList;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using bnhtrade.Core.Data.Amazon.SellingPartnerAPI;
|
||||
using FikaAmazonAPI;
|
||||
using FikaAmazonAPI.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using static FikaAmazonAPI.Utils.Constants;
|
||||
|
||||
namespace bnhtrade.Core.Data.Amazon.Feeds
|
||||
{
|
||||
public class GetFeed
|
||||
{
|
||||
private AmazonConnection amznConn = new SpApiConnection().Connection;
|
||||
|
||||
public void GetFeeds(string feedId)
|
||||
{
|
||||
var param = new FikaAmazonAPI.Parameter.Feed.ParameterGetFeed();
|
||||
param.pageSize = 100;
|
||||
param.processingStatuses = ProcessingStatuses.DONE;
|
||||
param.feedTypes = new List<FeedType> { FeedType.POST_PRODUCT_PRICING_DATA };
|
||||
|
||||
var result = amznConn.Feed.GetFeeds(param);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,450 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using FikaAmazonAPI;
|
||||
using FikaAmazonAPI.AmazonSpApiSDK.Models.Feeds;
|
||||
using FikaAmazonAPI.ConstructFeed;
|
||||
using FikaAmazonAPI.ConstructFeed.Messages;
|
||||
using FikaAmazonAPI.Utils;
|
||||
using static FikaAmazonAPI.ConstructFeed.BaseXML;
|
||||
using static FikaAmazonAPI.Utils.Constants;
|
||||
|
||||
|
||||
namespace bnhtrade.Core.Data.Amazon.Feeds
|
||||
{
|
||||
public class SampleFeeds
|
||||
{
|
||||
AmazonConnection amazonConnection;
|
||||
public SampleFeeds(AmazonConnection amazonConnection)
|
||||
{
|
||||
this.amazonConnection = amazonConnection;
|
||||
}
|
||||
|
||||
public void CallFlatfile()
|
||||
{
|
||||
string text = System.IO.File.ReadAllText(@"C:\Users\tareq\Downloads\Beispiel_Upload.txt");
|
||||
|
||||
var feedresultTXT = amazonConnection.Feed.SubmitFeed(text
|
||||
, FeedType.POST_FLAT_FILE_INVLOADER_DATA
|
||||
, new List<string>() { MarketPlace.UnitedArabEmirates.ID }
|
||||
, null
|
||||
, ContentType.TXT);
|
||||
|
||||
|
||||
string pathURL = string.Empty;
|
||||
while (pathURL == string.Empty)
|
||||
{
|
||||
Thread.Sleep(1000 * 30);
|
||||
var feedOutput = amazonConnection.Feed.GetFeed(feedresultTXT);
|
||||
if (feedOutput.ProcessingStatus == FikaAmazonAPI.AmazonSpApiSDK.Models.Feeds.Feed.ProcessingStatusEnum.DONE)
|
||||
{
|
||||
var outPut = amazonConnection.Feed.GetFeedDocument(feedOutput.ResultFeedDocumentId);
|
||||
|
||||
pathURL = outPut.Url;
|
||||
}
|
||||
}
|
||||
}
|
||||
public void GetFeeds()
|
||||
{
|
||||
|
||||
var data = amazonConnection.Feed.GetFeeds(new FikaAmazonAPI.Parameter.Feed.ParameterGetFeed()
|
||||
{
|
||||
processingStatuses = ProcessingStatuses.DONE,
|
||||
pageSize = 100,
|
||||
feedTypes = new List<FeedType> { FeedType.POST_PRODUCT_PRICING_DATA },
|
||||
createdSince = DateTime.UtcNow.AddDays(-6),
|
||||
createdUntil = DateTime.UtcNow.AddDays(-1),
|
||||
marketplaceIds = new List<string> { MarketPlace.UnitedArabEmirates.ID }
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public void CreateFeedDocument()
|
||||
{
|
||||
|
||||
var data = amazonConnection.Feed.CreateFeedDocument(ContentType.XML);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void GetFeedDocument()
|
||||
{
|
||||
|
||||
var data2 = amazonConnection.Feed.GetFeedDocument("amzn1.tortuga.3.92d8fd38-6ccf-49be-979f-6dc27375ea3e.T2DF7HINJ0NRA2");
|
||||
}
|
||||
|
||||
public void GetFeed()
|
||||
{
|
||||
|
||||
var data2 = amazonConnection.Feed.GetFeed("194146018872");
|
||||
}
|
||||
|
||||
public void CancelFeed()
|
||||
{
|
||||
|
||||
var data2 = amazonConnection.Feed.CancelFeed("194146018872");
|
||||
}
|
||||
|
||||
public void SubmitFeedInventory()
|
||||
{
|
||||
ConstructFeedService createDocument = new ConstructFeedService("A3J37AJU4O9RHK", "1.02");
|
||||
var list = new List<InventoryMessage>();
|
||||
list.Add(new InventoryMessage()
|
||||
{
|
||||
SKU = "API.853038006021.20789.1001",
|
||||
Quantity = 1
|
||||
});
|
||||
createDocument.AddInventoryMessage(list);
|
||||
var xml = createDocument.GetXML();
|
||||
|
||||
var feedID = amazonConnection.Feed.SubmitFeed(xml, FeedType.POST_INVENTORY_AVAILABILITY_DATA);
|
||||
GetFeedDetails(feedID);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// UnderTest
|
||||
/// </summary>
|
||||
public void SubmitFeedAddProductMessage(string ASIN, string SKU)
|
||||
{
|
||||
ConstructFeedService createDocument = new ConstructFeedService(amazonConnection.GetCurrentSellerID, "1.02");
|
||||
|
||||
var list = new List<ProductMessage>();
|
||||
list.Add(new ProductMessage()
|
||||
{
|
||||
SKU = SKU,
|
||||
|
||||
StandardProductID = new FikaAmazonAPI.ConstructFeed.Messages.StandardProductID()
|
||||
{
|
||||
Type = "ASIN",
|
||||
Value = ASIN
|
||||
}
|
||||
});
|
||||
createDocument.AddProductMessage(list, OperationType.Update);
|
||||
var xml = createDocument.GetXML();
|
||||
|
||||
var feedID = amazonConnection.Feed.SubmitFeed(xml, FeedType.POST_PRODUCT_DATA);
|
||||
|
||||
GetFeedDetails(feedID);
|
||||
}
|
||||
|
||||
public void SubmitFeedDeleteAddProductMessage()
|
||||
{
|
||||
ConstructFeedService createDocument = new ConstructFeedService("A3J37AJU4O9RHK", "1.02");
|
||||
|
||||
var list = new List<ProductMessage>();
|
||||
list.Add(new ProductMessage()
|
||||
{
|
||||
SKU = "8432225129778...."
|
||||
});
|
||||
createDocument.AddProductMessage(list, OperationType.Delete);
|
||||
var xml = createDocument.GetXML();
|
||||
|
||||
var feedID = amazonConnection.Feed.SubmitFeedContent(xml, FeedType.POST_PRODUCT_DATA);
|
||||
|
||||
GetFeedDetails(feedID);
|
||||
}
|
||||
public void AddOfferMessageMessage()
|
||||
{
|
||||
ConstructFeedService createDocument = new ConstructFeedService("A3J37AJU4O9RHK", "1.02");
|
||||
|
||||
var list = new List<OfferMessage>();
|
||||
list.Add(new OfferMessage()
|
||||
{
|
||||
SKU = "4049639414402_b"
|
||||
});
|
||||
createDocument.AddOfferMessage(list, OperationType.Delete);
|
||||
var xml = createDocument.GetXML();
|
||||
|
||||
var feedID = amazonConnection.Feed.SubmitFeed(xml, FeedType.POST_PRODUCT_DATA);
|
||||
|
||||
GetFeedDetails(feedID);
|
||||
}
|
||||
|
||||
public void SubmitFeedPRICING(double PRICE, string SKU)
|
||||
{
|
||||
|
||||
ConstructFeedService createDocument = new ConstructFeedService(amazonConnection.GetCurrentSellerID, "1.02");
|
||||
|
||||
var list = new List<PriceMessage>();
|
||||
list.Add(new PriceMessage()
|
||||
{
|
||||
SKU = SKU,
|
||||
StandardPrice = new StandardPrice()
|
||||
{
|
||||
currency = amazonConnection.GetCurrentMarketplace.CurrencyCode.ToString(),
|
||||
Value = (PRICE).ToString("0.00")
|
||||
}
|
||||
});
|
||||
createDocument.AddPriceMessage(list);
|
||||
|
||||
var xml = createDocument.GetXML();
|
||||
|
||||
var feedID = amazonConnection.Feed.SubmitFeed(xml, FeedType.POST_PRODUCT_PRICING_DATA);
|
||||
|
||||
GetFeedDetails(feedID);
|
||||
|
||||
}
|
||||
|
||||
public async void SubmitFeedPricingWithSalePrice(string sku, decimal price, decimal salePrice, DateTime startDate, DateTime endDate)
|
||||
{
|
||||
var currencyCode = amazonConnection.GetCurrentMarketplace.CurrencyCode.ToString();
|
||||
|
||||
var createDocument = new ConstructFeedService("A3J37AJU4O9RHK", "1.02");
|
||||
|
||||
var list = new List<PriceMessage>();
|
||||
list.Add(new PriceMessage
|
||||
{
|
||||
SKU = sku,
|
||||
StandardPrice = new StandardPrice
|
||||
{
|
||||
currency = currencyCode,
|
||||
Value = price.ToString("0.00")
|
||||
},
|
||||
Sale = new Sale
|
||||
{
|
||||
SalePrice = new StandardPrice
|
||||
{
|
||||
currency = currencyCode,
|
||||
Value = salePrice.ToString("0.00")
|
||||
},
|
||||
StartDate = startDate.ToUniversalTime().ToString("yyyy-MM-dd'T'HH:mm:ss.fffK"),
|
||||
EndDate = endDate.ToUniversalTime().ToString("yyyy-MM-dd'T'HH:mm:ss.fffK")
|
||||
}
|
||||
});
|
||||
createDocument.AddPriceMessage(list);
|
||||
|
||||
var xml = createDocument.GetXML();
|
||||
|
||||
var feedId = await amazonConnection.Feed.SubmitFeedAsync(xml, FeedType.POST_PRODUCT_PRICING_DATA);
|
||||
|
||||
GetFeedDetails(feedId);
|
||||
}
|
||||
|
||||
|
||||
public void SubmitFeedSale(double PRICE, string SKU)
|
||||
{
|
||||
|
||||
ConstructFeedService createDocument = new ConstructFeedService("A3J37AJU4O9RHK", "1.02");
|
||||
|
||||
var list = new List<PriceMessage>();
|
||||
list.Add(new PriceMessage()
|
||||
{
|
||||
SKU = SKU,
|
||||
StandardPrice = new StandardPrice()
|
||||
{
|
||||
currency = amazonConnection.GetCurrentMarketplace.CurrencyCode.ToString(),
|
||||
Value = (PRICE).ToString("0.00")
|
||||
},
|
||||
Sale = new Sale()
|
||||
{
|
||||
StartDate = DateTime.UtcNow.AddDays(+1).ToString("yyyy-MM-dd'T'HH:mm:ss.fffK"),
|
||||
EndDate = DateTime.UtcNow.AddDays(+2).ToString("yyyy-MM-dd'T'HH:mm:ss.fffK"),
|
||||
SalePrice = new StandardPrice()
|
||||
{
|
||||
currency = amazonConnection.GetCurrentMarketplace.CurrencyCode.ToString(),
|
||||
Value = (PRICE - 10).ToString("0.00")
|
||||
}
|
||||
}
|
||||
});
|
||||
createDocument.AddPriceMessage(list);
|
||||
|
||||
var xml = createDocument.GetXML();
|
||||
|
||||
var feedID = amazonConnection.Feed.SubmitFeed(xml, FeedType.POST_PRODUCT_PRICING_DATA);
|
||||
|
||||
GetFeedDetails(feedID);
|
||||
|
||||
}
|
||||
|
||||
public void FeebPostOrderFullfillment()
|
||||
{
|
||||
ConstructFeedService createDocument = new ConstructFeedService("{sellerId}", "1.02");
|
||||
|
||||
var list = new List<OrderFulfillmentMessage>();
|
||||
|
||||
list.Add(new OrderFulfillmentMessage()
|
||||
{
|
||||
AmazonOrderID = "{orderId}",
|
||||
FulfillmentDate = DateTime.Now.ToString("yyyy-MM-dd'T'HH:mm:ss.fffK"),
|
||||
FulfillmentData = new FulfillmentData()
|
||||
{
|
||||
CarrierName = "Correos Express",
|
||||
ShippingMethod = "ePaq",
|
||||
ShipperTrackingNumber = "{trackingNumber}"
|
||||
}
|
||||
});
|
||||
createDocument.AddOrderFulfillmentMessage(list);
|
||||
|
||||
var xml = createDocument.GetXML();
|
||||
|
||||
var feedID = amazonConnection.Feed.SubmitFeed(xml, FeedType.POST_ORDER_FULFILLMENT_DATA);
|
||||
|
||||
|
||||
GetFeedDetails(feedID);
|
||||
}
|
||||
|
||||
public void SubmitFeedOrderAcknowledgement()
|
||||
{
|
||||
ConstructFeedService createDocument = new ConstructFeedService("{sellerId}", "1.02");
|
||||
var list = new List<OrderAcknowledgementMessage>();
|
||||
list.Add(new OrderAcknowledgementMessage()
|
||||
{
|
||||
AmazonOrderID = "AMZ1234567890123",
|
||||
MerchantOrderID = "12345678",
|
||||
StatusCode = OrderAcknowledgementStatusCode.Success,
|
||||
Item = new List<OrderAcknowledgementItem>() {
|
||||
new OrderAcknowledgementItem() {
|
||||
AmazonOrderItemCode = "52986411826454",
|
||||
MerchantOrderItemID = "1"
|
||||
}
|
||||
}
|
||||
});
|
||||
createDocument.AddOrderAcknowledgementMessage(list);
|
||||
var xml = createDocument.GetXML();
|
||||
|
||||
var feedID = amazonConnection.Feed.SubmitFeed(xml, FeedType.POST_ORDER_ACKNOWLEDGEMENT_DATA);
|
||||
GetFeedDetails(feedID);
|
||||
}
|
||||
|
||||
public void SubmitFeedOrderAdjustment()
|
||||
{
|
||||
ConstructFeedService createDocument = new ConstructFeedService("{sellerId}", "1.02");
|
||||
var list = new List<OrderAdjustmentMessage>();
|
||||
list.Add(new OrderAdjustmentMessage()
|
||||
{
|
||||
AmazonOrderID = "AMZ1234567890123",
|
||||
ActionType = AdjustmentActionType.Refund,
|
||||
AdjustedItem = new List<AdjustedItem>() {
|
||||
new AdjustedItem() {
|
||||
AmazonOrderItemCode = "52986411826454",
|
||||
AdjustmentReason = AdjustmentReason.CustomerCancel,
|
||||
DirectPaymentAdjustments = new List<DirectPaymentAdjustments>()
|
||||
{
|
||||
new DirectPaymentAdjustments()
|
||||
{
|
||||
Component = new List<DirectPaymentAdjustmentsComponent>()
|
||||
{
|
||||
new DirectPaymentAdjustmentsComponent() {
|
||||
DirectPaymentType = "Credit Card Refund",
|
||||
Amount = new CurrencyAmount() {
|
||||
Value = 10.50M,
|
||||
currency = amazonConnection.GetCurrentMarketplace.CurrencyCode
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
createDocument.AddOrderAdjustmentMessage(list);
|
||||
var xml = createDocument.GetXML();
|
||||
|
||||
var feedID = amazonConnection.Feed.SubmitFeed(xml, FeedType.POST_PAYMENT_ADJUSTMENT_DATA);
|
||||
GetFeedDetails(feedID);
|
||||
}
|
||||
|
||||
public void CartonContentsRequestFeed()
|
||||
{
|
||||
ConstructFeedService createDocument2 = new ConstructFeedService("{SellerID}", "1.02");
|
||||
|
||||
var list22 = new List<CartonContentsRequest>();
|
||||
list22.Add(new CartonContentsRequest()
|
||||
{
|
||||
ShipmentId = "FBA123456",
|
||||
Carton = new List<Carton> {
|
||||
new Carton() {
|
||||
CartonId="1",
|
||||
Item=new List<CartonItem>(){
|
||||
new CartonItem() {
|
||||
QuantityInCase=1,
|
||||
QuantityShipped=1,
|
||||
SKU="7004"
|
||||
}
|
||||
}
|
||||
},
|
||||
new Carton() {
|
||||
CartonId="2",
|
||||
Item=new List<CartonItem>(){
|
||||
new CartonItem() {
|
||||
QuantityInCase=12,
|
||||
QuantityShipped=12,
|
||||
SKU="4051",
|
||||
ExpirationDate=DateTime.Now,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
createDocument2.AddCartonContentsRequest(list22);
|
||||
|
||||
var xml222 = createDocument2.GetXML();
|
||||
|
||||
var feedID = amazonConnection.Feed.SubmitFeed(xml222, FeedType.POST_FBA_INBOUND_CARTON_CONTENTS);
|
||||
GetFeedDetails(feedID);
|
||||
}
|
||||
|
||||
public void SubmitFeedEasyShipDocument()
|
||||
{
|
||||
ConstructFeedService createDocument = new ConstructFeedService("{sellerId}", "1.02");
|
||||
var list = new List<EasyShipDocumentMessage>();
|
||||
list.Add(new EasyShipDocumentMessage()
|
||||
{
|
||||
AmazonOrderID = "AMZ1234567890123",
|
||||
DocumentTypes = new List<EasyShipDocumentType>() {
|
||||
EasyShipDocumentType.ShippingLabel
|
||||
}
|
||||
});
|
||||
createDocument.AddEasyShipDocumentMessage(list);
|
||||
var xml = createDocument.GetXML();
|
||||
|
||||
var feedID = amazonConnection.Feed.SubmitFeed(xml, FeedType.POST_EASYSHIP_DOCUMENTS);
|
||||
GetFeedDetails(feedID);
|
||||
}
|
||||
|
||||
public void GetFeedDetails(string feedID)
|
||||
{
|
||||
string ResultFeedDocumentId = string.Empty;
|
||||
while (string.IsNullOrEmpty(ResultFeedDocumentId))
|
||||
{
|
||||
var feedOutput = amazonConnection.Feed.GetFeed(feedID);
|
||||
if (feedOutput.ProcessingStatus == Feed.ProcessingStatusEnum.DONE)
|
||||
{
|
||||
var outPut = amazonConnection.Feed.GetFeedDocument(feedOutput.ResultFeedDocumentId);
|
||||
|
||||
var reportOutput = outPut.Url;
|
||||
|
||||
var processingReport = amazonConnection.Feed.GetFeedDocumentProcessingReport(outPut);
|
||||
|
||||
DisplayProcessingReportMessage(processingReport);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (!(feedOutput.ProcessingStatus == Feed.ProcessingStatusEnum.INPROGRESS ||
|
||||
feedOutput.ProcessingStatus == Feed.ProcessingStatusEnum.INQUEUE))
|
||||
break;
|
||||
else Thread.Sleep(10000);
|
||||
}
|
||||
}
|
||||
private void DisplayProcessingReportMessage(ProcessingReportMessage processingReport)
|
||||
{
|
||||
Console.WriteLine("MessagesProcessed=" + processingReport.ProcessingSummary.MessagesProcessed);
|
||||
Console.WriteLine("MessagesSuccessful= " + processingReport.ProcessingSummary.MessagesSuccessful);
|
||||
Console.WriteLine("MessagesWithError=" + processingReport.ProcessingSummary.MessagesWithError);
|
||||
Console.WriteLine("MessagesWithWarning=" + processingReport.ProcessingSummary.MessagesWithWarning);
|
||||
|
||||
if (processingReport.Result != null && processingReport.Result.Count > 0)
|
||||
{
|
||||
foreach (var itm in processingReport.Result)
|
||||
{
|
||||
Console.WriteLine("ResultDescription=" + (itm.AdditionalInfo?.SKU ?? string.Empty) + " > " + itm.ResultDescription);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
using bnhtrade.Core.Data.Amazon.SellingPartnerAPI;
|
||||
using FikaAmazonAPI;
|
||||
using FikaAmazonAPI.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using static FikaAmazonAPI.Utils.Constants;
|
||||
|
||||
namespace bnhtrade.Core.Data.Amazon.Feeds
|
||||
{
|
||||
class SubmittFeed
|
||||
{
|
||||
private AmazonConnection amznConn = new SpApiConnection().Connection;
|
||||
private Logic.Log.LogEvent logEvent = new Logic.Log.LogEvent();
|
||||
|
||||
public bool FeedSubmissionRecived { get; set; } = false;
|
||||
|
||||
// make these functions only accept a database object
|
||||
public SubmittFeed()
|
||||
{
|
||||
}
|
||||
|
||||
public Model.Export.AmazonFeedSubmission FlatFileInvLoaderData(System.IO.MemoryStream filestream)
|
||||
{
|
||||
return Post("POST_FLAT_FILE_INVLOADER_DATA", filestream, "TXT");
|
||||
}
|
||||
|
||||
private Model.Export.AmazonFeedSubmission Post(string feedType, System.IO.MemoryStream filestream, string fileExtension)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
|
||||
if (filestream.Length == 0) { throw new Exception("Filestreeam is empty"); }
|
||||
if (string.IsNullOrEmpty(fileExtension)) { throw new Exception("Filestreeam is empty"); }
|
||||
|
||||
var feedresultTXT = amznConn.Feed.SubmitFeed(filestream.ToString()
|
||||
, GetFeedType(feedType)
|
||||
, new List<string>() { amznConn.GetCurrentMarketplace.ID }
|
||||
, null
|
||||
, ContentType.TXT);
|
||||
|
||||
string pathURL = string.Empty;
|
||||
while (pathURL == string.Empty)
|
||||
{
|
||||
Thread.Sleep(1000 * 30);
|
||||
var feedOutput = amznConn.Feed.GetFeed(feedresultTXT);
|
||||
if (feedOutput.ProcessingStatus == FikaAmazonAPI.AmazonSpApiSDK.Models.Feeds.Feed.ProcessingStatusEnum.DONE)
|
||||
{
|
||||
var outPut = amznConn.Feed.GetFeedDocument(feedOutput.ResultFeedDocumentId);
|
||||
|
||||
pathURL = outPut.Url;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private FeedType GetFeedType(string feedTypeText)
|
||||
{
|
||||
// add more here as needed
|
||||
if (feedTypeText == "POST_FLAT_FILE_INVLOADER_DATA")
|
||||
{ return FeedType.POST_FLAT_FILE_INVLOADER_DATA; }
|
||||
else
|
||||
{ throw new NotImplementedException("Need to implement feed type for " + feedTypeText); }
|
||||
}
|
||||
|
||||
public void SubmitFeed(Model.Export.AmazonFeedSubmission feedSubmission)
|
||||
{
|
||||
FeedSubmissionRecived = false;
|
||||
|
||||
if (feedSubmission.FileIsSet == false) { throw new Exception("Filestreeam is empty"); }
|
||||
|
||||
// get feed type
|
||||
var feedType = GetFeedType(feedSubmission.FeedType);
|
||||
|
||||
string text = feedSubmission.File.FileData.ToString();
|
||||
|
||||
var feedresultTXT = amznConn.Feed.SubmitFeed(text
|
||||
, feedType
|
||||
, new List<string>() { amznConn.GetCurrentMarketplace.ID }
|
||||
, null
|
||||
, ContentType.TXT);
|
||||
|
||||
var result = new FikaAmazonAPI.AmazonSpApiSDK.Models.Feeds.FeedDocument();
|
||||
int sleepTime = (1000 * 25);
|
||||
int retryCount = 0;
|
||||
int retryTimeout = 20;
|
||||
UI.Console.Wait("Feed:" + feedType + " submitted to Amazon, awaiting status check.", 5000);
|
||||
while (retryCount <= retryTimeout)
|
||||
{
|
||||
var feedOutput = amznConn.Feed.GetFeed(feedresultTXT);
|
||||
if (feedOutput.ProcessingStatus == FikaAmazonAPI.AmazonSpApiSDK.Models.Feeds.Feed.ProcessingStatusEnum.DONE)
|
||||
{
|
||||
result = amznConn.Feed.GetFeedDocument(feedOutput.ResultFeedDocumentId);
|
||||
break;
|
||||
}
|
||||
retryCount++;
|
||||
UI.Console.Wait("Feed: " + feedType + ", Processing status: " + feedOutput.ProcessingStatus + ", Retry: " + retryCount + " of "+ retryTimeout, sleepTime);
|
||||
}
|
||||
|
||||
// retry timeout
|
||||
if (retryCount > retryTimeout)
|
||||
{
|
||||
logEvent.LogError("Feed submission timeout. Feedtype:" + feedType + " FeedSubmissionId:" + feedSubmission.FeedSubmissionId);
|
||||
return;
|
||||
}
|
||||
|
||||
// get and do somehting with this
|
||||
string pathURL = string.Empty;
|
||||
pathURL = result.Url;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
using bnhtrade.Core.Data.Amazon.SellingPartnerAPI;
|
||||
using FikaAmazonAPI;
|
||||
using FikaAmazonAPI.AmazonSpApiSDK.Models.FulfillmentInbound;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace bnhtrade.Core.Data.Amazon.FulFillmentInbound
|
||||
{
|
||||
public class CreateInboundShipmentPlan
|
||||
{
|
||||
private AmazonConnection amznConn = new SpApiConnection().Connection;
|
||||
|
||||
public CreateInboundShipmentPlan()
|
||||
{
|
||||
}
|
||||
|
||||
public void CreatePlan(List<bnhtrade.Core.Model.AmazonFba.ShippingPlanItem> itemList)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
// complete, but not tested (need to do something with the result)
|
||||
|
||||
var request = new FikaAmazonAPI.AmazonSpApiSDK.Models.FulfillmentInbound.CreateInboundShipmentPlanRequest();
|
||||
request.LabelPrepPreference = FikaAmazonAPI.AmazonSpApiSDK.Models.FulfillmentInbound.LabelPrepPreference.SELLERLABEL;
|
||||
request.ShipFromAddress.Name = ConfigurationManager.AppSettings["AmazonFbaShipFrom.Name"];
|
||||
request.ShipFromAddress.AddressLine1 = ConfigurationManager.AppSettings["AmazonFbaShipFrom.AddressLine1"];
|
||||
request.ShipFromAddress.AddressLine2 = ConfigurationManager.AppSettings["AmazonFbaShipFrom.AddressLine2"];
|
||||
//request.ShipFromAddress.DistrictOrCounty = null; // not required
|
||||
request.ShipFromAddress.City = ConfigurationManager.AppSettings["AmazonFbaShipFrom.City"];
|
||||
request.ShipFromAddress.StateOrProvinceCode = ConfigurationManager.AppSettings["AmazonFbaShipFrom.StateOrProvinceCode"]; //required
|
||||
request.ShipFromAddress.PostalCode = ConfigurationManager.AppSettings["AmazonFbaShipFrom.PostalCode"];
|
||||
request.ShipFromAddress.CountryCode = ConfigurationManager.AppSettings["AmazonFbaShipFrom.CountryCode"];
|
||||
request.ShipToCountryCode = ConfigurationManager.AppSettings["AmazonFbaShipFrom.CountryCode"];
|
||||
|
||||
// add item list
|
||||
request.InboundShipmentPlanRequestItems = TransposeItemList(itemList);
|
||||
|
||||
var result = amznConn.FulFillmentInbound.CreateInboundShipmentPlan(request);
|
||||
}
|
||||
|
||||
private InboundShipmentPlanRequestItemList TransposeItemList(List<bnhtrade.Core.Model.AmazonFba.ShippingPlanItem> itemList)
|
||||
{
|
||||
var returnList = new InboundShipmentPlanRequestItemList();
|
||||
|
||||
foreach(var item in itemList)
|
||||
{
|
||||
var requestItem = new InboundShipmentPlanRequestItem();
|
||||
|
||||
requestItem.SellerSKU = item.SkuNumber;
|
||||
requestItem.ASIN = item.ASIN;
|
||||
if (Enum.TryParse(item.Condition, out Condition myStatus)) { requestItem.Condition = myStatus; }
|
||||
else { throw new Exception("Unable to parse string '" + item.Condition + "' to ENUM"); }
|
||||
requestItem.Quantity = item.Quantity;
|
||||
//requestItem.QuantityInCase;
|
||||
//requestItem.PrepDetailsList;
|
||||
|
||||
returnList.Add(requestItem);
|
||||
}
|
||||
|
||||
return returnList;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
using bnhtrade.Core.Data.Amazon.SellingPartnerAPI;
|
||||
using FikaAmazonAPI;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace bnhtrade.Core.Data.Amazon.FulFillmentInbound
|
||||
{
|
||||
public class GetShipmentItems
|
||||
{
|
||||
private AmazonConnection amznConn = new SpApiConnection().Connection;
|
||||
|
||||
public GetShipmentItems()
|
||||
{
|
||||
}
|
||||
|
||||
public List<Model.AmazonFba.ShipmentItemInfo> GetByDateRange(DateTime utcDateTimeAfter, DateTime utcDateTimeBefore)
|
||||
{
|
||||
var result = new List<Model.AmazonFba.ShipmentItemInfo>();
|
||||
|
||||
// build the request
|
||||
var parameter = new FikaAmazonAPI.Parameter.FulFillmentInbound.ParameterGetShipmentItems();
|
||||
parameter.MarketplaceId = amznConn.GetCurrentMarketplace.ID;
|
||||
parameter.QueryType = FikaAmazonAPI.Utils.Constants.QueryType.DATE_RANGE;
|
||||
parameter.LastUpdatedAfter = utcDateTimeAfter;
|
||||
parameter.LastUpdatedBefore = utcDateTimeBefore;
|
||||
|
||||
var apiResult = amznConn.FulFillmentInbound.GetShipmentItems(parameter);
|
||||
AppendNextToken(ref apiResult);
|
||||
return TransposeModel(apiResult);
|
||||
}
|
||||
|
||||
public List<Model.AmazonFba.ShipmentItemInfo> GetByShipmentId(string shipmentId)
|
||||
{
|
||||
var result = new List<Model.AmazonFba.ShipmentItemInfo>();
|
||||
if (string.IsNullOrEmpty(shipmentId)) { return result; }
|
||||
|
||||
// build the request
|
||||
//var parameter = new FikaAmazonAPI.Parameter.FulFillmentInbound.ParameterGetShipmentItems();
|
||||
//parameter.MarketplaceId = marketPlaceId;
|
||||
//parameter.QueryType = FikaAmazonAPI.Utils.Constants.QueryType.SHIPMENT;
|
||||
//parameter.ShipmentId = shipmentId;
|
||||
|
||||
var apiResult = amznConn.FulFillmentInbound.GetShipmentItemsByShipmentId(shipmentId);
|
||||
AppendNextToken(ref apiResult);
|
||||
return TransposeModel(apiResult);
|
||||
}
|
||||
|
||||
// checks for next-token, if true appends additional data to the ShipmentData
|
||||
private void AppendNextToken(ref FikaAmazonAPI.AmazonSpApiSDK.Models.FulfillmentInbound.InboundShipmentItemList shipmentList)
|
||||
{
|
||||
while (!string.IsNullOrEmpty(shipmentList.NextToken))
|
||||
{
|
||||
// build the request
|
||||
var parameter = new FikaAmazonAPI.Parameter.FulFillmentInbound.ParameterGetShipmentItems();
|
||||
parameter.MarketplaceId = amznConn.GetCurrentMarketplace.ID;
|
||||
parameter.QueryType = FikaAmazonAPI.Utils.Constants.QueryType.NEXT_TOKEN;
|
||||
parameter.NextToken = shipmentList.NextToken;
|
||||
|
||||
var result = amznConn.FulFillmentInbound.GetShipmentItems(parameter);
|
||||
|
||||
shipmentList.AddRange(result);
|
||||
shipmentList.NextToken = result.NextToken;
|
||||
}
|
||||
}
|
||||
|
||||
private void AppendNextToken(ref FikaAmazonAPI.AmazonSpApiSDK.Models.FulfillmentInbound.GetShipmentItemsResult shipmentList)
|
||||
{
|
||||
while (!string.IsNullOrEmpty(shipmentList.NextToken))
|
||||
{
|
||||
// build the request
|
||||
var parameter = new FikaAmazonAPI.Parameter.FulFillmentInbound.ParameterGetShipmentItems();
|
||||
parameter.MarketplaceId = amznConn.GetCurrentMarketplace.ID;
|
||||
parameter.QueryType = FikaAmazonAPI.Utils.Constants.QueryType.NEXT_TOKEN;
|
||||
parameter.NextToken = shipmentList.NextToken;
|
||||
|
||||
var result = amznConn.FulFillmentInbound.GetShipmentItems(parameter);
|
||||
|
||||
shipmentList.ItemData.AddRange(result);
|
||||
shipmentList.NextToken = result.NextToken;
|
||||
}
|
||||
}
|
||||
|
||||
private List<Model.AmazonFba.ShipmentItemInfo> TransposeModel(FikaAmazonAPI.AmazonSpApiSDK.Models.FulfillmentInbound.InboundShipmentItemList shipmentResult)
|
||||
{
|
||||
var returnList = new List<Model.AmazonFba.ShipmentItemInfo>();
|
||||
|
||||
for (var i = 0; i < shipmentResult.Count; i++)
|
||||
{
|
||||
var item = new Model.AmazonFba.ShipmentItemInfo();
|
||||
|
||||
// under new SP-API there are more details to be used, if needed
|
||||
item.AmazonFNSKU = shipmentResult[i].FulfillmentNetworkSKU;
|
||||
item.AmazonShipmentId = shipmentResult[i].ShipmentId;
|
||||
item.QuantityAllocated = shipmentResult[i].QuantityShipped.GetValueOrDefault();
|
||||
item.QuantityReceived = shipmentResult[i].QuantityReceived.GetValueOrDefault();
|
||||
item.SKUNumber = shipmentResult[i].SellerSKU;
|
||||
|
||||
returnList.Add(item);
|
||||
}
|
||||
|
||||
return returnList;
|
||||
}
|
||||
|
||||
private List<Model.AmazonFba.ShipmentItemInfo> TransposeModel(FikaAmazonAPI.AmazonSpApiSDK.Models.FulfillmentInbound.GetShipmentItemsResult shipmentResult)
|
||||
{
|
||||
var returnList = new List<Model.AmazonFba.ShipmentItemInfo>();
|
||||
|
||||
for (var i = 0; i < shipmentResult.ItemData.Count; i++)
|
||||
{
|
||||
var item = new Model.AmazonFba.ShipmentItemInfo();
|
||||
|
||||
// under new SP-API there are more details to be used, if needed
|
||||
item.AmazonFNSKU = shipmentResult.ItemData[i].FulfillmentNetworkSKU;
|
||||
item.AmazonShipmentId = shipmentResult.ItemData[i].ShipmentId;
|
||||
item.QuantityAllocated = shipmentResult.ItemData[i].QuantityShipped.GetValueOrDefault();
|
||||
item.QuantityReceived = shipmentResult.ItemData[i].QuantityReceived.GetValueOrDefault();
|
||||
item.SKUNumber = shipmentResult.ItemData[i].SellerSKU;
|
||||
|
||||
returnList.Add(item);
|
||||
}
|
||||
|
||||
return returnList;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
using bnhtrade.Core.Data.Amazon.SellingPartnerAPI;
|
||||
using FikaAmazonAPI;
|
||||
using FikaAmazonAPI.AmazonSpApiSDK.Models.FulfillmentInbound;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace bnhtrade.Core.Data.Amazon.FulFillmentInbound
|
||||
{
|
||||
public class GetShipments
|
||||
{
|
||||
private AmazonConnection amznConn = new SpApiConnection().Connection;
|
||||
|
||||
public GetShipments()
|
||||
{
|
||||
}
|
||||
|
||||
public List<Model.AmazonFba.ShipmentInfo> GetByDateRange(DateTime utcDateTimeAfter, DateTime utcDateTimeBefore)
|
||||
{
|
||||
// At least one of the ShipmentStatusList and ShipmentIdList must be provided
|
||||
|
||||
var result = new List<Model.AmazonFba.ShipmentInfo>();
|
||||
|
||||
// build the request
|
||||
var parameter = new FikaAmazonAPI.Parameter.FulFillmentInbound.ParameterGetShipments();
|
||||
parameter.MarketplaceId = amznConn.GetCurrentMarketplace.ID;
|
||||
parameter.QueryType = FikaAmazonAPI.Utils.Constants.QueryType.DATE_RANGE;
|
||||
parameter.LastUpdatedAfter = utcDateTimeAfter;
|
||||
parameter.LastUpdatedBefore = utcDateTimeBefore;
|
||||
AddShipmentStatusList(ref parameter);
|
||||
|
||||
var apiResult = amznConn.FulFillmentInbound.GetShipments(parameter);
|
||||
AppendNextToken(ref apiResult);
|
||||
return TransposeModel(apiResult);
|
||||
}
|
||||
|
||||
public List<Model.AmazonFba.ShipmentInfo> GetByShipmentIdList(List<string> shipmentIdList)
|
||||
{
|
||||
var result = new List<Model.AmazonFba.ShipmentInfo>();
|
||||
|
||||
// build the request
|
||||
var parameter = new FikaAmazonAPI.Parameter.FulFillmentInbound.ParameterGetShipments();
|
||||
parameter.MarketplaceId = amznConn.GetCurrentMarketplace.ID;
|
||||
parameter.QueryType = FikaAmazonAPI.Utils.Constants.QueryType.SHIPMENT;
|
||||
parameter.ShipmentIdList = shipmentIdList;
|
||||
|
||||
var apiResult = amznConn.FulFillmentInbound.GetShipments(parameter);
|
||||
AppendNextToken(ref apiResult);
|
||||
return TransposeModel(apiResult);
|
||||
}
|
||||
|
||||
private void AddShipmentStatusList(ref FikaAmazonAPI.Parameter.FulFillmentInbound.ParameterGetShipments parameters)
|
||||
{
|
||||
var list = new List<ShipmentStatus>();
|
||||
list.Add(ShipmentStatus.CANCELLED);
|
||||
list.Add(ShipmentStatus.CHECKED_IN);
|
||||
list.Add(ShipmentStatus.CLOSED);
|
||||
list.Add(ShipmentStatus.DELETED);
|
||||
list.Add(ShipmentStatus.DELIVERED);
|
||||
list.Add(ShipmentStatus.ERROR);
|
||||
list.Add(ShipmentStatus.IN_TRANSIT);
|
||||
list.Add(ShipmentStatus.READY_TO_SHIP);
|
||||
list.Add(ShipmentStatus.RECEIVING);
|
||||
list.Add(ShipmentStatus.SHIPPED);
|
||||
list.Add(ShipmentStatus.WORKING);
|
||||
|
||||
parameters.ShipmentStatusList = list;
|
||||
}
|
||||
|
||||
// checks for next-token, if true appends additional data to the ShipmentData
|
||||
private void AppendNextToken(ref FikaAmazonAPI.AmazonSpApiSDK.Models.FulfillmentInbound.GetShipmentsResult shipmentList)
|
||||
{
|
||||
while (!string.IsNullOrEmpty(shipmentList.NextToken))
|
||||
{
|
||||
// build the request
|
||||
var parameter = new FikaAmazonAPI.Parameter.FulFillmentInbound.ParameterGetShipments();
|
||||
parameter.MarketplaceId = amznConn.GetCurrentMarketplace.ID;
|
||||
parameter.QueryType = FikaAmazonAPI.Utils.Constants.QueryType.NEXT_TOKEN;
|
||||
parameter.NextToken = shipmentList.NextToken;
|
||||
|
||||
var result = amznConn.FulFillmentInbound.GetShipments(parameter);
|
||||
|
||||
shipmentList.ShipmentData.AddRange(result.ShipmentData);
|
||||
shipmentList.NextToken = result.NextToken;
|
||||
}
|
||||
}
|
||||
|
||||
// transposes return api object data to my model
|
||||
private List<Model.AmazonFba.ShipmentInfo> TransposeModel(FikaAmazonAPI.AmazonSpApiSDK.Models.FulfillmentInbound.GetShipmentsResult shipmentResult)
|
||||
{
|
||||
var returnList = new List<Model.AmazonFba.ShipmentInfo>();
|
||||
|
||||
for (var i = 0; i < shipmentResult.ShipmentData.Count; i++)
|
||||
{
|
||||
var item = new Model.AmazonFba.ShipmentInfo();
|
||||
|
||||
item.FbaShipmentId = shipmentResult.ShipmentData[i].ShipmentId;
|
||||
item.DestinationFulfillmentCenterId = shipmentResult.ShipmentData[i].DestinationFulfillmentCenterId;
|
||||
item.ShipmentName = shipmentResult.ShipmentData[i].ShipmentName;
|
||||
item.ShipmentStatus = shipmentResult.ShipmentData[i].ShipmentStatus.ToString();
|
||||
|
||||
returnList.Add(item);
|
||||
}
|
||||
|
||||
return returnList;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
//using MarketplaceWebServiceProducts.Model;
|
||||
using bnhtrade.Core.Data.Amazon.SellingPartnerAPI;
|
||||
using FikaAmazonAPI;
|
||||
using FikaAmazonAPI.AmazonSpApiSDK.Models.ProductFees;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace bnhtrade.Core.Data.Amazon.ProductFee
|
||||
{
|
||||
public class GetFeeEstimate
|
||||
{
|
||||
private AmazonConnection amznConn = new SpApiConnection().Connection;
|
||||
|
||||
public string CurrencyCode { get; set; } = "GBP";
|
||||
|
||||
public string MarketPlaceId { get; set; }
|
||||
|
||||
public GetFeeEstimate()
|
||||
{
|
||||
}
|
||||
|
||||
public Model.Amazon.ProductFeeEstimate GetFba(string asin, int productId, decimal listingPrice)
|
||||
{
|
||||
var returnObj = new Model.Amazon.ProductFeeEstimate();
|
||||
|
||||
if (string.IsNullOrWhiteSpace(asin))
|
||||
{
|
||||
throw new Exception("ASIN given to GetFeeEstimate is null or whitespace.");
|
||||
}
|
||||
|
||||
var listingPriceObj = new MoneyType(CurrencyCode, listingPrice);
|
||||
var priceToEstimateFees = new PriceToEstimateFees(listingPriceObj);
|
||||
|
||||
// create the request and get a response
|
||||
var request = new FeesEstimateRequest(MarketPlaceId, true, priceToEstimateFees, productId.ToString());
|
||||
var result = amznConn.ProductFee.GetMyFeesEstimateForASIN(asin, request);
|
||||
|
||||
if (result.FeesEstimateIdentifier.IdValue != asin)
|
||||
throw new Exception("returned ud value does not match ASIN");
|
||||
returnObj.Asin = asin;
|
||||
returnObj.ProductId = int.Parse(result.FeesEstimateIdentifier.SellerInputIdentifier);
|
||||
|
||||
// test for error
|
||||
if (result.Error != null)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
sb.AppendLine("ASIN: " + asin);
|
||||
sb.AppendLine("Error Code: " + result.Error.Code);
|
||||
if (result.Error.Detail != null)
|
||||
{ sb.AppendLine("Detail: " + result.Error.Detail); }
|
||||
if (result.Error.Message != null)
|
||||
{ sb.AppendLine("Message: " + result.Error.Message); }
|
||||
if (result.Error.Type != null)
|
||||
{ sb.AppendLine("Type: " + result.Error.Type); }
|
||||
|
||||
MiscFunction.EventLogInsert("Error running GetProductEstimateFee for ASIN:" + asin + ", further details attached.", 1, sb.ToString());
|
||||
throw new Exception("ProductFeeEstimate error, check logs for further details");
|
||||
}
|
||||
|
||||
returnObj.IsAmazonFulfilled = result.FeesEstimateIdentifier.IsAmazonFulfilled.Value;
|
||||
returnObj.TimeOfFeeEstimation = result.FeesEstimate.TimeOfFeesEstimation.Value;
|
||||
returnObj.TotalFeeEstimate = result.FeesEstimate.TotalFeesEstimate.Amount.Value;
|
||||
returnObj.CurrencyCode = result.FeesEstimate.TotalFeesEstimate.CurrencyCode;
|
||||
returnObj.PriceToEstimateFeeListingPrice = result.FeesEstimateIdentifier.PriceToEstimateFees.ListingPrice.Amount.Value;
|
||||
returnObj.PriceToEstimateFeeShipping = 0;
|
||||
if (result.FeesEstimateIdentifier.PriceToEstimateFees.Shipping != null)
|
||||
returnObj.PriceToEstimateFeeShipping = result.FeesEstimateIdentifier.PriceToEstimateFees.Shipping.Amount.Value;
|
||||
returnObj.PriceToEstimateFeePoints = 0;
|
||||
if (result.FeesEstimateIdentifier.PriceToEstimateFees.Points != null)
|
||||
returnObj.PriceToEstimateFeePoints = result.FeesEstimateIdentifier.PriceToEstimateFees.Points.PointsMonetaryValue.Amount.Value;
|
||||
|
||||
returnObj.ReferralFee = 0m;
|
||||
returnObj.VariableClosingFee = 0m;
|
||||
returnObj.FulfillmentFees = 0m;
|
||||
returnObj.PerItemFee = 0m;
|
||||
returnObj.OtherFee_Exception = 0m;
|
||||
|
||||
FeeDetailList feeDetailList = result.FeesEstimate.FeeDetailList;
|
||||
List<FeeDetail> feeDetail = feeDetailList;
|
||||
foreach (FeeDetail feeDetailItem in feeDetail)
|
||||
{
|
||||
if (feeDetailItem.FeeType == "AmazonReferralFee" || feeDetailItem.FeeType == "ReferralFee")
|
||||
{ returnObj.ReferralFee = (decimal)feeDetailItem.FinalFee.Amount; }
|
||||
else if (feeDetailItem.FeeType == "VariableClosingFee")
|
||||
{ returnObj.VariableClosingFee = (decimal)feeDetailItem.FinalFee.Amount; }
|
||||
else if (feeDetailItem.FeeType == "PerItemFee")
|
||||
{ returnObj.PerItemFee = (decimal)feeDetailItem.FinalFee.Amount; }
|
||||
else if (feeDetailItem.FeeType == "FBAFees" || feeDetailItem.FeeType == "FulfillmentFees")
|
||||
{ returnObj.FulfillmentFees = (decimal)feeDetailItem.FinalFee.Amount; }
|
||||
else
|
||||
{ returnObj.OtherFee_Exception = returnObj.OtherFee_Exception + (decimal)feeDetailItem.FinalFee.Amount; }
|
||||
}
|
||||
|
||||
return returnObj;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
using bnhtrade.Core.Data.Amazon.SellingPartnerAPI;
|
||||
using FikaAmazonAPI;
|
||||
using FikaAmazonAPI.AmazonSpApiSDK.Models.ProductPricing;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace bnhtrade.Core.Data.Amazon.ProductPricing
|
||||
{
|
||||
public class GetCompetitivePricing
|
||||
{
|
||||
private AmazonConnection amznConn = new SpApiConnection().Connection;
|
||||
|
||||
public string MarketPlaceId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets Amazon Buy Box price for a given product. Will return no price if page does not have buy box
|
||||
/// </summary>
|
||||
public GetCompetitivePricing()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrives current Buy Box price (+ additional info) for a given ASIN
|
||||
/// </summary>
|
||||
/// <param name="asin">Amazon ASIN product reference</param>
|
||||
/// <returns></returns>
|
||||
public Model.Amazon.ProductCompetitivePrice ByAsin(string asin)
|
||||
{
|
||||
var result = Execute(new List<string> { asin }, false);
|
||||
if (result.Any()) { return result[0]; }
|
||||
else { return null; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrives current Buy Box price (+ additional info) for a given ASIN
|
||||
/// </summary>
|
||||
/// <param name="asin">Amazon ASIN product reference</param>
|
||||
/// <returns></returns>
|
||||
public List<Model.Amazon.ProductCompetitivePrice> ByAsin(List<string> asinList)
|
||||
{
|
||||
return Execute(asinList, false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ideally use ASIN
|
||||
/// </summary>
|
||||
/// <param name="skuList"></param>
|
||||
/// <returns></returns>
|
||||
private Model.Amazon.ProductCompetitivePrice BySku(string sku)
|
||||
{
|
||||
var result = Execute(new List<string> { sku }, true);
|
||||
if (result.Any()) { return result[0]; }
|
||||
else { return null; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ideally use ASIN
|
||||
/// </summary>
|
||||
/// <param name="skuList"></param>
|
||||
/// <returns></returns>
|
||||
private List<Model.Amazon.ProductCompetitivePrice> BySku(List<string> skuList)
|
||||
{
|
||||
return Execute(skuList, true);
|
||||
}
|
||||
|
||||
private List<Model.Amazon.ProductCompetitivePrice> Execute(List<string> itemList, bool isSkuList)
|
||||
{
|
||||
var apiList = new List<Price>();
|
||||
|
||||
// max of 20 items in one call
|
||||
int i = 0;
|
||||
int total = itemList.Count;
|
||||
var itemRequestList = new List<string>();
|
||||
foreach (string sku in itemList)
|
||||
{
|
||||
i++;
|
||||
itemRequestList.Add(sku);
|
||||
|
||||
if (i == total || i % 20 == 0)
|
||||
{
|
||||
var parameter = new FikaAmazonAPI.Parameter.ProductPricing.ParameterGetCompetitivePricing();
|
||||
if (isSkuList) { parameter.Skus = itemRequestList; }
|
||||
else { parameter.Asins = itemRequestList; }
|
||||
parameter.MarketplaceId = MarketPlaceId;
|
||||
|
||||
apiList.AddRange(amznConn.ProductPricing.GetCompetitivePricing(parameter));
|
||||
itemRequestList = new List<string>();
|
||||
}
|
||||
}
|
||||
|
||||
return TransposeData(apiList);
|
||||
}
|
||||
|
||||
private List<Model.Amazon.ProductCompetitivePrice> TransposeData(IList<Price> spapiList)
|
||||
{
|
||||
var returnList = new List<Model.Amazon.ProductCompetitivePrice>();
|
||||
|
||||
foreach (var item in spapiList)
|
||||
{
|
||||
string asin = item.ASIN;
|
||||
decimal competitivePrice;
|
||||
bool competitivePriceIsSet;
|
||||
bool isBuyBox;
|
||||
bool buyBoxBelongsToRequester;
|
||||
int offersCountNew = 0;
|
||||
int offersCountUsed = 0;
|
||||
|
||||
if (item.Product.CompetitivePricing.CompetitivePrices.Count == 0)
|
||||
{
|
||||
competitivePrice = 0;
|
||||
competitivePriceIsSet = false;
|
||||
isBuyBox = false;
|
||||
buyBoxBelongsToRequester = false;
|
||||
}
|
||||
else if (item.Product.CompetitivePricing.CompetitivePrices.Count == 1)
|
||||
{
|
||||
if (item.Product.CompetitivePricing.CompetitivePrices[0].Condition != "New")
|
||||
throw new Exception("Condition returned is not new");
|
||||
|
||||
competitivePrice = item.Product.CompetitivePricing.CompetitivePrices[0].Price.LandedPrice.Amount.Value;
|
||||
competitivePriceIsSet = true;
|
||||
isBuyBox = true;
|
||||
buyBoxBelongsToRequester = item.Product.CompetitivePricing.CompetitivePrices[0].BelongsToRequester.Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("More than one competitive price returned");
|
||||
}
|
||||
|
||||
// get quanities
|
||||
foreach (var offer in item.Product.CompetitivePricing.NumberOfOfferListings)
|
||||
{
|
||||
if (offer.Condition == "New") { offersCountNew = offer.Count.Value; }
|
||||
if (offer.Condition == "Used") { offersCountUsed = offer.Count.Value; }
|
||||
}
|
||||
|
||||
// add to list
|
||||
var returnItem = new Model.Amazon.ProductCompetitivePrice(
|
||||
asin
|
||||
, competitivePrice
|
||||
, competitivePriceIsSet
|
||||
, isBuyBox
|
||||
, buyBoxBelongsToRequester
|
||||
, offersCountNew
|
||||
, offersCountUsed);
|
||||
returnList.Add(returnItem);
|
||||
}
|
||||
|
||||
return returnList;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using static FikaAmazonAPI.Utils.Constants;
|
||||
|
||||
namespace bnhtrade.Core.Data.Amazon.Report
|
||||
{
|
||||
public class FbaCustomerReturn : ReportLogic
|
||||
{
|
||||
public FbaCustomerReturn() : base(ReportTypes.GET_FBA_FULFILLMENT_CUSTOMER_RETURNS_DATA)
|
||||
{
|
||||
}
|
||||
|
||||
public void GetReport(DateTime startTime, DateTime endTime)
|
||||
{
|
||||
int maxRange = 0; // there doesn't appear to be any limit on time span
|
||||
|
||||
DownloadTimePeriodReport(startTime, endTime, maxRange);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using static FikaAmazonAPI.Utils.Constants;
|
||||
|
||||
namespace bnhtrade.Core.Data.Amazon.Report
|
||||
{
|
||||
public class FbaInventory : ReportLogic
|
||||
{
|
||||
public FbaInventory() : base (ReportTypes.GET_FBA_MYI_ALL_INVENTORY_DATA)
|
||||
{
|
||||
}
|
||||
|
||||
public void GetReport(int reportMaxAge = 30)
|
||||
{
|
||||
// Amazon will throttle (return 'FATAL' error) when requesting this report twice within 15 minutes
|
||||
|
||||
DownloadSnapshotReport(reportMaxAge);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using static FikaAmazonAPI.Utils.Constants;
|
||||
|
||||
namespace bnhtrade.Core.Data.Amazon.Report
|
||||
{
|
||||
public class FbaInventoryAdustment : ReportLogic
|
||||
{
|
||||
public FbaInventoryAdustment() : base(ReportTypes.GET_FBA_FULFILLMENT_INVENTORY_ADJUSTMENTS_DATA)
|
||||
{
|
||||
throw new Exception("report has been depreciated https://developer-docs.amazon.com/sp-api/docs/sp-api-deprecations");
|
||||
}
|
||||
|
||||
public void GetReport(DateTime startTime, DateTime endTime)
|
||||
{
|
||||
DownloadTimePeriodReport(startTime, endTime, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using static FikaAmazonAPI.Utils.Constants;
|
||||
|
||||
namespace bnhtrade.Core.Data.Amazon.Report
|
||||
{
|
||||
public class FbaInventoryAge : ReportLogic
|
||||
{
|
||||
public FbaInventoryAge() : base(ReportTypes.GET_FBA_INVENTORY_AGED_DATA)
|
||||
{
|
||||
throw new Exception("report has been depreciated https://developer-docs.amazon.com/sp-api/docs/sp-api-deprecations");
|
||||
}
|
||||
|
||||
public new void GetReport(int reportMaxAge = 30)
|
||||
{
|
||||
throw new Exception("GET_FBA_INVENTORY_AGED_DATA report has been retired since 22/06/2022 and replaced by GET_FBA_INVENTORY_PLANNING_DATA");
|
||||
|
||||
//DownloadSnapshotReport(reportMaxAge);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using static FikaAmazonAPI.Utils.Constants;
|
||||
|
||||
namespace bnhtrade.Core.Data.Amazon.Report
|
||||
{
|
||||
public class FbaInventoryReceipt : ReportLogic
|
||||
{
|
||||
/*
|
||||
* Not able to uniquley define each row in flat file and check for duplicate in DB
|
||||
* therefore, do not download report date range that has already been imported, as records will be duplicated
|
||||
*
|
||||
* Due to a MWS bug, MWS can/will include some records that are before the specified date range. As mws report is updated once daily,
|
||||
* it is safe to omitt lines < startDate when parsing/inserting lines into db (as these will have been previously imported)
|
||||
*/
|
||||
|
||||
public FbaInventoryReceipt() : base(ReportTypes.GET_FBA_FULFILLMENT_INVENTORY_RECEIPTS_DATA)
|
||||
{
|
||||
throw new Exception("report has been depreciated https://developer-docs.amazon.com/sp-api/docs/sp-api-deprecations");
|
||||
}
|
||||
|
||||
public void GetReport(DateTime startTime, DateTime endTime)
|
||||
{
|
||||
DownloadTimePeriodReport(startTime, endTime, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using static FikaAmazonAPI.Utils.Constants;
|
||||
|
||||
namespace bnhtrade.Core.Data.Amazon.Report
|
||||
{
|
||||
public class FbaReimbursement : ReportLogic
|
||||
{
|
||||
public FbaReimbursement() : base(ReportTypes.GET_FBA_REIMBURSEMENTS_DATA)
|
||||
{
|
||||
}
|
||||
|
||||
public void GetReport(DateTime startTime, DateTime endTime)
|
||||
{
|
||||
DownloadTimePeriodReport(startTime, endTime, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using static FikaAmazonAPI.Utils.Constants;
|
||||
|
||||
namespace bnhtrade.Core.Data.Amazon.Report
|
||||
{
|
||||
public class FbaRemovalOrder : ReportLogic
|
||||
{
|
||||
public FbaRemovalOrder() : base(ReportTypes.GET_FBA_FULFILLMENT_REMOVAL_ORDER_DETAIL_DATA)
|
||||
{
|
||||
}
|
||||
|
||||
public void GetReport(DateTime startTime, DateTime endTime)
|
||||
{
|
||||
DownloadTimePeriodReport(startTime, endTime, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using static FikaAmazonAPI.Utils.Constants;
|
||||
|
||||
namespace bnhtrade.Core.Data.Amazon.Report
|
||||
{
|
||||
public class FbaSaleShipment : ReportLogic
|
||||
{
|
||||
//public FbaSaleShipment() : base(ReportTypes.GET_FBA_FULFILLMENT_CUSTOMER_SHIPMENT_SALES_DATA)
|
||||
public FbaSaleShipment() : base(ReportTypes.GET_AMAZON_FULFILLED_SHIPMENTS_DATA_GENERAL)
|
||||
{
|
||||
}
|
||||
|
||||
public void GetReport(DateTime startTime, DateTime endTime)
|
||||
{
|
||||
DownloadTimePeriodReport(startTime, endTime, 30);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,236 @@
|
||||
using bnhtrade.Core.Data.Amazon.SellingPartnerAPI;
|
||||
using FikaAmazonAPI;
|
||||
using FikaAmazonAPI.Parameter.Report;
|
||||
using FikaAmazonAPI.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using static FikaAmazonAPI.Utils.Constants;
|
||||
|
||||
namespace bnhtrade.Core.Data.Amazon.Report
|
||||
{
|
||||
public class ReportLogic
|
||||
{
|
||||
private AmazonConnection amznConn = new SpApiConnection().Connection;
|
||||
private FikaAmazonAPI.AmazonSpApiSDK.Models.Reports.Report report;
|
||||
private ReportTypes reportType;
|
||||
protected Logic.Log.LogEvent log = new Logic.Log.LogEvent();
|
||||
|
||||
public DateTime? ReportCreatedTime
|
||||
{
|
||||
get
|
||||
{
|
||||
if (report == null) { return null; }
|
||||
else { return report.CreatedTime; }
|
||||
}
|
||||
}
|
||||
|
||||
public bool ReportDoneNoData { get; private set; }
|
||||
|
||||
public string ReportFilePath { get; private set; }
|
||||
|
||||
private FikaAmazonAPI.Utils.MarketplaceIds MarketPlaceIds { get; set; }
|
||||
|
||||
public bool ReportFilePathIsSet
|
||||
{
|
||||
get { return !string.IsNullOrWhiteSpace(ReportFilePath); }
|
||||
}
|
||||
|
||||
public ReportLogic(ReportTypes reportType)
|
||||
{
|
||||
this.reportType = reportType;
|
||||
this.MarketPlaceIds = new MarketplaceIds();
|
||||
this.MarketPlaceIds.Add(amznConn.GetCurrentMarketplace.ID);
|
||||
Innit();
|
||||
}
|
||||
|
||||
private void Innit()
|
||||
{
|
||||
ReportDoneNoData = false;
|
||||
ReportFilePath = null;
|
||||
report = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Always use this function to report and it's filepath, this ensures the two correlate
|
||||
/// </summary>
|
||||
/// <param name="report"></param>
|
||||
/// <param name="reportFilePath"></param>
|
||||
private void SetFilePath(FikaAmazonAPI.AmazonSpApiSDK.Models.Reports.Report report, string reportFilePath)
|
||||
{
|
||||
this.report = report;
|
||||
this.ReportFilePath = reportFilePath;
|
||||
}
|
||||
|
||||
protected void DownloadTimePeriodReport(DateTime utcDataStartTime, DateTime utcDataEndTime, int maxDateRangeDays)
|
||||
{
|
||||
if (utcDataStartTime.Kind != DateTimeKind.Utc || utcDataEndTime.Kind != DateTimeKind.Utc)
|
||||
throw new Exception("Report period time should be set to UTC");
|
||||
|
||||
if (maxDateRangeDays > 0 && (utcDataEndTime - utcDataStartTime).TotalDays > maxDateRangeDays)
|
||||
throw new Exception("Date range for report is greater than the maximum allowable");
|
||||
|
||||
var specification = new ParameterCreateReportSpecification();
|
||||
specification.marketplaceIds = this.MarketPlaceIds;
|
||||
specification.reportType = reportType;
|
||||
specification.dataStartTime = utcDataStartTime;
|
||||
specification.dataEndTime = utcDataEndTime;
|
||||
|
||||
DownloadReport(specification, false);
|
||||
}
|
||||
|
||||
protected void DownloadSnapshotReport(int snapshotMaxAge)
|
||||
{
|
||||
var specification = new ParameterCreateReportSpecification();
|
||||
specification.marketplaceIds = this.MarketPlaceIds;
|
||||
specification.reportType = reportType;
|
||||
|
||||
DownloadReport(specification, true, snapshotMaxAge);
|
||||
}
|
||||
|
||||
private void DownloadReport(ParameterCreateReportSpecification specification, bool isSnapshotReport, int snapshotMaxAge = 0)
|
||||
{
|
||||
// Amazon create report is throttled to 1 report every 15 minutes
|
||||
|
||||
Innit();
|
||||
|
||||
// check for existing report with same specification
|
||||
string reportId = ExistingReportSearch(specification);
|
||||
|
||||
if (reportId == null)
|
||||
{ reportId = amznConn.Reports.CreateReport(specification); }
|
||||
|
||||
var filePath = amznConn.Reports.GetReportFile(reportId);
|
||||
var report = amznConn.Reports.GetReport(reportId); // filePath and report need to be called in this order
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(filePath))
|
||||
{
|
||||
SetFilePath(report, filePath);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
// test for 'Fatal' return when report has recently been requested.
|
||||
report = amznConn.Reports.GetReport(reportId);
|
||||
if (report.ProcessingStatus == FikaAmazonAPI.AmazonSpApiSDK.Models.Reports.Report.ProcessingStatusEnum.CANCELLED)
|
||||
{
|
||||
// From SPAPI Documentation: The report was cancelled. There are two ways a report can be cancelled:
|
||||
// an explicit cancellation request before the report starts processing, or an automatic cancellation
|
||||
// if there is no data to return.
|
||||
log.Initialise();
|
||||
log.LogInformation("ReportID:" + reportId + " returned 'CANCELLED' status (no data).");
|
||||
ReportDoneNoData = true;
|
||||
return;
|
||||
}
|
||||
else if (report.ProcessingStatus == FikaAmazonAPI.AmazonSpApiSDK.Models.Reports.Report.ProcessingStatusEnum.FATAL)
|
||||
{
|
||||
if (isSnapshotReport)
|
||||
{
|
||||
SnapahotThrottleHanderler(ref report, specification, snapshotMaxAge);
|
||||
|
||||
filePath = amznConn.Reports.GetReportFile(report.ReportId);
|
||||
|
||||
if (string.IsNullOrWhiteSpace(filePath))
|
||||
{
|
||||
LogReportError(report, "Error while retriving report " + reportType.ToString());
|
||||
throw new Exception("Error while retriving report " + reportType.ToString());
|
||||
}
|
||||
|
||||
SetFilePath(report, filePath);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("Report processing status returned 'FATAL' report#" + reportType.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new Exception("Error while retriving " + reportType.ToString() + " report, nothing should be getting here!!");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If a duplicate report has been recently requested, Amazon may return 'FATAL'. This method tests for, and attempts to retrive the duplicate report that is causing the error.
|
||||
/// </summary>
|
||||
/// <param name="report">Report to test for throttled response</param>
|
||||
/// <param name="specification">The specification that created to throttle report.</param>
|
||||
private void SnapahotThrottleHanderler(ref FikaAmazonAPI.AmazonSpApiSDK.Models.Reports.Report report, ParameterCreateReportSpecification specification, int snapshotMaxAge)
|
||||
{
|
||||
if (report.ProcessingStatus != FikaAmazonAPI.AmazonSpApiSDK.Models.Reports.Report.ProcessingStatusEnum.FATAL)
|
||||
return;
|
||||
|
||||
if (snapshotMaxAge <= 0)
|
||||
{
|
||||
// report not avaiable
|
||||
throw new Exception( reportType.ToString() + " report not avaibale for requested timeframe");
|
||||
}
|
||||
|
||||
// search for valid reports with required timeframe
|
||||
var parameters = new ParameterReportList();
|
||||
parameters.reportTypes = new List<ReportTypes> { specification.reportType };
|
||||
parameters.createdSince = report.CreatedTime.Value.AddMinutes(-snapshotMaxAge);
|
||||
parameters.marketplaceIds = specification.marketplaceIds;
|
||||
var reports = amznConn.Reports.GetReports(parameters);
|
||||
|
||||
if (reports == null || !reports.Any())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var item in reports)
|
||||
{
|
||||
if (item.ProcessingStatus != FikaAmazonAPI.AmazonSpApiSDK.Models.Reports.Report.ProcessingStatusEnum.CANCELLED
|
||||
&& item.ProcessingStatus != FikaAmazonAPI.AmazonSpApiSDK.Models.Reports.Report.ProcessingStatusEnum.FATAL)
|
||||
{
|
||||
report = item;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private string ExistingReportSearch(ParameterCreateReportSpecification specification)
|
||||
{
|
||||
// amazon may return 'fatal' due to report already existing and/or report request matches an recent existing request
|
||||
|
||||
// search for valid reports with required timeframe
|
||||
var parameters = new ParameterReportList();
|
||||
parameters.reportTypes = new List<ReportTypes> { specification.reportType };
|
||||
parameters.marketplaceIds = specification.marketplaceIds;
|
||||
var reportList = amznConn.Reports.GetReports(parameters);
|
||||
|
||||
// list is ordered with the most recent first
|
||||
foreach (var item in reportList)
|
||||
{
|
||||
if (item.ProcessingStatus == FikaAmazonAPI.AmazonSpApiSDK.Models.Reports.Report.ProcessingStatusEnum.DONE
|
||||
|| item.ProcessingStatus == FikaAmazonAPI.AmazonSpApiSDK.Models.Reports.Report.ProcessingStatusEnum.INPROGRESS
|
||||
|| item.ProcessingStatus == FikaAmazonAPI.AmazonSpApiSDK.Models.Reports.Report.ProcessingStatusEnum.INQUEUE)
|
||||
{
|
||||
if(item.DataStartTime == specification.dataStartTime
|
||||
&& item.DataEndTime == specification.dataEndTime)
|
||||
{
|
||||
return item.ReportId;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void LogReportError(FikaAmazonAPI.AmazonSpApiSDK.Models.Reports.Report report, string errorTitle)
|
||||
{
|
||||
log.Initialise();
|
||||
log.LogError(errorTitle,
|
||||
"ReportType: " + report.ReportType + "\r\n"
|
||||
+ "ReportId: " + report.ReportId + "\r\n"
|
||||
+ "MarketplaceIds: " + report.MarketplaceIds + "\r\n"
|
||||
+ "CreatedTime: " + report.CreatedTime + "\r\n"
|
||||
+ "ReportScheduleId: " + report.ReportScheduleId + "\r\n"
|
||||
+ "ReportDocumentId: " + report.ReportDocumentId + "\r\n"
|
||||
+ "DataStartTime: " + report.DataStartTime + "\r\n"
|
||||
+ "DataEndTime: " + report.DataEndTime + "\r\n"
|
||||
+ "ProcessingStartTime: " + report.ProcessingStartTime + "\r\n"
|
||||
+ "ProcessingEndTime: " + report.ProcessingEndTime + "\r\n"
|
||||
+ "ProcessingStatus: " + report.ProcessingStatus + "\r\n"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
using bnhtrade.Core.Data.Amazon.SellingPartnerAPI;
|
||||
using FikaAmazonAPI;
|
||||
using FikaAmazonAPI.Parameter.Report;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using static FikaAmazonAPI.Utils.Constants;
|
||||
|
||||
namespace bnhtrade.Core.Data.Amazon.Report
|
||||
{
|
||||
public class SettlementReport
|
||||
{
|
||||
private AmazonConnection amznConn = new SpApiConnection().Connection;
|
||||
|
||||
public SettlementReport ()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of reportId (not settlement report Id) for settlement reports available on the amazon api
|
||||
/// </summary>
|
||||
/// <returns>ReportId list</returns>
|
||||
public List<string> ListAvaliableReports()
|
||||
{
|
||||
UI.Console.WriteLine("Requesting list of avaliable settlement reports form Amazon SP-API");
|
||||
|
||||
// set parameters
|
||||
var parameters = new ParameterReportList();
|
||||
parameters.reportTypes = new List<ReportTypes>() { ReportTypes.GET_V2_SETTLEMENT_REPORT_DATA_FLAT_FILE_V2};
|
||||
parameters.marketplaceIds.Add(amznConn.GetCurrentMarketplace.ID);
|
||||
|
||||
// request from amazon
|
||||
var result = amznConn.Reports.GetReports(parameters);
|
||||
|
||||
var returnList = new List<string>();
|
||||
foreach (var report in result)
|
||||
{
|
||||
returnList.Add(report.ReportId);
|
||||
}
|
||||
|
||||
UI.Console.WriteLine("{0} Settlement reports avaible on Amazon SP-API");
|
||||
return returnList;
|
||||
}
|
||||
|
||||
public string GetFile(string reportId)
|
||||
{
|
||||
return amznConn.Reports.GetReportFile(reportId);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
////using bnhtrade.Core.Data.Amazon.SellingPartnerAPI.Services;
|
||||
//using FikaAmazonAPI.Services;
|
||||
//using System;
|
||||
//using System.Collections.Generic;
|
||||
//using System.Text;
|
||||
|
||||
//namespace bnhtrade.Core.Data.Amazon.SellingPartnerAPI
|
||||
//{
|
||||
// public class AmazonConnection
|
||||
// {
|
||||
// private AmazonCredential Credentials { get; set; }
|
||||
|
||||
// public FbaInboundService FbaInbound => this._FbaInbound ?? throw _NoCredentials;
|
||||
// public FbaInventoryService FbaInventory => this._FbaInventory ?? throw _NoCredentials;
|
||||
// public FulFillmentInboundService FulFillmentInbound => this._FulFillmentInbound ?? throw _NoCredentials;
|
||||
// public ProductFeeService ProductFee => this._ProductFee ?? throw _NoCredentials;
|
||||
// public ProductPricingService ProductPricing => this._ProductPricing ?? throw _NoCredentials;
|
||||
// public ReportService Reports => this._Reports ?? throw _NoCredentials;
|
||||
// //public AplusContentService AplusContent => this._AplusContent ?? throw _NoCredentials;
|
||||
// //public AuthorizationService Authorization => this._Authorization ?? throw _NoCredentials;
|
||||
// //public CatalogItemService CatalogItem => this._CatalogItems ?? throw _NoCredentials;
|
||||
// //public FbaInboundEligibilityService FbaInboundEligibility => this._FbaInboundEligibility ?? throw _NoCredentials;
|
||||
// //public FbaOutboundService FbaOutbound => this._FbaOutbound ?? throw _NoCredentials;
|
||||
// //public FbaSmallandLightService FbaSmallandLight => this._FbaSmallandLight ?? throw _NoCredentials;
|
||||
// //public FeedService Feed => this._Feed ?? throw _NoCredentials;
|
||||
// //public FinancialService Financial => this._Financials ?? throw _NoCredentials;
|
||||
// //public FulFillmentOutboundService FulFillmentOutbound => this._FulFillmentOutbound ?? throw _NoCredentials;
|
||||
// //public ListingsItemService ListingsItem => this._ListingsItem ?? throw _NoCredentials;
|
||||
// //public MerchantFulfillmentService MerchantFulfillment => this._MerchantFulfillment ?? throw _NoCredentials;
|
||||
// //public MessagingService Messaging => this._Messaging ?? throw _NoCredentials;
|
||||
// //public NotificationService Notification => this._Notification ?? throw _NoCredentials;
|
||||
// //public OrderService Orders => this._Orders ?? throw _NoCredentials;
|
||||
// //public SalesService Sales => this._Sales ?? throw _NoCredentials;
|
||||
// //public SellerService Seller => this._Seller ?? throw _NoCredentials;
|
||||
// //public ServicesService Services => this._Services ?? throw _NoCredentials;
|
||||
// //public ShipmentInvoicingService ShipmentInvoicing => this._ShipmentInvoicing ?? throw _NoCredentials;
|
||||
// //public ShippingService Shipping => this._Shipping ?? throw _NoCredentials;
|
||||
// //public SolicitationService Solicitations => this._Solicitations ?? throw _NoCredentials;
|
||||
// //public TokenService Tokens => this._Tokens ?? throw _NoCredentials;
|
||||
// //public UploadService Upload => this._Upload ?? throw _NoCredentials;
|
||||
|
||||
|
||||
|
||||
// private FbaInboundService _FbaInbound { get; set; }
|
||||
// private FbaInventoryService _FbaInventory { get; set; }
|
||||
// private FulFillmentInboundService _FulFillmentInbound { get; set; }
|
||||
// private ProductFeeService _ProductFee { get; set; }
|
||||
// private ProductPricingService _ProductPricing { get; set; }
|
||||
// private ReportService _Reports { get; set; }
|
||||
// //private AplusContentService _AplusContent { get; set; }
|
||||
// //private AuthorizationService _Authorization { get; set; }
|
||||
// //private CatalogItemService _CatalogItems { get; set; }
|
||||
// //private FbaInboundEligibilityService _FbaInboundEligibility { get; set; }
|
||||
// //private FbaOutboundService _FbaOutbound { get; set; }
|
||||
// //private FbaSmallandLightService _FbaSmallandLight { get; set; }
|
||||
// private FeedService _Feed { get; set; }
|
||||
// //private FinancialService _Financials { get; set; }
|
||||
// //private FulFillmentOutboundService _FulFillmentOutbound { get; set; }
|
||||
// //private ListingsItemService _ListingsItem { get; set; }
|
||||
// //private MerchantFulfillmentService _MerchantFulfillment { get; set; }
|
||||
// //private MessagingService _Messaging { get; set; }
|
||||
// //private NotificationService _Notification { get; set; }
|
||||
// //private OrderService _Orders { get; set; }
|
||||
// //private SalesService _Sales { get; set; }
|
||||
// //private SellerService _Seller { get; set; }
|
||||
// //private ServicesService _Services { get; set; }
|
||||
// //private ShipmentInvoicingService _ShipmentInvoicing { get; set; }
|
||||
// //private ShippingService _Shipping { get; set; }
|
||||
// //private SolicitationService _Solicitations { get; set; }
|
||||
// //private TokenService _Tokens { get; set; }
|
||||
// //private UploadService _Upload { get; set; }
|
||||
|
||||
// private UnauthorizedAccessException _NoCredentials = new UnauthorizedAccessException($"Error, you cannot make calls to Amazon without credentials!");
|
||||
|
||||
|
||||
// public AmazonConnection(AmazonCredential Credentials)
|
||||
// {
|
||||
// this.Authenticate(Credentials);
|
||||
// }
|
||||
|
||||
// public void Authenticate(AmazonCredential Credentials)
|
||||
// {
|
||||
// if (this.Credentials == default(AmazonCredential))
|
||||
// Init(Credentials);
|
||||
// else
|
||||
// throw new InvalidOperationException("Error, you are already authenticated to amazon in this AmazonConnection, dispose of this connection and create a new one to connect to a different account.");
|
||||
// }
|
||||
|
||||
// private void Init(AmazonCredential Credentials)
|
||||
// {
|
||||
// this.Credentials = Credentials;
|
||||
|
||||
// this._FbaInbound = new FbaInboundService(this.Credentials);
|
||||
// this._FbaInventory = new FbaInventoryService(this.Credentials);
|
||||
// this._FulFillmentInbound = new FulFillmentInboundService(this.Credentials);
|
||||
// this._ProductFee = new ProductFeeService(this.Credentials);
|
||||
// this._ProductPricing = new ProductPricingService(this.Credentials);
|
||||
// this._Reports = new ReportService(this.Credentials);
|
||||
// //this._AplusContent = new AplusContentService(this.Credentials);
|
||||
// //this._CatalogItems = new CatalogItemService(this.Credentials);
|
||||
// //this._FbaInboundEligibility = new FbaInboundEligibilityService(this.Credentials);
|
||||
// //this._FbaOutbound = new FbaOutboundService(this.Credentials);
|
||||
// //this._FbaSmallandLight = new FbaSmallandLightService(this.Credentials);
|
||||
// this._Feed = new FeedService(this.Credentials);
|
||||
// //this._Financials = new FinancialService(this.Credentials);
|
||||
// //this._FulFillmentOutbound= new FulFillmentOutboundService(this.Credentials);
|
||||
// //this._ListingsItem = new ListingsItemService(this.Credentials);
|
||||
// //this._MerchantFulfillment = new MerchantFulfillmentService(this.Credentials);
|
||||
// //this._Messaging= new MessagingService(this.Credentials);
|
||||
// //this._Notification= new NotificationService(this.Credentials);
|
||||
// //this._Orders = new OrderService(this.Credentials);
|
||||
// //this._Sales= new SalesService(this.Credentials);
|
||||
// //this._Seller= new SellerService(this.Credentials);
|
||||
// //this._Services= new ServicesService(this.Credentials);
|
||||
// //this._ShipmentInvoicing= new ShipmentInvoicingService(this.Credentials);
|
||||
// //this._Shipping= new ShippingService(this.Credentials);
|
||||
// //this._Solicitations = new SolicitationService(this.Credentials);
|
||||
// //this._Tokens= new TokenService(this.Credentials);
|
||||
// //this._Upload= new UploadService(this.Credentials);
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
@@ -0,0 +1,103 @@
|
||||
//using bnhtrade.Core.Data.Amazon.SellingPartnerAPI.SDK.Models.Token;
|
||||
//using bnhtrade.Core.Data.Amazon.SellingPartnerAPI.Utils;
|
||||
using FikaAmazonAPI.AmazonSpApiSDK.Models.Token;
|
||||
using FikaAmazonAPI.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
using System.Text;
|
||||
using static FikaAmazonAPI.AmazonSpApiSDK.Models.Token.CacheTokenData;
|
||||
using static FikaAmazonAPI.Utils.Constants;
|
||||
//using static bnhtrade.Core.Data.Amazon.SellingPartnerAPI.SDK.Models.Token.CacheTokenData;
|
||||
//using static bnhtrade.Core.Data.Amazon.SellingPartnerAPI.Utils.Constants;
|
||||
|
||||
namespace bnhtrade.Core.Data.Amazon.SellingPartnerAPI
|
||||
{
|
||||
public class AmazonCredential
|
||||
{
|
||||
public string AccessKey { get; set; }
|
||||
public string SecretKey { get; set; }
|
||||
public string RoleArn { get; set; }
|
||||
public string ClientId { get; set; }
|
||||
public string ClientSecret { get; set; }
|
||||
public string RefreshToken { get; set; }
|
||||
public MarketPlace MarketPlace { get; set; }
|
||||
private CacheTokenData CacheTokenData { get; set; } = new CacheTokenData();
|
||||
public bool IsActiveLimitRate { get; set; } = true;
|
||||
public Environments Environment { get; set; } = Environments.Production;
|
||||
|
||||
public AmazonCredential()
|
||||
{
|
||||
// attempt to retrive credentials from app.local.config
|
||||
try
|
||||
{
|
||||
Innit(ConfigurationManager.AppSettings["SpapiAccessKey"]
|
||||
, ConfigurationManager.AppSettings["SpapiSecretKey"]
|
||||
, ConfigurationManager.AppSettings["SpapiRoleArn"]
|
||||
, ConfigurationManager.AppSettings["SpapiClientId"]
|
||||
, ConfigurationManager.AppSettings["SpapiClientSecret"]
|
||||
, ConfigurationManager.AppSettings["SpapiRefreshToken"]);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(ConfigurationManager.AppSettings["SpapiMarketplaceId"]))
|
||||
{
|
||||
this.MarketPlace = MarketPlace.UnitedKingdom;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new Exception("Unable to retirve Amazon SP API credentials: " + ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
private AmazonCredential(string accessKey, string secretKey, string roleArn, string clientId, string clientSecret, string refreshToken)
|
||||
{
|
||||
// Use other method by default, however can change this method back to public is the need arises.
|
||||
Innit(accessKey
|
||||
, secretKey
|
||||
, roleArn
|
||||
, clientId
|
||||
, clientSecret
|
||||
, refreshToken);
|
||||
}
|
||||
|
||||
public AmazonCredential(Core.Model.Credentials.AmazonSPAPI userCredentials)
|
||||
{
|
||||
Innit(userCredentials.AccessKey
|
||||
, userCredentials.SecretKey
|
||||
, userCredentials.RoleArn
|
||||
, userCredentials.ClientId
|
||||
, userCredentials.ClientSecret
|
||||
, userCredentials.RefreshToken);
|
||||
}
|
||||
|
||||
private void Innit(string accessKey, string secretKey, string roleArn, string clientId, string clientSecret, string refreshToken)
|
||||
{
|
||||
this.AccessKey = accessKey;
|
||||
this.SecretKey = secretKey;
|
||||
this.RoleArn = roleArn;
|
||||
this.ClientId = clientId;
|
||||
this.ClientSecret = clientSecret;
|
||||
this.RefreshToken = refreshToken;
|
||||
}
|
||||
|
||||
public TokenResponse GetToken(TokenDataType tokenDataType)
|
||||
{
|
||||
return CacheTokenData.GetToken(tokenDataType);
|
||||
}
|
||||
|
||||
public void SetToken(TokenDataType tokenDataType, TokenResponse token)
|
||||
{
|
||||
CacheTokenData.SetToken(tokenDataType, token);
|
||||
}
|
||||
|
||||
public AWSAuthenticationTokenData GetAWSAuthenticationTokenData()
|
||||
{
|
||||
return CacheTokenData.GetAWSAuthenticationTokenData();
|
||||
}
|
||||
|
||||
public void SetAWSAuthenticationTokenData(AWSAuthenticationTokenData tokenData)
|
||||
{
|
||||
CacheTokenData.SetAWSAuthenticationTokenData(tokenData);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
using FikaAmazonAPI.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace bnhtrade.Core.Data.Amazon.SellingPartnerAPI
|
||||
{
|
||||
public class Defaults
|
||||
{
|
||||
public MarketPlace MarketPlaceId()
|
||||
{
|
||||
return MarketPlace.GetMarketPlaceByID(ConfigurationManager.AppSettings["SpapiMarketplaceId"]);
|
||||
}
|
||||
public string MarketPlaceIdAsString()
|
||||
{
|
||||
return ConfigurationManager.AppSettings["SpapiMarketplaceId"];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,318 @@
|
||||
//using System;
|
||||
//using System.Collections.Generic;
|
||||
//using System.IO;
|
||||
//using System.Text;
|
||||
|
||||
//namespace bnhtrade.Core.Data.Amazon.SellingPartnerAPI.Services
|
||||
//{
|
||||
// public class ReportService : RequestService
|
||||
// {
|
||||
// private Dictionary<string, RestSharp.RestResponse<SDK.Models.Reports.Report>> reportList;
|
||||
// private Dictionary<string, string> filePath;
|
||||
// private bool fatalEncounter = false;
|
||||
// protected Logic.Log.LogEvent log = new Logic.Log.LogEvent();
|
||||
// private int reportRequestCount = 0;
|
||||
|
||||
// public ReportService() : base (new AmazonCredential())
|
||||
// {
|
||||
// Innit();
|
||||
// }
|
||||
|
||||
// public ReportService(AmazonCredential amazonCredential) : base(amazonCredential)
|
||||
// {
|
||||
// Innit();
|
||||
// }
|
||||
|
||||
// public void Innit()
|
||||
// {
|
||||
// reportList = new Dictionary<string, RestSharp.RestResponse<FikaAmazonAPI.AmazonSpApiSDK.Models.Reports.Report>>();
|
||||
// filePath = new Dictionary<string, string>();
|
||||
// }
|
||||
|
||||
// public FikaAmazonAPI.AmazonSpApiSDK.Models.Reports.Report GetReport(string reportId, bool forceRequery = false)
|
||||
// {
|
||||
// // Rate limit: 2.0 requests per second, 15 burst
|
||||
// int rateLimitMilliseconds = 500;
|
||||
|
||||
// if (reportList.ContainsKey(reportId))
|
||||
// {
|
||||
// if (forceRequery)
|
||||
// {
|
||||
// reportList.Remove(reportId);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// return reportList[reportId].Data;
|
||||
// }
|
||||
// }
|
||||
|
||||
// // request report form amaozn
|
||||
// if (reportRequestCount == 0)
|
||||
// {
|
||||
// UI.Console.WriteLine("Requesting report from amazon SPAPI (ReportId:" + reportId + ").");
|
||||
// reportRequestCount = reportRequestCount + 1;
|
||||
// }
|
||||
|
||||
// CreateAuthorizedRequest(ReportApiUrls.GetReport(reportId), RestSharp.Method.Get);
|
||||
// var response = ExecuteRequestWithHttpInfo<SDK.Models.Reports.Report>(rateLimitMilliseconds);
|
||||
|
||||
// if (response == null)
|
||||
// { return null; }
|
||||
|
||||
// reportList.Add(response.Data.ReportId, response);
|
||||
// return response.Data;
|
||||
// }
|
||||
|
||||
// public List<SDK.Models.Reports.Report> GetReports(ParameterReportList parameterReportList)
|
||||
// {
|
||||
// var parameters = parameterReportList.getParameters();
|
||||
|
||||
// CreateAuthorizedRequest(ReportApiUrls.GetReports, RestSharp.Method.Get, parameters);
|
||||
// var response = ExecuteRequest<GetReportsResponseV00>();
|
||||
// parameterReportList.nextToken = response.NextToken;
|
||||
// var list = response.Reports;
|
||||
|
||||
// while (!string.IsNullOrEmpty(parameterReportList.nextToken))
|
||||
// {
|
||||
// var nextTokenResponse = GetReportsByNextToken(parameterReportList);
|
||||
// list.AddRange(nextTokenResponse.Reports);
|
||||
// parameterReportList.nextToken = nextTokenResponse.NextToken;
|
||||
// }
|
||||
// return list;
|
||||
// }
|
||||
|
||||
// public bool CancelReport(string reportId)
|
||||
// {
|
||||
|
||||
// CreateAuthorizedRequest(ReportApiUrls.CancelReport(reportId), RestSharp.Method.Delete);
|
||||
// var response = ExecuteRequest<CancelReportResponse>();
|
||||
// if (response != null && response.Errors != null)
|
||||
// return false;
|
||||
// return true;
|
||||
// }
|
||||
|
||||
// public ReportScheduleList GetReportSchedules(ParameterReportSchedules parametersSchedules)
|
||||
// {
|
||||
// var parameters = parametersSchedules.getParameters();
|
||||
// CreateAuthorizedRequest(ReportApiUrls.GetReportSchedules, RestSharp.Method.Get, parameters);
|
||||
// var response = ExecuteRequest<GetReportSchedulesResponseV00>();
|
||||
// if (response != null && response.ReportSchedules != null)
|
||||
// return response.ReportSchedules;
|
||||
// return null;
|
||||
// }
|
||||
|
||||
// private GetReportsResponseV00 GetReportsByNextToken(ParameterReportList parameterReportList)
|
||||
// {
|
||||
// var parameterReportListNew = new ParameterReportList();
|
||||
// parameterReportListNew.nextToken = parameterReportList.nextToken;
|
||||
// var parameters = parameterReportListNew.getParameters();
|
||||
|
||||
// CreateAuthorizedRequest(ReportApiUrls.GetReports, RestSharp.Method.Get, parameters);
|
||||
// var response = ExecuteRequest<GetReportsResponseV00>();
|
||||
// return response;
|
||||
// }
|
||||
|
||||
// public string CreateReport(ParameterCreateReportSpecification createReportSpecification)
|
||||
// {
|
||||
// CreateAuthorizedRequest(ReportApiUrls.CreateReport, RestSharp.Method.Post, null, createReportSpecification);
|
||||
// var response = ExecuteRequest<SDK.Models.Reports.CreateReportResult>();
|
||||
|
||||
// if (response == null)
|
||||
// return null;
|
||||
|
||||
// string reportId = response.ReportId;
|
||||
|
||||
// return response.ReportId;
|
||||
// }
|
||||
|
||||
// public string CreateReportSchedule(ParameterCreateReportScheduleSpecification createReportScheduleSpecification)
|
||||
// {
|
||||
// CreateAuthorizedRequest(ReportApiUrls.CreateReportSchedule, RestSharp.Method.Post, null, createReportScheduleSpecification);
|
||||
// var response = ExecuteRequest<CreateReportScheduleResult>();
|
||||
|
||||
// if (response == null)
|
||||
// return null;
|
||||
|
||||
|
||||
// return response.ReportScheduleId;
|
||||
// }
|
||||
|
||||
// public ReportSchedule GetReportSchedule(string reportScheduleId)
|
||||
// {
|
||||
|
||||
// CreateAuthorizedRequest(ReportApiUrls.GetReportSchedule(reportScheduleId), RestSharp.Method.Get);
|
||||
// var response = ExecuteRequest<ReportSchedule>();
|
||||
// if (response != null)
|
||||
// return response;
|
||||
// return null;
|
||||
// }
|
||||
|
||||
// public ReportDocument GetReportDocument(string reportDocumentId, IParameterBasedPII ParameterBasedPII = null)
|
||||
// {
|
||||
// CreateAuthorizedRequest(ReportApiUrls.GetReportDocument(reportDocumentId), RestSharp.Method.Get, parameter: ParameterBasedPII);
|
||||
// var response = ExecuteRequest<ReportDocument>();
|
||||
// if (response != null)
|
||||
// return response;
|
||||
// return null;
|
||||
// }
|
||||
|
||||
// public bool WaitForReportProcessing(SDK.Models.Reports.Report report)
|
||||
// {
|
||||
// // wait for report processing loop
|
||||
// int checkCount = 0;
|
||||
// int checkRequency = 10000;
|
||||
|
||||
// while (true)
|
||||
// {
|
||||
// checkCount++;
|
||||
// if (checkCount > 60)
|
||||
// {
|
||||
// throw new Exception("GetReport timedout requesting reportId:" + report.ReportId + ".");
|
||||
// }
|
||||
|
||||
// if (report.ProcessingStatus == SDK.Models.Reports.Report.ProcessingStatusEnum.DONE)
|
||||
// {
|
||||
// UI.Console.WriteLine("Report proccessing status is 'DONE' (ReportId:" + report.ReportId + ").");
|
||||
// return true;
|
||||
// }
|
||||
// else if (report.ProcessingStatus == SDK.Models.Reports.Report.ProcessingStatusEnum.INPROGRESS)
|
||||
// {
|
||||
// // wait for 10 seconds between chacks
|
||||
// UI.Console.Wait("Report processing 'In Progress'. Updating in {0} seconds...", checkRequency);
|
||||
// report = GetReport(report.ReportId, true);
|
||||
// }
|
||||
// else if (report.ProcessingStatus == SDK.Models.Reports.Report.ProcessingStatusEnum.INQUEUE)
|
||||
// {
|
||||
// // wait for 10 seconds between chacks
|
||||
// UI.Console.Wait("Report processing 'In Queue'. Updating in {0} seconds...", checkRequency);
|
||||
// report = GetReport(report.ReportId, true);
|
||||
// }
|
||||
// else if (report.ProcessingStatus == SDK.Models.Reports.Report.ProcessingStatusEnum.CANCELLED)
|
||||
// {
|
||||
// // when report has been cancelled by client or amazon (no data)
|
||||
// return false;
|
||||
// }
|
||||
// else if (report.ProcessingStatus == SDK.Models.Reports.Report.ProcessingStatusEnum.FATAL)
|
||||
// {
|
||||
// // some report requests will return a 'FATAL' if they have already been requsted recently (15 minutes).
|
||||
// return false;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// throw new Exception("New ReportProcessingStatusEnum '" + report.ProcessingStatus + "' "
|
||||
// + " found for reportid:" + report.ReportId);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// /// <summary>
|
||||
// /// Retrives file containing Amazon SP-API report
|
||||
// /// </summary>
|
||||
// /// <param name="reportId">Amazon SP-API unique report id</param>
|
||||
// /// <returns>File path for report</returns>
|
||||
// public string GetReportFile(string reportId)
|
||||
// {
|
||||
// if (string.IsNullOrWhiteSpace(reportId))
|
||||
// {
|
||||
// throw new Exception("invalid Report ID");
|
||||
// }
|
||||
|
||||
// // check for cached filepath
|
||||
// if (!filePath.ContainsKey(reportId))
|
||||
// {
|
||||
// var report = GetReport(reportId); // this can return null, need to deal with this
|
||||
|
||||
// if (WaitForReportProcessing(report))
|
||||
// {
|
||||
// // download report from url
|
||||
// string reportFilePath = GetFile(reportId);
|
||||
// filePath.Add(reportId, reportFilePath);
|
||||
// return reportFilePath;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// return null;
|
||||
// }
|
||||
// }
|
||||
|
||||
// return filePath[reportId];
|
||||
// }
|
||||
|
||||
// private string GetFile(string reportId)
|
||||
// {
|
||||
// // fatal error and reportDoument Id check
|
||||
// if (fatalEncounter)
|
||||
// {
|
||||
// if (string.IsNullOrWhiteSpace(reportList[reportId].Data.ReportDocumentId))
|
||||
// {
|
||||
// log.LogError("Fatal error from Amazon SPAPI when requesting reportId:" + reportId
|
||||
// , "The reason for the fatal error is unknown, no document was available for further information.");
|
||||
|
||||
// return "FATAL";
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// log.LogError("Fatal error from Amazon SPAPI when requesting reportId:" + reportId
|
||||
// , "The report was aborted due to a fatal error and a reportDocumentId is present. Check reportDocumentId as it may explain why the report processing ended.");
|
||||
// }
|
||||
// fatalEncounter = false;
|
||||
// }
|
||||
|
||||
// // as file url expires after 5 minutes, request just before download
|
||||
// UI.Console.WriteLine("Requesting download url for Amazon report (ReportId:" + reportId + ").");
|
||||
// var reportDocument = GetReportDocument(reportList[reportId].Data.ReportDocumentId);
|
||||
|
||||
// // download report from url
|
||||
// log.LogInformation("Downloading Amazon report #" + reportId, "Report Document ID: " + reportDocument.ReportDocumentId);
|
||||
// var response = new byte[0];
|
||||
// using (var webClient = new System.Net.WebClient())
|
||||
// {
|
||||
// response = webClient.DownloadData(reportDocument.Url);
|
||||
// }
|
||||
|
||||
// string report = null;
|
||||
|
||||
// // decrypt report
|
||||
// UI.Console.WriteLine("Processing download (ReportId:" + reportId + ").");
|
||||
// if (reportDocument.EncryptionDetails != null)
|
||||
// {
|
||||
// byte[] key = Encoding.ASCII.GetBytes(reportDocument.EncryptionDetails.Key);
|
||||
// byte[] iv = Encoding.ASCII.GetBytes(reportDocument.EncryptionDetails.InitializationVector);
|
||||
// report = Logic.Utilities.FileTransform.DecryptString(key, iv, response);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// report = Encoding.ASCII.GetString(response);
|
||||
// }
|
||||
|
||||
// // decompress
|
||||
// if (reportDocument.CompressionAlgorithm != null)
|
||||
// {
|
||||
// report = Logic.Utilities.FileTransform.Decompress(report);
|
||||
// }
|
||||
|
||||
// // save to file
|
||||
// string reportFilePath = MiscFunction.GetTempFilePath(reportId + ".txt");
|
||||
// System.IO.File.WriteAllText(reportFilePath, report);
|
||||
// log.LogInformation("Amazon report #" + reportId + " sucessfully saved to disk.");
|
||||
// return reportFilePath;
|
||||
// }
|
||||
|
||||
// public bool CancelReportSchedule(string reportScheduleId)
|
||||
// {
|
||||
|
||||
// CreateAuthorizedRequest(ReportApiUrls.CancelReportSchedule(reportScheduleId), RestSharp.Method.Delete);
|
||||
// var response = ExecuteRequest<CancelReportScheduleResponse>();
|
||||
// if (response != null && response.Errors != null)
|
||||
// return false;
|
||||
// return true;
|
||||
// }
|
||||
|
||||
// protected void SleepForRateLimit(IList<RestSharp.Parameter> headers)
|
||||
// {
|
||||
// // get report has limit rate 0.0222 per second (1 every 45 seconds) and a burst of 10
|
||||
// int defaultTime = 46000;
|
||||
// SleepForRateLimit(headers, defaultTime);
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
@@ -0,0 +1,50 @@
|
||||
using FikaAmazonAPI;
|
||||
using FikaAmazonAPI.Utils;
|
||||
using FikaAmazonAPI.AmazonSpApiSDK.Models.Token;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using static FikaAmazonAPI.AmazonSpApiSDK.Services.EnvironemntManager;
|
||||
|
||||
namespace bnhtrade.Core.Data.Amazon.SellingPartnerAPI
|
||||
{
|
||||
class SpApiConnection
|
||||
{
|
||||
public AmazonConnection Connection { get; private set; }
|
||||
//public MarketPlace MarketPlace { get; private set; }
|
||||
//public string MarketPlaceId { get; private set; }
|
||||
|
||||
public SpApiConnection()
|
||||
{
|
||||
InnitConnection();
|
||||
}
|
||||
|
||||
private void InnitConnection()
|
||||
{
|
||||
// attempt to create credential object from app.local.config
|
||||
var credential = new FikaAmazonAPI.AmazonCredential();
|
||||
try
|
||||
{
|
||||
credential = new FikaAmazonAPI.AmazonCredential();
|
||||
credential.AccessKey = ConfigurationManager.AppSettings["SpapiAccessKey"];
|
||||
credential.SecretKey = ConfigurationManager.AppSettings["SpapiSecretKey"];
|
||||
credential.RoleArn = ConfigurationManager.AppSettings["SpapiRoleArn"];
|
||||
credential.ClientId = ConfigurationManager.AppSettings["SpapiClientId"];
|
||||
credential.ClientSecret = ConfigurationManager.AppSettings["SpapiClientSecret"];
|
||||
credential.RefreshToken = ConfigurationManager.AppSettings["SpapiRefreshToken"];
|
||||
credential.MarketPlaceID = ConfigurationManager.AppSettings["SpapiMarketplaceId"];
|
||||
credential.IsDebugMode = true;
|
||||
credential.MaxThrottledRetryCount = 3;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new Exception("Unable to retirve Amazon SP API credentials: " + ex.Message);
|
||||
}
|
||||
|
||||
this.Connection = new AmazonConnection(credential);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Xml;
|
||||
|
||||
namespace bnhtrade.Core.Data.Amazon.SellingPartnerAPI.Utils
|
||||
{
|
||||
public class CurrentDateTime
|
||||
{
|
||||
public DateTime GetUtc()
|
||||
{
|
||||
var xmlDoc = new XmlDocument();
|
||||
xmlDoc.Load("https://mws.amazonservices.com/");
|
||||
DateTime returnTime = default(DateTime);
|
||||
|
||||
XmlNodeList elemList = xmlDoc.GetElementsByTagName("Timestamp");
|
||||
for (int i = 0; i < elemList.Count; i++)
|
||||
{
|
||||
string attrVal = elemList[i].Attributes["timestamp"].Value;
|
||||
if (!string.IsNullOrWhiteSpace(attrVal))
|
||||
{
|
||||
returnTime = DateTime.SpecifyKind(DateTime.Parse(attrVal), DateTimeKind.Utc);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (returnTime == default(DateTime))
|
||||
{
|
||||
throw new Exception("Error requesting time from Amazon");
|
||||
}
|
||||
|
||||
returnTime = returnTime.AddTicks(-(returnTime.Ticks % TimeSpan.TicksPerSecond));
|
||||
|
||||
return returnTime;
|
||||
}
|
||||
|
||||
public DateTime GetLocal()
|
||||
{
|
||||
return GetUtc().ToLocalTime();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user