Amazon SP-API Listings接口调用失败(403错误)求助
以下是针对你遇到的问题的排查和解决步骤:
1. 检查SP-API应用权限配置
你能成功调用sellers/v1/marketplaceParticipations接口,说明IAM角色的基础权限和LWA令牌的获取流程是正常的,但Listings接口需要额外的权限授权:
- 登录亚马逊开发者后台,找到你的SP-API应用,确认已申请并获批
Listings Items相关权限(具体为listings_items:read)。 - 如果是刚更新的权限,需要重新生成刷新令牌(refresh_token),旧令牌不会自动包含新增的权限。
2. 修正AWS区域参数
你的代码中使用的region是eu-north-1,但欧盟区域的SP-API对应的正确AWS签名区域是eu-west-1,区域不匹配会导致SigV4签名验证失败,进而返回403错误。修改代码中的区域参数:
# 原代码 region = 'eu-north-1' # 修改为 region = 'eu-west-1'
3. 验证请求参数完整性
Listings 2020-09-01版本的items接口,若你的IAM角色关联了多个卖家账户,需要额外指定sellerId参数,确保参数与目标店铺信息匹配:
params = { 'marketplaceIds': marketplace_ids, 'sellerId': '你的卖家账户ID' # 单账户场景可省略,多账户场景必须添加 }
你的错误日志:
Assumed IAM role successfully. Obtained LWA access token successfully. 403 Forbidden error. Response details: { "errors": [ { "code": "Unauthorized", "message": "Access to requested resource is denied.", "details": "" } ] } HTTP error occurred: 403 Client Error: for url: https://sellingpartnerapi-eu.amazon.com/listings/2020-09-01/items?marketplaceIds=A1PA6795UKMFR9
你的代码:
import boto3 import requests import json from requests.auth import AuthBase from aws_requests_auth.aws_auth import AWSRequestsAuth from botocore.exceptions import NoCredentialsError, PartialCredentialsError # Load credentials from JSON file with open('amazon_creds.json', 'r') as f: creds = json.load(f) # Assume IAM Role def assume_role(role_arn, aws_access_key, aws_secret_key): sts_client = boto3.client('sts', aws_access_key_id=aws_access_key, aws_secret_access_key=aws_secret_key) assumed_role_object = sts_client.assume_role( RoleArn=role_arn, RoleSessionName="AssumeRoleSession1" ) return assumed_role_object['Credentials'] # Get LWA Access Token def get_lwa_access_token(client_id, client_secret, refresh_token): url = "https://api.amazon.com/auth/o2/token" params = { 'grant_type': 'refresh_token', 'refresh_token': refresh_token, 'client_id': client_id, 'client_secret': client_secret } response = requests.post(url, data=params) response.raise_for_status() # Raise an error for bad status codes return response.json()['access_token'] # Custom Auth Class for AWS SigV4 class AWSV4Auth(AuthBase): def __init__(self, aws_access_key, aws_secret_access_key, aws_session_token, region, service): self.aws_access_key = aws_access_key self.aws_secret_access_key = aws_secret_access_key self.aws_session_token = aws_session_token self.region = region self.service = service def __call__(self, r): auth = AWSRequestsAuth( aws_access_key=self.aws_access_key, aws_secret_access_key=self.aws_secret_access_key, aws_token=self.aws_session_token, aws_host='sellingpartnerapi-eu.amazon.com', aws_region=self.region, aws_service=self.service ) return auth(r) # Make API Request def make_sp_api_request(credentials, access_token, region, marketplace_ids): endpoint = f"https://sellingpartnerapi-eu.amazon.com/listings/2020-09-01/items" headers = { 'x-amz-access-token': access_token, 'Content-Type': 'application/json', 'Accept': 'application/json' } params = { 'marketplaceIds': marketplace_ids } auth = AWSV4Auth( aws_access_key=credentials['AccessKeyId'], aws_secret_access_key=credentials['SecretAccessKey'], aws_session_token=credentials['SessionToken'], region=region, service='execute-api' ) response = requests.get(endpoint, headers=headers, params=params, auth=auth) if response.status_code == 403: print("403 Forbidden error. Response details:") print(response.text) response.raise_for_status() # Raise an error for bad status codes return response.json() try: # Assume the IAM role credentials = assume_role(creds['role_arn'], creds['aws_access_key'], creds['aws_secret_key']) print("Assumed IAM role successfully.") # Get LWA access token access_token = get_lwa_access_token(creds['lwa_client_id'], creds['lwa_client_secret'], creds['refresh_token']) print("Obtained LWA access token successfully.") # Make the SP-API request region = 'eu-north-1' marketplace_ids = 'A1PA6795UKMFR9' response = make_sp_api_request(credentials, access_token, region, marketplace_ids) print("API response received successfully.") print(json.dumps(response, indent=4)) except (NoCredentialsError, PartialCredentialsError) as e: print("Error with AWS credentials: ", str(e)) except requests.exceptions.HTTPError as e: print("HTTP error occurred: ", str(e)) except Exception as e: print("An error occurred: ", str(e))
内容的提问来源于stack exchange,提问作者joel
相关产品推荐
相关产品推荐

