From a934e5b55e1da98fc0f37eea9644510602e55899 Mon Sep 17 00:00:00 2001 From: matin jamshidi Date: Sun, 19 Jan 2025 14:46:16 +0330 Subject: [PATCH] chore: sms service with configs --- .env.example | 7 ++++- package.json | 1 + pnpm-lock.yaml | 30 +++++++++++++++++++ src/configs/sms.config.ts | 30 +++++++++++++++++++ src/modules/utils/constants.ts | 1 + src/modules/utils/interfaces/ISms.ts | 18 +++++++++++ src/modules/utils/providers/sms.service.ts | 35 ++++++++++++++++++++++ src/modules/utils/utils.module.ts | 14 +++++++-- 8 files changed, 132 insertions(+), 4 deletions(-) create mode 100644 src/configs/sms.config.ts create mode 100644 src/modules/utils/constants.ts create mode 100644 src/modules/utils/interfaces/ISms.ts create mode 100644 src/modules/utils/providers/sms.service.ts diff --git a/.env.example b/.env.example index 2f6d057..a0841c5 100644 --- a/.env.example +++ b/.env.example @@ -6,4 +6,9 @@ DB_HOST=localhost DB_PORT=5432 DB_NAME=danak-dsc DB_USER=danak -DB_PASS=jkm3q2wux56RHYuTuKN11Too6+4pIpGQj3Q/fkNbahM \ No newline at end of file +DB_PASS=jkm3q2wux56RHYuTuKN11Too6+4pIpGQj3Q/fkNbahM + +URL=https://RestfulSms.com/api/UltraFastSend/direct +SMS_API_KEY= +SMS_SECRET= +SMS_PATTERN_OTP= \ No newline at end of file diff --git a/package.json b/package.json index 66edeef..f2997ee 100644 --- a/package.json +++ b/package.json @@ -27,6 +27,7 @@ "@nestjs/platform-fastify": "^10.4.15", "@nestjs/swagger": "^8.1.1", "@nestjs/typeorm": "^10.0.2", + "axios": "^1.7.9", "pg": "^8.13.1", "reflect-metadata": "^0.2.2", "rxjs": "^7.8.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 66f5bf4..527c0cd 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -29,6 +29,9 @@ importers: '@nestjs/typeorm': specifier: ^10.0.2 version: 10.0.2(@nestjs/common@10.4.15(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.4.15(@nestjs/common@10.4.15(reflect-metadata@0.2.2)(rxjs@7.8.1))(reflect-metadata@0.2.2)(rxjs@7.8.1))(reflect-metadata@0.2.2)(rxjs@7.8.1)(typeorm@0.3.20(pg@8.13.1)(ts-node@10.9.2(@types/node@20.17.14)(typescript@5.7.3))) + axios: + specifier: ^1.7.9 + version: 1.7.9 pg: specifier: ^8.13.1 version: 8.13.1 @@ -1094,6 +1097,9 @@ packages: avvio@8.4.0: resolution: {integrity: sha512-CDSwaxINFy59iNwhYnkvALBwZiTydGkOecZyPkqBpABYR1KqGEsET0VOOYDwtleZSUIdeY36DC2bSZ24CO1igA==} + axios@1.7.9: + resolution: {integrity: sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw==} + babel-jest@29.7.0: resolution: {integrity: sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -1804,6 +1810,15 @@ packages: flatted@3.3.2: resolution: {integrity: sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==} + follow-redirects@1.15.9: + resolution: {integrity: sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + for-each@0.3.3: resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} @@ -2957,6 +2972,9 @@ packages: resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} engines: {node: '>= 0.10'} + proxy-from-env@1.1.0: + resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + punycode@2.3.1: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} @@ -5005,6 +5023,14 @@ snapshots: '@fastify/error': 3.4.1 fastq: 1.18.0 + axios@1.7.9: + dependencies: + follow-redirects: 1.15.9 + form-data: 4.0.1 + proxy-from-env: 1.1.0 + transitivePeerDependencies: + - debug + babel-jest@29.7.0(@babel/core@7.26.0): dependencies: '@babel/core': 7.26.0 @@ -5844,6 +5870,8 @@ snapshots: flatted@3.3.2: {} + follow-redirects@1.15.9: {} + for-each@0.3.3: dependencies: is-callable: 1.2.7 @@ -7162,6 +7190,8 @@ snapshots: forwarded: 0.2.0 ipaddr.js: 1.9.1 + proxy-from-env@1.1.0: {} + punycode@2.3.1: {} pure-rand@6.1.0: {} diff --git a/src/configs/sms.config.ts b/src/configs/sms.config.ts new file mode 100644 index 0000000..7973321 --- /dev/null +++ b/src/configs/sms.config.ts @@ -0,0 +1,30 @@ +import { ConfigService } from "@nestjs/config"; + +export function SmsConfigs() { + return { + inject: [ConfigService], + useFactory(configService: ConfigService) { + return { + URL: configService.getOrThrow("URL"), + API_KEY: configService.getOrThrow("API_KEY"), + SECRET_KEY: configService.getOrThrow("SECRET_KEY"), + SMS_PATTERN_OTP: configService.getOrThrow("SMS_PATTERN_OTP"), + SMS_SECRET_BODY: { + UserApiKey: configService.getOrThrow("API_KEY"), + SecretKey: configService.getOrThrow("SECRET_KEY"), + }, + }; + }, + }; +} + +export interface ISmsConfigs { + URL: string; + API_KEY: string; + SECRET_KEY: string; + SMS_PATTERN_OTP: string; + SMS_SECRET_BODY: { + UserApiKey: string; + SecretKey: string; + }; +} diff --git a/src/modules/utils/constants.ts b/src/modules/utils/constants.ts new file mode 100644 index 0000000..9ffb806 --- /dev/null +++ b/src/modules/utils/constants.ts @@ -0,0 +1 @@ +export const SMS_CONFIG = "SMS_CONFIG"; \ No newline at end of file diff --git a/src/modules/utils/interfaces/ISms.ts b/src/modules/utils/interfaces/ISms.ts new file mode 100644 index 0000000..25b36ea --- /dev/null +++ b/src/modules/utils/interfaces/ISms.ts @@ -0,0 +1,18 @@ +export interface ISmsBody { + ParameterArray: IParameterArray[]; + Mobile: string; + TemplateId: string; + UserApiKey: string; + SecretKey: string; +} + +export interface IParameterArray { + Parameter: string; + ParameterValue: string; +} + +export interface ISmsResponse { + VerificationCodeId: number; + isSuccessful: boolean; + Message: string; +} \ No newline at end of file diff --git a/src/modules/utils/providers/sms.service.ts b/src/modules/utils/providers/sms.service.ts new file mode 100644 index 0000000..d70f31e --- /dev/null +++ b/src/modules/utils/providers/sms.service.ts @@ -0,0 +1,35 @@ +import { Inject, Injectable, Logger } from "@nestjs/common"; +import axios from "axios"; +import { ISmsConfigs } from "../../../configs/sms.config"; +import { SMS_CONFIG } from "../constants"; +import { ISmsBody } from "../interfaces/ISms"; + +@Injectable() +export class SmsService { + private logger = new Logger(SmsService.name); + constructor(@Inject(SMS_CONFIG) private smsConfigs: ISmsConfigs) {} + + async sendSmsVerifyCode(mobile: string, otpCode: string) { + const smsData: ISmsBody = { + ParameterArray: [{ Parameter: "otp", ParameterValue: otpCode }], + Mobile: mobile, + TemplateId: this.smsConfigs.SMS_PATTERN_OTP, + ...this.smsConfigs.SMS_SECRET_BODY, + }; + + return this.sendSms(smsData); + } + + private async sendSms(body: ISmsBody) { + try { + const { data } = await axios.post(this.smsConfigs.URL, body, { + headers: { + "Content-Type": "application/json", + }, + }); + return data; + } catch (error) { + this.logger.error(error); + } + } +} diff --git a/src/modules/utils/utils.module.ts b/src/modules/utils/utils.module.ts index 8c85963..ef2e389 100644 --- a/src/modules/utils/utils.module.ts +++ b/src/modules/utils/utils.module.ts @@ -1,7 +1,15 @@ import { Module } from "@nestjs/common"; +import { SMS_CONFIG } from "./constants"; +import { SmsConfigs } from "../../configs/sms.config"; @Module({ - providers: [], - exports: [], + providers: [ + { + provide: SMS_CONFIG, + useFactory: SmsConfigs().useFactory, + inject: SmsConfigs().inject + }, + ], + exports: [SMS_CONFIG] }) -export class UtilsModule {} +export class UtilsModule { }