amzn / selling-partner-api-models

This repository contains OpenAPI models for developers to use when developing software to call Selling Partner APIs.
Apache License 2.0
608 stars 731 forks source link

Selling Partner API Launch #690

Closed seanevan closed 3 years ago

seanevan commented 4 years ago

Hi all,

We have launched the ability for all developers to register for Selling Partner API!

You can get started by logging in to Seller Central and going to the App &Services -> Develop Apps menu. Once there, you will need to complete your Developer Profile if you have not done so previously, and you can then add a new application.

We're all excited to see what innovations you'll build using SP-API. Our support teams stand ready to assist you with this process - please don't hesitate to ask if you have any questions or concerns.

Best regards, Sean Evans Manager, Support Engineering

daapower commented 4 years ago

I'm trying to swap MWS tokens for the new Seller API tokens for my users

I have successfully registered a Hybrid application,

Did Steps 1-4 1.) got LWA token 2.) built selling partner API URI to the Authorization API 3.) added headers to the URI 4.) created authorization via Postman for AWS using IAM access key and secret from the "Create IAM user"

Using Postman, I'm getting the below error message. I'm assuming it is an issue with how my IAM policy is setup? I've been experimenting with it for a couple days now and can't figure it out. Is there a way to test the policy in the "Policy Simulator"?

Or a way to get a more detailed error message?

{ "errors": [ { "message": "Access to requested resource is denied.", "code": "Unauthorized", "details": "" } ] }

Thanks

Update: adding case ID: 7444932081

tanguy-r commented 4 years ago

@seanevan - I cannot see my existing app under App &Services -> Develop Apps menu How can I contact you to send you some confidential details so that you can look this up? Thank you!

seanevan commented 4 years ago

@daapower and @tanguy-r: Please contact our Developer Support team so we can pursue troubleshooting for the issues you've encountered.

deekay00 commented 4 years ago

Hello,

I am also trying to test out the new SP-API.

I am getting the same error response. { "errors": [ { "message": "Access to requested resource is denied.", "code": "Unauthorized", "details": "" } ] }

I am trying to test with PostMan and using the AWS Authentication feature from it. Here is what my request looks like:

GET /orders/v0/orders?MarketplaceIds=ATVPDKIKX0DER HTTP/1.1 Host: sellingpartnerapi-na.amazon.com x-amz-access-token: <access token from https://api.amazon.com/auth/o2/token response> x-amz-date: 20201004T025618Z Authorization: AWS4-HMAC-SHA256 Credential=/20201004/us-east-1/execute-api/aws4_request, SignedHeaders=host;x-amz-access-token;x-amz-date, Signature=ceeabe98cf1d22384ea4ea6b5b1220e4915724500ead2b47b6b1378fe69571d5

Any hints on what the error response might mean?

Thank you!!

EDIT: I have a case open 7453589751 if it helps anything. Looking forward to working with this API! Thanks!

ifulfilment commented 4 years ago

Hi,

@seanevan We also have an 'Access to requested resource is denied' error returned when using the Seller Partner API. We have exchanged the refresh token for an access token okay but can not access any of the endpoints using it ( for example search for products ).

We have triple check everything from the docs and created multiple apps/was users in order to check we haven't missed anything, is it possible something was missing from the documentation for the setup process?

An issue has also been raised as a case log (ID: 7460091481) but thought it might be helpful to also raise that is might be a bigger issue?

Thanks

tmyers273 commented 4 years ago

Just wanted to echo that we're running into a similar issue as @ifulfilment as well. We've triple checked everything a few times and get the very ambiguous "Access to requested resource is denied" for all our requests. Case log ID: 7450250381.

ahlmackie commented 4 years ago

seeing the same message "Access to requested resource is denied"

https://sellingpartnerapi-eu.amazon.com

tried different paths and the NA server too. As above double checked signing and its all ok

caseId 6386016452

seanevan commented 4 years ago

Hi all,

If you are receiving the "Access to requested resource is denied" message, please open a support case with our team so we can troubleshoot.

Thanks, Sean Evans Manager, Support Engineering

rodrigojob commented 4 years ago

You can get started by logging in to Seller Central and going to the App &Services -> Develop Apps menu. Once there, you will > need to complete your Developer Profile if you have not done so previously, and you can then add a new application.

Must to be Seller Central with site combo list in www.amazon.com , I EVER forgot this and have looking for the "Develop Apps" menu. https://sellercentral.amazon.com.br/sellingpartner/developerconsole/ref=xx_DevCon_dnav_xx

