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
580 stars 730 forks source link

Order Reports API Question! #1195

Closed AmericanY closed 2 years ago

AmericanY commented 3 years ago

Hello,

I've been struggling for 2 days with the following orders-api

image

Where i keep getting

You exceeded your quota for the requested resource.

This is a part of my Python code:

timeout = cycle(list(range(5, 65, 5)))
def get_orders(authdata, access):
    params = {
        'MarketplaceIds': marketplaceId,
        'CreatedAfter': '2021-04-07T00:00:00',
        'OrderStatuses': 'Shipped,Unshipped',
    }
    with requests.Session() as req:
        req.auth = authdata
        req.headers.update({
            'x-amz-access-token': access
        })
        while True:
            r = req.get(
                'https://sellingpartnerapi-na.amazon.com/orders/v0/orders/', params=params)

            if r.status_code != 200:
                tout = next(timeout)
                print('Sleeping For {} Seconds, Reason: {}'.format(
                    tout, r.json()['errors'][0]['message']))
                sleep(tout)
                continue

            mykey = r.json()['payload']
            for order in mykey['Orders']:
                if order['OrderStatus'] in ['Shipped', 'Unshipped']:
                    yield order['AmazonOrderId'], order['PurchaseDate'], order['OrderTotal']['Amount'], order['OrderStatus']
                else:
                    print(order['OrderStatus'])
            try:
                req.params.update(
                    {'NextToken': mykey['NextToken']})
            except KeyError:
                break

imagine that i need to repeat the same circle for calling getOrders to get the list of orders and then calling getOrderBuyerInfo for each order# to get the buyer email and name. then calling getOrderAddress to get the address associated with the order and finally calling getOrderItems to getASN, SKU, ITEM Name

And i couldn't understand the reason, and what is Burst mean here as I've limit my requests for 1 request per second and even increased it. i did found a solution where i keep increment the sleep timeout to avoid API block but that's will really take too long time .

image

After reading some other issues, i see many recommendation for the Order-Reports

My target is to get all Shipped/Unshipped orders information such as the following:

It's ok if there's some info not available.

First Name, Last Name, Address, City, State, Phone, Email, Order Date, Price, ASIN Number, SKU# , Quantity ordered, SubTotal, Tax, Item Total.

After checking the Orders-Report, it's mentioned that i can get Shipped/Unshipped orders. but i don't understand for which period it's will be ?

Also i tried to call it.

I got the following error:

{'code': 'Unauthorized', 'message': 'Access to the resource is forbidden', 'details': ''}
AmericanY commented 3 years ago

@stefnats hopefully i didn't missed any info.

AmericanY commented 3 years ago

is there any specific Role which i need to give access for it ?

AmericanY commented 3 years ago

Ticket# ID8199928671

AmericanY commented 3 years ago

Here's all my configurations:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "execute-api:Invoke",
            "Resource": "arn:aws:execute-api:*:*:*"
        }
    ]
}

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::760040966547:root"
      },
      "Action": "sts:AssumeRole",
      "Condition": {}
    }
  ]
}

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": "sts:AssumeRole",
            "Resource": "arn:aws:iam::760040966547:role/MyRole"
        }
    ]
}
rugved1991 commented 3 years ago

Hi @AmericanY,

I checked your applications and I can confirm you have the right permissions associated with the application. You have added the "Inventory and Order Management" role to the app. I noticed you have configured IAM Role on the applications. The IAM permissions you mentioned in the thread look correct. Can you confirm if you are calling the AssumeRole operation first and then using the temporary credentials to calculate the AWS Signature?

Thanks, Rugved Solutions Architect, SP API

AmericanY commented 3 years ago

@rugved1991 Hi Rugved, Thanks for following up. Yes! i confirm that am able to call STS before calling the reports API. The strange point here that am able to communicate with orders-API but not with Reports!

AmericanY commented 3 years ago

@rugved1991 Hello Rugved, i still waiting for your reply.

My Code:

import boto3
import httpx
import trio
from SecureData import *
from httpx_auth import AWS4Auth
from pprint import pprint as pp

async def gettoken():
    async with httpx.AsyncClient(timeout=None) as client:
        data = {
            'grant_type': 'refresh_token',
            'refresh_token': Refresh_Token,
            'client_id': Client_Id,
            'client_secret': Client_Secret
        }
        r = await client.post('https://api.amazon.com/auth/o2/token', data=data)
        return r.json()['access_token']

async def requiredAuth():
    return list(boto3.client(
        'sts',
        aws_access_key_id=AWS_Id,
        aws_secret_access_key=AWS_Secret,
        region_name=Region_Name
    ).assume_role(RoleArn=Role_Arn, RoleSessionName=Role_Name)['Credentials'].values())

