fix(desktop/weixin-gzh): tolerate numeric appMsgId and classify login timeout

The MP draft API sometimes returns appMsgId as a number or under the
appmsgid alias; coerce both shapes before treating the response as a
success. Also extend the platform auth adapter to recognize 登录超时/
请重新登录 wording so the runtime drives the account back to re-auth.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-29 17:11:19 +08:00
parent 7ca79723cd
commit 8dcd60b604
3 changed files with 25 additions and 3 deletions
@@ -45,7 +45,8 @@ type WeixinCropResponse = {
};
type WeixinOperateResponse = {
appMsgId?: string;
appMsgId?: string | number;
appmsgid?: string | number;
ret?: number;
base_resp?: {
ret?: number;
@@ -376,6 +377,17 @@ function formatWeixinError(response: WeixinOperateResponse | null | undefined):
return typeof ret === "number" ? map[ret] || `同步到草稿箱失败 (错误码: ${ret})` : "同步到草稿箱失败";
}
function normalizeWeixinArticleId(response: WeixinOperateResponse | null | undefined): string {
const value = response?.appMsgId ?? response?.appmsgid;
if (typeof value === "number") {
return Number.isFinite(value) ? String(value) : "";
}
if (typeof value === "string") {
return value.trim();
}
return "";
}
function buildOperateForm(
context: PublishAdapterContext,
meta: WeixinMeta,
@@ -558,7 +570,7 @@ export const weixinGzhAdapter: PublishAdapter = {
},
}));
const articleId = response.appMsgId?.trim() || "";
const articleId = normalizeWeixinArticleId(response);
if (!articleId) {
const message = formatWeixinError(response);
if (isWeixinChallengeMessage(message)) {
@@ -94,6 +94,16 @@ describe("platform auth adapters", () => {
).toBe("challenge");
});
it("classifies Weixin GZH login timeout as auth failure", () => {
const adapter = getPlatformAdapter("weixin_gzh");
expect(
adapter.classifyFailure({
message: "登录超时,请重新登录",
}),
).toBe("auth_failure");
});
it("classifies ZOL missing login as auth failure", () => {
const adapter = getPlatformAdapter("zol");
@@ -53,7 +53,7 @@ function classifyFailure(input: PlatformFailureInput): PlatformFailureClassifica
}
if (
/(not_logged_in|unauthorized|unauthenticated|login redirect|login required|signin|sign in|expired|401|登录态失效|请先登录|未登录)/i
/(not_logged_in|unauthorized|unauthenticated|login redirect|login required|signin|sign in|expired|401|登录态失效|登录超时|请重新登录|请先登录|未登录)/i
.test(text)
) {
return "auth_failure";