rodrigojob commented 4 years ago

@seanevan - I cannot see my existing app under App &Services -> Develop Apps menu How can I contact you to send you some confidential details so that you can look this up? Thank you!

Must to be Seller Central with site combo list in www.amazon.com ,

buzali commented 4 years ago

We are experiencing the same error.

@seanevan, we tried to contact support but all our tickets get rejected because our account appears deactivated. When we try to reactivate the account, but those messages also get rejected and we get an immediate response indicating that that inbox no longer receives messages.

It seems like our account gets deactivated after a period of time without any sales, but since this account is only intended for development purposes it won't have sales and we can get ahold of anyone that understands our situation.

I will appreciate if you can point me to someone that can help us resolve these issues in order to develop for your platform.

Thanks

statico commented 4 years ago

Same problem here, case ID 7482455361.

I can confirm that posting our app's refresh token to https://api.amazon.com/auth/o2/token gives us what appears to be a valid access token.

Requesting a GET to https://api.amazon.com/auth/o2/tokeninfo?access_token=Atza|xxxxx returns what appears to be a valid response, even though it's not used for anything. As a test, I changed a character in the access token and received an "invalid token" error. So the access token seems valid.

But every request to sellingpartnerapi-na.amazon.com returns { "message": "Access to requested resource is denied.", "code": "Unauthorized", "details": "" }. Even a GET to /. Changing anything else about the request results in errors or invalid signatures, so it must be in the guts of AWS internal permission resolution somewhere.

seanevan commented 4 years ago

Hi all,

Thanks to those of you who have provided details in support cases. Our support engineers will help diagnose via that channel.

@buzali, are you able to share a case number that was closed without action due to your account deactivation?

Best regards, Sean Evans Manager, Support Engineering

buzali commented 4 years ago

@seanevan the case number is 7469155131

gabrielpiassetta commented 4 years ago

I'm facing the same issue trying to call Selling Partner API.

{
  "errors": [
    {
      "message": "Access to requested resource is denied.",
      "code": "Unauthorized",
      "details": ""
    }
  ]
}

I can confirm that I have followed the SellingPartnerApiDeveloperGuide, twice. Always with the same error. I have used Insomnia and Postman AWS plugins to authenticate the iam:user

https://github.com/amzn/selling-partner-api-docs/blob/main/guides/developer-guide/SellingPartnerApiDeveloperGuide.md

charliecode commented 4 years ago

@seanevan In this issue I noticed you're directing people to contact developer support. I contacted developer support about an issue 1 week ago today and have yet to receive the customary reply from a support engineer which has been assigned to the case. Maybe it's just that wait times are long right now, just wanted to make sure my issue wasn't lost in the shuffle. Case ID 7469845851. Thanks a bunch.

daapower commented 4 years ago

I opened my case 14 days ago and support acknowledged the case and that's it. I'm wondering if anyone has been successful in calling it with a hybrid app

rcalv002 commented 4 years ago

We've also experienced problems trying to develop local integrations to pull down amazon seller data because so far, its required you to pay for a seller central account (that we will never use) just to be able to generate a developer account. Is that still the case for this new, very welcome, next-gen api with sandbox (finally) ? If not, what is the best path forward to start building integrations with AWS accounts to pull down order information? These are typically built and deployed as on site windows services so they would use the "self authorize" method described in the docs to bypass the entire oauth2 flow? What is the minimum needed to create a "hello world" style project against amazon seller api? Your direction on this would be greatly appreciated.

p-prins commented 4 years ago

We also receive the "Access to requested resource is denied." error. We opened a case with seller support and received the following case ID: 7498135001.

rogersv commented 4 years ago

I got the same error. Case ID 7506922381 I used the "self authorization" to get the refresh_token and used the sandbox-endpoints.

EDIT: I got it to work. The problem was that I missed that I needed to assume the role to get new credentials with a session-token. The call worked after I added the x-amz-security-token with the session-token in the header. I used boto3 for my test see https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/sts.html#STS.Client.assume_role

response = client.assume_role(
    RoleArn='my_role_added_in_the_app',
    RoleSessionName='guid'
)

The call above gave me an AccessKeyId, SecretAccessKey and SessionToken which I used in my call to the SP-API. In the call to /sellers/v1/marketplaceParticipations I used both x-amz-access-token and x-amz-security-token.

I could not see this information in the documentation. I hope this is a correct way to do this call.

