Python调用Walmart API提交POST报表请求失败排查求助
问题排查:Walmart报表API请求误判失败
问题现象
调用Walmart按需报表生成API时,返回JSON明确显示requestStatus: RECEIVED(请求已接收),但代码却输出Report request failed.的错误提示。
相关代码
Walmart交互类代码
class Walmart(object): def __init__(self, client_id, client_secret): """To get client_id and client_secret for your Walmart Marketplace visit: https://developer.walmart.com/#/generateKey """ self.client_id = client_id self.client_secret = client_secret self.token = None self.token_expires_in = None self.base_url = "https://marketplace.walmartapis.com/v3" session = requests.Session() session.headers.update({ "WM_SVC.NAME": "Walmart Marketplace", "WM_QOS.CORRELATION_ID": uuid.uuid4().hex, "Content-Type": "application/x-www-form-urlencoded", "Accept": "application/json", }) session.auth = HTTPBasicAuth(self.client_id, self.client_secret) self.session = session # Get the token required for API requests self.authenticate() def authenticate(self): data = self.send_request( "POST", "{}/token".format(self.base_url), body={ "grant_type": "client_credentials", }, ) self.token = data["access_token"] self.token_expires_in = data["expires_in"] self.session.headers["WM_SEC.ACCESS_TOKEN"] = self.token @property def report(self): return Report(connection=self) def send_request( self, method, url, params=None, body=None, json=None, request_headers=None ): # A unique ID which identifies each API call and used to track # and debug issues; use a random generated GUID for this ID headers = { "WM_QOS.CORRELATION_ID": uuid.uuid4().hex, "WM_SVC.NAME": "Walmart Marketplace", "Content-Type": "application/x-www-form-urlencoded", "Accept": "application/json", } if request_headers: headers.update(request_headers) response = None if method == "GET": response = self.session.get(url, params=params, headers=headers) elif method == "PUT": response = self.session.put( url, params=params, headers=headers, data=body ) elif method == "POST": request_params = { "params": params, "headers": headers, } if json is not None: request_params["json"] = json else: request_params["data"] = body response = self.session.post(url, **request_params) if response is not None: try: response.raise_for_status() except requests.exceptions.HTTPError: if response.status_code == 401: raise WalmartAuthenticationError(( "Invalid client_id or client_secret. Please verify " "your credentials from https://developer.walmart." "com/#/generateKey" )) elif response.status_code == 400: data = response.json() if "error" in data and data["error"][0]["code"] == \ "INVALID_TOKEN.GMP_GATEWAY_API": # Refresh the token as the current token has expired self.authenticate() return self.send_request( method, url, params, body, request_headers ) raise try: return response.json() except ValueError: # In case of reports, there is no JSON response, so return the # content instead which contains the actual report return response.content
请求代码
api_key = '<key>' api_secret='<secret>' wm = Walmart(api_key, api_secret) wm.authenticate() url = "https://marketplace.walmartapis.com/v3/reports/reportRequests" headers = { "WM_QOS.CORRELATION_ID": uuid.uuid4().hex, "WM_SVC.NAME": "Walmart Marketplace", "Content-Type": "application/x-www-form-urlencoded", "Accept": "application/json", } data= { "reportType": "ITEM_PERFORMANCE", "reportVersion": "v1", } method="POST" response_dict = wm.send_request(method, url, request_headers=headers, params=data) if 'status_code' in response_dict and response_dict['status_code'] == 200: response_json = response_dict.get('json') request_id = response_json.get('requestId') print(f'Report request submitted. Request ID: {request_id}') else: print('Report request failed.') if 'json' in response_dict: print(response_dict['json']) else: print(response_dict)
实际返回结果
Report request failed.
{'requestId': '46a864e8-80e8-4019-86f0-d7a1575349a4', 'requestStatus': 'RECEIVED', 'requestSubmissionDate': '2023-02-15T18:55:03Z', 'reportType': 'ITEM_PERFORMANCE', 'reportVersion': 'v1'}
问题原因及解决方法
1. 核心判断逻辑错误
send_request方法返回的是响应的原始JSON数据,而非包含status_code和json的嵌套字典。你的判断代码if 'status_code' in response_dict永远不成立,导致误判请求失败。
Walmart报表生成API接收请求后会返回202状态码(表示请求已接受,后台异步处理),send_request方法中response.raise_for_status()不会抛出异常(202不属于错误状态码),直接返回了API返回的JSON数据。
2. 请求参数传递错误
调用send_request时,你把报表参数放在了params参数(URL查询参数)中,但根据API要求,报表生成的POST请求需要将参数放在**请求体(JSON格式)**中,而非URL参数。
修正后的请求代码
api_key = '<key>' api_secret='<secret>' wm = Walmart(api_key, api_secret) # __init__方法中已自动调用authenticate,无需重复执行 url = "https://marketplace.walmartapis.com/v3/reports/reportRequests" data= { "reportType": "ITEM_PERFORMANCE", "reportVersion": "v1", } method="POST" # 用json参数传递请求体,而非params response_json = wm.send_request(method, url, json=data) # 根据API返回的requestStatus判断请求状态 if response_json.get('requestStatus') == 'RECEIVED': request_id = response_json.get('requestId') print(f'Report request submitted. Request ID: {request_id}') else: print('Report request failed.') print(response_json)
额外优化点
- 无需手动设置
headers,send_request方法会自动生成并处理必要的头部信息,重复设置可能导致冲突(如重复的WM_QOS.CORRELATION_ID)。
内容的提问来源于stack exchange,提问作者sandibaeva52
相关产品推荐
相关产品推荐

