小i機器人(Xiaoi)提供 NLP 開放平台,採用 Digest Access Authentication 風格的簽名機制:AppKey + Realm + AppSecret 經 SHA-1 產生 HA1,Method + URI 產生 HA2,再結合 nonce 產生最終 signature。本範例封裝完整流程。
String realm = "xiaoi.com";
String method = "POST";
String uri = "/robot/ask.do";
// 1. 隨機 nonce(20 bytes → 40 hex chars)
byte[] b = new byte[20];
new Random().nextBytes(b);
String nonce = new String(Hex.encodeHex(b));
// 2. HA1 = SHA1(AppKey:realm:AppSecret)
String HA1 = DigestUtils.shaHex(AppKey + ":" + realm + ":" + AppSecret);
// 3. HA2 = SHA1(Method:URI)
String HA2 = DigestUtils.shaHex(method + ":" + uri);
// 4. signature = SHA1(HA1:nonce:HA2)
String signature = DigestUtils.shaHex(HA1 + ":" + nonce + ":" + HA2);
// 5. 請求頭
String authHeader = "app_key=\"" + AppKey + "\", nonce=\"" + nonce + "\", signature=\"" + signature + "\"";
HttpClient client = new HttpClient();
PostMethod post = new PostMethod("https://nlp.xiaoi.com/robot/ask.do");
post.getParams().setParameter(HttpMethodParams.HTTP_CONTENT_CHARSET, "utf-8");
post.addRequestHeader("X-Auth", authHeader);
post.setParameter("platform", "weixin");
post.setParameter("type", "0");
post.setParameter("userId", userId); // 使用者識別
post.setParameter("question", question); // 使用者提問
int status = client.executeMethod(post);
if (status == 200) return post.getResponseBodyAsString();
<dependency>
<groupId>commons-codec</groupId> <artifactId>commons-codec</artifactId> <version>1.15</version>
</dependency>
<dependency>
<groupId>commons-httpclient</groupId> <artifactId>commons-httpclient</artifactId> <version>3.1</version>
</dependency>
<dependency>
<groupId>commons-lang</groupId> <artifactId>commons-lang</artifactId> <version>2.6</version>
</dependency>
注意:commons-httpclient 為舊版(3.x),新專案建議改用 HttpComponents HttpClient 4.5+ 或 OkHttp,簽名邏輯不變,只需調整請求建構方式。
APP_KEY/SECRET 勿硬編碼,放入配置中心或環境變數。signature、question 等敏感資訊。https://nlp.xiaoi.com,驗證伺服器憑證。