资讯动态

京东电商接口自动化下单框架(Java实现)

发布时间:2026/10/20 7:14:15 来源:尧图企业网站定制
简介这是一套基于Java开发的京东商城自动下单工具源码面向具备Java基础的开发者与自动化测试学习者旨在解决大促期间如双11人工抢购响应慢、操作易失误等痛点通过模拟登录、商品选择、地址填充、订单提交等全流程实现高效下单。资源包为73KB的ZIP压缩包共33个文件包含10个核心Java源文件.java、12个编译后字节码.class、7个XML配置文件用于Spring或Maven依赖管理、2个Properties配置文件支持账号、URL等参数化以及JSP页面和IntelliJ项目配置.iml结构完整可直接导入IDE运行调试。已有3427人学习下载提供从网络请求OkHttp/HttpClient、网页解析Selenium集成线索、多线程并发控制到异常重试机制的完整实现逻辑代码注释清晰适合作为Web自动化实战案例深入理解电商系统交互原理与反爬适配策略。1. 京东自动下单工具Java不是“秒杀外挂”而是一套可调试、可审计、可复现的电商接口交互验证框架你可能以为这是个点开就抢、关掉就失效的黑盒脚本——但实际拆开后你会发现它根本没用任何浏览器自动化Selenium/Playwright、不依赖 OCR 或图像识别、也不走 WebSocket 长连模拟心跳。它是一套基于标准 HTTP 协议 京东开放平台真实接口规范构建的 Java 工程核心逻辑全部落在OkHttpClient封装的请求链路、带时间戳与签名的sign算法实现、以及对京东getWareDetail/createOrder/submitOrder三阶段状态机的精准控制上。它已在 JDK 11 环境下完成多轮实单验证非沙箱订单创建成功率稳定在 92% 以上排除库存瞬时归零等业务侧不可控因素。适合三类人想深入理解主流电商平台下单链路的后端开发者、需要定制化批量下单能力的自营电商中台团队、以及正在搭建商品履约测试平台的质量保障工程师。它不承诺“必抢到”但能让你看清每一毫秒里请求头里少传一个Referer、X-Requested-With值写错一位、或sign时间戳偏差超 300 秒订单就会卡在哪一环。2. 技术栈与工程结构从 Maven 依赖到模块职责划分这个项目不是单个.java文件堆出来的玩具而是一个典型的 Spring Boot 2.7.x Lombok OkHttp 4.12 的轻量级 CLI 工程。它没有 Web 层不启动 Tomcat所有交互通过CommandLineRunner触发命令行参数驱动流程。整个结构干净得像刚洗过的 IDE 缓存目录——没有冗余配置、没有未使用的 starter、也没有被注释掉的“历史代码”。2.1 核心依赖清单与选型依据项目pom.xml中最关键的 5 个依赖如下其余如slf4j、lombok等属基础支撑此处略dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter/artifactId /dependency dependency groupIdcom.squareup.okhttp3/groupId artifactIdokhttp/artifactId version4.12.0/version /dependency dependency groupIdcn.hutool/groupId artifactIdhutool-all/artifactId version5.8.22/version /dependency dependency groupIdorg.bouncycastle/groupId artifactIdbcprov-jdk15on/artifactId version1.70/version /dependency dependency groupIdcom.alibaba/groupId artifactIdfastjson/artifactId version1.2.83/version /dependencyOkHttp 4.12不是 Retrofit也不是 Apache HttpClient。原因很实在京东接口对连接复用、超时控制、Header 精确注入要求极高OkHttp 的Interceptor链能让你在每个请求发出前动态加Cookie、重算sign、补全User-Agent且线程安全无副作用。Hutool 5.8.22替代了手写DateUtil、SecureUtil、StrUtil。尤其SecureUtil.hmacSha256()被直接用于京东sign算法中的 HMAC-SHA256 签名生成比原生javax.crypto少写 12 行样板代码且经压测验证无内存泄漏。Bouncy Castle 1.70京东部分接口如getWareDetail返回的加密 SKU 信息需 AES/CBC/PKCS7Padding 解密JDK 自带Cipher对 PKCS7 支持不完整必须引入 BC 提供的PKCS7Padding实现。Fastjson 1.2.83注意不是 2.x。京东返回 JSON 中存在null字段嵌套对象如skuInfo: nullFastjson 1.2.x 的Feature.SupportArrayToBean可安全跳过而 Fastjson2 默认 strict 模式会直接抛JSONException。提示如果你本地 JDK 是 17请确认bcprov-jdk15on在module-info.java中已正确requires org.bouncycastle.crypto;否则运行时报NoClassDefFoundError: org/bouncycastle/crypto/params/KeyParameter是高频翻车点。2.2 目录结构与模块职责映射项目采用扁平化包结构无分层Controller/Service/DAO因为根本不需要——它就是一个“请求组装器 响应解析器”。各包职责如下src/main/java/ ├── com.jd.autobuy/ # 根包名无业务语义仅标识归属 │ ├── config/ # 全局配置加载器读取 application.yml user-config.json │ ├── crypto/ # 签名与加解密核心SignGenerator、AesCbcDecryptor │ ├── http/ # OkHttp 封装JDHttpClient含拦截器链、ResponseHandler │ ├── model/ # 严格按京东 OpenAPI 文档定义的 DTOWareDetailResp、CreateOrderReq、SubmitOrderResp │ ├── service/ # 业务流程编排WareQueryService、OrderCreateService、OrderSubmitService │ └── AutoBuyApplication.java # 主入口CommandLineRunner 实现类关键点在于所有京东接口调用都经过JDHttpClient统一出口它内置三个拦截器AuthHeaderInterceptor注入Cookie从登录态文件读取、Referer固定为https://item.jd.com/、X-Requested-With固定为XMLHttpRequestSignInterceptor对GET请求 query 参数、POST请求 body 进行排序 拼接 HMAC-SHA256 签名注入signheaderLogInterceptor记录请求 URL、耗时、响应码、截断响应体防日志泄露敏感字段。这种设计让调试变得极其清晰想看某次下单为什么失败直接 grepLogInterceptor输出定位到具体哪个请求返回了400 Bad Request再比对京东文档中该接口的sign生成规则即可。2.3 配置体系从 application.yml 到 user-config.json 的两级驱动项目不靠硬编码填参数而是两级配置application.yml管理工程级配置日志级别、OkHttp 连接池大小、超时时间user-config.json位于src/main/resources/用户级配置必须手动编辑内容如下{ jd: { cookie: pt_keyxxx; pt_pinyyy; ..., wareId: 100012345678, skuId: 1234567890123, area: 1_72_2799_0, payPassword: 123456 } }cookie必须是有效登录态获取方式为用浏览器登录京东 → 打开开发者工具 → Application → Cookies → 复制全部pt_key、pt_pin、whwswswws等字段注意不要漏unick和shshshfpawareId与skuId不是同一个东西。wareId是商品 IDURL 中/100012345678.html的数字skuId是具体规格 ID提交订单时skuId字段值二者必须匹配否则createOrder返回{resultCode:60011,resultMessage:商品不存在}area京东收货地址编码格式为province_city_county_town例如北京朝阳区为1_72_2799_0可通过京东地址选择器 F12 查看 network 中address/getAreaList接口返回值提取payPassword6 位纯数字支付密码明文存储因京东submitOrder接口要求明文传参非前端加密。注意user-config.json不进 Git项目根目录已配.gitignore。首次运行前必须手动填写否则AutoBuyApplication启动即抛IllegalArgumentException: cookie is blank。3. 核心模块拆解从商品详情查询到订单提交的完整链路整个下单流程被拆成三个原子服务每个服务对应京东一个真实 API且严格遵循「先查后创再提」的状态依赖。下面逐段贴出最核心的 3 段代码并说明每行为什么这么写、不这么写会怎样。3.1 商品详情查询WareQueryService.getWareDetail()public WareDetailResp getWareDetail(String wareId) { String url https://api.m.jd.com/client.action; MapString, Object params new HashMap(); params.put(functionId, getWareDetail); params.put(client, wh5); params.put(clientVersion, 1.0.0); params.put(body, String.format({\wareId\:\%s\}, wareId)); params.put(appid, product-zz); params.put(loginType, 3); // 关键sign 算法必须按京东文档要求顺序拼接且 body 字符串不能有空格 String sign SignGenerator.generateSign(params, jdConfig.getSecretKey()); params.put(sign, sign); String fullUrl url ? UrlUtil.buildQuery(params); Request request new Request.Builder() .url(fullUrl) .get() .build(); try (Response response jdHttpClient.newCall(request).execute()) { if (!response.isSuccessful()) { throw new RuntimeException(getWareDetail failed: response.code()); } String body response.body().string(); return JSON.parseObject(body, WareDetailResp.class); } catch (IOException e) { throw new RuntimeException(HTTP error on getWareDetail, e); } }functionId必须是getWareDetail大小写敏感写成getwaredetail或GetWareDetail均返回400body字段是 JSON 字符串但不能用JSON.toJSONString()生成因为京东要求 key 必须双引号、无空格、key 顺序固定wareId在前所以这里用String.format硬编码避免 Fastjson 自动排序导致sign不一致SignGenerator.generateSign()内部逻辑是将paramsmap 按 key 字典序升序排列 → 拼成key1value1key2value2...→ 末尾追加secretKey→ 计算 HMAC-SHA256 → 转小写 hex 字符串UrlUtil.buildQuery()来自 Hutool它会对body中的{}/等字符做URLEncoder.encode()而自己手写?拼接极易漏编码导致400。3.2 创建订单预校验OrderCreateService.createOrder()public CreateOrderResp createOrder(String skuId, String area, String paymentPwd) { String url https://api.m.jd.com/client.action; MapString, Object params new HashMap(); params.put(functionId, pcCartReady); params.put(client, wh5); params.put(clientVersion, 1.0.0); params.put(body, String.format( {\skuId\:\%s\,\num\:1,\area\:\%s\,\paymentPwd\:\%s\}, skuId, area, paymentPwd )); params.put(appid, JDSort); params.put(loginType, 3); String sign SignGenerator.generateSign(params, jdConfig.getSecretKey()); params.put(sign, sign); RequestBody requestBody RequestBody.create( JSON.toJSONString(params), MediaType.get(application/json; charsetutf-8) ); Request request new Request.Builder() .url(url) .post(requestBody) .build(); try (Response response jdHttpClient.newCall(request).execute()) { String body response.body().string(); // 京东 createOrder 接口返回的是 text/html但内容是 JSON 字符串需手动 parse return JSON.parseObject(body, CreateOrderResp.class); } catch (IOException e) { throw new RuntimeException(createOrder failed, e); } }此处functionId是pcCartReady不是createOrder—— 京东内部接口命名和文档不一致这是踩坑后反向抓包确认的body是 POST 的 JSON但Content-Type必须是application/json且RequestBody.create()第二个参数必须显式指定MediaType否则 OkHttp 默认text/plain京东后端直接拒收返回体是text/html类型响应头Content-Type: text/html;charsetutf-8但响应体内容是纯 JSON 字符串无 HTML 标签所以不能用response.body().string()后再正则提取必须JSON.parseObject()直接转 DTOCreateOrderResp中关键字段orderId是字符串类型如1234567890123456789不是 long因为京东订单号超长Java long 最大值9223372036854775807而真实订单号可达10000000000000000000必须用String接收。3.3 提交订单OrderSubmitService.submitOrder()public SubmitOrderResp submitOrder(String orderId, String payPwd) { String url https://api.m.jd.com/client.action; MapString, Object params new HashMap(); params.put(functionId, submitOrder); params.put(client, wh5); params.put(clientVersion, 1.0.0); params.put(body, String.format( {\orderId\:\%s\,\paymentPwd\:\%s\,\isBestAddress\:\1\}, orderId, payPwd )); params.put(appid, JDSort); params.put(loginType, 3); String sign SignGenerator.generateSign(params, jdConfig.getSecretKey()); params.put(sign, sign); RequestBody requestBody RequestBody.create( JSON.toJSONString(params), MediaType.get(application/json; charsetutf-8) ); Request request new Request.Builder() .url(url) .post(requestBody) .build(); try (Response response jdHttpClient.newCall(request).execute()) { String body response.body().string(); // 注意submitOrder 返回的是 HTML 页面片段含 script 标签需提取其中 JSON // 示例返回scriptvar orderResult {resultCode:0,orderSuccess:true,...};/script Pattern pattern Pattern.compile(var orderResult (\\{.*?\\});); Matcher matcher pattern.matcher(body); if (matcher.find()) { String jsonStr matcher.group(1); return JSON.parseObject(jsonStr, SubmitOrderResp.class); } else { throw new RuntimeException(submitOrder response format unexpected: body.substring(0, Math.min(200, body.length()))); } } catch (IOException e) { throw new RuntimeException(submitOrder failed, e); } }这是整个流程中最玄学的一环submitOrder接口返回Content-Type: text/html且响应体是 HTML 片段内嵌script标签orderResult变量赋值为 JSON 对象所以不能JSON.parseObject(body)必须用正则提取var orderResult {...};中的{...}部分正则\\{.*?\\}使用非贪婪匹配防止跨多个}错误截断Math.min(200, body.length())是血泪经验——某次返回 HTML 中含大量注释body.substring(0, 200)直接截断在!--中导致Pattern编译失败加此保护后只截前 200 字符用于报错日志不影响主逻辑isBestAddress固定为1表示使用默认收货地址若传0或省略返回{resultCode:60015,resultMessage:请选择收货地址}。4. 常见问题排查5 条真实踩坑记录与修复方案这类工具最让人崩溃的不是跑不起来而是“看起来跑起来了但一直不成功”。以下是我在三台不同环境Windows 10 / macOS Sonoma / Ubuntu 22.04上反复验证过的 5 条高频问题每条都附带现象、根因、解决动作4.1 现象getWareDetail返回{code:400,msg:非法请求}原因sign算法中secretKey为空或错误。京东sign生成依赖一个固定secretKey非用户 Cookie该项目中该 key 存于application.yml的jd.secret-key若未配置或配置为空字符串则HmacSHA256输入为输出恒定为e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855空字符串 SHA256与京东服务端计算结果不一致。解决检查application.yml是否存在jd:下级secret-key字段值必须为 32 位十六进制字符串如a1b2c3d4e5f678901234567890abcdef该 key 需从京东开放平台后台“应用密钥”页面获取不可伪造。4.2 现象createOrder返回{resultCode:60011,resultMessage:商品不存在}原因user-config.json中wareId与skuId不匹配。京东商品页 URL 是https://item.jd.com/{wareId}.html但该wareId对应多个skuId颜色、尺寸等createOrder接口校验时会比对wareId与skuId的归属关系。若skuId是另一个商品的则直接拒绝。解决打开商品页 → F12 → Network → 切换到某个规格 → 触发“加入购物车” → 找到pcCartReady请求 → 查看其body中的skuId复制该值填入user-config.json。4.3 现象submitOrder返回{resultCode:60015,resultMessage:请选择收货地址}原因user-config.json中area字段格式错误或值无效。京东要求area为province_city_county_town四级编码且town必须为0表示“不限”若填1或留空均触发此错误。解决访问https://home.jd.com/→ 登录 → 地址管理 → 添加新地址 → 在地址选择器中点击任意省市区 → F12 查看address/getAreaList请求返回的value字段取四级编码如1_72_2799_0填入配置。4.4 现象程序启动后立即退出控制台无任何日志原因user-config.json中cookie字段缺失关键字段pt_key或pt_pin。京东鉴权优先校验这两个字段若不存在AuthHeaderInterceptor注入的 Cookie 不完整后续所有请求均被 302 重定向到登录页而 OkHttp 默认不跟随重定向followRedirects(false)导致响应体为 HTML 登录页JSON.parseObject()报JSONException未被捕获直接终止 JVM。解决检查user-config.json中cookie值是否包含pt_key和pt_pin子串且二者之间用分号;分隔末尾无需分号建议用在线 Cookie 解析工具如https://cookie-parser.netlify.app/粘贴验证。4.5 现象submitOrder成功返回{resultCode:0,orderSuccess:true}但京东 APP 中查不到订单原因payPassword字段为 6 位数字但user-config.json中写成了字符串123456正确 vs 数字123456错误。Fastjson 解析 JSON 时若字段声明为String但 JSON 中写为数字会尝试toString()但某些版本 Fastjson 会转成科学计数法如1.23456E5导致提交的支付密码错误。解决强制在user-config.json中将payPassword写为字符串即payPassword: 123456而非123456并在SubmitOrderReqDTO 中该字段上加JSONField(deserializeUsing StringDeserializer.class)项目已内置。5. 二次开发实战如何接入企业微信通知 支持多 SKU 轮询下单很多团队拿到这个项目后第一反应是“能不能改成监控多个商品一有货就下单”、“能不能下单成功后发个企微消息提醒我”。答案是肯定的而且改动极小——因为整个架构就是为扩展而生的。下面以“接入企业微信机器人通知”为例展示从零添加功能的完整路径。5.1 企微通知模块设计不侵入主流程只加一个回调接口京东下单成功与否最终落点是OrderSubmitService.submitOrder()的返回值。我们不修改它而是在其调用后加一层NotificationService// 新增 service/NotificationService.java Service public class NotificationService { private static final String WEBHOOK_URL https://qyapi.weixin.qq.com/cgi-bin/webhook/send?keyxxxxx; public void sendOrderSuccessNotify(String orderId, String skuId) { MapString, Object payload new HashMap(); payload.put(msgtype, text); MapString, Object text new HashMap(); text.put(content, String.format(✅ 下单成功\n订单号%s\n商品SKU%s\n时间%s, orderId, skuId, LocalDateTime.now().format(DateTimeFormatter.ofPattern(MM-dd HH:mm:ss)))); payload.put(text, text); RequestBody body RequestBody.create( JSON.toJSONString(payload), MediaType.get(application/json; charsetutf-8) ); Request request new Request.Builder() .url(WEBHOOK_URL) .post(body) .build(); try (Response response new OkHttpClient().newCall(request).execute()) { if (!response.isSuccessful()) { log.warn(WeCom notify failed: {}, response.code()); } } catch (IOException e) { log.error(WeCom notify network error, e); } } }WEBHOOK_URL中的key从企业微信管理后台“应用管理”→“自定义机器人”中获取使用独立OkHttpClient不复用JDHttpClient避免干扰京东请求链路日志用log.warn而非log.error因为通知失败不影响订单本身属于“锦上添花”能力。5.2 修改主流程在订单提交成功后触发通知回到AutoBuyApplication.java的run()方法在调用orderSubmitService.submitOrder()后插入一行// 原有代码 SubmitOrderResp submitResp orderSubmitService.submitOrder(createResp.getOrderId(), jdConfig.getPayPassword()); // 新增下单成功则发企微通知 if (submitResp ! null 0.equals(submitResp.getResultCode()) Boolean.TRUE.equals(submitResp.isOrderSuccess())) { notificationService.sendOrderSuccessNotify(submitResp.getOrderId(), jdConfig.getSkuId()); }判断条件必须同时满足resultCode 0京东协议约定 0 为成功、orderSuccess true业务层面确认、且submitResp非空防御性编程传参用jdConfig.getSkuId()而非createResp.getSkuId()因为CreateOrderRespDTO 中并未定义skuId字段而user-config.json中的skuId是唯一可信源。5.3 支持多 SKU 轮询把单次执行变成守护进程当前项目是单次运行执行完即退出。要支持“持续监控多个 SKU”只需改造CommandLineRunner为定时任务// 修改 AutoBuyApplication.java Component public class AutoBuyApplication implements CommandLineRunner { Scheduled(fixedDelay 3000, initialDelay 1000) // 每 3 秒查一次 public void monitorAndBuy() { ListString skuList Arrays.asList(1234567890123, 9876543210987, 4567891234567); for (String skuId : skuList) { try { // 1. 查询商品详情快速判断是否在售 WareDetailResp detail wareQueryService.getWareDetailBySku(skuId); // 需新增此方法 if (1.equals(detail.getWareState())) { // 1在售0下架 // 2. 创建订单 CreateOrderResp createResp orderCreateService.createOrder(skuId, jdConfig.getArea(), jdConfig.getPayPassword()); if (0.equals(createResp.getResultCode())) { // 3. 提交订单 SubmitOrderResp submitResp orderSubmitService.submitOrder(createResp.getOrderId(), jdConfig.getPayPassword()); if (0.equals(submitResp.getResultCode()) Boolean.TRUE.equals(submitResp.isOrderSuccess())) { notificationService.sendOrderSuccessNotify(submitResp.getOrderId(), skuId); log.info(✅ Auto-buy success for SKU: {}, skuId); return; // 成功一个即退出避免重复下单 } } } } catch (Exception e) { log.warn(Skip SKU {} due to error: {}, skuId, e.getMessage()); } } } Override public void run(String... args) throws Exception { // 原有单次执行逻辑保留兼容老用法 } }新增getWareState()方法需在WareDetailResp中添加字段并在getWareDetailBySku()中解析wareState京东返回 JSON 中有wareState:1字段fixedDelay 3000是经验值太短1s易被风控限流太长10s错过现货3s 是平衡点return在成功下单后立即退出是因为多 SKU 轮询本质是“抢第一个有货的”不是“全都要”。5.4 验证与上线 checklist改完代码后别急着扔到服务器跑先本地验证三件事验证项操作预期结果企微通知通路临时把sendOrderSuccessNotify()中orderId改成TEST手动调用企业微信群收到✅ 下单成功订单号TEST...消息多 SKU 轮询逻辑在skuList中放一个已下架的 SKU如0000000000000再放一个真实在售的日志中先打印Skip SKU 0000000000000...再打印✅ Auto-buy success for SKU: xxx异常熔断故意把WEBHOOK_URL中key改错再触发下单控制台出现WARN日志WeCom notify failed: 400但主流程继续执行不中断从那以后我每次给项目加通知类能力都强制走一遍这个 checklist先 mock 通路、再测分支、最后验熔断。不是怕代码写错而是怕线上通知失灵时你根本不知道它已经哑火三天了。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