deekay00 commented 4 years ago

the workaround in amzn/selling-partner-api-models#699 is working for me. I also registered a new FBA Developer App with my user ARN directly.

edit: using the self authorize option.

gabrielpiassetta commented 4 years ago

I can confirm @rogersv solution works for me.

GbalsaC commented 4 years ago

@rogersv solution worked for me as well, for those looking for a NodeJS implementation:

const https = require('https')
const aws4 = require('aws4')
const AWS = require('aws-sdk');

new aws_sdk.STS().assumeRole({
            RoleArn: 'arn:aws:iam::719...<Omitted role>', // One created in the guide during IAM step
            RoleSessionName: 'sp-api'
        }, function (err, data) {
            if (err) console.log(err, err.stack); // an error occurred
            else console.log(data);           // successful response
        })

/*
Successful response has this body
Credentials: {
    AccessKeyId: 'ASIA2.....',
    SecretAccessKey: 'GYarqdtY5......',
    SessionToken: 'FwoGZXIvYXdzEGMaDJZNgsGIkPg9CsIFcSKqAXztT9zQ...........',
    Expiration: 2020-10-23T02:22:58.000Z
  }

I use the data above to fill my next call
*/

function requestTest(opts) { https.request(opts, function (res) { res.pipe(process.stdout) }).end(opts.body || '') }

function makeTestCall() {
    const ss = aws4.sign({
        host: 'sellingpartnerapi-na.amazon.com',
        method: 'GET',
        path: '/orders/v0/orders?MarketplaceIds=ATVPDKIKX0DER&CreatedAfter=2020-05-10',
        region: 'us-east-1',
        service: 'execute-api',
        headers: {
            'User-Agent': 'Fiscalpop/2.0 (Language=JavaScript; Platform=Ubuntu/16)',
            'x-amz-access-token': 'Atza|IwEBIObmsjqIMdmeYDxdF-iA8979Mf0umKiaiOyL9yd6oQBWmPEkT9tZ9YAl3eA39FRkWOxS_1IENwi8Ni-5uxBPGxLlJ8OKsYYhqAKriK3pFVCuQanLXFuBTcrKBxFhD0ilxufrCQm0F7UwoBIUxFptEf0n3zx-KIXbumCEQDc0Q7yca4Rpv1WpE9PxKwrO2cup-V4IPax-mEUnTjMOLnVgc-6ChryyMHvb63zcGlBr_VQ2I-IgEm-UMTTvt9t-HIbKRL68Hk7WAqoZ42pBlvULHEfbWwbV2ZWaUu_n_zb8uh1QUGBdPsGxsxsHnV58dYf3f9zs3BNO3BbUpOssYF91qPyH'

        }
    }, { 
        accessKeyId: 'ASIA2PIENJRBJJ...<omitted the rest>', 
        secretAccessKey: 'GYarqdtY59cbKSoTS9bnIc...<omitted the rest>', 
        sessionToken: 'FwoGZXIvYXdzEGMaDJZNgsGIkPg9CsIFcSKqAXztT9....<omitted the rest>' 
    })
    console.log(ss);
    return ss;
}

Finally received successful response like:

{
  "payload": {
            "CreatedBefore": "2020-10-23T01:27:28Z",
             "Orders" : []
      }
}
rcalv002 commented 4 years ago

We've also experienced problems trying to develop local integrations to pull down amazon seller data because so far, its required you to pay for a seller central account (that we will never use) just to be able to generate a developer account. Is that still the case for this new, very welcome, next-gen api with sandbox (finally) ? If not, what is the best path forward to start building integrations with AWS accounts to pull down order information? These are typically built and deployed as on site windows services so they would use the "self authorize" method described in the docs to bypass the entire oauth2 flow? What is the minimum needed to create a "hello world" style project against amazon seller api? Your direction on this would be greatly appreciated.

Can anyone comment on the process for a new developer to get api keys to _start developing_ ?

chenlixin93 commented 4 years ago

I got the same error. Case ID 7535046551

etc-chmod commented 4 years ago

I got it to work. The problem was that I missed that I needed to assume the role to get new credentials with a session-token. The call worked after I added the x-amz-security-token with the session-token in the header. I used boto3 for my test see https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/sts.html#STS.Client.assume_role

response = client.assume_role(
    RoleArn='my_role_added_in_the_app',
    RoleSessionName='guid'
)

