This commit is contained in:
2026-02-09 17:09:18 +03:00
parent e87a5b507e
commit c26c27c2a7
5 changed files with 100 additions and 14 deletions
+24 -1
View File
@@ -6,10 +6,33 @@ import { OtpService } from './otp.service';
import { SmsService } from './sms.service';
import { MailService } from './mail.service';
import { AppRedisModule } from './redis.provider';
import { SmsProvider } from './sms/sms.provider';
import { AfricasTalkingSmsProvider } from './sms/africastalking.provider';
import { LeopardSmsProvider } from './sms/leopard.provider';
@Module({
imports: [AppRedisModule],
controllers: [AuthController],
providers: [OtpService,SmsService,MailService],
providers: [
OtpService,
SmsService,
MailService,
AfricasTalkingSmsProvider,
LeopardSmsProvider,
{
provide: SmsProvider,
useFactory: (
atProvider: AfricasTalkingSmsProvider,
leopardProvider: LeopardSmsProvider,
) => {
return process.env.SMS_PROVIDER === 'leopard'
? leopardProvider
: atProvider;
},
inject: [AfricasTalkingSmsProvider, LeopardSmsProvider],
},
],
})
export class AppModule {}
+6 -13
View File
@@ -1,22 +1,15 @@
// sms.service.ts
import { Injectable } from '@nestjs/common';
import AfricasTalking from 'africastalking';
import { SmsProvider } from './sms/sms.provider';
@Injectable()
export class SmsService {
private client;
constructor() {
this.client = AfricasTalking({
apiKey: process.env.AT_API_KEY,
username: process.env.AT_USERNAME
});
}
constructor(private smsProvider: SmsProvider) {}
async sendOtp(phone: string, otp: string) {
await this.client.SMS.send({
to: [phone],
message: `Your verification code is ${otp}. Expires in 5 minutes.`
});
await this.smsProvider.send(
phone,
`Your verification code is ${otp}. Expires in 5 minutes.`
);
}
}
+22
View File
@@ -0,0 +1,22 @@
import { Injectable } from '@nestjs/common';
import { SmsProvider } from './sms.provider';
import AfricasTalking from 'africastalking';
@Injectable()
export class AfricasTalkingSmsProvider implements SmsProvider {
private client;
constructor() {
this.client = AfricasTalking({
apiKey: process.env.AT_API_KEY,
username: process.env.AT_USERNAME,
});
}
async send(to: string, message: string): Promise<any> {
return this.client.SMS.send({
to: [to],
message: message,
});
}
}
+42
View File
@@ -0,0 +1,42 @@
import { Injectable, Logger } from '@nestjs/common';
import { SmsProvider } from './sms.provider';
@Injectable()
export class LeopardSmsProvider implements SmsProvider {
private readonly logger = new Logger(LeopardSmsProvider.name);
async send(to: string, message: string): Promise<any> {
const url = 'https://api.smsleopard.com/v1/sms/send';
const auth = Buffer.from(`${process.env.LEOPARD_API_KEY}:${process.env.LEOPARD_API_SECRET}`).toString('base64');
try {
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Basic ${auth}`
},
body: JSON.stringify({
source: process.env.LEOPARD_SENDER_ID || 'SMS_Leopard',
message: message,
destination: [
{
number: to
}
]
})
});
if (!response.ok) {
const errorText = await response.text();
this.logger.error(`SMS Leopard failed: ${response.status} ${response.statusText} - ${errorText}`);
throw new Error(`SMS Leopard failed: ${response.statusText}`);
}
return await response.json();
} catch (error) {
this.logger.error('Error sending SMS via Leopard', error);
throw error;
}
}
}
+6
View File
@@ -0,0 +1,6 @@
import { Injectable } from '@nestjs/common';
@Injectable()
export abstract class SmsProvider {
abstract send(to: string, message: string): Promise<any>;
}