京东评论接口调用、签名生成与异常处理

一、核心背景说明

京东开放平台所有 API 调用都需要签名验证 (MD5/HMAC-SHA256),这是平台的安全机制,防止请求被篡改或伪造。商品评论相关接口(如jd.union.open.goods.jingfen.query包含评论摘要、jd.comment.read.findCommentInfo需特殊权限)的调用流程,核心就是「参数组装→签名生成→接口调用→异常处理」。


二、完整实战方案

1. 核心思路
  • 步骤 1:准备调用凭证(appkey、appsecret,需从京东开放平台申请);
  • 步骤 2:组装接口请求参数(公共参数 + 业务参数);
  • 步骤 3:按京东规则生成签名(核心);
  • 步骤 4:发送 HTTP 请求调用接口;
  • 步骤 5:针对不同异常类型(签名错误、权限不足、请求超时等)做针对性处理。
2. 完整代码实现(含签名 + 调用 + 异常处理)

python

运行

复制代码
import requests
import time
import hashlib
import json
from urllib.parse import urlencode, quote_plus

class JDCommentAPIClient:
    """京东开放平台评论相关API客户端(含签名生成、接口调用、异常处理)"""
    
    def __init__(self, appkey, appsecret, server_url="https://api.jd.com/routerjson"):
        """
        初始化客户端
        :param appkey: 京东开放平台申请的appkey
        :param appsecret: 京东开放平台申请的appsecret
        :param server_url: 京东API网关地址(正式环境)
        """
        self.appkey = appkey
        self.appsecret = appsecret
        self.server_url = server_url

    def _generate_sign(self, params):
        """
        生成京东API签名(核心步骤)
        签名规则:
        1. 按参数名ASCII码升序排序
        2. 拼接为 appsecret + key1 + value1 + key2 + value2 + ... + appsecret
        3. MD5加密后转大写
        :param params: 待签名的参数字典
        :return: 签名串
        """
        try:
            # 步骤1:按参数名升序排序
            sorted_params = sorted(params.items(), key=lambda x: x[0])
            
            # 步骤2:拼接字符串(appsecret + key + value 串联)
            sign_str = self.appsecret
            for key, value in sorted_params:
                # 空值不参与签名,值需转字符串
                if value is None or value == "":
                    continue
                sign_str += f"{key}{str(value)}"
            sign_str += self.appsecret
            
            # 步骤3:MD5加密并转大写
            sign = hashlib.md5(sign_str.encode("utf-8")).hexdigest().upper()
            return sign
        except Exception as e:
            raise RuntimeError(f"签名生成失败:{str(e)}")

    def call_comment_api(self, method, business_params, version="1.0", format_type="json"):
        """
        调用京东评论相关API
        :param method: API接口名(如jd.comment.read.findCommentInfo)
        :param business_params: 业务参数字典(如商品ID、页码等)
        :param version: API版本号
        :param format_type: 返回格式(固定json)
        :return: 接口返回的原始数据(字典)
        """
        # 1. 组装公共参数(所有API必传)
        public_params = {
            "app_key": self.appkey,
            "method": method,
            "format": format_type,
            "v": version,
            "timestamp": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()),  # 北京时间
            "sign_method": "md5",  # 签名方式(固定md5)
            "param_json": json.dumps(business_params, ensure_ascii=False)  # 业务参数转JSON
        }

        # 2. 生成签名
        try:
            sign = self._generate_sign(public_params)
            public_params["sign"] = sign  # 把签名加入参数
        except RuntimeError as e:
            print(f"【签名异常】{e}")
            return None

        # 3. 发送请求(京东API仅支持POST)
        headers = {
            "Content-Type": "application/x-www-form-urlencoded; charset=utf-8",
            "User-Agent": "JD-OpenAPI-Python-Client/1.0"
        }
        
        try:
            # 发送POST请求(参数需urlencode编码)
            response = requests.post(
                url=self.server_url,
                data=urlencode(public_params, quote_via=quote_plus),
                headers=headers,
                timeout=15  # 超时时间15秒
            )
            response.raise_for_status()  # 抛出HTTP状态码异常(4xx/5xx)
            
            # 解析返回结果
            result = response.json()
            
            # 4. 处理业务异常(京东API自身的错误码)
            if "error_response" in result:
                error = result["error_response"]
                error_code = error.get("code", "")
                error_msg = error.get("msg", "")
                sub_code = error.get("sub_code", "")
                sub_msg = error.get("sub_msg", "")
                raise ValueError(
                    f"【业务异常】错误码:{error_code},错误信息:{error_msg} "
                    f"子码:{sub_code},子信息:{sub_msg}"
                )
            
            return result

        # 异常分类处理
        except requests.exceptions.ConnectTimeout:
            print("【网络异常】连接超时,请检查网络或京东API网关状态")
            return None
        except requests.exceptions.ReadTimeout:
            print("【网络异常】读取超时,API响应过慢")
            return None
        except requests.exceptions.HTTPError as e:
            print(f"【HTTP异常】状态码:{e.response.status_code},响应内容:{e.response.text}")
            return None
        except json.JSONDecodeError:
            print("【解析异常】API返回非JSON格式数据:", response.text)
            return None
        except ValueError as e:
            print(e)
            return None
        except Exception as e:
            print(f"【未知异常】调用失败:{str(e)}")
            return None