The call above gave me an AccessKeyId, SecretAccessKey and SessionToken which I used in my call to the SP-API. In the call to /sellers/v1/marketplaceParticipations I used both x-amz-access-token and x-amz-security-token.

I could not see this information in the documentation. I hope this is a correct way to do this call.

@rogersv - I cannot thank you enough!! Tried for many hours to get this to work and your comment was the breakthrough.

Maybe it is useful for fellow python developers to add that the resulting 'SessionToken' is assigned to the x-amz-security-token and while the x-amz-security-token is added to the header, it is not added to the canonical_request.

Also, for python programmers: I built my access based on the GET-example for python in the AWS Signing documentation.

etc-chmod commented 3 years ago

Hi all,

We have launched the ability for all developers to register for Selling Partner API!

You can get started by logging in to Seller Central and going to the App &Services -> Develop Apps menu. Once there, you will need to complete your Developer Profile if you have not done so previously, and you can then add a new application.

We're all excited to see what innovations you'll build using SP-API. Our support teams stand ready to assist you with this process - please don't hesitate to ask if you have any questions or concerns.

Best regards, Sean Evans Manager, Support Engineering

Hello @seanevan ,

as a seller and developer based in Germany I am unable to open a support ticket via the support links you provide here. It seems that the support only allows questions by developers or sellers with an account registered in the US. Am I missing something here or how do I open a SP-API support ticket in Germany so that it actually reaches someone in the SP-API team.

Kind regards, Felix

PS: I try to get support for issue amzn/selling-partner-api-models#758

rogersv commented 3 years ago

A really ugly solution is to login to your seller account and select germany in the drop-down. Copy the query parameters and then add them to the url for the US page for support form. You will then see the support form for your market. I could not find a real link that works.

etc-chmod commented 3 years ago

@rogersv Thank you so much (again) Roger! It works.

So for everybody else out there from Germany - in order to open a sp-api support ticket with amazon, you can use the following link to German sp-api and mws support.

vdanyliv commented 3 years ago

If someone interested in a quick guide on how to register as a developer and create your first amazon application, take a look at my article on medium https://medium.com/@vdanyliv/amazon-selling-partner-api-spa-how-to-quickly-and-simply-integrate-with-new-api-part-1-c3ca05a91b43

educatornum commented 3 years ago

Screen Shot 2020-11-17 at 9 11 27 Screen Shot 2020-11-17 at 9 16 04

Same error.

I found a refresh token but I have this problem, How can I fix it?

[](https://sellingpartnerapi-fe.amazon.com/sellers /v1/marketplaceParticipations?marketplace=A1VC38T7YXB528)

{
    "errors": [
        {
            "message": "Access to requested resource is denied.",
            "code": "Unauthorized",
            "details": ""
        }
    ]
}
ericblade commented 3 years ago

This sounds to me like a fairly serious problem in the documentation -- either we need to be able to configure the IAM settings in such a fashion that we don't need to have a full AWS SDK forcing us to call STS and AssumeRole, or the documentation needs to be updated to say that you DO need to call STS and AssumeRole.

@seanevan .. or anyone else who's better versed in AWS than I am (i haven't touched it in a few years now, so what I did know is very outdated and rusty).. are you able to comment on this ?

ionafan2 commented 3 years ago

Hi @rogersv can you help a PHP folk?


require '../vendor/autoload.php';

use Aws\Signature\SignatureV4;
use Aws\Credentials\Credentials;
use GuzzleHttp\Client;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Handler\CurlHandler;
use Aws\Sts\StsClient;

$options = [
    'region' => 'us-east-1',
    'service' => 'execute-api',
    'aws_user_key' => 'AKIAXXXXXXXXXXX',
    'aws_user_secret' => '9KnrxHQ2ki9KnrxP0KnXXXXXXXXXXXX',
    'app_client_id' => 'amzn1.application-oa2-client.XXXXXXXXXXXXXXXX',
    'app_client_secret' => '248157ab9aaa4d7e55e4895XXXXXXXXXXXXXX',
];

$credentials = new Credentials(
    $options['aws_user_key'],
    $options['aws_user_secret']
);

$sts = new StsClient([
    'region' => $options['region'],
    'version' => '2011-06-15',
    'credentials' => $credentials
]);

$stsResult = $sts->assumeRole([
    'RoleArn' => 'arn:aws:iam::XXXXXXX:role/SellingPartnerAPIRole',
    'RoleSessionName' => 'sp-api'
]);

$credentialsRes = $stsResult->get('Credentials');

