开店需要验证手机号

This commit is contained in:
2026-07-12 17:51:20 +08:00
parent b550ee2255
commit 908a5dcf0f
7 changed files with 235 additions and 9 deletions
@@ -84,6 +84,7 @@ export class AuthService {
return ClientApp.HQ_WEB;
case SmsScene.PARTNER_LOGIN:
case SmsScene.PARTNER_STAFF_ADD:
case SmsScene.PARTNER_STORE_OPEN:
return ClientApp.PARTNER_H5;
case SmsScene.HQ_LOGIN:
return ClientApp.HQ_WEB;
@@ -119,6 +120,13 @@ export class AuthService {
});
return account ? { refType: 'STORE', refId: account.id } : undefined;
}
case SmsScene.PARTNER_STORE_OPEN: {
const account = await this.prisma.storeAccount.findUnique({
where: { phone },
select: { id: true },
});
return account ? { refType: 'STORE', refId: account.id } : undefined;
}
case SmsScene.PARTNER_LOGIN:
case SmsScene.PARTNER_STAFF_ADD: {
const account = await this.prisma.partnerAccount.findUnique({
@@ -292,6 +300,9 @@ export class AuthService {
if (scene === SmsScene.PARTNER_PROXY_ORDER) {
return;
}
if (scene === SmsScene.PARTNER_STORE_OPEN) {
return;
}
}
async verifySmsCode(phone: string, code: string, scene: SmsScene) {
@@ -41,6 +41,11 @@ export class PartnerStoreController {
return this.storeService.partnerCheckStorePhone(phone ?? '');
}
@Post('send-phone-sms')
sendPhoneSms(@Body() body: { phone: string }) {
return this.storeService.sendPartnerStorePhoneSms(body.phone);
}
@Get(':id')
detail(@CurrentUser() user: AuthUser, @Param('id') id: string) {
return this.storeService.partnerGetStore(user.actorId, BigInt(id));
@@ -4,7 +4,7 @@ import {
Injectable,
NotFoundException,
} from '@nestjs/common';
import { loadAppConfig } from '@dukang/shared-types';
import { loadAppConfig, ClientApp, SmsScene } from '@dukang/shared-types';
import { PARTNER_STAFF_ROLE_LABELS, PartnerStaffRole, type PartnerLeaderboardPeriod } from '@dukang/shared-types';
import { PrismaService } from '../../common/prisma/prisma.module';
import { serializeBigInt } from '../../common/decorators/current-user.decorator';
@@ -12,6 +12,7 @@ import { mapStoreCompat } from '../../common/compat/v31-compat';
import { parseBigIntParam } from '../../common/parse-bigint';
import { AnalyticsService } from '../analytics/analytics.service';
import { PartnerCityService } from '../city-scope/partner-city.service';
import { AuthService } from '../iam/auth.service';
@Injectable()
export class StoreService {
@@ -21,6 +22,7 @@ export class StoreService {
private readonly prisma: PrismaService,
private readonly analyticsService: AnalyticsService,
private readonly partnerCityService: PartnerCityService,
private readonly authService: AuthService,
) {}
async listOpenStores(cityCode?: string) {
@@ -139,9 +141,29 @@ export class StoreService {
};
}
async sendPartnerStorePhoneSms(phone: string) {
const check = await this.partnerCheckStorePhone(phone);
if (!check.available) {
throw new BadRequestException(check.message ?? '该手机号不可用于门店账号');
}
return this.authService.sendSms(phone.trim(), SmsScene.PARTNER_STORE_OPEN, {
clientApp: ClientApp.PARTNER_H5,
}).then(() => {
const normalizedPhone = phone.trim();
const masked =
normalizedPhone.length >= 7
? `${normalizedPhone.slice(0, 3)}****${normalizedPhone.slice(-4)}`
: normalizedPhone;
return { ok: true, maskedPhone: masked };
});
}
async createStore(partnerAccountId: bigint, body: Record<string, unknown>) {
const { primaryId } = await this.resolvePartnerScope(partnerAccountId);
const normalizedPhone = String(body.phone).trim();
const smsCode = body.smsCode ? String(body.smsCode).trim() : '';
if (!smsCode) throw new BadRequestException('请输入门店手机号验证码');
await this.authService.verifySmsCode(normalizedPhone, smsCode, SmsScene.PARTNER_STORE_OPEN);
const confirmBindExisting = body.confirmBindExisting === true || body.confirmBindExisting === 'true';
await this.assertStorePhoneAvailable(normalizedPhone, confirmBindExisting);