Closed smithburger closed 1 year ago
Hi
Not sure you have went through this process to create your application:
https://github.com/amzn/selling-partner-api-docs/blob/main/guides/developer-guide/SellingPartnerApiDeveloperGuide.md
After your are done with above, then you can follow these steps for getting your orders:
Step 1: Make sure you self auth your app in seller central. and click Generate Token to get your refresh token.
Step 2: Make sure you download the credentials of the user (AWS key and secret) you created in above documentation
Step 3: Go ahead and download this: https://github.com/amzn/selling-partner-api-models/tree/main/clients/sellingpartner-api-aa-csharp
IMPORTANT NOTE: These are R&D examples/codes and code, and there is no guarantee that it will work for you or anybody else.. I am still in learning and wanted to share my experience
Step 4: Add new console app and then add Amazon.SellingPartnerAPIAA to console app
Step 5: Setup your request
var resource = $"/orders/v0/orders"; IRestRequest restRequest = new RestRequest(resource, Method.GET);
restRequest.AddParameter("MarketplaceIds", MARKETPLACE_ID, ParameterType.QueryString);
restRequest.AddParameter("CreatedAfter", DateTime.UtcNow.AddDays(-5).ToString("yyyy-MM-dd"), ParameterType.QueryString);
Step 6: The most important step, ppl (like me) spent days to figure out how to that... Create two functions to sign your app with your access token and your AWS keys
private static IRestRequest SignWithAccessToken(IRestRequest restRequest, string clientId, string clientSecret, string refreshToken) { var lwaAuthorizationCredentials = new LWAAuthorizationCredentials { ClientId = clientId, ClientSecret = clientSecret, Endpoint = new Uri("https://api.amazon.com/auth/o2/token"), RefreshToken = refreshToken, };
return new LWAAuthorizationSigner(lwaAuthorizationCredentials).Sign(restRequest);
}
and this is for your AWS keys
Note1: roleARN This is the role IRN you created with your app (refer the first document) Note2: The Amazon documents are missing (surprised, surprised) steps. This AssumeRole call is very important otherwise you will keep getting Forbidden
private static IRestRequest SignWithSTSKeysAndSecurityTokenn(IRestRequest restRequest, string host, string roleARN, string accessKey, string secretKey) { AssumeRoleResponse response1 = null; using (var STSClient = new AmazonSecurityTokenServiceClient(accessKey, secretKey, RegionEndpoint.USEast1)) { var req = new AssumeRoleRequest() { RoleArn = roleARN, DurationSeconds = 950, //put anything you want here RoleSessionName = Guid.NewGuid().ToString() };
response1 = STSClient.AssumeRoleAsync(req, new CancellationToken()).Result;
}
//auth step 3
var awsAuthenticationCredentials = new AWSAuthenticationCredentials
{
AccessKeyId = response1.Credentials.AccessKeyId,
SecretKey = response1.Credentials.SecretAccessKey,
Region = "us-east-1"
};
restRequest.AddHeader("x-amz-security-token", response1.Credentials.SessionToken);
return new AWSSigV4Signer(awsAuthenticationCredentials)
.Sign(restRequest, host);
}
Now sign your request:
create some class like that and fill it wit your info
public class SellerAPICredentials { public string ClientId { get; set; } public string ClientSecret { get; set; } public string RefreshToken { get; set; } public string AWSKey { get; set; } public string AWSSecret { get; set; } public string RoleARN { get; set; } }
Then call these functions to sign your request
restRequest = SignWithAccessToken(restRequest, credentials.ClientId, credentials.ClientSecret, credentials.RefreshToken);
restRequest = SignWithSTSKeysAndSecurityTokenn(restRequest, Client.BaseUrl.Host, credentials.RoleARN, credentials.AWSKey, credentials.AWSSecret, overrideHost);
Step 5: Finally use your request to call
var client = new RestClient("https://sellingpartnerapi-na.amazon.com"); var response = client.Execute(restRequest);
Good luck!
Oguz
@tenitre The entire AWS user access, role, user ARN, STS stuff is wild for someone who has never done it. So many moving parts. I am pretty sure I did it correctly and our application is authorized by Amazon for our vendor central account but I am still getting a forbidden error. For what it is worth below is the code in it's entirety.
I appreciate you responding and giving some help. I presume my issue at this point has to do with IAM or the application authorization process and I would need Amazon customer service to respond to a ticket some time in the next year to move forward. If you notice any issues below let me know. If I figure anything out I will post it here as well so everyone can see.
using Amazon;
using Amazon.SecurityToken;
using Amazon.SecurityToken.Model;
using Amazon.SellingPartnerAPIAA;
using RestSharp;
using System;
using System.Threading;
namespace amazon_df_scratchpad
{
class Program
{
static void Main(string[] args)
{
var resource = $"/vendor/directFulfillment/orders/v1/purchaseOrders";
IRestRequest restRequest = new RestRequest(resource, Method.GET);
restRequest.AddParameter("createdAfter", DateTime.UtcNow.AddDays(-5).ToString("yyyy-MM-dd"), ParameterType.QueryString);
restRequest.AddParameter("createdBefore", DateTime.UtcNow.ToString("yyyy-MM-dd"), ParameterType.QueryString);
var client = new RestClient("https://sellingpartnerapi-na.amazon.com");
var credentials = new SellerAPICredentials();
restRequest = SignWithAccessToken(restRequest, credentials.ClientId, credentials.ClientSecret, credentials.RefreshToken);
restRequest = SignWithSTSKeysAndSecurityTokenn(restRequest, client.BaseUrl.Host, credentials.RoleARN, credentials.AWSKey, credentials.AWSSecret);
var response = client.Execute(restRequest);
Console.WriteLine("");
}
private static IRestRequest SignWithAccessToken(IRestRequest restRequest, string clientId, string clientSecret, string refreshToken)
{
var lwaAuthorizationCredentials = new LWAAuthorizationCredentials
{
ClientId = clientId,
ClientSecret = clientSecret,
Endpoint = new Uri("https://api.amazon.com/auth/o2/token"),
RefreshToken = refreshToken,
};
return new LWAAuthorizationSigner(lwaAuthorizationCredentials).Sign(restRequest);
}
private static IRestRequest SignWithSTSKeysAndSecurityTokenn(IRestRequest restRequest, string host, string roleARN, string accessKey, string secretKey)
{
AssumeRoleResponse response1 = null;
using (var STSClient = new AmazonSecurityTokenServiceClient(accessKey, secretKey, RegionEndpoint.USEast1))
{
var req = new AssumeRoleRequest()
{
RoleArn = roleARN,
DurationSeconds = 950, //put anything you want here
RoleSessionName = Guid.NewGuid().ToString()
};
response1 = STSClient.AssumeRoleAsync(req, new CancellationToken()).Result;
}
//auth step 3
var awsAuthenticationCredentials = new AWSAuthenticationCredentials
{
AccessKeyId = response1.Credentials.AccessKeyId,
SecretKey = response1.Credentials.SecretAccessKey,
Region = "us-east-1"
};
restRequest.AddHeader("x-amz-security-token", response1.Credentials.SessionToken);
return new AWSSigV4Signer(awsAuthenticationCredentials)
.Sign(restRequest, host);
}
}
public class SellerAPICredentials
{
public string ClientId = xxxxxxxxxxxxxxxxxxx;
public string ClientSecret = xxxxxxxxxxxxxxxxxxx;
public string RefreshToken = xxxxxxxxxxxxxxxxxxx;
public string AWSKey = xxxxxxxxxxxxxxxxxxx;
public string AWSSecret = xxxxxxxxxxxxxxxxxxx;
public string RoleARN = xxxxxxxxxxxxxxxxxxx;
}
}
`
Hey @smithburger
your code works just fine... First I tried it with my credentials for this endpoint (/vendor/directFulfillment/orders/v1/purchaseOrders) and I also got Forbidden, then I tried to hit this endpoint
var resource = $"/orders/v0/orders";
It worked just fine... So I think there is something wrong with your request parameters.
Can you also let me know where this (/vendor/directFulfillment/orders/v1/purchaseOrders) endpoint? I never used it before
BTW the weird thing is when you have wrong param names or values etc. (especially datetime) instead of getting badrequest, you usually get this forbidden error.
Another note that make sure to use role ARN, not user ARN
Hey @smithburger
your code works just fine... First I tried it with my credentials for this endpoint (/vendor/directFulfillment/orders/v1/purchaseOrders) and I also got Forbidden, then I tried to hit this endpoint
var resource = $"/orders/v0/orders";
It worked just fine... So I think there is something wrong with your request parameters.
Can you also let me know where this (/vendor/directFulfillment/orders/v1/purchaseOrders) endpoint? I never used it before
We are a Direct Fulfillment vendor with Amazon. When you buy our products on Amazon it is sold under the Amazon name. This is not normal 3PP access. The URL I used is the API end point for that call. The SP-API is the same though.
I am guessing our issue is with some IAM policy or ARN somewhere. I did make sure to use the Role ARN in the app. I made the User mistake then fixed it. Went from getting an error about sig not matching to just forbidden. I will open a case with Amazon and see what they say. Hopefully it doesn't take 60 days for them to respond this time.
Yes you are right... It should be your policy, I recommend you open a support ticket on seller central, but let me tell you this, you need to tell them several times that you are opening the ticket for SP API... After that they will escalate the issue to level2, then you will get your answer.. This is exactly what happened in my case regarding my feeds getting cancelled issue..
Good luck
This is crrrrrrrrrrrazy!
I've been working on this for almost a week and I've not been able to retrieve anything from Amazon other than an access code.
Since your @smithburger code has been tested and worked for @tenitre, I've abandoned mine and adopted yours.
However, I still get the same error with yours which is "The request signature we calculated does not match the signature you provided.". I've worked on this project for 12.5 hrs today and haven't really got anywhere!
The thing is that it's so close. If I remove a parameter, it knows and tells me about it. It's close!
I've changed the DLL slightly as I've found that X-Amz-Date is apparently supposed to be lower case. Also put it back and I still get the same error.
I'm stuck....
This is crrrrrrrrrrrazy!
I've been working on this for almost a week and I've not been able to retrieve anything from Amazon other than an access code.
Since your @smithburger code has been tested and worked for @tenitre, I've abandoned mine and adopted yours.
However, I still get the same error with yours which is "The request signature we calculated does not match the signature you provided.". I've worked on this project for 12.5 hrs today and haven't really got anywhere!
The thing is that it's so close. If I remove a parameter, it knows and tells me about it. It's close!
I've changed the DLL slightly as I've found that X-Amz-Date is apparently supposed to be lower case. Also put it back and I still get the same error.
I'm stuck....
Share a sample of your request. One guess is that the problem is the query parameters since they need a special encoding but it is hard to know without seeing the request.
Hi everyone,
I've done a lot of diagnostics and I can see the problem - ish!
This is my request (tokens are correct):
GET /orders/v0/orders createdAfter=2020-11-28&MarketplaceIds=A1F83G8C2ARO7P host:sellingpartnerapi-eu.amazon.com x-amz-access-token:[Atza|token] x-amz-date:20201212T115219Z x-amz-security-token:[token]
host;x-amz-access-token;x-amz-date;x-amz-security-token e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
Signed AWS4-HMAC-SHA256 20201212T115219Z 20201212/eu-west-1/execute-api/aws4_request cc7b50fe0ec2c6c157959a3dbaa6aca5411ea2d4d19e4989666e2867fc879c4d
The Canonical String for this request should have been
GET /orders/v0/orders MarketplaceIds=A1F83G8C2ARO7P&createdAfter=2020-11-28 host:sellingpartnerapi-eu.amazon.com x-amz-access-token:[Atza|token] x-amz-date:20201212T115219Z x-amz-security-token:[token]
host;x-amz-access-token;x-amz-date;x-amz-security-token e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
The String-to-Sign should have been AWS4-HMAC-SHA256 20201212T115219Z 20201212/eu-west-1/execute-api/aws4_request 55da72cdf7472117ec97337419681da54838ca4f4dd4e26cc98e60d6713ce959
The marketplace id and date seems to be mixed around? The hashed string to sign should be correct as the string is correct!?
Swap the params around and it says:
The Canonical String for this request should have been 'GET /orders/v0/orders CreatedAfter=2020-11-28&MarketplaceIds=A1F83G8C2ARO7P
I resolved this "The request signature we calculated does not match the signature you provided." by fixing the case sensitivity of the parameter names.
不错👍
using the code provided by smithburger, but at line response1 = STSClient.AssumeRoleAsync(req).Result; get this error: Task does not contains a definition of Result. any idea?
@smithburger Did you able to resolve the signature issue? I am stuck while calling the AmazonFullfillment SP-API endpoint.please help if you found the issue.
@smithburger Did you able to resolve the signature issue? I am stuck while calling the AmazonFullfillment SP-API endpoint.please help if you found the issue.
Not directly. Amazon CS finally got back to me after 45 days asking for all my request info which I passed on. Their response to that made it seem like my AWS credentials are not correct. I asked them for help and it has been 30+ days again. Amazon CS is awful. I don't want to nuke all my credentials and start from scratch because I don't know how long a new approval would take.
They never said my request was bad though. So I think my code from above should work.
I resolved this "The request signature we calculated does not match the signature you provided." by fixing the case sensitivity of the parameter names.
Hello @antonycartwright - May I know what exactly the parameter name you modified to fix the case sensitivity and do you mind pasting part of the code here? I am able to successfully make calls to getReports resource, however, using the same code, I am having issues while trying to createReport using POST method. I am getting the error "The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details....The String-to-Sign should have been 'AWS4-HMAC-SHA256.. etc"
Hello ,
How can i find the class AmazonSecurityTokenServiceClient and STSAssumeRoleSessionCredentialsProvider ? In which sdk ?
Hi @leo1695
Not sure what is that class but here is how I use Assume Role in SP API:
using (var STSClient = new AmazonSecurityTokenServiceClient(accessKey, secretKey, RegionEndpoint.USEast1)) { var req = new AssumeRoleRequest() { RoleArn = roleARN, DurationSeconds = 950, RoleSessionName = Guid.NewGuid().ToString() };
assumeRoleResponse = STSClient.AssumeRoleAsync(req, new CancellationToken()).Result;
}
You can find these classes in this nuget package:
.nuget\packages\awssdk.securitytoken\3.5.1.22\lib\netcoreapp3.1\AWSSDK.SecurityToken.dll
Hi, @tenitre When i call the STSClient.AssumeRoleAsync , i get the response : "user XXX is not authorized to perform: sts:AssumeRole on resource XXX" , so I cannot use this method.
I have call the sp api ok with use the https://github.com/amzn/selling-partner-api-models/tree/main/clients/sellingpartner-api-aa-csharp AWSSigV4Signer .
For those who want to copy and paste and see it work successfully, I have made changes needed to work correctly as of April 9, 2021 (renamed the variables to be more clear what client id/secret are required and added comments to show what some of them should start with). Be sure to add nuget package of AWSSDK.SecurityToken (and maybe RestSharp).
using Amazon;
using Amazon.SecurityToken;
using Amazon.SecurityToken.Model;
using Amazon.SellingPartnerAPIAA;
using RestSharp;
using System;
using System.Threading;
namespace amazon_test_code
{
class Program
{
static string MARKETPLACE_ID = "ATVPDKIKX0DER"; // for US. See https://github.com/amzn/selling-partner-api-docs/blob/main/guides/en-US/developer-guide/SellingPartnerApiDeveloperGuide.md#marketplaceid-values for other countries.
static void Main(string[] args)
{
var resource = $"/orders/v0/orders";
IRestRequest restRequest = new RestRequest(resource, Method.GET);
restRequest.AddParameter("MarketplaceIds", MARKETPLACE_ID, ParameterType.QueryString);
restRequest.AddParameter("CreatedAfter", DateTime.UtcNow.AddDays(-5).ToString("yyyy-MM-dd"), ParameterType.QueryString);
restRequest.AddParameter("CreatedBefore", DateTime.UtcNow.ToString("yyyy-MM-dd"), ParameterType.QueryString);
var client = new RestClient("https://sellingpartnerapi-na.amazon.com");
var credentials = new SellerAPICredentials();
restRequest = SignWithAccessToken(restRequest, credentials.LWA_App_ClientId, credentials.LWA_App_ClientSecret, credentials.RefreshToken);
restRequest = SignWithSTSKeysAndSecurityTokenn(restRequest, client.BaseUrl.Host, credentials.RoleARN, credentials.AWSKey, credentials.AWSSecret);
var response = client.Execute(restRequest);
Console.WriteLine("");
}
private static IRestRequest SignWithAccessToken(IRestRequest restRequest, string clientId, string clientSecret, string refreshToken)
{
var lwaAuthorizationCredentials = new LWAAuthorizationCredentials
{
ClientId = clientId,
ClientSecret = clientSecret,
Endpoint = new Uri("https://api.amazon.com/auth/o2/token"),
RefreshToken = refreshToken,
};
return new LWAAuthorizationSigner(lwaAuthorizationCredentials).Sign(restRequest);
}
private static IRestRequest SignWithSTSKeysAndSecurityTokenn(IRestRequest restRequest, string host, string roleARN, string accessKey, string secretKey)
{
AssumeRoleResponse response1 = null;
using (var STSClient = new AmazonSecurityTokenServiceClient(accessKey, secretKey, RegionEndpoint.USEast1))
{
var req = new AssumeRoleRequest()
{
RoleArn = roleARN,
DurationSeconds = 950, //put anything you want here
RoleSessionName = Guid.NewGuid().ToString()
};
response1 = STSClient.AssumeRoleAsync(req, new CancellationToken()).Result;
}
//auth step 3
var awsAuthenticationCredentials = new AWSAuthenticationCredentials
{
AccessKeyId = response1.Credentials.AccessKeyId,
SecretKey = response1.Credentials.SecretAccessKey,
Region = "us-east-1"
};
restRequest.AddHeader("x-amz-security-token", response1.Credentials.SessionToken);
return new AWSSigV4Signer(awsAuthenticationCredentials)
.Sign(restRequest, host);
}
}
public class SellerAPICredentials
{
public string LWA_App_ClientId = xxxxxxxxxxxxxxx; //amzn...
public string LWA_App_ClientSecret = xxxxxxxxxxxxxxx;
public string RefreshToken = xxxxxxxxxxxxxxx; //Atzr...
public string AWSKey = xxxxxxxxxxxxxxx;
public string AWSSecret = xxxxxxxxxxxxxxx;
public string RoleARN = xxxxxxxxxxxxxxx; //arn...
}
}
Hi
Not sure you have went through this process to create your application: https://github.com/amzn/selling-partner-api-docs/blob/main/guides/developer-guide/SellingPartnerApiDeveloperGuide.md
After your are done with above, then you can follow these steps for getting your orders:
Step 1: Make sure you self auth your app in seller central. and click Generate Token to get your refresh token.
Step 2: Make sure you download the credentials of the user (AWS key and secret) you created in above documentation
Step 3: Go ahead and download this: https://github.com/amzn/selling-partner-api-models/tree/main/clients/sellingpartner-api-aa-csharp
IMPORTANT NOTE: These are R&D examples/codes and code, and there is no guarantee that it will work for you or anybody else.. I am still in learning and wanted to share my experience
Step 4: Add new console app and then add Amazon.SellingPartnerAPIAA to console app
Step 5: Setup your request
var resource = $"/orders/v0/orders"; IRestRequest restRequest = new RestRequest(resource, Method.GET);
restRequest.AddParameter("MarketplaceIds", MARKETPLACE_ID, ParameterType.QueryString); restRequest.AddParameter("CreatedAfter", DateTime.UtcNow.AddDays(-5).ToString("yyyy-MM-dd"), ParameterType.QueryString);
Step 6: The most important step, ppl (like me) spent days to figure out how to that... Create two functions to sign your app with your access token and your AWS keys
private static IRestRequest SignWithAccessToken(IRestRequest restRequest, string clientId, string clientSecret, string refreshToken) { var lwaAuthorizationCredentials = new LWAAuthorizationCredentials { ClientId = clientId, ClientSecret = clientSecret, Endpoint = new Uri("https://api.amazon.com/auth/o2/token"), RefreshToken = refreshToken, };
return new LWAAuthorizationSigner(lwaAuthorizationCredentials).Sign(restRequest); }
and this is for your AWS keys
Note1: roleARN This is the role IRN you created with your app (refer the first document) Note2: The Amazon documents are missing (surprised, surprised) steps. This AssumeRole call is very important otherwise you will keep getting Forbidden
private static IRestRequest SignWithSTSKeysAndSecurityTokenn(IRestRequest restRequest, string host, string roleARN, string accessKey, string secretKey) { AssumeRoleResponse response1 = null; using (var STSClient = new AmazonSecurityTokenServiceClient(accessKey, secretKey, RegionEndpoint.USEast1)) { var req = new AssumeRoleRequest() { RoleArn = roleARN, DurationSeconds = 950, //put anything you want here RoleSessionName = Guid.NewGuid().ToString() };
response1 = STSClient.AssumeRoleAsync(req, new CancellationToken()).Result; } //auth step 3 var awsAuthenticationCredentials = new AWSAuthenticationCredentials { AccessKeyId = response1.Credentials.AccessKeyId, SecretKey = response1.Credentials.SecretAccessKey, Region = "us-east-1" }; restRequest.AddHeader("x-amz-security-token", response1.Credentials.SessionToken); return new AWSSigV4Signer(awsAuthenticationCredentials) .Sign(restRequest, host); }
Now sign your request:
create some class like that and fill it wit your info
public class SellerAPICredentials { public string ClientId { get; set; } public string ClientSecret { get; set; } public string RefreshToken { get; set; } public string AWSKey { get; set; } public string AWSSecret { get; set; } public string RoleARN { get; set; } }
Then call these functions to sign your request
restRequest = SignWithAccessToken(restRequest, credentials.ClientId, credentials.ClientSecret, credentials.RefreshToken);
restRequest = SignWithSTSKeysAndSecurityTokenn(restRequest, Client.BaseUrl.Host, credentials.RoleARN, credentials.AWSKey, credentials.AWSSecret, overrideHost);
Step 5: Finally use your request to call
var client = new RestClient("https://sellingpartnerapi-na.amazon.com"); var response = client.Execute(restRequest);
Good luck!
Oguz
Why are all these links giving 404 Not Found ?
hi I followed the amazon directions exactly, and I downloaded your latest code, its giving me an error like this One or more errors occurred. (User: arn:**:user/*.com is not authorized to perform: sts:AssumeRole on resource: arn:aws:iam***:role/***ner-role). what am I doing wrong. please help
@dannyatftecu hello, your code worked for me, but when I tried to get the date by a specific time it gave me a forbidden error, I tried DateTime.UtcNow.ToString("o"); also, DateTime.UtcNow.ToString("yyyy-MM-ddTHH\:mm\:ss.fffffffzzz");
have you tried that?
@tenitre Thank you for the answer and code. I wonder where can I found the refresh token? I couldn't find anything about it refresh token in the migration guide.
For those who want to copy and paste and see it work successfully, I have made changes needed to work correctly as of April 9, 2021 (renamed the variables to be more clear what client id/secret are required and added comments to show what some of them should start with). Be sure to add nuget package of AWSSDK.SecurityToken (and maybe RestSharp).
using Amazon; using Amazon.SecurityToken; using Amazon.SecurityToken.Model; using Amazon.SellingPartnerAPIAA; using RestSharp; using System; using System.Threading; namespace amazon_test_code { class Program { static string MARKETPLACE_ID = "ATVPDKIKX0DER"; // for US. See https://github.com/amzn/selling-partner-api-docs/blob/main/guides/en-US/developer-guide/SellingPartnerApiDeveloperGuide.md#marketplaceid-values for other countries. static void Main(string[] args) { var resource = $"/orders/v0/orders"; IRestRequest restRequest = new RestRequest(resource, Method.GET); restRequest.AddParameter("MarketplaceIds", MARKETPLACE_ID, ParameterType.QueryString); restRequest.AddParameter("CreatedAfter", DateTime.UtcNow.AddDays(-5).ToString("yyyy-MM-dd"), ParameterType.QueryString); restRequest.AddParameter("CreatedBefore", DateTime.UtcNow.ToString("yyyy-MM-dd"), ParameterType.QueryString); var client = new RestClient("https://sellingpartnerapi-na.amazon.com"); var credentials = new SellerAPICredentials(); restRequest = SignWithAccessToken(restRequest, credentials.LWA_App_ClientId, credentials.LWA_App_ClientSecret, credentials.RefreshToken); restRequest = SignWithSTSKeysAndSecurityTokenn(restRequest, client.BaseUrl.Host, credentials.RoleARN, credentials.AWSKey, credentials.AWSSecret); var response = client.Execute(restRequest); Console.WriteLine(""); } private static IRestRequest SignWithAccessToken(IRestRequest restRequest, string clientId, string clientSecret, string refreshToken) { var lwaAuthorizationCredentials = new LWAAuthorizationCredentials { ClientId = clientId, ClientSecret = clientSecret, Endpoint = new Uri("https://api.amazon.com/auth/o2/token"), RefreshToken = refreshToken, }; return new LWAAuthorizationSigner(lwaAuthorizationCredentials).Sign(restRequest); } private static IRestRequest SignWithSTSKeysAndSecurityTokenn(IRestRequest restRequest, string host, string roleARN, string accessKey, string secretKey) { AssumeRoleResponse response1 = null; using (var STSClient = new AmazonSecurityTokenServiceClient(accessKey, secretKey, RegionEndpoint.USEast1)) { var req = new AssumeRoleRequest() { RoleArn = roleARN, DurationSeconds = 950, //put anything you want here RoleSessionName = Guid.NewGuid().ToString() }; response1 = STSClient.AssumeRoleAsync(req, new CancellationToken()).Result; } //auth step 3 var awsAuthenticationCredentials = new AWSAuthenticationCredentials { AccessKeyId = response1.Credentials.AccessKeyId, SecretKey = response1.Credentials.SecretAccessKey, Region = "us-east-1" }; restRequest.AddHeader("x-amz-security-token", response1.Credentials.SessionToken); return new AWSSigV4Signer(awsAuthenticationCredentials) .Sign(restRequest, host); } } public class SellerAPICredentials { public string LWA_App_ClientId = xxxxxxxxxxxxxxx; //amzn... public string LWA_App_ClientSecret = xxxxxxxxxxxxxxx; public string RefreshToken = xxxxxxxxxxxxxxx; //Atzr... public string AWSKey = xxxxxxxxxxxxxxx; public string AWSSecret = xxxxxxxxxxxxxxx; public string RoleARN = xxxxxxxxxxxxxxx; //arn... } }
Yep, this worket for me.
I was missing the SignWithSTSKeysAndSecurityTokenn (I didn't found nothning about it in the docs).
Thank you very much!
Hi
Not sure you have went through this process to create your application: https://github.com/amzn/selling-partner-api-docs/blob/main/guides/developer-guide/SellingPartnerApiDeveloperGuide.md
After your are done with above, then you can follow these steps for getting your orders:
Step 1: Make sure you self auth your app in seller central. and click Generate Token to get your refresh token.
Step 2: Make sure you download the credentials of the user (AWS key and secret) you created in above documentation
Step 3: Go ahead and download this: https://github.com/amzn/selling-partner-api-models/tree/main/clients/sellingpartner-api-aa-csharp
IMPORTANT NOTE: These are R&D examples/codes and code, and there is no guarantee that it will work for you or anybody else.. I am still in learning and wanted to share my experience
Step 4: Add new console app and then add Amazon.SellingPartnerAPIAA to console app
Step 5: Setup your request
var resource = $"/orders/v0/orders"; IRestRequest restRequest = new RestRequest(resource, Method.GET);
restRequest.AddParameter("MarketplaceIds", MARKETPLACE_ID, ParameterType.QueryString); restRequest.AddParameter("CreatedAfter", DateTime.UtcNow.AddDays(-5).ToString("yyyy-MM-dd"), ParameterType.QueryString);
Step 6: The most important step, ppl (like me) spent days to figure out how to that... Create two functions to sign your app with your access token and your AWS keys
private static IRestRequest SignWithAccessToken(IRestRequest restRequest, string clientId, string clientSecret, string refreshToken) { var lwaAuthorizationCredentials = new LWAAuthorizationCredentials { ClientId = clientId, ClientSecret = clientSecret, Endpoint = new Uri("https://api.amazon.com/auth/o2/token"), RefreshToken = refreshToken, };
return new LWAAuthorizationSigner(lwaAuthorizationCredentials).Sign(restRequest); }
and this is for your AWS keys
Note1: roleARN This is the role IRN you created with your app (refer the first document) Note2: The Amazon documents are missing (surprised, surprised) steps. This AssumeRole call is very important otherwise you will keep getting Forbidden
private static IRestRequest SignWithSTSKeysAndSecurityTokenn(IRestRequest restRequest, string host, string roleARN, string accessKey, string secretKey) { AssumeRoleResponse response1 = null; using (var STSClient = new AmazonSecurityTokenServiceClient(accessKey, secretKey, RegionEndpoint.USEast1)) { var req = new AssumeRoleRequest() { RoleArn = roleARN, DurationSeconds = 950, //put anything you want here RoleSessionName = Guid.NewGuid().ToString() };
response1 = STSClient.AssumeRoleAsync(req, new CancellationToken()).Result; } //auth step 3 var awsAuthenticationCredentials = new AWSAuthenticationCredentials { AccessKeyId = response1.Credentials.AccessKeyId, SecretKey = response1.Credentials.SecretAccessKey, Region = "us-east-1" }; restRequest.AddHeader("x-amz-security-token", response1.Credentials.SessionToken); return new AWSSigV4Signer(awsAuthenticationCredentials) .Sign(restRequest, host); }
Now sign your request:
create some class like that and fill it wit your info
public class SellerAPICredentials { public string ClientId { get; set; } public string ClientSecret { get; set; } public string RefreshToken { get; set; } public string AWSKey { get; set; } public string AWSSecret { get; set; } public string RoleARN { get; set; } }
Then call these functions to sign your request
restRequest = SignWithAccessToken(restRequest, credentials.ClientId, credentials.ClientSecret, credentials.RefreshToken);
restRequest = SignWithSTSKeysAndSecurityTokenn(restRequest, Client.BaseUrl.Host, credentials.RoleARN, credentials.AWSKey, credentials.AWSSecret, overrideHost);
Step 5: Finally use your request to call
var client = new RestClient("https://sellingpartnerapi-na.amazon.com"); var response = client.Execute(restRequest);
Good luck!
Oguz
thank you it solved my problem i got rid of wasting time
Has anyone successfully built a working SDK from the swagger templates? I was finally able to get past the myriad of build errors and get CSC to compile all modules, apis and the client into a single dll using the instructions. However, there is absolutely no documentation on using the SDK in a project. If anyone has a working example of a simple call using credentials with the client SDK I'd appreciate a peek. :)
hi everyone here, thank g-d we have a c# example on how to make calls to amazon. thanks @tenitre, it was a huge help, now we need to code modified in order to use it when calling the authorization API and when getting new clients authenticated, is anyone ready to help us, we are willing to pay, and the code will remain posted here
Hi everyone, I made a package for Amazon SP-API request, here is the NuGet's link, currently it help you sign the request, refresh Amazon complicate authorization flow. Currently I implement order and feed API, If you are interested building this package with me please contact me.
Has anyone successfully built a working SDK from the swagger templates? I was finally able to get past the myriad of build errors and get CSC to compile all modules, apis and the client into a single dll using the instructions. However, there is absolutely no documentation on using the SDK in a project. If anyone has a working example of a simple call using credentials with the client SDK I'd appreciate a peek. :)
I was able to roll the solution documented by @tenitre into the SellingPartnerAPIAA so that the compiled library can be used to handle the STS token header with the compiled C# SDK without having to make code changes to the SPAPI SDK. I've added a SessionToken property, and a GetSTSAuthenticationCredentials() method, which returns the Credentials and session token from the AssumeRole Response to the APIAA.AWSAuthenticationCredentials class.
In my app, I've passed my IAM user credentials and RoleARN to the new method in order to get the fully compatible AWSAuthenticationCredentials back, including the SessionToken. The session token then gets passed to the API Call using the SDK's Configuration.AddDefaultHeader() method.
I would rather not have to modify Amazon's source code to get this to work, but I've taken the lightest touch approach I could think of. Hopefully, they will make similar changes to the APIAA code in order to account for the AssumeRole requirements.
What this means for me is that I can now use all of the SDK modules and SPAPI Client out of the box, without having to implement my own API Call solution for calling each and every sp-api.
If anyone is interested, I will post my modifications here. just let me know.
@jamesaq12wsx I started using your stuff, it looks great, does it have a call to call the GetAuthorizationCode call, I cant find it.
did anyone succeed product feed with c# ? could anyone show the way? =)
On Sun, Aug 1, 2021 at 11:44 PM nafberger @.***> wrote:
@jamesaq12wsx https://github.com/jamesaq12wsx I started using your stuff, it looks great, does it have a call to call the GetAuthorizationCode call, I cant fine it.
— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/amzn/selling-partner-api-models/issues/31#issuecomment-890583851, or unsubscribe https://github.com/notifications/unsubscribe-auth/AKV4JUK4F5PZTMB4H3QUUGTT2WWZ5ANCNFSM4T5EFVWQ .
@nafberger Thanks for your feedback. I haven't add GetAuthorizationCode, I'll update asap. By the way, according from amazon, to let GetAuthrizationCode call works (prod or sandbox) need your application been published with SP-API or Hybrid mode.
Huge thanks @jamesaq12wsx. yes our app is hybrid now. waiting for your change
I observed your package it needs lots of help! interfaces are dropped its only useful for authorize. Keep it going it seems lot of people gonna use it
On Thu, Jul 29, 2021 at 8:49 PM James Lin @.***> wrote:
Hi everyone, I made a package for Amazon SP-API request, here is the NuGet's link https://www.nuget.org/packages/AmzSpApi/, currently it help you sign the request, refresh Amazon complicate authorization flow. Currently I implement order and feed API, If you are interested building this package with me please contact me.
— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/amzn/selling-partner-api-models/issues/31#issuecomment-889340963, or unsubscribe https://github.com/notifications/unsubscribe-auth/AKV4JUISSTBGZGDYP22VOT3T2GIBLANCNFSM4T5EFVWQ .
@tenitre The entire AWS user access, role, user ARN, STS stuff is wild for someone who has never done it. So many moving parts. I am pretty sure I did it correctly and our application is authorized by Amazon for our vendor central account but I am still getting a forbidden error. For what it is worth below is the code in it's entirety.
I appreciate you responding and giving some help. I presume my issue at this point has to do with IAM or the application authorization process and I would need Amazon customer service to respond to a ticket some time in the next year to move forward. If you notice any issues below let me know. If I figure anything out I will post it here as well so everyone can see.
using Amazon; using Amazon.SecurityToken; using Amazon.SecurityToken.Model; using Amazon.SellingPartnerAPIAA; using RestSharp; using System; using System.Threading; namespace amazon_df_scratchpad { class Program { static void Main(string[] args) { var resource = $"/vendor/directFulfillment/orders/v1/purchaseOrders"; IRestRequest restRequest = new RestRequest(resource, Method.GET); restRequest.AddParameter("createdAfter", DateTime.UtcNow.AddDays(-5).ToString("yyyy-MM-dd"), ParameterType.QueryString); restRequest.AddParameter("createdBefore", DateTime.UtcNow.ToString("yyyy-MM-dd"), ParameterType.QueryString); var client = new RestClient("https://sellingpartnerapi-na.amazon.com"); var credentials = new SellerAPICredentials(); restRequest = SignWithAccessToken(restRequest, credentials.ClientId, credentials.ClientSecret, credentials.RefreshToken); restRequest = SignWithSTSKeysAndSecurityTokenn(restRequest, client.BaseUrl.Host, credentials.RoleARN, credentials.AWSKey, credentials.AWSSecret); var response = client.Execute(restRequest); Console.WriteLine(""); } private static IRestRequest SignWithAccessToken(IRestRequest restRequest, string clientId, string clientSecret, string refreshToken) { var lwaAuthorizationCredentials = new LWAAuthorizationCredentials { ClientId = clientId, ClientSecret = clientSecret, Endpoint = new Uri("https://api.amazon.com/auth/o2/token"), RefreshToken = refreshToken, }; return new LWAAuthorizationSigner(lwaAuthorizationCredentials).Sign(restRequest); } private static IRestRequest SignWithSTSKeysAndSecurityTokenn(IRestRequest restRequest, string host, string roleARN, string accessKey, string secretKey) { AssumeRoleResponse response1 = null; using (var STSClient = new AmazonSecurityTokenServiceClient(accessKey, secretKey, RegionEndpoint.USEast1)) { var req = new AssumeRoleRequest() { RoleArn = roleARN, DurationSeconds = 950, //put anything you want here RoleSessionName = Guid.NewGuid().ToString() }; response1 = STSClient.AssumeRoleAsync(req, new CancellationToken()).Result; } //auth step 3 var awsAuthenticationCredentials = new AWSAuthenticationCredentials { AccessKeyId = response1.Credentials.AccessKeyId, SecretKey = response1.Credentials.SecretAccessKey, Region = "us-east-1" }; restRequest.AddHeader("x-amz-security-token", response1.Credentials.SessionToken); return new AWSSigV4Signer(awsAuthenticationCredentials) .Sign(restRequest, host); } } public class SellerAPICredentials { public string ClientId = xxxxxxxxxxxxxxxxxxx; public string ClientSecret = xxxxxxxxxxxxxxxxxxx; public string RefreshToken = xxxxxxxxxxxxxxxxxxx; public string AWSKey = xxxxxxxxxxxxxxxxxxx; public string AWSSecret = xxxxxxxxxxxxxxxxxxx; public string RoleARN = xxxxxxxxxxxxxxxxxxx; } } `
same code i have added into my application, i got the access token but when i call the order API i am getting the Access denied issue. please guild me what i am missing.
You have an invalid date format. It should be in ISO-8601 date/time format.
Document Link https://www.cnblogs.com/Cxiaoao/p/14326709.html
Git Source Link https://github.com/Cxiaoao/amazon-sellingpartner-api
Note : Your need change query param in source as example below request.AddQueryParameter("MarketplaceIds", "A2EUQ1WTGCTBG2"); To request.AddParameter("MarketplaceIds", "ATVPDKIKX0DER", ParameterType.QueryString); request.AddParameter("CreatedAfter", DateTime.UtcNow.AddDays(-50).ToString("yyyy-MM-dd"), ParameterType.QueryString);
God bless your hands but just a little problem it only getting orders its %10 of whole sp-api.
5 Ağu 2021 Per 11:43 tarihinde Sankine Software Inc < @.***> şunu yazdı:
I shared doc and guid, source code me have fined , it working 100% with .net
1.
Document Link https://www.cnblogs.com/Cxiaoao/p/14326709.html 2.
Git Source Link https://github.com/Cxiaoao/amazon-sellingpartner-api
— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/amzn/selling-partner-api-models/issues/31#issuecomment-893279254, or unsubscribe https://github.com/notifications/unsubscribe-auth/AKV4JUK4AZS276CFGN33IIDT3JFKHANCNFSM4T5EFVWQ . Triage notifications on the go with GitHub Mobile for iOS https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Android https://play.google.com/store/apps/details?id=com.github.android&utm_campaign=notification-email .
God bless your hands but just a little problem it only getting orders its %10 of whole sp-api. 5 Ağu 2021 Per 11:43 tarihinde Sankine Software Inc < @.***> şunu yazdı: … I shared doc and guid, source code me have fined , it working 100% with .net 1. Document Link https://www.cnblogs.com/Cxiaoao/p/14326709.html 2. Git Source Link https://github.com/Cxiaoao/amazon-sellingpartner-api — You are receiving this because you commented. Reply to this email directly, view it on GitHub <#31 (comment)>, or unsubscribe https://github.com/notifications/unsubscribe-auth/AKV4JUK4AZS276CFGN33IIDT3JFKHANCNFSM4T5EFVWQ . Triage notifications on the go with GitHub Mobile for iOS https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Android https://play.google.com/store/apps/details?id=com.github.android&utm_campaign=notification-email .
You need call with another region and market place to get all order on Seller Center
Hello guys, anyone know where I can find refresh token?
go to sellercentral => develop apps => authorize and you can generate a refresh token.
On Tue, Sep 7, 2021 at 6:37 AM Almazzzzzz891 @.***> wrote:
Hello guys, anyone know where I can find refresh token?
— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/amzn/selling-partner-api-models/issues/31#issuecomment-913965500, or unsubscribe https://github.com/notifications/unsubscribe-auth/AKV4JUOBLII6CP4XUCYLTK3UAWCF3ANCNFSM4T5EFVWQ . Triage notifications on the go with GitHub Mobile for iOS https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Android https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub.
go to sellercentral => develop apps => authorize and you can generate a refresh token. … On Tue, Sep 7, 2021 at 6:37 AM Almazzzzzz891 @.***> wrote: Hello guys, anyone know where I can find refresh token? — You are receiving this because you commented. Reply to this email directly, view it on GitHub <#31 (comment)>, or unsubscribe https://github.com/notifications/unsubscribe-auth/AKV4JUOBLII6CP4XUCYLTK3UAWCF3ANCNFSM4T5EFVWQ . Triage notifications on the go with GitHub Mobile for iOS https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Android https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub.
thx
Hi,
I am an Amazon MWS developer and will be migrating from MWS to SP-API. I want you to help me add new products. I couldn't find any sources in the new product feed. I have the product.xsd file but I can't figure out how to make an XML file with it. Can you help me on this issue? For example, I don't know how to select the category, how to enter the product properties for the category, etc. Thanks in advance for the help.
Hi, I am trying to get the SP-API process working. Where is the method AmazonSecurityTokenServiceClient located from the examples above ? Any help is appreciated.
It's also possible to use MFA/OTP when assuming role:
var req = new AssumeRoleRequest()
{
RoleArn = roleARN,
DurationSeconds = 950, //put anything you want here
RoleSessionName = Guid.NewGuid().ToString()
SerialNumber = userArn,
TokenCode = OneTimeOTPKey
};
I shared doc and guid, source code me have fined , it working 100% with .net
- Document Link https://www.cnblogs.com/Cxiaoao/p/14326709.html
- Git Source Link https://github.com/Cxiaoao/amazon-sellingpartner-api
Note : Your need change query param in source as example below request.AddQueryParameter("MarketplaceIds", "A2EUQ1WTGCTBG2"); To request.AddParameter("MarketplaceIds", "ATVPDKIKX0DER", ParameterType.QueryString); request.AddParameter("CreatedAfter", DateTime.UtcNow.AddDays(-50).ToString("yyyy-MM-dd"), ParameterType.QueryString);
@quehvbg your sample to do with invoke using rolearn doesnt work for me, think its to do with the setup I have in AWS and STS, I'm unable to follow the screenshot in documentation as it not being in english Sorry.
I have registered my app in seller central with IAM User Have you attached STS policy to user or Role in the screenshot? I have it attached to the user as below. is that correct?
Here's a link to my repo which has all the amazon selling partner api client's with some usage samples built via nswag using httpclient vs. amazon's restsharp implementation.
https://github.com/jadanah/amazon-selling-partner-api-csharp-samples
Closing as resolution by dev community.
Are there any C# code examples that work as a test by just replacing the credentials? Something simple like get Purchase Order information? I am trying to work off the C# client library and other documentation and am completely lost. The Java documentation is a lot more fleshed out. With C# I can't get past step one.
The code in the readme is incomplete on it's own. As far as I can tell it presumes some type of previous knowledge to get working.