//$credentialsRes['AccessKeyId'];
//$credentialsRes['SecretAccessKey'];
//$credentialsRes['SessionToken'];

$signatureV4 = new SignatureV4(
    $options['service'],
    $options['region']
);

$handler = new CurlHandler();
$stack = HandlerStack::create($handler);

// Widdleware to sign each request
$stack->push(
    \GuzzleHttp\Middleware::mapRequest(
        function (\Psr\Http\Message\RequestInterface $request) use ($signatureV4, $credentials) {
            $request = $signatureV4->signRequest($request, $credentials);
            return $request;
        }
    )
);

$client = new Client([
    'handler' => $stack,
    'base_uri' => 'https://api.amazon.com'
]);

$response = $client->post(
    '/auth/o2/token',
    [
        'Content-Type' => 'application/x-www-form-urlencoded',
        'User-Agent' => 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)',
        'form_params' => [
            'grant_type' => 'refresh_token',
            'refresh_token' => 'Atzr|IwEBIAlMkYGL4Ui2EJMu8ZgX...',
            'client_id' => $options['app_client_id'],
            'client_secret' => $options['app_client_secret'],
        ]
    ]
);

$resultData = json_decode($response->getBody()->getContents());

//$resultData->access_token;

$client = new Client([
    'handler' => $stack,
    'base_uri' => 'https://sellingpartnerapi-na.amazon.com',
    'debug' => true
]);

$response = $client->get(
    '/orders/v0/orders',
    [
        'Content-Type' => 'application/json',
        'User-Agent' => 'BCP/5.0 (Macintosh; Intel Mac OS X 10_15_7)',
        'query' => ['MarketplaceId' => 'ATVPDKIKX0DER'],
        'x-amz-access-token' => $resultData->access_token,
        'x-amz-security-token' => $credentialsRes['SessionToken']
    ]
);

I did as you. I Received an AccessKeyId, SecretAccessKey and SessionToken which I used in my call to the SP-API. But it didn’t work out.

"message": "The security token included in the request is invalid",
rogersv commented 3 years ago

It looks like you have the wrong credentials sent to the middleware. You need to use the role credentials that you got in a previous step.

p-prins commented 3 years ago

@ericblade thank you for raising this question. I can successfully authenticate without STS by granting the user permission to use the policy. Hence, it might not be necessary to use STS. However, I'm working in the sandbox environment and I'm uncertain whether there are any negative consequences of using the user permission approach in production. I opened a new issue to discuss this: amzn/selling-partner-api-models#786.

ionafan2 commented 3 years ago

It looks like you have the wrong credentials sent to the middleware. You need to use the role credentials that you got in a previous step.

Hi @rogersv and thanks for fast reply. You right. It's working now! Here is fully working solution. I also tested it in Postman. BTW x-amz-access-token IS case-sensitive. I spent about 2 hours before I figured that out. It was funny, the server responded Access token is missing in the request header. anyway. Hopes this is saved someone's time.

<?php

require '../vendor/autoload.php';

use Aws\Signature\SignatureV4;
use Aws\Credentials\Credentials;
use GuzzleHttp\Client;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Handler\CurlHandler;
use Aws\Sts\StsClient;

$options = [
    'region' => 'us-east-1',
    'service' => 'execute-api',
    'aws_user_key' => 'xxxxx', 
    'aws_user_secret' => 'xxxxxxxx',
    'app_client_id' => 'amzn1.application-oa2-client.xxxxxxxxxxxx',
    'app_client_secret' => 'xxxxxxxxxxxx',
];

$stsClient = new StsClient([
    'region' => $options['region'],
    'version' => '2011-06-15',
    'credentials' => new Credentials(
        $options['aws_user_key'],
        $options['aws_user_secret']
    )
]);

$stsResult = $stsClient->assumeRole([
    'RoleArn' => 'arn:aws:iam::xxxxxxxxxx:role/SellingPartnerAPIRole',
    'RoleSessionName' => 'api-session'
]);

$credentialsRes = $stsResult->get('Credentials');

//$credentialsRes has 'AccessKeyId', 'SecretAccessKey'and 'SessionToken'

$credentials = new Credentials(
    $credentialsRes['AccessKeyId'],
    $credentialsRes['SecretAccessKey'],
    $credentialsRes['SessionToken']
);

$signatureV4 = new SignatureV4($options['service'], $options['region']);

