import { Injectable, Logger } from '@nestjs/common'; import { resolveMockSmsFixedCode } from '@dukang/shared-types'; import { PrismaService } from '../../common/prisma/prisma.module'; import { MockSmsCodeService } from '../../common/mock-sms-code/mock-sms-code.service'; import type { ISmsProvider, SmsActorRef, SmsSendResult } from './sms.interface'; import { SmsCodeStore } from './sms-code.store'; function maskPhone(phone: string) { return `${phone.slice(0, 3)}****${phone.slice(-4)}`; } @Injectable() export class SmsMockProvider implements ISmsProvider { private readonly logger = new Logger(SmsMockProvider.name); constructor( private readonly smsCodeStore: SmsCodeStore, private readonly prisma: PrismaService, private readonly mockSmsCodeService: MockSmsCodeService, ) {} async send(phone: string, scene: string, actorRef?: SmsActorRef): Promise { const fixedCode = resolveMockSmsFixedCode(process.env); const code = await this.smsCodeStore.storeCode(phone, scene, fixedCode); await this.mockSmsCodeService.record(phone, scene, code); const masked = maskPhone(phone); this.logger.log(`Mock SMS → ${masked} scene=${scene} code=${code}`); const log = await this.prisma.logThirdParty.create({ data: { provider: 'SMS', scene, refType: actorRef?.refType, refId: actorRef?.refId, requestBody: { phone: masked, mode: 'MOCK', scene }, responseBody: { mock: true, hint: 'see HQ system settings mock SMS list' }, status: 'SUCCESS', }, }); return { logId: log.id, ok: true }; } async verify(phone: string, code: string, scene: string): Promise { await this.smsCodeStore.verifyAndConsume(phone, scene, code); } }