Amazon SP-API授权异常排查:令牌有效仍返回Unauthorized错误
错误信息
{ "error": { "errors": [ { "code": "Unauthorized", "details": "The access token you provided is revoked, malformed or invalid.", "message": "Access to requested resource is denied." } ] } }
代码实现
import boto3 import botocore from botocore.auth import SigV4Auth from botocore.awsrequest import AWSRequest from botocore.credentials import Credentials from flask import Flask, redirect, request, session, url_for, jsonify import requests app = Flask(__name__) app.secret_key = 'test' # OAuth credentials CLIENT_ID = 'amzn1.application-oa2-client.XXXX' CLIENT_SECRET = 'amzn1.oa2-cs.v1.XXXX' REDIRECT_URI = 'https://example.com/callback' AUTHORIZATION_URL = 'https://www.amazon.com/ap/oa' TOKEN_URL = 'https://api.amazon.com/auth/o2/token' SOLICITATIONS_URL = 'https://sellingpartnerapi-na.amazon.com/solicitations/v1/orders' AWS_ACCESS_KEY_ID = "XXXX" AWS_SECRET_ACCESS_KEY = "XXXX" AWS_REGION = 'us-east-1' def get_aws_credentials(): return Credentials( access_key=AWS_ACCESS_KEY_ID, secret_key=AWS_SECRET_ACCESS_KEY ) @app.route('/') def home(): return '<a href="/login">Login with Amazon</a>' @app.route('/login') def login(): scope = 'sellingpartnerapi::notifications' auth_url = f'{AUTHORIZATION_URL}?client_id={CLIENT_ID}&scope={scope}&response_type=code&redirect_uri={REDIRECT_URI}' return redirect(auth_url) @app.route('/callback') def callback(): code = request.args.get('code') token_data = { 'grant_type': 'authorization_code', 'code': code, 'client_id': CLIENT_ID, 'client_secret': CLIENT_SECRET, 'redirect_uri': REDIRECT_URI, } token_response = requests.post(TOKEN_URL, data=token_data) token_json = token_response.json() session['access_token'] = token_json['access_token'] session['refresh_token'] = token_json['refresh_token'] return redirect(url_for('solicitations')) def get_spapi_access_token(): refresh_token = session.get('refresh_token') token_data = { 'grant_type': 'refresh_token', 'refresh_token': refresh_token, 'client_id': CLIENT_ID, 'client_secret': CLIENT_SECRET, } token_response = requests.post(TOKEN_URL, data=token_data) token_json = token_response.json() return token_json['access_token'] @app.route('/solicitations') def solicitations(): access_token = get_spapi_access_token() amazon_order_id = 'ORDER ID' # 已替换为真实订单ID marketplace_id = 'ATVPDKIKX0DER' solicitations_url = f'{SOLICITATIONS_URL}/{amazon_order_id}/solicitations/productReviewAndSellerFeedback?marketplaceIds={marketplace_id}' headers = {'x-amz-access-token': access_token, 'content-type': 'application/json'} request_obj = AWSRequest(method='POST', url=solicitations_url, headers=headers) credentials = get_aws_credentials() SigV4Auth(credentials, 'execute-api', AWS_REGION).add_auth(request_obj) prepared_request = requests.Request( method=request_obj.method, url=request_obj.url, headers=dict(request_obj.headers), data=request_obj.body ).prepare() response = requests.Session().send(prepared_request) return jsonify(response.json()), response.status_code
问题描述
已成功获取access token,但调用SP-API的索评接口时返回上述Unauthorized错误。已确认卖家中心开发者账号已获批solicitations权限,需排查令牌使用方式或请求签名是否存在问题。
已尝试操作
- 遵循OAuth流程获取并存储access token和refresh token
- 使用该access token向
solicitations/productReviewAndSellerFeedback端点发送POST请求 - 使用IAM凭证通过AWS Signature Version 4对请求签名后发送
预期结果
API处理索评请求并返回HTTP 200响应,确认请求已被接受。
实际结果
返回Unauthorized(403)错误,提示access token"已撤销、格式错误或无效"。
排查与解决方案
1. OAuth权限范围不匹配
登录时设置的scope为sellingpartnerapi::notifications,但实际调用的是索评接口,需要包含solicitations相关权限。修改登录路由的scope:
scope = 'sellingpartnerapi::solicitations sellingpartnerapi::notifications'
注意:权限范围需与开发者账号获批的权限一致,确保包含solicitations。
2. SigV4签名服务名称错误
SP-API的SigV4签名服务名称应为sellingpartnerapi,而非代码中的execute-api。修改签名代码:
SigV4Auth(credentials, 'sellingpartnerapi', AWS_REGION).add_auth(request_obj)
错误的服务名称会导致签名验证失败,触发权限错误。
3. 额外检查项
- 订单有效性:确认订单ID真实有效,且符合索评条件(如订单完成时间在过去30-365天内,未触发索评限制)
- Access Token有效性:打印
get_spapi_access_token()返回的token,确认格式正确(Bearer开头的JWT令牌),可通过JWT解析工具验证其包含solicitations权限 - 请求URL与区域匹配:确保调用的端点区域(
sellingpartnerapi-na对应北美)与卖家账号所在区域一致,marketplaceId正确 - IAM权限:确认用于签名的IAM用户已被授予
sellingpartnerapi::Solicitations相关权限,且策略配置正确
内容的提问来源于stack exchange,提问作者Mahmood M. Shilleh
相关产品推荐
相关产品推荐