# ==================== 实战调用示例 ====================
if __name__ == "__main__":
    # 替换为你从京东开放平台申请的真实凭证
    APP_KEY = "你的appkey"
    APP_SECRET = "你的appsecret"
    
    # 初始化客户端
    client = JDCommentAPIClient(appkey=APP_KEY, appsecret=APP_SECRET)
    
    # 示例1:调用商品评论摘要接口(需先申请权限)
    # 接口名:jd.union.open.goods.jingfen.query(包含评论数、好评率等)
    method = "jd.union.open.goods.jingfen.query"
    business_params = {
        "skuIds": "100082848364",  # 商品ID,多个用逗号分隔
        "fields": "commentCount,goodRate,goodCount,generalCount,poorCount"  # 需获取的评论相关字段
    }
    
    # 调用接口
    result = client.call_comment_api(method=method, business_params=business_params)
    
    # 打印结果
    if result:
        print("接口调用成功,返回数据:")
        print(json.dumps(result, ensure_ascii=False, indent=2))
    else:
        print("接口调用失败(详见上方异常提示)")
3. 关键模块解析
(1)签名生成(核心)

京东签名的核心规则(必须严格遵守,否则签名无效):

  • 参数排序:按参数名的 ASCII 码升序排列(如app_keymethod前);
  • 拼接规则:appsecret + key1 + value1 + key2 + value2 + ... + appsecret
  • 加密方式:MD5 加密后转大写(部分新接口支持 HMAC-SHA256,需对应调整);
  • 注意点:空值参数不参与签名,参数值需为原始字符串(不能 urlencode)。
(2)接口调用
  • 请求方式:京东开放平台 API仅支持 POST ,参数需application/x-www-form-urlencoded编码;
  • 公共参数:app_key(必填)、method(接口名)、timestamp(北京时间,格式YYYY-MM-DD HH:MM:SS)、sign(签名)等是所有 API 必传的;
  • 业务参数:需封装为 JSON 字符串,通过param_json参数传递。
(3)异常处理(分 4 类)

表格

异常类型 场景说明 处理方式
签名异常 参数排序错误、appsecret 错误、空值参与签名 校验参数排序、核对 appsecret、过滤空值
网络异常(超时 / 连接失败) 网络波动、API 网关不可用 增加重试机制、延长超时时间
HTTP 异常(4xx/5xx) 403(权限不足)、400(参数错误)、500(平台故障) 核对权限、校验参数格式、稍后重试
业务异常(错误码) 60000(appkey 无效)、60002(签名错误)、20000(业务参数错误) 按错误码查京东开放平台文档,针对性修复
4. 前置条件与注意事项
  1. 凭证获取

    • 需先注册京东开放平台企业账号(https://open.jd.com/),完成资质认证;
    • 申请对应评论接口的调用权限(审核周期 1-3 个工作日);
    • 获取appkeyappsecret(需妥善保管,不要泄露)。
  2. 依赖安装

    bash

    运行

    复制代码
    pip install requests
  3. 避坑点

    • timestamp必须是北京时间,且与京东服务器时间误差不超过 10 分钟;
    • 业务参数中的特殊字符(如中文、空格)需在 JSON 序列化时保留(ensure_ascii=False);
    • 不要高频次调用(平台有 QPS 限制,超出会被限流)。
相关推荐
赵谨言1 小时前
基于Python实现地理空间数据批处理技术探讨及实现--以“多规合一“总体规划数据空间叠加分析为例
大数据·开发语言·经验分享·python
天竺鼠不该去劝架2 小时前
RPA 平台选型指南(2026):金智维 vs 来也RPA vs 艺赛旗 vs 阿里云 RPA 深度对比
大数据·数据库·人工智能
独自破碎E2 小时前
BISHI40数组取精
java·开发语言
DN20202 小时前
AI销售:从不迟到早退,永远秒回,您的忠实员工
人工智能·python
丑八怪大丑2 小时前
Java面向对象(进阶)
java·开发语言
java1234_小锋2 小时前
Java高频面试题:Java中变量和常量有什么区别?
java·开发语言·面试
编程之升级打怪2 小时前
Python的图形框架tkinter使用案例
python
enjoy嚣士2 小时前
Java 之 实现C++库函数等价函数遇到的问题
java·开发语言·c++
毕设源码-郭学长3 小时前
【开题答辩全过程】以 基于java的停车管理系统的设计与实为例,包含答辩的问题和答案
java·开发语言