$handler = new CurlHandler();
$stack = HandlerStack::create($handler);
$stack->push(
    \GuzzleHttp\Middleware::mapRequest(
        function (\Psr\Http\Message\RequestInterface $request) use ($signatureV4, $credentials) {
            return $signatureV4->signRequest($request, $credentials);
        }
    )
);

$client = new Client([
    'handler' => $stack,
    'base_uri' => 'https://api.amazon.com',
    'debug' => true,
]);

$response = $client->request(
    'POST',
    '/auth/o2/token',
    [
        'headers' => [
            'Content-Type' => 'application/x-www-form-urlencoded',
        ],
        'form_params' => [
            'grant_type' => 'refresh_token',
            'refresh_token' => 'Atzr|IwEBIAf43U18I3GsHyV.....',
            'client_id' => $options['app_client_id'],
            'client_secret' => $options['app_client_secret'],
        ]
    ]
);

$resultData = json_decode($response->getBody()->getContents());

//$resultData->access_token;

$client = new Client([
    'handler' => $stack,
    'base_uri' => 'https://sellingpartnerapi-na.amazon.com',
    'debug' => true
]);

$response = $client->request(
    'GET',
    '/orders/v0/orders',
    [
        'query' => [
            'MarketplaceIds' => 'ATVPDKIKX0DER',
            'CreatedAfter' => '2020-11-19'
        ],
        'headers' => [
            'x-amz-access-token' => $resultData->access_token,
        ]
    ]
);

$resultData = json_decode($response->getBody()->getContents());
var_dump($resultData);
zhanglaoye commented 3 years ago

@ionafan2 Hello, can you send me the address of the aws toolkit? Thank you

ionafan2 commented 3 years ago

@zhanfjunjun You can install them by composer

"guzzlehttp/guzzle": "^6.4",
"aws/aws-sdk-php": "^3.163"
zhanglaoye commented 3 years ago

@ionafan2 Great, thank you

ionafan2 commented 3 years ago

@zhanfjunjun If you need more information on how to connect to SP API with PHP, go here https://github.com/staysmartway/amazon-sp-api-php I forked clousale/amazon-sp-api-php. I'll add signature request in my fork so it should be the best working solution for PHP as of today. And very welcome to contribute off course! It also would be cool to add a Symphony Bundle on top of it.

nicolasheady commented 3 years ago

I'm getting the same error:

{ message: 'Access to requested resource is denied.', code: 'Unauthorized', details: '' }

I'm going to try the NodeJS solution by @GbalsaC but I'm curious to hear the official ruling on this - does documentation need to be changed or some IAM role/policy setting?

hpehpe commented 3 years ago

I got the same error. Case ID 7506922381 I used the "self authorization" to get the refresh_token and used the sandbox-endpoints.

EDIT: I got it to work. The problem was that I missed that I needed to assume the role to get new credentials with a session-token. The call worked after I added the x-amz-security-token with the session-token in the header. I used boto3 for my test see https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/sts.html#STS.Client.assume_role

response = client.assume_role(
    RoleArn='my_role_added_in_the_app',
    RoleSessionName='guid'
)

The call above gave me an AccessKeyId, SecretAccessKey and SessionToken which I used in my call to the SP-API. In the call to /sellers/v1/marketplaceParticipations I used both x-amz-access-token and x-amz-security-token.

I could not see this information in the documentation. I hope this is a correct way to do this call.

Hi, awesome that you made it work. My problem is that I try to test the sandbox in Postman and I get the error there. I have no idea how to assume_role in Postman...

I might have to skip Postman and go directly for code...

zhanglaoye commented 3 years ago

@ionafan2 Hello, I have used this toolkit. It has helped me a lot. In the process of using it, I found that this package lacks some information, such as upload-api. May I ask, can this be completed?

ionafan2 commented 3 years ago

@zhanfjunjun I guess you just need to generate your own PHP library with swagger-codegen if you are not satisfied with someone else. Here is about swagger-codgen. Then run somthing like this java -jar swagger-codegen-cli-2.2.1.jar generate -l php -c swager-config.json -i amzn/selling-partner-api-models/models/uploads-api-model/uploads_2020-11-01.json and it will do magic for you. Don’t forget to set up your own swager-config.json. Here is an example:

{
  "composerVendorName": "zhanfjunjun",
  "composerProjectName": "amazon-sp-api-php",
  "packagePath": ".",
  "invokerPackage": "Your\\Namespase",
  "modelPackage": "Your\\Namespase\\Model",
  "apiPackage": "Your\\Namespase\\Api"
}

