Skip to content

Commit 12da359

Browse files
authored
Merge pull request #884 from TManITtech/main
2 parents f1f6e88 + 0d69822 commit 12da359

File tree

10 files changed

+277
-8
lines changed

10 files changed

+277
-8
lines changed

Source/FikaAmazonAPI.SampleCode/FeedsSample.cs

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,7 @@ public async Task SubmitFeedPRICING_JSONAsync(string SKU, decimal PRICE, decimal
230230

231231
}
232232

233-
public async Task SubmitInventoryJSON_Async(string SKU, int quantity, DateTime? restockDate = null)
233+
public async Task SubmitInventoryJSON_Async(string SKU, int quantity, int? leadTimeToShip = null, DateTime? restockDate = null)
234234
{
235235
ConstructJSONFeedService createDocument = new ConstructJSONFeedService(amazonConnection.GetCurrentSellerID);
236236

@@ -239,6 +239,7 @@ public async Task SubmitInventoryJSON_Async(string SKU, int quantity, DateTime?
239239
{
240240
SKU = SKU,
241241
Quantity = quantity,
242+
FulfillmentLatency = leadTimeToShip.HasValue ? leadTimeToShip.Value.ToString() : null,
242243
RestockDate = restockDate
243244
};
244245

@@ -250,7 +251,27 @@ public async Task SubmitInventoryJSON_Async(string SKU, int quantity, DateTime?
250251
string feedID = await amazonConnection.Feed.SubmitFeedAsync(jsonString, FeedType.JSON_LISTINGS_FEED, null, null, ContentType.JSON);
251252

252253
await GetJsonFeedDetails(feedID);
254+
}
255+
256+
public async Task SubmitMerchantShippingGroupJSON_Async(string sku, string merchant_shipping_group_id)
257+
{
258+
ConstructJSONFeedService createDocument = new ConstructJSONFeedService(amazonConnection.GetCurrentSellerID);
259+
260+
var list = new List<MerchantShippingGroupMessage>();
261+
var msg = new MerchantShippingGroupMessage()
262+
{
263+
SKU = sku,
264+
MerchantShippingGroupId = merchant_shipping_group_id
265+
};
253266

267+
list.Add(msg);
268+
createDocument.AddMerchantShippingGroupMessage(list);
269+
270+
var jsonString = createDocument.GetJSON();
271+
272+
string feedID = await amazonConnection.Feed.SubmitFeedAsync(jsonString, FeedType.JSON_LISTINGS_FEED, null, null, ContentType.JSON);
273+
274+
await GetJsonFeedDetails(feedID);
254275
}
255276

256277
public async Task SubmitFeedPricingWithSalePrice(string sku, decimal price, decimal salePrice, DateTime startDate, DateTime endDate)
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
2+
using FikaAmazonAPI.ConstructFeed.Messages;
3+
using FikaAmazonAPI.Parameter.ListingItem;
4+
using FikaAmazonAPI.Parameter.ProductTypes;
5+
using FikaAmazonAPI.Utils;
6+
using System;
7+
using System.Collections.Generic;
8+
using System.Threading.Tasks;
9+
10+
namespace FikaAmazonAPI.SampleCode
11+
{
12+
public class MerchantShippingTemplateSample
13+
{
14+
private readonly AmazonConnection _amazonConnection;
15+
16+
public MerchantShippingTemplateSample(AmazonConnection amazonConnection)
17+
{
18+
_amazonConnection = amazonConnection;
19+
}
20+
21+
public async Task PopulateMerchantShippingGroupNamesKeys()
22+
{
23+
var parameter = new GetDefinitionsProductTypeParameter()
24+
{
25+
sellerId = _amazonConnection.GetCurrentSellerID,
26+
marketplaceIds = new List<string>() { MarketPlace.US.ID },
27+
productTypeVersion = "LATEST",
28+
requirements = Requirements.LISTING,
29+
locale = AmazonSpApiSDK.Models.ProductTypes.LocaleEnum.en_US,
30+
version = "LATEST",
31+
productType = "PRODUCT",
32+
};
33+
34+
await _amazonConnection.MerchantShippingTemplate.PopulateMerchantShippingGroupNamesKeysAsync(parameter);
35+
36+
Console.WriteLine($"MerchantShippingGroupNamesKeys populated successfully with {MerchantShippingGroupMessage.MerchantShippingGroupNamesKeys.Count} shipping templates.");
37+
38+
if (MerchantShippingGroupMessage.MerchantShippingGroupNamesKeys.Count > 0)
39+
{
40+
foreach (var template in MerchantShippingGroupMessage.MerchantShippingGroupNamesKeys)
41+
{
42+
Console.WriteLine($"MerchantShippingTemplate: '{template.Key}': '{template.Value}'");
43+
}
44+
}
45+
}
46+
}
47+
}

Source/FikaAmazonAPI/AmazonConnection.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
using System;
66
using System.Globalization;
77
using System.Threading;
8+
using System.Net.Http;
9+
using static FikaAmazonAPI.Utils.Constants;
810

911
namespace FikaAmazonAPI
1012
{
@@ -49,7 +51,9 @@ public class AmazonConnection
4951
public VendorDirectFulfillmentOrderService VendorDirectFulfillmentOrders => this._VendorDirectFulfillmentOrders ?? throw _NoCredentials;
5052
public VendorOrderService VendorOrders => this._VendorOrders ?? throw _NoCredentials;
5153
public VendorDirectFulfillmentInventoryService VendorDirectFulfillmentInventory => this._VendorDirectFulfillmentInventory ?? throw _NoCredentials;
52-
public VendorTransactionStatusService VendorTransactionStatus => this._VendorTransactionStatus ?? throw _NoCredentials;
54+
public VendorTransactionStatusService VendorTransactionStatus => this._VendorTransactionStatus ?? throw _NoCredentials;
55+
public MerchantShippingTemplateService MerchantShippingTemplate => this._MerchantShippingTemplate ?? throw _NoCredentials;
56+
5357

5458
private AppIntegrationsServiceV20240401 _AppIntegrationsServiceV20240401 { get; set; }
5559
private OrderService _Orders { get; set; }
@@ -89,6 +93,7 @@ public class AmazonConnection
8993
private VendorOrderService _VendorOrders { get; set; }
9094
private VendorTransactionStatusService _VendorTransactionStatus { get; set; }
9195
private VendorDirectFulfillmentInventoryService _VendorDirectFulfillmentInventory { get; set; }
96+
private MerchantShippingTemplateService _MerchantShippingTemplate { get; set; }
9297

9398
private UnauthorizedAccessException _NoCredentials = new UnauthorizedAccessException($"Error, you cannot make calls to Amazon without credentials!");
9499

@@ -154,6 +159,7 @@ private void Init(AmazonCredential Credentials)
154159
this._VendorOrders = new VendorOrderService(this.Credentials, _loggerFactory);
155160
this._VendorTransactionStatus = new VendorTransactionStatusService(this.Credentials, _loggerFactory);
156161
this._VendorDirectFulfillmentInventory = new VendorDirectFulfillmentInventoryService(this.Credentials, _loggerFactory);
162+
this._MerchantShippingTemplate = new MerchantShippingTemplateService(this.Credentials, _loggerFactory);
157163

158164
AmazonCredential.DebugMode = this.Credentials.IsDebugMode;
159165
}

Source/FikaAmazonAPI/AmazonSpApiSDK/Models/ProductTypes/SchemaLink.cs

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using FikaAmazonAPI.AmazonSpApiSDK.Models.Solicitations;
12
using Newtonsoft.Json;
23
using System;
34
using System.Runtime.Serialization;
@@ -18,7 +19,7 @@ public class SchemaLink
1819
/// <value>Link to retrieve the schema.</value>
1920
[DataMember(Name = "link", EmitDefaultValue = false)]
2021
[JsonProperty(PropertyName = "link")]
21-
public Object Link { get; set; }
22+
public SchemaLinkObject Link { get; set; }
2223

2324
/// <summary>
2425
/// Checksum hash of the schema (Base64 MD5). Can be used to verify schema contents, identify changes between schema versions, and for caching.
@@ -51,6 +52,48 @@ public string ToJson()
5152
{
5253
return JsonConvert.SerializeObject(this, Formatting.Indented);
5354
}
55+
}
56+
57+
[DataContract]
58+
public class SchemaLinkObject
59+
{
60+
/// <summary>
61+
/// A URI for this object.
62+
/// </summary>
63+
/// <value>A URI for this object.</value>
64+
[DataMember(Name = "resource", EmitDefaultValue = false)]
65+
[JsonProperty(PropertyName = "resource")]
66+
public string ResourceUrl { get; set; }
67+
68+
/// <summary>
69+
/// The HTTP Verb Method to use when calling the resource url.
70+
/// </summary>
71+
/// <value>The HTTP Verb Method to use when calling the resource url.</value>
72+
[DataMember(Name = "verb", EmitDefaultValue = false)]
73+
[JsonProperty(PropertyName = "verb")]
74+
public string Verb { get; set; }
75+
76+
/// <summary>
77+
/// Returns the string presentation of the object
78+
/// </summary>
79+
/// <returns>String presentation of the object</returns>
80+
public override string ToString()
81+
{
82+
var sb = new StringBuilder();
83+
sb.Append("class " + nameof(SchemaLinkObject) + " {\n");
84+
sb.Append(" ResourceUrl: ").Append(ResourceUrl).Append("\n");
85+
sb.Append(" Verb: ").Append(Verb).Append("\n");
86+
sb.Append("}\n");
87+
return sb.ToString();
88+
}
5489

90+
/// <summary>
91+
/// Returns the JSON string presentation of the object
92+
/// </summary>
93+
/// <returns>JSON string presentation of the object</returns>
94+
public string ToJson()
95+
{
96+
return JsonConvert.SerializeObject(this, Formatting.Indented);
97+
}
5598
}
5699
}

