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 = { type WeixinOperateResponse = {
appMsgId?: string; appMsgId?: string | number;
appmsgid?: string | number;
ret?: number; ret?: number;
base_resp?: { base_resp?: {
ret?: number; ret?: number;
@@ -376,6 +377,17 @@ function formatWeixinError(response: WeixinOperateResponse | null | undefined):
return typeof ret === "number" ? map[ret] || `同步到草稿箱失败 (错误码: ${ret})` : "同步到草稿箱失败"; 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( function buildOperateForm(
context: PublishAdapterContext, context: PublishAdapterContext,
meta: WeixinMeta, meta: WeixinMeta,
@@ -558,7 +570,7 @@ export const weixinGzhAdapter: PublishAdapter = {
}, },
})); }));
const articleId = response.appMsgId?.trim() || ""; const articleId = normalizeWeixinArticleId(response);
if (!articleId) { if (!articleId) {
const message = formatWeixinError(response); const message = formatWeixinError(response);
if (isWeixinChallengeMessage(message)) { if (isWeixinChallengeMessage(message)) {
@@ -94,6 +94,16 @@ describe("platform auth adapters", () => {
).toBe("challenge"); ).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", () => { it("classifies ZOL missing login as auth failure", () => {
const adapter = getPlatformAdapter("zol"); const adapter = getPlatformAdapter("zol");
@@ -53,7 +53,7 @@ function classifyFailure(input: PlatformFailureInput): PlatformFailureClassifica
} }
if ( 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) .test(text)
) { ) {
return "auth_failure"; return "auth_failure";