It's not a full solution but a good starting point. After code generation, I override ApiClient and re-implemented public function callApi so inside there I use \GuzzleHttp\Client and do http requests by it.
I found \GuzzleHttp\Client useful because I set up request signing as middleware so now each request is signed. In a code example above you can see how I did it. Good luck!

educatornum commented 3 years ago

I got the same error. Case ID 7506922381 I used the "self authorization" to get the refresh_token and used the sandbox-endpoints.

EDIT: I got it to work. The problem was that I missed that I needed to assume the role to get new credentials with a session-token. The call worked after I added the x-amz-security-token with the session-token in the header. I used boto3 for my test see https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/sts.html#STS.Client.assume_role

response = client.assume_role(
    RoleArn='my_role_added_in_the_app',
    RoleSessionName='guid'
)

The call above gave me an AccessKeyId, SecretAccessKey and SessionToken which I used in my call to the SP-API. In the call to /sellers/v1/marketplaceParticipations I used both x-amz-access-token and x-amz-security-token.

I could not see this information in the documentation. I hope this is a correct way to do this call.

@rogersv Thank you for the sharing, I'm a newbie Could you share some example python script? I got a Credentials with boto3 but on the next call, I don't have any idea. Could you help me?

noor-mohmmad commented 3 years ago

facing this issue during generating access-token from $response = $client->request( 'POST', '/auth/o2/token', [ 'headers' => [ 'Content-Type' => 'application/x-www-form-urlencoded', ], 'form_params' => [ 'grant_type' => 'refresh_token', 'refresh_token' => 'Atzr|IwEBIAf43U18I3GsHyV.....', 'client_id' => $options['app_client_id'], 'client_secret' => $options['app_client_secret'], ] ] );

Fatal error: Uncaught GuzzleHttp\Exception\ClientException: Client error: POST https://sellingpartnerapi-na.amazon.com/auth/o2/token resulted in a 403 Forbidden response: { "errors": [ { "message": "Access to requested resource is denied.", "code": "Unauthorized", "det (truncated...) in /Users/noormohmmad/Sites/AmzSalesReport/lib/Uploads/vendor/guzzlehttp/guzzle/src/Exception/RequestException.php:113 Stack trace:

noor-mohmmad commented 3 years ago

@ionafan2

facing this issue during generating access-token from $response = $client->request( 'POST', '/auth/o2/token', [ 'headers' => [ 'Content-Type' => 'application/x-www-form-urlencoded', ], 'form_params' => [ 'grant_type' => 'refresh_token', 'refresh_token' => 'Atzr|IwEBIAf43U18I3GsHyV.....', 'client_id' => $options['app_client_id'], 'client_secret' => $options['app_client_secret'], ] ] );

Fatal error: Uncaught GuzzleHttp\Exception\ClientException: Client error: POST https://sellingpartnerapi-na.amazon.com/auth/o2/token resulted in a 403 Forbidden response: { "errors": [ { "message": "Access to requested resource is denied.", "code": "Unauthorized", "det (truncated...) in /Users/noormohmmad/Sites/AmzSalesReport/lib/Uploads/vendor/guzzlehttp/guzzle/src/Exception/RequestException.php:113 Stack trace:

tharrington commented 3 years ago

It looks like you have the wrong credentials sent to the middleware. You need to use the role credentials that you got in a previous step.

Hi @rogersv and thanks for fast reply. You right. It's working now! Here is fully working solution. I also tested it in Postman. BTW x-amz-access-token IS case-sensitive. I spent about 2 hours before I figured that out. It was funny, the server responded Access token is missing in the request header. anyway. Hopes this is saved someone's time.

<?php

require '../vendor/autoload.php';

use Aws\Signature\SignatureV4;
use Aws\Credentials\Credentials;
use GuzzleHttp\Client;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Handler\CurlHandler;
use Aws\Sts\StsClient;

$options = [
    'region' => 'us-east-1',
    'service' => 'execute-api',
    'aws_user_key' => 'xxxxx', 
    'aws_user_secret' => 'xxxxxxxx',
    'app_client_id' => 'amzn1.application-oa2-client.xxxxxxxxxxxx',
    'app_client_secret' => 'xxxxxxxxxxxx',
];

$stsClient = new StsClient([
    'region' => $options['region'],
    'version' => '2011-06-15',
    'credentials' => new Credentials(
        $options['aws_user_key'],
        $options['aws_user_secret']
    )
]);

