锁定微信登录失败提示
微信登录和绑手机号失败不再向页面透出原生或后端错误细节 微信 web-view auth 测试覆盖登录失败和绑手机号失败稳定提示 native shell 总门禁反查微信 auth 失败边界
This commit is contained in:
@@ -24,6 +24,8 @@ const AUTH_RESULT_STORAGE_KEY = 'genarrative:mini-program-auth-result';
|
||||
const AUTH_ACTION_LOGIN = 'login';
|
||||
const PAY_RESULT_RECHECK_DELAY_MS = 120;
|
||||
const WEB_VIEW_SHARE_TITLE = '陶泥儿';
|
||||
const WECHAT_LOGIN_UNAVAILABLE_MESSAGE = '微信登录失败,请稍后重试。';
|
||||
const WECHAT_BIND_PHONE_UNAVAILABLE_MESSAGE = '绑定手机号失败,请稍后重试。';
|
||||
|
||||
function showWebViewShareMenu() {
|
||||
if (typeof wx.showShareMenu !== 'function') {
|
||||
@@ -281,10 +283,12 @@ function wxLogin() {
|
||||
resolve(result.code);
|
||||
return;
|
||||
}
|
||||
reject(new Error('微信登录未返回 code'));
|
||||
console.error('[web-view] wx.login returned no code', result);
|
||||
reject(new Error(WECHAT_LOGIN_UNAVAILABLE_MESSAGE));
|
||||
},
|
||||
fail(error) {
|
||||
reject(new Error(error.errMsg || '微信登录失败'));
|
||||
console.error('[web-view] wx.login failed', error);
|
||||
reject(new Error(WECHAT_LOGIN_UNAVAILABLE_MESSAGE));
|
||||
},
|
||||
});
|
||||
});
|
||||
@@ -320,16 +324,12 @@ function requestMiniProgramLogin(code, displayName) {
|
||||
resolve(response.data);
|
||||
return;
|
||||
}
|
||||
const message =
|
||||
response.data &&
|
||||
response.data.error &&
|
||||
response.data.error.message
|
||||
? response.data.error.message
|
||||
: `微信登录失败:${response.statusCode}`;
|
||||
reject(new Error(message));
|
||||
console.error('[web-view] mini program login failed', response);
|
||||
reject(new Error(WECHAT_LOGIN_UNAVAILABLE_MESSAGE));
|
||||
},
|
||||
fail(error) {
|
||||
reject(new Error(error.errMsg || '微信登录请求失败'));
|
||||
console.error('[web-view] mini program login request failed', error);
|
||||
reject(new Error(WECHAT_LOGIN_UNAVAILABLE_MESSAGE));
|
||||
},
|
||||
});
|
||||
});
|
||||
@@ -366,16 +366,12 @@ function requestMiniProgramBindPhone(authToken, wechatPhoneCode, displayName) {
|
||||
resolve(response.data);
|
||||
return;
|
||||
}
|
||||
const message =
|
||||
response.data &&
|
||||
response.data.error &&
|
||||
response.data.error.message
|
||||
? response.data.error.message
|
||||
: `绑定手机号失败:${response.statusCode}`;
|
||||
reject(new Error(message));
|
||||
console.error('[web-view] mini program bind phone failed', response);
|
||||
reject(new Error(WECHAT_BIND_PHONE_UNAVAILABLE_MESSAGE));
|
||||
},
|
||||
fail(error) {
|
||||
reject(new Error(error.errMsg || '绑定手机号请求失败'));
|
||||
console.error('[web-view] mini program bind phone request failed', error);
|
||||
reject(new Error(WECHAT_BIND_PHONE_UNAVAILABLE_MESSAGE));
|
||||
},
|
||||
});
|
||||
});
|
||||
@@ -542,10 +538,10 @@ function createWechatWebViewPage() {
|
||||
webViewUrl: resolveWebViewUrl(authResult, this._lastLaunchQuery || {}),
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('[web-view] auth flow failed', error);
|
||||
this.setData({
|
||||
authResult: null,
|
||||
errorMessage:
|
||||
error && error.message ? error.message : '微信登录失败,请稍后重试。',
|
||||
errorMessage: WECHAT_LOGIN_UNAVAILABLE_MESSAGE,
|
||||
loggingIn: false,
|
||||
loading: false,
|
||||
nicknameRequired: false,
|
||||
@@ -647,12 +643,10 @@ function createWechatWebViewPage() {
|
||||
),
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('[web-view] bind phone failed', error);
|
||||
this.setData({
|
||||
bindingPhone: false,
|
||||
errorMessage:
|
||||
error && error.message
|
||||
? error.message
|
||||
: '绑定手机号失败,请稍后重试。',
|
||||
errorMessage: WECHAT_BIND_PHONE_UNAVAILABLE_MESSAGE,
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1942,6 +1942,52 @@ function assertWechatSubscribeResultBoundaries() {
|
||||
}
|
||||
}
|
||||
|
||||
function assertWechatAuthFailureBoundaries() {
|
||||
const webViewShellSource = fs.readFileSync(
|
||||
'miniprogram/shell/webView.js',
|
||||
'utf8',
|
||||
);
|
||||
const authTestSource = fs.readFileSync(
|
||||
'scripts/miniprogram-web-view-auth.test.ts',
|
||||
'utf8',
|
||||
);
|
||||
|
||||
for (const snippet of [
|
||||
"WECHAT_LOGIN_UNAVAILABLE_MESSAGE = '微信登录失败,请稍后重试。'",
|
||||
"WECHAT_BIND_PHONE_UNAVAILABLE_MESSAGE = '绑定手机号失败,请稍后重试。'",
|
||||
"console.error('[web-view] wx.login failed', error)",
|
||||
"console.error('[web-view] mini program login request failed', error)",
|
||||
"console.error('[web-view] mini program bind phone failed', response)",
|
||||
'errorMessage: WECHAT_LOGIN_UNAVAILABLE_MESSAGE',
|
||||
'errorMessage: WECHAT_BIND_PHONE_UNAVAILABLE_MESSAGE',
|
||||
]) {
|
||||
if (!webViewShellSource.includes(snippet)) {
|
||||
throw new Error(`wechat auth shell must include ${snippet}`);
|
||||
}
|
||||
}
|
||||
for (const forbiddenSnippet of [
|
||||
"reject(new Error(error.errMsg || '微信登录失败'))",
|
||||
"reject(new Error(error.errMsg || '微信登录请求失败'))",
|
||||
"reject(new Error(error.errMsg || '绑定手机号请求失败'))",
|
||||
"error && error.message ? error.message : '微信登录失败,请稍后重试。'",
|
||||
'response.data.error.message',
|
||||
]) {
|
||||
if (webViewShellSource.includes(forbiddenSnippet)) {
|
||||
throw new Error(`wechat auth shell must not expose native failure detail via ${forbiddenSnippet}`);
|
||||
}
|
||||
}
|
||||
for (const snippet of [
|
||||
'微信登录失败不向页面透出原生错误',
|
||||
'绑定手机号失败不向页面透出后端错误体',
|
||||
"expect(page.data.errorMessage).toBe('微信登录失败,请稍后重试。')",
|
||||
"expect(page.data.errorMessage).toBe('绑定手机号失败,请稍后重试。')",
|
||||
]) {
|
||||
if (!authTestSource.includes(snippet)) {
|
||||
throw new Error(`wechat auth boundary test must include ${snippet}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function assertHostBridgeLayerLayout() {
|
||||
assertSameList(
|
||||
readDirectoryFileList(
|
||||
@@ -2175,6 +2221,9 @@ assertWechatPaymentResultBoundaries();
|
||||
console.log('[check:native-shells] wechat-subscribe-result-boundaries');
|
||||
assertWechatSubscribeResultBoundaries();
|
||||
|
||||
console.log('[check:native-shells] wechat-auth-failure-boundaries');
|
||||
assertWechatAuthFailureBoundaries();
|
||||
|
||||
console.log('[check:native-shells] h5-host-bridge-event-subscription-gates');
|
||||
assertH5HostBridgeEventSubscriptionGates();
|
||||
|
||||
|
||||
@@ -113,6 +113,7 @@ function loadCommonJsModule(
|
||||
describe('mini-program web-view auth page', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
vi.spyOn(console, 'error').mockImplementation(() => {});
|
||||
});
|
||||
|
||||
test('默认进入时不预登录,直接打开未登录 web-view', async () => {
|
||||
@@ -303,4 +304,55 @@ describe('mini-program web-view auth page', () => {
|
||||
expect(page.data.loading).toBe(false);
|
||||
expect(page.data.phoneBindingRequired).toBe(true);
|
||||
});
|
||||
|
||||
test('微信登录失败不向页面透出原生错误', async () => {
|
||||
const wxMock = createWxMock();
|
||||
const loginError = { errMsg: 'login:fail private native detail' };
|
||||
wxMock.login.mockImplementation(({ fail }) => {
|
||||
fail(loginError);
|
||||
});
|
||||
const page = loadWebViewPage(wxMock);
|
||||
|
||||
await page.onLoad({ authAction: 'login', returnTo: 'previous' });
|
||||
|
||||
expect(page.data.errorMessage).toBe('微信登录失败,请稍后重试。');
|
||||
expect(console.error).toHaveBeenCalledWith(
|
||||
'[web-view] wx.login failed',
|
||||
loginError,
|
||||
);
|
||||
expect(page.data.phoneBindingRequired).toBe(false);
|
||||
});
|
||||
|
||||
test('绑定手机号失败不向页面透出后端错误体', async () => {
|
||||
const wxMock = createWxMock();
|
||||
const page = loadWebViewPage(wxMock);
|
||||
page.data.authResult = {
|
||||
token: 'jwt-pending-wechat',
|
||||
bindingStatus: 'pending_bind_phone',
|
||||
};
|
||||
wxMock.request.mockImplementation(({ success }) => {
|
||||
success({
|
||||
statusCode: 500,
|
||||
data: {
|
||||
error: {
|
||||
message: 'private backend detail',
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
await page.handleGetPhoneNumber({
|
||||
detail: {
|
||||
code: 'wechat-phone-code',
|
||||
},
|
||||
});
|
||||
|
||||
expect(page.data.errorMessage).toBe('绑定手机号失败,请稍后重试。');
|
||||
expect(console.error).toHaveBeenCalledWith(
|
||||
'[web-view] mini program bind phone failed',
|
||||
expect.objectContaining({
|
||||
statusCode: 500,
|
||||
}),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user