Source/FikaAmazonAPI/AmazonSpApiSDK/Runtime/LWAClient.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using System.IO;
77
using System.Threading;
88
using System.Threading.Tasks;
9+
using System.Diagnostics;
910

1011
namespace FikaAmazonAPI.AmazonSpApiSDK.Runtime
1112
{
@@ -67,7 +68,7 @@ public virtual async Task<TokenResponse> GetAccessTokenAsync(CancellationToken c
6768
if (!IsSuccessful(response))
6869
{
6970
var message = string.IsNullOrEmpty(response.ErrorMessage)
70-
? "Unsuccessful LWA token exchange"
71+
? $"Unsuccessful LWA token exchange: {response.Content}"
7172
: $"Unsuccessful LWA token exchange: {response.ErrorMessage}";
7273
throw new IOException(message);
7374
}
@@ -77,7 +78,8 @@ public virtual async Task<TokenResponse> GetAccessTokenAsync(CancellationToken c
7778
}
7879
catch (Exception e)
7980
{
80-
throw new SystemException("Error getting LWA Access Token", e);
81+
//Debug.WriteLine(e.Message + Environment.NewLine + e.InnerException?.Message);
82+
throw new SystemException("Error getting LWA Access Token!", e);
8183
}
8284
}
8385

Source/FikaAmazonAPI/ConstructFeed/ConstructJSONFeedService.cs

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,37 @@ public void AddInventoryMessage(IList<InventoryMessage> messages)
137137
{
138138
op = "replace",
139139
path = "/attributes/fulfillment_availability",
140-
value =new List<PatcheValueData>{ patcheValueData }
140+
value = new List<PatcheValueData>{ patcheValueData }
141+
}
142+
}
143+
};
144+
145+
jsonMessagesData.messages.Add(msg);
146+
}
147+
}
148+
149+
public void AddMerchantShippingGroupMessage(IList<MerchantShippingGroupMessage> messages)
150+
{
151+
int index = jsonMessagesData.messages.Count;
152+
foreach (var itm in messages)
153+
{
154+
var msg = new MessagesData()
155+
{
156+
messageId = ++index,
157+
sku = itm.SKU,
158+
operationType = "PATCH",
159+
productType = "PRODUCT",
160+
patches = new List<PatcheData>{
161+
new PatcheData()
162+
{
163+
op = "replace",
164+
path = "/attributes/merchant_shipping_group",
165+
value = new List<PatcheValueData>{
166+
new PatcheValueData()
167+
{
168+
value = itm.MerchantShippingGroupId
169+
}
170+
}
141171
}
142172
}
143173
};
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
using System;
2+
using System.Collections.Generic;
3+
4+
namespace FikaAmazonAPI.ConstructFeed.Messages
5+
{
6+
public class MerchantShippingGroupMessage
7+
{
8+
/// A dictionary containing all the possible Merchant Shipping Groups.
9+
/// The dict keys = the merchant_shipping_group_name. The dict values = merchant_shipping_group enum id key.
10+
/// This is meant to be set once (in the beginning) and it will reuse it every time.
11+
public static Dictionary<string, string> MerchantShippingGroupNamesKeys { get; set; }
12+
13+
public string SKU { get; set; }
14+
15+
public string MerchantShippingGroupId { get; set; }
16+
17+
private string merchant_shipping_group_name;
18+
public string MerchantShippingGroupName
19+
{
20+
get => merchant_shipping_group_name;
21+
set
22+
{
23+
merchant_shipping_group_name = value;
24+
25+
if (MerchantShippingGroupNamesKeys?.ContainsKey(value) == true)
26+
{
27+
MerchantShippingGroupId = MerchantShippingGroupNamesKeys[value];
28+
}
29+
else if (MerchantShippingGroupNamesKeys?.Count > 0)
30+
{
31+
MerchantShippingGroupId = null;
32+
throw new Exception($"Merchant Shipping Group Id not found for '{MerchantShippingGroupName}'!");
33+
}
34+
}
35+
36+
}
37+
}
38+
}

Source/FikaAmazonAPI/Parameter/ProductTypes/GetDefinitionsProductTypeParameter.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ public class GetDefinitionsProductTypeParameter : ParameterBased
1212
public string sellerId { get; set; }
1313
public ICollection<string> marketplaceIds { get; set; } = new List<string>();
1414
public string productTypeVersion { get; set; }
15+
public string version { get; set; }
1516
public Requirements? requirements { get; set; }
1617
public RequirementsEnforcedEnum? requirementsEnforced { get; set; }
1718
public LocaleEnum? locale { get; set; }
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
2+
using FikaAmazonAPI.AmazonSpApiSDK.Models.ProductTypes;
3+
using FikaAmazonAPI.AmazonSpApiSDK.Models.Token;
4+
using FikaAmazonAPI.ConstructFeed.Messages;
5+
using FikaAmazonAPI.Parameter.ProductTypes;
6+
using FikaAmazonAPI.Utils;
7+
using Microsoft.Extensions.Logging;
8+
using Newtonsoft.Json;
9+
using Newtonsoft.Json.Linq;
10+
using RestSharp;
11+
using System;
12+
using System.Collections.Generic;
13+
using System.IO;
14+
using System.Linq;
15+
using System.Net.Http;
16+
using System.Text.Json;
17+
using System.Threading;
18+
using System.Threading.Tasks;
19+
using static FikaAmazonAPI.Utils.Constants;
20+
21+
namespace FikaAmazonAPI.Services
22+
{
23+
public class MerchantShippingTemplateService : RequestService
24+
{
25+
private readonly HttpClient _httpClient = new HttpClient();
26+
private ProductTypeService _ProductType;
27+
28+
public MerchantShippingTemplateService(AmazonCredential amazonCredential, ILoggerFactory? loggerFactory) : base(amazonCredential, loggerFactory)
29+
{
30+
this._ProductType = new ProductTypeService(amazonCredential, loggerFactory);
31+
}
32+
33+
34+
public Dictionary<string, string> GetMerchantShippingTemplates(GetDefinitionsProductTypeParameter parameter) =>
35+
Task.Run(() => GetMerchantShippingTemplatesAsync(parameter)).ConfigureAwait(false).GetAwaiter().GetResult();
36+
37+
public async Task<Dictionary<string, string>> GetMerchantShippingTemplatesAsync(GetDefinitionsProductTypeParameter parameter, CancellationToken cancellationToken = default)
38+
{
39+
var productTypeDefinition = await _ProductType.GetDefinitionsProductTypeAsync(parameter, cancellationToken);
40+
41+
if (productTypeDefinition.Schema == null || string.IsNullOrEmpty(productTypeDefinition.Schema.Link.ResourceUrl))
42+
{
43+
throw new Exception("Could not retrieve schema link resource url from the Product Type Definition!");
44+
}
45+
46+
var schemaUrl = productTypeDefinition.Schema.Link.ResourceUrl;
47+
var schemaJson = await _httpClient.GetStringAsync(schemaUrl);
48+
var schema = JObject.Parse(schemaJson);
49+
50+
var shippingGroup = schema["properties"]?["merchant_shipping_group"];
51+
if (shippingGroup == null)
52+
{
53+
return new Dictionary<string, string>(); // Or throw an exception if this is unexpected
54+
}
55+
56+
var valueProperties = shippingGroup["items"]?["properties"]?["value"];
57+
if (valueProperties == null)
58+
{
59+
return new Dictionary<string, string>();
60+
}
61+
62+
var enums = valueProperties["enum"]?.ToObject<List<string>>();
63+
var enumNames = valueProperties["enumNames"]?.ToObject<List<string>>();
64+
65+
if (enums == null || enumNames == null || enums.Count() != enumNames.Count())
66+
{
67+
return new Dictionary<string, string>(); // Data is not as expected
68+
}
69+
70+
var merchantShippingGroups = Enumerable.Range(0, enums.Count()).ToDictionary(i => enumNames[i], i => enums[i]);
71+
72+
return merchantShippingGroups;
73+
}
74+
75+
public async Task PopulateMerchantShippingGroupNamesKeysAsync(GetDefinitionsProductTypeParameter parameter, CancellationToken cancellationToken = default)
76+
{
77+
var merchantShippingGroups = await GetMerchantShippingTemplatesAsync(parameter, cancellationToken);
78+
MerchantShippingGroupMessage.MerchantShippingGroupNamesKeys = merchantShippingGroups;
79+
}
80+
}
81+
}

Source/FikaAmazonAPI/Services/ProductTypeService.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ public async Task<ProductTypeList> SearchDefinitionsProductTypesAsync(SearchDefi
3030

3131

3232
public ProductTypeDefinition GetDefinitionsProductType(GetDefinitionsProductTypeParameter parameter) =>
33-
Task.Run(() => SearchDefinitionsProductTypesAsync(parameter)).ConfigureAwait(false).GetAwaiter().GetResult();
34-
public async Task<ProductTypeDefinition> SearchDefinitionsProductTypesAsync(GetDefinitionsProductTypeParameter parameter, CancellationToken cancellationToken = default)
33+
Task.Run(() => GetDefinitionsProductTypeAsync(parameter)).ConfigureAwait(false).GetAwaiter().GetResult();
34+
public async Task<ProductTypeDefinition> GetDefinitionsProductTypeAsync(GetDefinitionsProductTypeParameter parameter, CancellationToken cancellationToken = default)
3535
{
3636
if (parameter.marketplaceIds == null || parameter.marketplaceIds.Count == 0)
3737
parameter.marketplaceIds.Add(AmazonCredential.MarketPlace.ID);

0 commit comments

Comments
 (0)