$stsResult = $stsClient->assumeRole([
    'RoleArn' => 'arn:aws:iam::xxxxxxxxxx:role/SellingPartnerAPIRole',
    'RoleSessionName' => 'api-session'
]);

$credentialsRes = $stsResult->get('Credentials');

//$credentialsRes has 'AccessKeyId', 'SecretAccessKey'and 'SessionToken'

$credentials = new Credentials(
    $credentialsRes['AccessKeyId'],
    $credentialsRes['SecretAccessKey'],
    $credentialsRes['SessionToken']
);

$signatureV4 = new SignatureV4($options['service'], $options['region']);

$handler = new CurlHandler();
$stack = HandlerStack::create($handler);
$stack->push(
    \GuzzleHttp\Middleware::mapRequest(
        function (\Psr\Http\Message\RequestInterface $request) use ($signatureV4, $credentials) {
            return $signatureV4->signRequest($request, $credentials);
        }
    )
);

$client = new Client([
    'handler' => $stack,
    'base_uri' => 'https://api.amazon.com',
    'debug' => true,
]);

$response = $client->request(
    'POST',
    '/auth/o2/token',
    [
        'headers' => [
            'Content-Type' => 'application/x-www-form-urlencoded',
        ],
        'form_params' => [
            'grant_type' => 'refresh_token',
            'refresh_token' => 'Atzr|IwEBIAf43U18I3GsHyV.....',
            'client_id' => $options['app_client_id'],
            'client_secret' => $options['app_client_secret'],
        ]
    ]
);

$resultData = json_decode($response->getBody()->getContents());

//$resultData->access_token;

$client = new Client([
    'handler' => $stack,
    'base_uri' => 'https://sellingpartnerapi-na.amazon.com',
    'debug' => true
]);

$response = $client->request(
    'GET',
    '/orders/v0/orders',
    [
        'query' => [
            'MarketplaceIds' => 'ATVPDKIKX0DER',
            'CreatedAfter' => '2020-11-19'
        ],
        'headers' => [
            'x-amz-access-token' => $resultData->access_token,
        ]
    ]
);

$resultData = json_decode($response->getBody()->getContents());
var_dump($resultData);

@ionafan2 How did you get this working in Postman? Is there a way to mimic the "Assume Role" functionality?

wanghuoling commented 3 years ago

@ionafan2 Use your code,I've replaced the parameters with my own:options ,RoleArn,refresh_token . I received error message: { "errors": [ { "message": "Access to requested resource is denied.", "code": "Unauthorized", "det (truncated...) }

GuzzleHttp's log:

GET /orders/v0/orders?MarketplaceIds=ATVPDKIKX0DER&CreatedAfter=2020-11-19 HTTP/1.1 Host: sellingpartnerapi-na.amazon.com User-Agent: GuzzleHttp/7 x-amz-access-token: Atza|Ixxxxxxxxx X-Amz-Date: 20201202T075815Z X-Amz-Security-Token: FwoGZXIvYXdzECkaDCQixf31xxxxxxxxx Authorization: AWS4-HMAC-SHA256 Credential=ASIAWJHHNZDNDLVN6EP4/20201202/us-east-1/execute-api/aws4_request, SignedHeaders=host;x-amz-access-token;x-amz-date;x-amz-security-token, Signature=3e7a8c4d332523c4cf3d0da04f228074bba97b9b95f8aee859efa0c6fc8b7df3

then in the document "SellingPartnerApiDeveloperGuide.md" ,"SignedHeaders" field include user-agent. But run your code ,it is not include user-agent. Why? Finally, I want ask,occur this error,what 's main reason for this ? Hope attain your help,thanks a lot.

ionafan2 commented 3 years ago

@wanghuoling

  1. Setup AWS User/Role, and you got these: aws_user_key, aws_user_secret, RoleArn
  2. Setup SP Application, and you got these: app_client_id, app_client_secret
  3. Authorize your Application by Website workflow or Self Authorization
  4. Assume role with RoleArn, and you got CredentialsForSignature
  5. Setup Request Signing using CredentialsForSignature (Each time you sign you need to assume role first.)
  6. (sign it) Request access_token using refresf_token from Self Authorization or authorization_code from Website workflow
  7. (sign it) Do API Call using access_token

But run your code ,it is not include user-agent.

It does by GuzzleHttp eventually. I don’t why you don’t see it

x-amz-access-token: Atza|Ixxxxxxxxx

Make sure your access token from step 4 in my list