You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Amazon SP-API授权异常排查:令牌有效仍返回Unauthorized错误

Flask调用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 00:12:05