async def signreq(rauth):
    return AWS4Auth(
        service='execute-api',
        access_id=rauth[0],
        secret_key=rauth[1],
        security_token=rauth[2],
        region=Region_Name
    )

async def getReport(sdata, token):
    async with httpx.AsyncClient(timeout=None) as client:
        client.headers.update({
            "x-amz-access-token": token
        })
        r = await client.get('https://sellingpartnerapi-na.amazon.com/reports/2021-06-30/reports', auth=sdata)
        pp(r.json())
        print("*" * 20)
        pp(dict(r.headers))

async def main():
    rauth = await requiredAuth()
    sdata = await signreq(rauth)
    token = await gettoken()
    grep = await getReport(sdata, token)

if __name__ == "__main__":
    trio.run(main)

Output:

{'errors': [{'code': 'Unauthorized',
             'details': '',
             'message': 'Access to requested resource is denied.'}]}
********************
{'connection': 'keep-alive',
 'content-length': '141',
 'content-type': 'application/json',
 'date': 'Mon, 12 Apr 2021 06:27:54 GMT',
 'x-amz-apigw-id': 'dqFAqHqhoAMFTcw=',
 'x-amzn-errortype': 'AccessDeniedException',
 'x-amzn-requestid': 'eb73449c-3920-48b9-8a95-1695a85aef82'}
hinavinayak commented 3 years ago

Hi @AmericanY ,

Are you able to request the report w/ https://sellingpartnerapi-na.amazon.com/reports/2020-09-04/reports?

reports/2021-06-30/ is the upcoming change which will not need decryption of reports will become available in June.

AmericanY commented 3 years ago

@hinavinayak Just tried that out but am still getting Unauthorized MSG.

async def getReport(sdata, token):
    async with httpx.AsyncClient(timeout=None) as client:
        client.headers.update({"x-amz-access-token": token})
        params = {
            "reportTypes": "GET_FLAT_FILE_ORDER_REPORT_DATA_SHIPPING",
            "marketplaceIds": "ATVPDKIKX0DER"
        }
        r = await client.get('https://sellingpartnerapi-na.amazon.com/reports/2020-09-04/reports', auth=sdata, params=params)
        pp(r.json())
        print("*" * 20)
        pp(dict(r.headers))

Output:

{'errors': [{'code': 'Unauthorized',
             'details': '',
             'message': 'Access to the resource is forbidden'}]}
********************
{'connection': 'keep-alive',
 'content-length': '139',
 'content-type': 'application/json',
 'date': 'Thu, 15 Apr 2021 10:55:41 GMT',
 'x-amz-apigw-id': 'd0lDCGD7oAMFbbg=',
 'x-amzn-requestid': 'de73a6e3-57b6-4e71-ae02-1fc206fabd13',
 'x-amzn-trace-id': 'Root=1-60781bac-7e78acc411af6ed31b3634f4'}
rugved1991 commented 3 years ago

Hi @AmericanY,

You are calling "GET_FLAT_FILE_ORDER_REPORT_DATA_SHIPPING" report which requires access to restricted role "Direct-To-Consumer Shipping". Can you try calling one of the Order tracking reports?

Thanks, Rugved Solutions Architect, SP API

AmericanY commented 3 years ago

@rugved1991 i tried to call. but the response as the following:

{'payload': []}
rugved1991 commented 3 years ago

Hi @AmericanY,

Try calling the sandbox endpoint to make sure you are able to call the API successfully. Please use the sandbox behavior request details mentioned in the swagger model for the getReports operation.

Thanks, Rugved Solutions Architect, SP API

johnkw commented 3 years ago

Where is information on this "2021-06-30"? I haven't migrated off of MWS yet due to so many bugs. For example, does it fix bug amzn/selling-partner-api-models#722 ?

johnkw commented 3 years ago

As per bug amzn/selling-partner-api-models#1005 the "2021-06-30" is now available. This ticket should probably be closed as the original issue was regarding "2021-06-30" not being available yet.

github-actions[bot] commented 2 years ago

This is a very old issue that is probably not getting as much attention as it deserves. We encourage you to check if this is still an issue after the latest release and if you find that this is still a problem, please feel free to open a new issue and make a reference to this one.

MichalOrm commented 1 year ago

*bump...problem still exists. client is able to create report type GET_MERCHANT_LISTINGS_ALL_DATA, but calling GET_REFERRAL_FEE_PREVIEW_REPORT resulting with error

{
    "errors": [
        {
            "code": "Unauthorized",
            "message": "Access to the resource is forbidden",
            "details": ""
        }
    ]
}