开店需要验证手机号
This commit is contained in:
@@ -6,6 +6,7 @@ export type StoreDraftForm = {
|
|||||||
district: string;
|
district: string;
|
||||||
name: string;
|
name: string;
|
||||||
phone: string;
|
phone: string;
|
||||||
|
storeSmsCode: string;
|
||||||
address: string;
|
address: string;
|
||||||
intro: string;
|
intro: string;
|
||||||
coverUrl: string;
|
coverUrl: string;
|
||||||
@@ -34,6 +35,7 @@ export const defaultStoreForm = (): StoreDraftForm => ({
|
|||||||
cityId: '',
|
cityId: '',
|
||||||
name: '',
|
name: '',
|
||||||
phone: '',
|
phone: '',
|
||||||
|
storeSmsCode: '',
|
||||||
address: '',
|
address: '',
|
||||||
intro: '',
|
intro: '',
|
||||||
coverUrl: '',
|
coverUrl: '',
|
||||||
@@ -64,6 +66,7 @@ function normalizeForm(raw: Record<string, unknown>): StoreDraftForm {
|
|||||||
district: String(raw.district ?? base.district),
|
district: String(raw.district ?? base.district),
|
||||||
name: String(raw.name ?? base.name),
|
name: String(raw.name ?? base.name),
|
||||||
phone: String(raw.phone ?? base.phone),
|
phone: String(raw.phone ?? base.phone),
|
||||||
|
storeSmsCode: String(raw.storeSmsCode ?? base.storeSmsCode),
|
||||||
address: String(raw.address ?? base.address),
|
address: String(raw.address ?? base.address),
|
||||||
intro: String(raw.intro ?? base.intro),
|
intro: String(raw.intro ?? base.intro),
|
||||||
coverUrl: String(raw.coverUrl ?? base.coverUrl),
|
coverUrl: String(raw.coverUrl ?? base.coverUrl),
|
||||||
@@ -112,13 +115,18 @@ const PHONE_RE = /^1\d{10}$/;
|
|||||||
const BANK_RE = /^\d{16,19}$/;
|
const BANK_RE = /^\d{16,19}$/;
|
||||||
|
|
||||||
export function validateStoreStep1(
|
export function validateStoreStep1(
|
||||||
form: Pick<StoreDraftForm, 'regionCodes' | 'cityId' | 'name' | 'phone' | 'address' | 'intro'>,
|
form: Pick<
|
||||||
|
StoreDraftForm,
|
||||||
|
'regionCodes' | 'cityId' | 'name' | 'phone' | 'storeSmsCode' | 'address' | 'intro'
|
||||||
|
>,
|
||||||
): string | null {
|
): string | null {
|
||||||
if (!form.regionCodes || form.regionCodes.length < 3) return '请选择省 / 市 / 区县';
|
if (!form.regionCodes || form.regionCodes.length < 3) return '请选择省 / 市 / 区县';
|
||||||
if (!form.cityId) return '所选地区未匹配到开城城市,请联系总部配置开城区划';
|
if (!form.cityId) return '所选地区未匹配到开城城市,请联系总部配置开城区划';
|
||||||
if (!form.name.trim()) return '请填写门店名称';
|
if (!form.name.trim()) return '请填写门店名称';
|
||||||
if (!form.phone.trim()) return '请填写联系电话';
|
if (!form.phone.trim()) return '请填写联系电话';
|
||||||
if (!PHONE_RE.test(form.phone.trim())) return '联系电话须为11位手机号';
|
if (!PHONE_RE.test(form.phone.trim())) return '联系电话须为11位手机号';
|
||||||
|
if (!form.storeSmsCode.trim()) return '请输入门店手机号验证码';
|
||||||
|
if (!/^\d{4,6}$/.test(form.storeSmsCode.trim())) return '验证码格式不正确';
|
||||||
if (!form.address.trim()) return '请填写详细地址';
|
if (!form.address.trim()) return '请填写详细地址';
|
||||||
if (form.intro.trim()) {
|
if (form.intro.trim()) {
|
||||||
const len = form.intro.trim().length;
|
const len = form.intro.trim().length;
|
||||||
|
|||||||
@@ -8,4 +8,12 @@ export function checkStorePhoneAvailable(phone: string) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function sendStorePhoneSms(phone: string) {
|
||||||
|
return request<{ ok: boolean; maskedPhone: string }>('PARTNER_H5', '/partner/stores/send-phone-sms', {
|
||||||
|
method: 'POST',
|
||||||
|
body: JSON.stringify({ phone: phone.trim() }),
|
||||||
|
silent: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
export type { PartnerStorePhoneAvailableResponse };
|
export type { PartnerStorePhoneAvailableResponse };
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import { toastError, toastSuccess } from '../lib/toast';
|
|||||||
|
|
||||||
import { resolveRegionBinding } from '../lib/china-region';
|
import { resolveRegionBinding } from '../lib/china-region';
|
||||||
|
|
||||||
import { checkStorePhoneAvailable } from '../lib/storePhone';
|
import { checkStorePhoneAvailable, sendStorePhoneSms } from '../lib/storePhone';
|
||||||
|
|
||||||
import { fetchPartnerCities, type OpenCityOption } from '../lib/upload';
|
import { fetchPartnerCities, type OpenCityOption } from '../lib/upload';
|
||||||
|
|
||||||
@@ -54,6 +54,8 @@ type FieldErrors = {
|
|||||||
|
|
||||||
phone?: string;
|
phone?: string;
|
||||||
|
|
||||||
|
storeSmsCode?: string;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -68,7 +70,7 @@ function isPhoneConflictMessage(message: string) {
|
|||||||
|
|
||||||
function isPhoneValidationMessage(message: string) {
|
function isPhoneValidationMessage(message: string) {
|
||||||
|
|
||||||
return message.includes('联系电话') || message.includes('手机号');
|
return message.includes('联系电话') || message.includes('手机号') || message.includes('验证码');
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,6 +110,10 @@ export default function StoreCreatePage() {
|
|||||||
|
|
||||||
const [citiesError, setCitiesError] = useState('');
|
const [citiesError, setCitiesError] = useState('');
|
||||||
|
|
||||||
|
const [smsCooldown, setSmsCooldown] = useState(0);
|
||||||
|
|
||||||
|
const [smsHint, setSmsHint] = useState('');
|
||||||
|
|
||||||
function reportFormError(message: string) {
|
function reportFormError(message: string) {
|
||||||
setSubmitError(message);
|
setSubmitError(message);
|
||||||
}
|
}
|
||||||
@@ -216,16 +222,28 @@ export default function StoreCreatePage() {
|
|||||||
|
|
||||||
function patchForm(patch: Partial<StoreDraftForm>) {
|
function patchForm(patch: Partial<StoreDraftForm>) {
|
||||||
|
|
||||||
setForm((prev) => ({ ...prev, ...patch }));
|
|
||||||
|
|
||||||
setSubmitError('');
|
setSubmitError('');
|
||||||
|
|
||||||
|
let nextPatch = patch;
|
||||||
|
|
||||||
if ('phone' in patch) {
|
if ('phone' in patch) {
|
||||||
|
|
||||||
setFieldErrors((prev) => ({ ...prev, phone: undefined }));
|
setFieldErrors((prev) => ({ ...prev, phone: undefined, storeSmsCode: undefined }));
|
||||||
|
|
||||||
|
setSmsHint('');
|
||||||
|
|
||||||
|
nextPatch = { ...patch, storeSmsCode: '' };
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ('storeSmsCode' in patch) {
|
||||||
|
|
||||||
|
setFieldErrors((prev) => ({ ...prev, storeSmsCode: undefined }));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
setForm((prev) => ({ ...prev, ...nextPatch }));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -286,6 +304,70 @@ export default function StoreCreatePage() {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
async function sendStorePhoneCode() {
|
||||||
|
|
||||||
|
const phone = form.phone.trim();
|
||||||
|
|
||||||
|
if (!/^1\d{10}$/.test(phone)) {
|
||||||
|
|
||||||
|
setFieldErrors({ phone: '请先填写正确的11位手机号' });
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
setSmsHint('');
|
||||||
|
|
||||||
|
setFieldErrors((prev) => ({ ...prev, phone: undefined }));
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
const phoneCheck = await checkStorePhoneAvailable(phone);
|
||||||
|
|
||||||
|
if (!phoneCheck.available) {
|
||||||
|
|
||||||
|
setFieldErrors({ phone: phoneCheck.message ?? '该手机号不可用于门店账号' });
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const res = await sendStorePhoneSms(phone);
|
||||||
|
|
||||||
|
setSmsHint(`验证码已发送至 ${res.maskedPhone}`);
|
||||||
|
|
||||||
|
setSmsCooldown(60);
|
||||||
|
|
||||||
|
const timer = setInterval(() => {
|
||||||
|
|
||||||
|
setSmsCooldown((s) => {
|
||||||
|
|
||||||
|
if (s <= 1) {
|
||||||
|
|
||||||
|
clearInterval(timer);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return s - 1;
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
}, 1000);
|
||||||
|
|
||||||
|
} catch (e) {
|
||||||
|
|
||||||
|
const msg = e instanceof Error ? e.message : '验证码发送失败';
|
||||||
|
|
||||||
|
setFieldErrors({ phone: msg });
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
async function handleNext() {
|
async function handleNext() {
|
||||||
|
|
||||||
if (step === 1) {
|
if (step === 1) {
|
||||||
@@ -293,7 +375,15 @@ export default function StoreCreatePage() {
|
|||||||
const msg = validateStoreStep1(form);
|
const msg = validateStoreStep1(form);
|
||||||
|
|
||||||
if (msg) {
|
if (msg) {
|
||||||
reportFormError(msg);
|
if (isPhoneValidationMessage(msg)) {
|
||||||
|
if (msg.includes('验证码')) {
|
||||||
|
setFieldErrors({ storeSmsCode: msg });
|
||||||
|
} else {
|
||||||
|
setFieldErrors({ phone: msg });
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
reportFormError(msg);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -365,7 +455,12 @@ export default function StoreCreatePage() {
|
|||||||
|
|
||||||
if (step1Msg) {
|
if (step1Msg) {
|
||||||
if (isPhoneValidationMessage(step1Msg)) {
|
if (isPhoneValidationMessage(step1Msg)) {
|
||||||
setFieldErrors({ phone: step1Msg });
|
if (step1Msg.includes('验证码')) {
|
||||||
|
setFieldErrors({ storeSmsCode: step1Msg });
|
||||||
|
} else {
|
||||||
|
setFieldErrors({ phone: step1Msg });
|
||||||
|
}
|
||||||
|
goStep(1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
reportFormError(step1Msg);
|
reportFormError(step1Msg);
|
||||||
@@ -448,6 +543,8 @@ export default function StoreCreatePage() {
|
|||||||
|
|
||||||
phone: form.phone.trim(),
|
phone: form.phone.trim(),
|
||||||
|
|
||||||
|
smsCode: form.storeSmsCode.trim(),
|
||||||
|
|
||||||
district: form.district.trim(),
|
district: form.district.trim(),
|
||||||
|
|
||||||
address: form.address.trim(),
|
address: form.address.trim(),
|
||||||
@@ -481,6 +578,11 @@ export default function StoreCreatePage() {
|
|||||||
setFieldErrors({ phone: message });
|
setFieldErrors({ phone: message });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (/验证码/.test(message)) {
|
||||||
|
setFieldErrors({ storeSmsCode: message });
|
||||||
|
goStep(1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
setSubmitError(message);
|
setSubmitError(message);
|
||||||
toastError(message);
|
toastError(message);
|
||||||
} finally {
|
} finally {
|
||||||
@@ -631,6 +733,74 @@ export default function StoreCreatePage() {
|
|||||||
|
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
<p className="label-md text-muted" style={{ marginTop: 8 }}>
|
||||||
|
|
||||||
|
验证码将发送至该手机号,需门店负责人确认后方可录入
|
||||||
|
|
||||||
|
</p>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="partner-field">
|
||||||
|
|
||||||
|
<label>门店账号验证码 <span className="text-primary">*</span></label>
|
||||||
|
|
||||||
|
<div className="partner-input-row">
|
||||||
|
|
||||||
|
<div className="partner-input-wrap" style={{ flex: 1 }}>
|
||||||
|
|
||||||
|
<span className="material-symbols-outlined partner-input-icon">shield</span>
|
||||||
|
|
||||||
|
<input
|
||||||
|
|
||||||
|
className="partner-input"
|
||||||
|
|
||||||
|
type="text"
|
||||||
|
|
||||||
|
inputMode="numeric"
|
||||||
|
|
||||||
|
maxLength={6}
|
||||||
|
|
||||||
|
placeholder="请输入短信验证码"
|
||||||
|
|
||||||
|
value={form.storeSmsCode}
|
||||||
|
|
||||||
|
onChange={(e) => patchForm({ storeSmsCode: e.target.value.replace(/\D/g, '') })}
|
||||||
|
|
||||||
|
/>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button
|
||||||
|
|
||||||
|
type="button"
|
||||||
|
|
||||||
|
className="partner-code-btn"
|
||||||
|
|
||||||
|
disabled={smsCooldown > 0 || checkingPhone}
|
||||||
|
|
||||||
|
onClick={() => void sendStorePhoneCode()}
|
||||||
|
|
||||||
|
>
|
||||||
|
|
||||||
|
{smsCooldown > 0 ? `${smsCooldown}s` : '获取验证码'}
|
||||||
|
|
||||||
|
</button>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{smsHint && (
|
||||||
|
|
||||||
|
<p className="label-md text-muted" style={{ marginTop: 8 }}>{smsHint}</p>
|
||||||
|
|
||||||
|
)}
|
||||||
|
|
||||||
|
{fieldErrors.storeSmsCode && (
|
||||||
|
|
||||||
|
<p className="partner-field-error" role="alert">{fieldErrors.storeSmsCode}</p>
|
||||||
|
|
||||||
|
)}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="partner-field">
|
<div className="partner-field">
|
||||||
|
|||||||
@@ -48,6 +48,8 @@ export enum SmsScene {
|
|||||||
REDEEM_PHONE_CONFIRM = 'REDEEM_PHONE_CONFIRM',
|
REDEEM_PHONE_CONFIRM = 'REDEEM_PHONE_CONFIRM',
|
||||||
/** 合伙人代下单:线下代发货确认验证码(发至用户手机) */
|
/** 合伙人代下单:线下代发货确认验证码(发至用户手机) */
|
||||||
PARTNER_PROXY_ORDER = 'PARTNER_PROXY_ORDER',
|
PARTNER_PROXY_ORDER = 'PARTNER_PROXY_ORDER',
|
||||||
|
/** 合伙人录店:门店登录手机号验证码(发至门店负责人手机) */
|
||||||
|
PARTNER_STORE_OPEN = 'PARTNER_STORE_OPEN',
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum OrderType {
|
export enum OrderType {
|
||||||
|
|||||||
@@ -84,6 +84,7 @@ export class AuthService {
|
|||||||
return ClientApp.HQ_WEB;
|
return ClientApp.HQ_WEB;
|
||||||
case SmsScene.PARTNER_LOGIN:
|
case SmsScene.PARTNER_LOGIN:
|
||||||
case SmsScene.PARTNER_STAFF_ADD:
|
case SmsScene.PARTNER_STAFF_ADD:
|
||||||
|
case SmsScene.PARTNER_STORE_OPEN:
|
||||||
return ClientApp.PARTNER_H5;
|
return ClientApp.PARTNER_H5;
|
||||||
case SmsScene.HQ_LOGIN:
|
case SmsScene.HQ_LOGIN:
|
||||||
return ClientApp.HQ_WEB;
|
return ClientApp.HQ_WEB;
|
||||||
@@ -119,6 +120,13 @@ export class AuthService {
|
|||||||
});
|
});
|
||||||
return account ? { refType: 'STORE', refId: account.id } : undefined;
|
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_LOGIN:
|
||||||
case SmsScene.PARTNER_STAFF_ADD: {
|
case SmsScene.PARTNER_STAFF_ADD: {
|
||||||
const account = await this.prisma.partnerAccount.findUnique({
|
const account = await this.prisma.partnerAccount.findUnique({
|
||||||
@@ -292,6 +300,9 @@ export class AuthService {
|
|||||||
if (scene === SmsScene.PARTNER_PROXY_ORDER) {
|
if (scene === SmsScene.PARTNER_PROXY_ORDER) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (scene === SmsScene.PARTNER_STORE_OPEN) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async verifySmsCode(phone: string, code: string, scene: SmsScene) {
|
async verifySmsCode(phone: string, code: string, scene: SmsScene) {
|
||||||
|
|||||||
@@ -41,6 +41,11 @@ export class PartnerStoreController {
|
|||||||
return this.storeService.partnerCheckStorePhone(phone ?? '');
|
return this.storeService.partnerCheckStorePhone(phone ?? '');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Post('send-phone-sms')
|
||||||
|
sendPhoneSms(@Body() body: { phone: string }) {
|
||||||
|
return this.storeService.sendPartnerStorePhoneSms(body.phone);
|
||||||
|
}
|
||||||
|
|
||||||
@Get(':id')
|
@Get(':id')
|
||||||
detail(@CurrentUser() user: AuthUser, @Param('id') id: string) {
|
detail(@CurrentUser() user: AuthUser, @Param('id') id: string) {
|
||||||
return this.storeService.partnerGetStore(user.actorId, BigInt(id));
|
return this.storeService.partnerGetStore(user.actorId, BigInt(id));
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import {
|
|||||||
Injectable,
|
Injectable,
|
||||||
NotFoundException,
|
NotFoundException,
|
||||||
} from '@nestjs/common';
|
} 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 { PARTNER_STAFF_ROLE_LABELS, PartnerStaffRole, type PartnerLeaderboardPeriod } from '@dukang/shared-types';
|
||||||
import { PrismaService } from '../../common/prisma/prisma.module';
|
import { PrismaService } from '../../common/prisma/prisma.module';
|
||||||
import { serializeBigInt } from '../../common/decorators/current-user.decorator';
|
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 { parseBigIntParam } from '../../common/parse-bigint';
|
||||||
import { AnalyticsService } from '../analytics/analytics.service';
|
import { AnalyticsService } from '../analytics/analytics.service';
|
||||||
import { PartnerCityService } from '../city-scope/partner-city.service';
|
import { PartnerCityService } from '../city-scope/partner-city.service';
|
||||||
|
import { AuthService } from '../iam/auth.service';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class StoreService {
|
export class StoreService {
|
||||||
@@ -21,6 +22,7 @@ export class StoreService {
|
|||||||
private readonly prisma: PrismaService,
|
private readonly prisma: PrismaService,
|
||||||
private readonly analyticsService: AnalyticsService,
|
private readonly analyticsService: AnalyticsService,
|
||||||
private readonly partnerCityService: PartnerCityService,
|
private readonly partnerCityService: PartnerCityService,
|
||||||
|
private readonly authService: AuthService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async listOpenStores(cityCode?: string) {
|
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>) {
|
async createStore(partnerAccountId: bigint, body: Record<string, unknown>) {
|
||||||
const { primaryId } = await this.resolvePartnerScope(partnerAccountId);
|
const { primaryId } = await this.resolvePartnerScope(partnerAccountId);
|
||||||
const normalizedPhone = String(body.phone).trim();
|
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';
|
const confirmBindExisting = body.confirmBindExisting === true || body.confirmBindExisting === 'true';
|
||||||
await this.assertStorePhoneAvailable(normalizedPhone, confirmBindExisting);
|
await this.assertStorePhoneAvailable(normalizedPhone, confirmBindExisting);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user