Closed jmawebtech closed 2 years ago
its very strange its request Authentication Token because this will generate the token , I also add this method in library and i get another error { "errors": [ { "message": "Access to requested resource is denied.", "code": "Unauthorized", "details": "" } ] }
Hi,
Thanks for the information. I have an Amazon user using the Amazon MWS API. I have a seller ID, marketplace ID, and MWS token. Do you have to code to migrate the user to SP API? How do I generate a refresh token from a seller ID, marketplace ID and MWS token?
It's look like no other code only the method you mentioned and I added to library
Do more search I will do from my side to check
Hello @jmawebtech
Do you found any solution for this ?
Yes the app must be in published status in the Amazon Developer console.
Sent via the Samsung Galaxy S10e, an AT&T 5G Evolution capable smartphone Get Outlook for Androidhttps://aka.ms/AAb9ysg
From: Tareq Abuzuhri @.> Sent: Wednesday, March 9, 2022 9:41:45 AM To: abuzuhri/Amazon-SP-API-CSharp @.> Cc: JMA Web Technologies @.>; Mention @.> Subject: Re: [abuzuhri/Amazon-SP-API-CSharp] Migrate users from MWS to SP API (Issue #123)
Hello @jmawebtechhttps://github.com/jmawebtech
Do you found any solution for this ?
— Reply to this email directly, view it on GitHubhttps://github.com/abuzuhri/Amazon-SP-API-CSharp/issues/123#issuecomment-1062991167, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AAM2E6LJPMUFW3GVA6MSXNTU7C2CTANCNFSM5PKT3QXA. Triage notifications on the go with GitHub Mobile for iOShttps://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Androidhttps://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub. You are receiving this because you were mentioned.Message ID: @.***>
which application you mean its look like no application id as parameter can you share request sample to add it to library
hi @abuzuhri do u please have any examples on using the getAuthorizationCode call with your library, would really appreciate that
Hello @nafberger No its not work with me when i test
I will wait @jmawebtech reply to give more details to fix this in the API
You need to sign the request. The request needs the client ID and secret. See attached code. I had to build my own integration, since my business requirements are different.
Joseph Anderson
CEO and Founder
Sync with Connex
Author: The $20 SaaS Companyhttps://www.amazon.com/gp/product/B096SW23Z8?pf_rd_r=APQMAN9Z89W82P1N6TYR&pf_rd_p=8fe9b1d0-f378-4356-8bb8-cada7525eadd&pd_rd_r=45df3ff2-9ece-4440-8555-d7807923bfd4&pd_rd_w=3q6Vu&pd_rd_wg=FbsAX&ref_=pd_gw_unk
Web: https://www.syncwithconnex.com
From: Tareq Abuzuhri @.> Sent: Thursday, March 10, 2022 5:29 PM To: abuzuhri/Amazon-SP-API-CSharp @.> Cc: JMA Web Technologies @.>; Mention @.> Subject: Re: [abuzuhri/Amazon-SP-API-CSharp] Migrate users from MWS to SP API (Issue #123)
Hello @nafbergerhttps://github.com/nafberger No its not work with me when i test
I will wait @jmawebtechhttps://github.com/jmawebtech reply to give more details to fix this in the API
— Reply to this email directly, view it on GitHubhttps://github.com/abuzuhri/Amazon-SP-API-CSharp/issues/123#issuecomment-1064571346, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AAM2E6NNFLNCY56MSKPRB73U7JZUZANCNFSM5PKT3QXA. Triage notifications on the go with GitHub Mobile for iOShttps://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Androidhttps://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub. You are receiving this because you were mentioned.Message ID: @.***>
/// <summary>
/// Gets generic access token, so user can generate code and get access token for itself.
/// </summary>
/// <returns></returns>
public AmazonOAuth GetAccessTokenForSPAPIMigration()
{
string data = string.Empty;
using (HttpClient client = new HttpClient())
{
client.BaseAddress = new Uri("https://api.amazon.com");
var byteArray = Encoding.ASCII.GetBytes($"{credentials.LWA_App_ClientId}:{credentials.LWA_App_ClientSecret}");
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteArray));
Dictionary<string, string> items = new Dictionary<string, string>();
items.Add("grant_type", "client_credentials");
items.Add("scope", "sellingpartnerapi::migration");
items.Add("client_id", credentials.LWA_App_ClientId);
items.Add("client_secret", credentials.LWA_App_ClientSecret);
FormUrlEncodedContent formUrlEncodedContent = new FormUrlEncodedContent(items);
var rs = client.PostAsync("/auth/o2/token", formUrlEncodedContent).Result;
data = rs.Content.ReadAsStringAsync().Result;
}
return JsonConvert.DeserializeObject<AmazonOAuth>(data, Serialization.Settings);
}
/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
/// <summary>
/// Returns the Login with Amazon (LWA) authorization code for an existing Amazon MWS authorization.
/// </summary>
/// <param name="sellingPartnerId">The seller ID of the seller for whom you are requesting Selling Partner API authorization. This must be the seller ID of the seller who authorized your application on the Marketplace Appstore.</param>
/// <param name="developerId">Your developer ID. This must be one of the developer ID values that you provided when you registered your application in Developer Central.</param>
/// <param name="mwsAuthToken">The MWS Auth Token that was generated when the seller authorized your application on the Marketplace Appstore.</param>
/// <returns>Success.</returns>
/// <exception cref="ApiException">A server side error occurred.</exception>
public virtual async Task<GetAuthorizationCodeResponse> GetAuthorizationCodeAsync(string sellingPartnerId, string developerId, string mwsAuthToken, string accessToken, System.Threading.CancellationToken cancellationToken)
{
StringBuilder urlBuilder_ = new StringBuilder();
urlBuilder_.Append(GetBaseUrl() != null ? GetBaseUrl().TrimEnd('/') : "").Append("/authorization/v1/authorizationCode?");
urlBuilder_.Append(System.Uri.EscapeDataString("sellingPartnerId") + "=").Append(Uri.EscapeDataString(AmazonObjectConverter.StringConverter(sellingPartnerId))).Append("&");
urlBuilder_.Append(System.Uri.EscapeDataString("developerId") + "=").Append(Uri.EscapeDataString(AmazonObjectConverter.StringConverter(developerId))).Append("&");
urlBuilder_.Append(System.Uri.EscapeDataString("mwsAuthToken") + "=").Append(Uri.EscapeDataString(AmazonObjectConverter.StringConverter(mwsAuthToken))).Append("&");
urlBuilder_.Length--;
using (HttpRequestMessage request_ = new HttpRequestMessage())
{
request_.Method = new HttpMethod("GET");
request_.Headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse("application/json"));
string url_ = urlBuilder_.ToString();
request_.RequestUri = new Uri(url_, UriKind.RelativeOrAbsolute);
HttpClient client = new HttpClient();
client.BaseAddress = new Uri(GetBaseUrl());
client.DefaultRequestHeaders.Add("x-amz-access-token", accessToken);
AWSAuthenticationCredentials awsAuthenticationCredentials = new AWSAuthenticationCredentials
{
AccessKeyId = credentials.AWSKey,
SecretKey = credentials.AWSSecret,
Region = "us-east-1"
};
client = new AWSSigV4Signer(awsAuthenticationCredentials)
.Sign(client, request_, client.BaseAddress.Host);
var response_ = await client.SendAsync(request_, HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false);
var headers_ = PopulateResponseHeaders(response_);
ResponseHandler responseHandler = new ResponseHandler(false);
var objectResponse_ = await responseHandler.ReadObjectResponseAsync<GetAuthorizationCodeResponse>(response_, headers_, cancellationToken).ConfigureAwait(false);
return objectResponse_.Object;
}
so @jmawebtech can u please incorporate it in the code of @abuzuhri please
Hello @jmawebtech I do some fix for our API to do the same code you sent , but i can't test beaucse i dont have MWS application and keys, can you please test this code after get last commit https://github.com/abuzuhri/Amazon-SP-API-CSharp/commit/94ef5ea5e039a84bbfe1f7110c4b4a67e0de7a02
AmazonConnection codeAmazonConnection = new AmazonConnection(new AmazonCredential()
{
AccessKey = config.GetSection("MWSAmazonAPI:AccessKey").Value,
SecretKey = config.GetSection("MWSAmazonAPI:SecretKey").Value,
ClientId = config.GetSection("MWSAmazonAPI:ClientId").Value,
ClientSecret = config.GetSection("MWSAmazonAPI:ClientSecret").Value,
MarketPlace = MarketPlace.GetMarketPlaceByID(config.GetSection("FikaAmazonAPI:MarketPlaceID").Value),
IsActiveLimitRate = true
});
var code = codeAmazonConnection.Authorization.GetAuthorizationCode(new Parameter.Authorization.ParameterAuthorizationCode()
{
developerId = "999999999999999",
mwsAuthToken = "amzn.mws.9999999-ac85-07fc-999-9999999",
sellingPartnerId = "AAAAAAAAAAA"
});
With your code, I get this error:
{ "errors": [ { "message": "Access to requested resource is denied.", "code": "Unauthorized", "details": "" } ] }
My best guess is you have an issue generating the access token. My code throws a different error. In the app settings, should I leave refreshToken blank?
{ "FikaAmazonAPI": { "AccessKey": "X", "SecretKey": "X", "RoleArn": "", "ClientId": "X", "ClientSecret": "X", "RefreshToken": "", "MarketPlaceID": "ATVPDKIKX0DER" } }
Did you add this code to get the access token? public AmazonOAuth GetAccessTokenForSPAPIMigration() { string data = string.Empty;
using (HttpClient client = new HttpClient())
{
client.BaseAddress = new Uri("https://api.amazon.com");
var byteArray = Encoding.ASCII.GetBytes($"{credentials.LWA_App_ClientId}:{credentials.LWA_App_ClientSecret}");
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteArray));
Dictionary<string, string> items = new Dictionary<string, string>();
items.Add("grant_type", "client_credentials");
items.Add("scope", "sellingpartnerapi::migration");
items.Add("client_id", credentials.LWA_App_ClientId);
items.Add("client_secret", credentials.LWA_App_ClientSecret);
FormUrlEncodedContent formUrlEncodedContent = new FormUrlEncodedContent(items);
var rs = client.PostAsync("/auth/o2/token", formUrlEncodedContent).Result;
data = rs.Content.ReadAsStringAsync().Result;
}
return JsonConvert.DeserializeObject<AmazonOAuth>(data, Serialization.Settings);
}
Yes this code exist already ,
Can you debug the code to double check form your side , it's hard for me test this
ok I will
this library does it successfully.
https://github.com/amz-tools/amazon-sp-api.
I checked your version and his, it seems that u skip the call to https://sts.amazonaws.com/
the other code should work. i added 2 lines for the "code" and "redirecturi"
public AmazonOAuth GetAccessTokenForSPAPIMigration(string code, string appRedirectUri)
{
string data = string.Empty;
using (HttpClient client = new HttpClient())
{
client.BaseAddress = new Uri("https://api.amazon.com");
var byteArray = Encoding.ASCII.GetBytes($"{credentials.LWA_App_ClientId}:{credentials.LWA_App_ClientSecret}");
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteArray));
Dictionary<string, string> items = new Dictionary<string, string>();
items.Add("grant_type", "client_credentials");
items.Add("scope", "sellingpartnerapi::migration");
items.Add("client_id", credentials.LWA_App_ClientId);
items.Add("client_secret", credentials.LWA_App_ClientSecret);
items.Add("code", code);
items.Add("redirect_uri", appRedirectUri);
FormUrlEncodedContent formUrlEncodedContent = new FormUrlEncodedContent(items);
var rs = client.PostAsync("/auth/o2/token", formUrlEncodedContent).Result;
data = rs.Content.ReadAsStringAsync().Result;
}
return JsonConvert.DeserializeObject<AmazonOAuth>(data, Serialization.Settings);
}
}
this library does it successfully.
https://github.com/amz-tools/amazon-sp-api.
I checked your version and his, it seems that u skip the call to https://sts.amazonaws.com/
Can you mention the problem in which file and line
I will try again review my code and check
i will try to help u later, i just started my day
On Tue, Mar 15, 2022 at 1:31 PM Tareq Abuzuhri @.***> wrote:
I will try again review my code and check
— Reply to this email directly, view it on GitHub https://github.com/abuzuhri/Amazon-SP-API-CSharp/issues/123#issuecomment-1068258324, or unsubscribe https://github.com/notifications/unsubscribe-auth/AGHJOKYWJMN6A5LOKOVQVU3VADCQFANCNFSM5PKT3QXA . 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.
You are receiving this because you were mentioned.Message ID: @.***>
but I really want to help u, because u helped me A LOT
Did you add this code to get the access token? public AmazonOAuth GetAccessTokenForSPAPIMigration() { string data = string.Empty;
using (HttpClient client = new HttpClient()) { client.BaseAddress = new Uri("https://api.amazon.com"); var byteArray = Encoding.ASCII.GetBytes($"{credentials.LWA_App_ClientId}:{credentials.LWA_App_ClientSecret}"); client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteArray)); Dictionary<string, string> items = new Dictionary<string, string>(); items.Add("grant_type", "client_credentials"); items.Add("scope", "sellingpartnerapi::migration"); items.Add("client_id", credentials.LWA_App_ClientId); items.Add("client_secret", credentials.LWA_App_ClientSecret); FormUrlEncodedContent formUrlEncodedContent = new FormUrlEncodedContent(items); var rs = client.PostAsync("/auth/o2/token", formUrlEncodedContent).Result; data = rs.Content.ReadAsStringAsync().Result; } return JsonConvert.DeserializeObject<AmazonOAuth>(data, Serialization.Settings); }
Now I change to use same method you use
@jmawebtech and @nafberger please give another try
public static async Task<TokenResponse> GetAccessTokenForSPAPIMigration(string ClientId, string ClientSecret)
{
string data = string.Empty;
using (HttpClient client = new HttpClient())
{
client.BaseAddress = new Uri("https://api.amazon.com");
var byteArray = Encoding.ASCII.GetBytes($"{ClientId}:{ClientSecret}");
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteArray));
Dictionary<string, string> items = new Dictionary<string, string>();
items.Add("grant_type", "client_credentials");
items.Add("scope", "sellingpartnerapi::migration");
items.Add("client_id", ClientId);
items.Add("client_secret", ClientSecret);
FormUrlEncodedContent formUrlEncodedContent = new FormUrlEncodedContent(items);
var rs = client.PostAsync("/auth/o2/token", formUrlEncodedContent).Result;
data = await rs.Content.ReadAsStringAsync();
}
return JsonConvert.DeserializeObject<TokenResponse>(data);
}
Lets not get confused, in order to migrate MWS credentials to seller-api and get a token and refresh token u need 2 steps, first is to call GetAuthorizationCode and get a code, and then use that to call GetAccessTokenForSPAPIMigration.
I tested the GetAuthorizationCode call and its not working (access denied) the reason is that u need to call https://sts.amazonaws.com/ and get a session token as u do with all other calls. your call is missing the x-amz-security-token header which comes from the session token as u know.
I couldn't test the GetAccessTokenForSPAPIMigration but is it missing the 2 parameters I added. it doesn't need all the fancy amazon security stuff, and the authorizations header is not needed. its a plain simple call which you can do in postman. but it needs the code and the appredirecturl as query parameters
I tested the GetAuthorizationCode call and its not working (access denied) the reason is that u need to call https://sts.amazonaws.com/ and get a session token as u do with all other calls. your call is missing the x-amz-security-token header which comes from the session token as u know.
I don't think this true in GetAuthorizationCode , but we need help from @jmawebtech he know how its work
Closed by mistake
my answer was based on examining the API traffic from the the other library. which works
OTHER GET /authorization/v1/authorizationCode?developerId=0000000&mwsAuthToken=amzn.mws.00000000000sellingPartnerId=00000 HTTP/1.1 Authorization: AWS4-HMAC-SHA256 Credential=ASIAYNSEBDN7UV2PJH7H/20220315/us-east-1/execute-api/aws4_request, SignedHeaders=host;x-amz-access-token;x-amz-date, Signature=0b1f27d1b35205a2998d3cbcd0f555cae2a208227068b8786e06fc4658e7e3e5 Content-Type: application/json; charset=utf-8 host: sellingpartnerapi-na.amazon.com x-amz-access-token: Atc|MQEBIBJdjkJB61bTZfuJFnYRUlR_r................. x-amz-security-token: FwoGZXIvYXdzEBcaDHW1hA9oeLfXdtjWuSKwAZd3vLX2IflV............... x-amz-date: 20220315T212106Z Connection: close
the other makes a successful call. I spent my time researching it in order to help
I see the library add x-amz-security-token header and to use this we need to call STS with roleRTN .
But @jmawebtech he don't mention this header in the code
Yes, you need that header. GetAccessTokenForSPAPIMigration generates an access token used for the x-amz-security-token header. In the Amazon console, go to edit app. Enter SPI and MWS as the types.
Now its should work with last version because I get this error , error mean app not published { "errors": [ { "code": "InvalidInput", "message": "A published application with the provided app-id not found", "details": "" } ] }
Please @jmawebtech and @nafberger try also from your side
If you get that message than your code works. Inside the app listing select mws and sp api as the type. Under developer ID enter the developer ID for each region where you have an account. Amazon must publish for these to take affect.
Sent via the Samsung Galaxy S10e, an AT&T 5G Evolution capable smartphone Get Outlook for Androidhttps://aka.ms/AAb9ysg
From: Tareq Abuzuhri @.> Sent: Wednesday, March 16, 2022 7:00:09 PM To: abuzuhri/Amazon-SP-API-CSharp @.> Cc: JMA Web Technologies @.>; Mention @.> Subject: Re: [abuzuhri/Amazon-SP-API-CSharp] Migrate users from MWS to SP API (Issue #123)
Please @jmawebtechhttps://github.com/jmawebtech and @nafbergerhttps://github.com/nafberger try also from your side
— Reply to this email directly, view it on GitHubhttps://github.com/abuzuhri/Amazon-SP-API-CSharp/issues/123#issuecomment-1069723643, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AAM2E6JU2L63SW4OHJVGOATVAJRXTANCNFSM5PKT3QXA. Triage notifications on the go with GitHub Mobile for iOShttps://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Androidhttps://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub. You are receiving this because you were mentioned.Message ID: @.***>
Then it's work :) I will close the bug
thanks @abuzuhri @jmawebtech, both parts are working, but u need to change the GetAccessTokenFromCodeAsync method and put "grant_type":"authorization_code", not "client_credentials", because with client_credentials u get only an access token, with authorization_code you get back both, an access token and a refresh token, and that's the correct way as in the documentations.
see picture
Hi @abuzuhri - This is the area that seems to be broken when trying to migrate MSW users to SPAPI. It appears there was a commit that solved this maybe at one point that got rolled back?
https://github.com/abuzuhri/Amazon-SP-API-CSharp/commit/94ef5ea5e039a84bbfe1f7110c4b4a67e0de7a02
I think the problem is here:
public static async Task
Where GetAccessTokenFromCodeAsync is not changing grant_type to authorization_code
I tried to create a branch and PR for the change, but I don't have access (I am not to familiar with doing PRs in GitHub).
My suggested change is this:
public async Task<TokenResponse> GetAccessTokenFromCodeAsync(string code, string appRedirectUri)
{
return await TokenGeneration.GetAccessTokenFromCodeAsync(AmazonCredential.ClientId, AmazonCredential.ClientSecret, code, appRedirectUri);
}
public async Task<TokenResponse> GetRrefreshTokenFromCodeAsync(string code, string appRedirectUri)
{
return await TokenGeneration.GetAccessTokenFromCodeAsync(AmazonCredential.ClientId, AmazonCredential.ClientSecret, code, appRedirectUri, grant_type: "authorization_code");
}
public static async Task<TokenResponse> GetAccessTokenFromCodeAsync(string clientId, string clientSecret, string code, string appRedirectUri)
{
return await TokenGeneration.GetAccessTokenFromCodeAsync(clientId, clientSecret, code, appRedirectUri);
}
public static async Task<TokenResponse> GetRefreshTokenFromCodeAsync(string clientId, string clientSecret, string code, string appRedirectUri)
{
return await TokenGeneration.GetAccessTokenFromCodeAsync(clientId, clientSecret, code, appRedirectUri, grant_type: "authorization_code");
}
Have managed to create a PR (I think I have done it right): https://github.com/abuzuhri/Amazon-SP-API-CSharp/pull/255
If possible are you able to complete and make new packages?
Now merge and published, please share sample to add in read me
sorununuz çözüldü mü ben de aynı sorunla uğraşıyorum yardımcı olabilir misin
Hi,
I have users running on the MWS Amazon API:
https://docs.developer.amazonservices.com/en_US/dev_guide/index.html
I have a seller ID, marketplace ID, and an MWSAuthToken. How do I generate an access and refresh token from these fields? I tried this call, but it failed to work. Do you have logic?
https://sellingpartnerapi-na.amazon.com/authorization/v1/authorizationCode?sellingPartnerId=X&developerId=X&mwsAuthToken=X
{ "errors": [ { "message": "Access to requested resource is denied.", "code": "MissingAuthenticationToken" } ] }