京东双十一自動化注文システムの Java 実装架构と運用ガイド
本ガイドでは、京东(JD.com)の双十一大促イベント向けに設計された Java ベースの自動注文システムについて解説します。このプロジェクトは Python スクリプトや外部エンジンに依存せず、純粋な Java 実装で構成されています。ログイン状態の維持、商品のカート追加、配送先住所の選択、订单提交(オーダーサブミット)に至るまでの全フローをカバーし、現在の京东インターフェースパラメータに適合しています。
プロジェクトは標準的な Maven 構造を採用し、pom.xml、src/main/java ソースディレクトリ、IDE 設定ファイルを含んでいます。IntelliJ IDEA または Eclipse でのインポートとデバッグを想定しており、軽量な UI モジュールも内蔵されています。UI は IntelliJ UI Designer をベースに構築されており、ビジュアル操作界面の起動だけでなく、ヘッドレスモードでの核心メソッド呼び出しもサポートします。すべての HTTP リクエストは可読性の高い Java クラスにカプセル化されており、HttpClient、Cookie 管理、JSON パーシングに精通した技術者が容易に理解、修正、拡張できるよう設計されています。
1. プロジェクト概要:デバッグ可能で監査可能なエンジニアリングアプローチ
双十一の零点において、手動での購入試行はネットワーク速度や反応速度に依存せざるを得ません。一方、単純な Python スクリプトはインターフェースの逆エンジニアリング能力や Cookie の有効期限に左右されます。本システムが目指すのは、リズムを安定させ、問題を迅速に特定し、いつでもブレークポイントに切り替えてデバッグ可能な構造が明確で、論理が層別化され、完全に制御可能な Java エン지니어링です。
本プロジェクトは「秒杀成功」を保証するものではありませんが、すべてのステップが見え、停止でき、変更でき、検証できることを保証します。核心キーワードである「京东自動注文」、「Java 購入ツール」、「双十一注文プログラム」はマーケティング用語ではなく、能力の境界を正直に示すものです。EXE ファイルとしてワンクリック実行できるようにパッケージ化したり、HTTP の詳細を隠蔽してブラックボックス化したりすることはしません。
代わりに、注文リンク全体を AuthSessionHandler、ItemReservationService、AddressLocator、CheckoutCommand という 4 つの責任が明確なモジュールに分解します。各クラスは平均 200 行未満のコードで構成され、すべてのネットワーク呼び出しは Apache HttpClient 4.5.14 に基づいています(OkHttp や Spring WebClient ではなく、CookieStore の制御がより低レベルで透明であるため)。JSON パーシングには Jackson 2.15.2 を使用し、歴史的なセキュリティリスクや日付の逆シリアライズ曖昧さを回避しています。
このエンジニアリングが適合する対象は以下の通りです:
- 電商システムの実習生を指導する教育者が、真实で準拠し、構造が規範的な HTTP 実践案例を必要とする場合。
- クロスボーダー電商会社でフルフィルメントミドルウェアを担当する Java エンジニアが、大手企業レベルのログイン状態クロスドメイン維持戦略を参照したい場合。
- 簡易クローラーを構築したが京东の風制御に拦截される開発者が、
pt_key/pt_pin双 Token メカニズム、rid動的生成ロジック、およびカート追加インターフェースにcallbackUrlパラメータが必要な理由を理解したい場合。
このプロジェクトの価値は「購入できるかどうか」ではなく、「なぜ購入できなかったか」を特定できる点にあります。CheckoutCommand.java の任意の行にブレークポイントを設定し、requestEntity 内にどのフィールドが不足しているかを確認できます。また、HttpUtil.java に臨時のログ出力を追加し、302 リダイレクトで Referer が失われたのか、412 プリチェック失敗なのかを確認することも可能です。
2. 全体アーキテクチャ設計と主要な技術選定
2.1 純粋な Java 実装を堅持する理由
「Python requests + selenium」や「Puppeteer によるブラウザ模擬」が一般的な路径ですが、本プロジェクトでは以下の理由により積極的に放弃されています。
第一に、環境の一貫性が制御不可能である点。 双十一零点は家庭ネットワーク、ノートパソコン、あるいは臨時レンタルのクラウドサーバーで発生することが多いです。Python は特定バージョン(3.8+)のマッチング、chromedriver のインストール、headless モード下のフォントレンダリング差異の処理が必要です。Node.js は npm install 依存関係の処理や V8 メモリオーバーフローの対策が必要です。一方、Java は JDK 11+ 仅需し、java -jar コマンド一つで UI を起動するか、Maven コマンドで核心ロジックを直接実行できます。
第二に、スレッドモデルと状態管理が注文シナリオに適合している点。 京东注文は厳密な時系列依存を持つステートマシンです:ログイン→ユーザー情報取得→商品在庫確認→カート追加→住所選択→提交。Python の asyncio や Node.js の Promise チェーンは異常ブランチでコンテキストを失いやすい(例:検証コード失敗後にセッションがリセットされない)ですが、Java の ExecutorService と CompletableFuture は「失敗リトライ+状態ロールバック」を自然にサポートします。
第三に、IDE デバッグ体験がスクリプト言語を圧倒する点。 submitOrder がエラーを返す際、Python では手動で payload 辞書を印刷してドキュメントフィールドと比較する必要があります。Java では、メソッド末尾にブレークポイントを追加するだけで、マップ内の各キーバリューのリアルタイム値をマウスホバーで確認でき、その場で値を変更して再実行することも可能です。
注記:本プロジェクトは Spring Boot を使用せず、自動設定によるブラックボックス動作を意図的に回避しています。すべての Bean(HttpClient インスタンス、CookieStore など)は手動で生成および注入され、各オブジェクトのライフサイクルを明確に把握できるようにしています。
2.2 UI モジュールの選定:IntelliJ UI Designer
ディレクトリ内の uiDesigner.xml ファイルは、本プロジェクトを他の「Java 購入ツール」と区別する关键标识です。Swing でハードコードされた JFrame や JavaFX の FXML ではなく、IntelliJ IDEA 公式 UI Designer が生成する XML レイアウトファイルを採用しています。
選定理由は以下の通りです:
- 開発効率と維持コストのバランス: JavaFX は学習曲線が急峻であり、Swing の原生レイアウトコードは冗長です。UI Designer はドラッグ&ドロップ設計+リアルタイムプレビューを提供し、生成された Java コードは完全に読可能で編集可能です。
- IDEA デバッグフローとのシームレスな連携: UI Designer 生成コンポーネントは、IDEA の「Debug Swing UI」機能を自然にサポートします。「ログイン」ボタンクリック時にビジネスロジックをデバッグできるだけでなく、「Components」デバッグウィンドウでラベルのテキスト属性やボタンの有効状態をリアルタイムで確認できます。
2.3 Maven 構造設計と設定ファイルの保持
.idea ディレクトリの存在は疏忽ではなく、深思熟慮の結果です。
- IDE 設定の隔たりを消除:
compiler.xmlで出力パスを明確に指定し、misc.xmlで JDK バージョンをロックします。これにより、異なる IDE や環境でもClassNotFoundExceptionなどの事故を防止します。 - リソースパスの一貫性保障: 設定ファイルでプロジェクトルート相対のパスを指定することで、どのマシンで実行しても Cookie 保存ディレクトリなどが予期せぬ場所に作成されるのを防ぎます。
- 構築詳細の暴露:
pom.xmlにおいてプラグインバージョンをロックし、パッケージの再配置(relocation)規則を設定しています。これにより、ユーザープロジェクト内の他の HttpClient バージョンとの衝突を回避し、SSL ハンドシェイク失敗などの問題を防止します。
3. 核心モジュール详解と実装要点
3.1 ログイン状態維持モジュール:双 Token メカニズムの破解
京东ログインは単なるアカウントパスワード POST ではありません。現在の主流フローは以下の通りです:
passport.jd.comへアクセスし、loginUrlとuuidを取得。- アカウントパスワードを提交し、
pt_key(長期有効 Token)とpt_pin(ユーザー标识)を取得。 - 以降のすべてのリクエストで Cookie を携带し、一部インターフェースでは Referer が必要。
AuthSessionHandler.java はこのフローを再利用可能で中断可能、リトライ可能なステートマシンとしてカプセル化します。
public class AuthSessionHandler {
private final CloseableHttpClient client;
private final CookieStore sessionStore; // 重要!すべてのリクエストでこの Store を共有
public Optional<SessionContext> establishSession(String accountId, String credential) {
// Step 1: 初期ログインページ取得、uuid と loginUrl 抽出
Optional<LoginPageData> pageData = fetchInitialPage();
if (pageData.isEmpty()) return Optional.empty();
// Step 2: フォーム提交模擬(暗号化パスワード、タイムスタンプ、乱数含む)
Optional<AuthResponse> authResult = submitCredentials(
pageData.get().getUuid(),
cryptCredential(credential), // 京东フロントエンド JS と同源アルゴリズム使用
System.currentTimeMillis()
);
// Step 3: Cookie に pt_key/pt_pin が含まれるか検証
if (verifySessionCookies()) {
return Optional.of(new SessionContext(sessionStore));
}
return Optional.empty();
}
}
关键細節と実装要点:
- パスワード暗号化アルゴリズムの同期:
CredentialEncoder.javaは京东ログインページのlogin_encrypt.jsと完全に一致する SM3 ハッシュ+AES-CBC 暗号化ロジックを実装しています。 - CookieStore のグローバル唯一性:
HttpClientインスタンスは単一化され、すべてのサービスクラスが同一の Cookie コンテナを操作するように注入されます。 - Referer ヘッダーの動的生成: すべての HTTP リクエストサブクラスで Referer ヘッダーを強制設定し、上一步レスポンスの Location ヘッダーまたは手動設定商品ページ URL から取得します。
3.2 商品カート追加モジュール:在庫インターフェースの動的ポーリング
カート追加(Add to Cart)は表面は単純ですが、以下の三重の陷阱があります:
- SKU 有効性検証: 在庫フィールドが文字列または数字の場合があり、Jackson 逆シリアライズで統一処理が必要。
- 在庫リアルタイム性: 接口返回在庫>0 でも下单時仍有貨とは限りません。「在庫事前占有」メカニズム採用のため、カート追加成功は短時間(通常 30 秒)の在庫预留権獲得に過ぎません。
- Referer 強依存: 商品詳細ページ URL を Referer として携带必须。
ItemReservationService.java の解決策は:「查询」と「追加」動作を分離し、ローカルキャッシュを導入することです。
public class ItemReservationService {
private final Cache<String, Integer> inventoryCache; // Caffeine キャッシュ、key=itemCode, value=stock
public boolean reserveItem(String itemCode, int quantity) {
// Step 1: キャッシュ確認、頻繁な接口呼び出し回避
Integer cachedStock = inventoryCache.getIfPresent(itemCode);
if (cachedStock != null && cachedStock < quantity) {
return false; // キャッシュ在庫不足
}
// Step 2: 京东在庫接口呼び出し(Referer 携带)
Optional<StockInfo> stockInfo = queryStockStatus(itemCode);
if (stockInfo.isEmpty()) return false;
// Step 3: キャッシュ更新(TTL=15 秒、真实在庫変動反映)
inventoryCache.put(itemCode, stockInfo.get().getAvailable());
// Step 4: カート追加実行(同样 Referer 携带)
return executeReservation(itemCode, quantity);
}
}
パラメータ計算と設定説明:
- キャッシュ TTL 15 秒: 接口レスポンス遅延と在庫変化粒度を考慮し、無効リクエスト削減とデータ鮮度維持のバランスを取ります。
- Referer 構築規則: 在庫確認時は商品ページ URL、カート追加時はカートアクション URL を使用します。
- カート追加リクエスト本体关键字段:
callbackUrlは Referer と一致必须。
3.3 住所選択と订单提交:协同設計
订单提交は全流程の成否关键です。京东は住所リスト取得、ID 選択、複雑なリクエスト本体提交を要求します。
AddressLocator.java と CheckoutCommand.java は契約式协作を採用します。
public class CheckoutCommand {
public Optional<OrderResult> executePurchase(AddressInfo address, String itemCode, int quantity) {
Map<String, Object> payload = new HashMap<>();
// 1. 住所情報填充(Address オブジェクト由来)
payload.put("addrId", address.getId());
payload.put("receiverName", address.getName());
payload.put("phoneNum", address.getMobile());
// 2. 動態字段填充(リアルタイム取得必要)
payload.put("payType", resolvePaymentMethod()); // 接口取得最新编码
payload.put("requestId", createRequestFingerprint()); // 6 桁乱数+タイムスタンプ MD5
payload.put("retryCount", "1"); // 強制リトライ回数
// 3. HTTP リクエスト構築
HttpPost postReq = new HttpPost("https://marathon.jd.com/order/submitOrder.action");
postReq.setEntity(new UrlEncodedFormEntity(convertToPairs(payload)));
return processRequest(postReq, OrderResult.class);
}
}
動態字段生成原理:
requestId生成: 風制御システム識別「合法クライアント」の关键指紋。形式错误或重複するとエラー返却。payType取得: 支付類型接口を呼び出し、JSON 解析。キャッシュ化(TTL=1 時間)により効率向上。retryCount: 高並発時降级処理回避のため、内部リトライロジック触发。
4. 実運用フローと关键环节実装
4.1 環境準備とプロジェクトインポート
ステップ 1:JDK バージョン確認
JDK 11 をインストールし、IDE 設定でプロジェクト SDK および言語レベルを 11 に設定します。
ステップ 2:Maven プロジェクトインポート
IDE で pom.xml 所在ディレクトリを開き、Maven モデルとしてインポートします。依存関係ダウンロード完了後、核心パッケージ(httpclient, jackson など)の存在を確認します。
ステップ 3:実行パラメータ設定
メインクラスを実行設定に登録します。UI モード実行時に JavaFX モジュール不足エラーが出る場合、OpenJFX SDK のパスを VM オプションに追加します。
ステップ 4:初回実行とログイン検証
UI 起動後、アカウント情報を入力してログイン実行します。コンソールログで Cookie 検証通過を確認し、Cookie ファイル生成をチェックします。失敗時はステータスコード(403、500、302)に基づき原因を特定します。
4.2 核心注文フローデモ
商品リンクを入力し、解析ボタンをクリックすると SKU ID 抽出と価格・在庫情報取得が自動実行されます。在庫数値は UI パネルに色分け表示されます。
「カート追加」ボタンクリック後、コンソールに在庫查询と追加成功ログが出力され、官网カートページに商品存在を確認できます。
住所選択後、「订单提交」実行。コンソールに注文リクエスト本体構築ログ、requestId 生成ログ、订单成功ログが表示され、订单番号が UI およびログファイルに記録されます。
4.3 关键設定ファイル详解
config.properties 核心パラメータ:
jd.cookie.store.path:Cookie 持久化ディレクトリ。生産環境では絶対パス推奨。jd.request.timeout:HTTP リクエストタイムアウト。高並発時短縮可能。jd.retry.times:単一接口最大リトライ回数。ログイン失敗時は増設、カート追加時は減設。cache.stock.ttl.seconds:在庫キャッシュ有効期限。熱門商品時は短縮。
logback.xml ログ設定要点:
- コンソールアペンダーは時間特定容易なフォーマット使用。
- ファイルアペンダーは日付ローテーション設定、30 日保持。
- 成功订单专用 Logger により、运维監控容易化。
5. 常见问题と排查技巧
5.1 ログイン失敗:403 Forbidden と 302 リダイレクト丢失
現象: ログイン後 403 エラー表示、または 302 後 Cookie 書き込みなし。
排查思路:
- Referer ヘッダー確認: ログインページ URL に一致する Referer 設定必須。
- 302 跳转処理検証: HttpClient でリダイレクト戦略(LaxRedirectStrategy)明示的有効化必要。無効化すると Entity 空となり Token 抽出失敗。
- パスワード暗号化キー期限切れ: 京东フロントエンド JS 更新に伴い、暗号化キー同步更新必要。開発者ツールで最新キー取得し置換。
5.2 カート追加失敗:400 Bad Request と在庫キャッシュ失效
現象: 400 エラー返却、または在庫 0 表示但网页端有貨。
排查思路:
- Referer 検証失敗: 商品ページ URL 形式厳守。特殊リンクからは SKU ID 正規表現抽出必要。
- 在庫キャッシュ更新遅延: ログ確認し、頻繁な 0 表示時は TTL 短縮または強制無効化ロジック追加。
- 接口パラメータ変更: 浏览器パケットキャプチャ比較し、不足字段(source、ext など)追加。
5.3 订单提交失敗:6001 パラメータ錯誤と requestId 生成異常
現象: 6001 エラーまたは 6002 システム繁忙。
排查思路:
- requestId 形式錯誤: 6 桁数字_13 桁ミリ秒タイムスタンプ形式厳守。システム時間 NTP 校准必要。
- payType 编码过期: 支付類型接口最新値確認し、ハードコード値更新。
- addrId 不存在: 住所リスト取得後、ID 字段型確認。Jackson 逆シリアライズ設定調整必要。
5.4 UI 界面異常:コンポーネント非表示とイベント無反応
現象: 界面空白、またはボタンクリック無反応。
排查思路:
- Swing スレッド違反: 所有 UI 更新は Event Dispatch Thread(EDT)内実行必須。耗时操作は
SwingUtilities.invokeLaterでラップ。 - UI Designer コンポーネント初期化不足: 初期化メソッド呼び出し確認。手動修正時は GUI フォーム再生成。
- フォントレンダリング問題: Linux/Mac 環境ではシステム AA フォント設定プロパティ追加し、中文字体インストール確認。