合伙人端登录验证调整还有日志落地

This commit is contained in:
2026-07-07 14:34:02 +08:00
parent af989c9d33
commit 2e61caa49c
23 changed files with 1018 additions and 47 deletions
@@ -167,6 +167,44 @@ export class AuthService {
});
}
private trackPartnerEvent(
partnerAccountId: bigint | undefined,
partnerId: bigint,
clientApp: ClientApp | string,
eventName: string,
extraJson?: Record<string, unknown>,
ref?: { refType?: string; refId?: bigint },
) {
this.analyticsService.trackPartnerOneSafe(partnerAccountId, clientApp, {
partnerId,
eventName,
refType: ref?.refType,
refId: ref?.refId,
extraJson,
});
}
private async assertPartnerAccountByPhone(phone: string) {
const account = await this.prisma.partnerAccount.findUnique({
where: { phone },
include: { partner: true },
});
if (!account) throw new BadRequestException('未找到合伙人账号');
if (account.status !== 'ACTIVE') throw new BadRequestException('合伙人账号已停用');
return account;
}
async checkPartnerPhone(phone: string) {
const normalizedPhone = this.assertMobilePhone(phone);
const account = await this.assertPartnerAccountByPhone(normalizedPhone);
return {
ok: true,
maskedPhone: this.maskPhone(normalizedPhone),
name: account.name,
companyName: account.partner.companyName,
};
}
private async assertSmsSendAllowed(phone: string, scene: SmsScene) {
if (scene === SmsScene.STORE_LOGIN) {
const account = await this.prisma.storeAccount.findUnique({ where: { phone } });
@@ -177,6 +215,10 @@ export class AuthService {
if (scene === SmsScene.STORE_ACCOUNT_OPEN) {
const existing = await this.prisma.storeAccount.findUnique({ where: { phone } });
if (existing) throw new BadRequestException('该手机号已绑定门店');
return;
}
if (scene === SmsScene.PARTNER_LOGIN || scene === SmsScene.PARTNER_STAFF_ADD) {
await this.assertPartnerAccountByPhone(phone);
}
}
@@ -252,6 +294,28 @@ export class AuthService {
});
}
}
if (
(scene === SmsScene.PARTNER_LOGIN || scene === SmsScene.PARTNER_STAFF_ADD) &&
actorRef?.refType === 'PARTNER'
) {
const partnerAccount = await this.prisma.partnerAccount.findUnique({
where: { id: actorRef.refId },
select: { id: true, partnerId: true },
});
if (partnerAccount) {
this.trackPartnerEvent(
partnerAccount.id,
partnerAccount.partnerId,
clientApp,
'partner_sms_send',
{
scene,
phone: this.maskPhone(normalizedPhone),
status: 'success',
},
);
}
}
} catch (err) {
if (err instanceof BadRequestException) throw err;
const message = err instanceof Error ? err.message : '短信发送失败';
@@ -504,16 +568,34 @@ export class AuthService {
async loginPartner(phone: string, code: string, clientApp: ClientApp) {
const normalizedPhone = this.assertMobilePhone(phone);
await this.smsProvider.verify(normalizedPhone, code, SmsScene.PARTNER_LOGIN);
try {
await this.smsProvider.verify(normalizedPhone, code, SmsScene.PARTNER_LOGIN);
} catch (err) {
const account = await this.prisma.partnerAccount.findUnique({ where: { phone: normalizedPhone } });
if (account) {
this.trackPartnerEvent(account.id, account.partnerId, clientApp, 'partner_sms_verify_fail', {
phone: this.maskPhone(normalizedPhone),
reason: err instanceof BadRequestException ? err.message : '验证码错误',
});
}
throw err;
}
const account = await this.prisma.partnerAccount.findUnique({
where: { phone: normalizedPhone },
include: { partner: true },
});
if (!account) throw new BadRequestException('合伙人账号不存在');
if (!account) throw new BadRequestException('未找到合伙人账号');
if (account.status !== 'ACTIVE') throw new BadRequestException('合伙人账号已停用');
await this.prisma.partnerAccount.update({
where: { id: account.id },
data: { lastLoginAt: new Date() },
});
this.trackPartnerEvent(account.id, account.partnerId, clientApp, 'partner_sms_login', {
phone: this.maskPhone(normalizedPhone),
});
this.trackPartnerEvent(account.id, account.partnerId, clientApp, 'partner_login_success', {
method: 'sms',
});
return this.issueToken('PARTNER', account.id, clientApp, false, undefined, undefined, {
id: account.id.toString(),
partnerId: account.partnerId.toString(),
@@ -1012,6 +1094,8 @@ export class AuthService {
include: { partner: true },
});
this.trackPartnerEvent(updated.id, updated.partnerId, clientApp, 'partner_wechat_bind', { platform });
return this.issueToken('PARTNER', updated.id, clientApp, false, undefined, undefined, {
id: updated.id.toString(),
partnerId: updated.partnerId.toString(),
@@ -1057,6 +1141,11 @@ export class AuthService {
include: { partner: true },
});
this.trackPartnerEvent(account.id, account.partnerId, clientApp, 'partner_wechat_login', { platform });
this.trackPartnerEvent(account.id, account.partnerId, clientApp, 'partner_login_success', {
method: 'wechat',
});
return this.issueToken('PARTNER', account.id, clientApp, false, undefined, undefined, {
id: account.id.toString(),
partnerId: account.partnerId.toString(),