From eebe3c5dc631f2e8c049e7ff6a3cd245d1643bfe Mon Sep 17 00:00:00 2001 From: ileostar Date: Sun, 14 Jul 2024 23:26:13 +0800 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20finish=20sms=20module?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .vscode/settings.json | 2 + apps/server/package.json | 5 + apps/server/src/common/sms.ts | 37 ++++++ apps/server/src/config/sms.ts | 25 ---- apps/server/src/sms/dto/sms.dto.ts | 2 +- apps/server/src/sms/sms.service.ts | 31 ++--- apps/server/src/user/user.controller.ts | 31 ++++- apps/server/src/utils/index.ts | 9 +- pnpm-lock.yaml | 152 +++++++++++++++++++++++- 9 files changed, 245 insertions(+), 49 deletions(-) create mode 100644 apps/server/src/common/sms.ts delete mode 100644 apps/server/src/config/sms.ts diff --git a/.vscode/settings.json b/.vscode/settings.json index f8ee93ee..c9735e4e 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,8 +1,10 @@ { "cSpell.words": [ + "aliyuncs", "autoincrement", "autorestart", "ctsx", + "Dysmsapi", "EDITMSG", "gitmoji", "ianvs", diff --git a/apps/server/package.json b/apps/server/package.json index 2b871bb5..1556bf13 100644 --- a/apps/server/package.json +++ b/apps/server/package.json @@ -39,6 +39,11 @@ }, "devDependencies": { "@alicloud/sms-sdk": "^1.1.6", + "@alicloud/tea-typescript": "^1.7.1", + "@alicloud/dysmsapi20170525": "3.0.0", + "@alicloud/openapi-client": "^0.4.8", + "@alicloud/tea-console": "^1.0.0", + "@alicloud/tea-util": "^1.4.7", "@nestjs/cli": "^10.0.0", "@nestjs/schematics": "^10.0.0", "@nestjs/testing": "^10.0.0", diff --git a/apps/server/src/common/sms.ts b/apps/server/src/common/sms.ts new file mode 100644 index 00000000..63dd2e09 --- /dev/null +++ b/apps/server/src/common/sms.ts @@ -0,0 +1,37 @@ +// This file is auto-generated, don't edit it +// 依赖的模块可通过下载工程中的模块依赖文件或右上角的获取 SDK 依赖信息查看 +import Dysmsapi20170525, * as $Dysmsapi20170525 from '@alicloud/dysmsapi20170525'; +import * as $OpenApi from '@alicloud/openapi-client'; +import * as $Util from '@alicloud/tea-util'; + +export default class Client { + /** + * 使用AK&SK初始化账号Client + * @return Client + * @throws Exception + */ + static createClient(): Dysmsapi20170525 { + // 工程代码泄露可能会导致 AccessKey 泄露,并威胁账号下所有资源的安全性。以下代码示例仅供参考。 + // 建议使用更安全的 STS 方式,更多鉴权访问方式请参见:https://help.aliyun.com/document_detail/378664.html。 + let config = new $OpenApi.Config({ + // 必填,请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_ID。 + accessKeyId: process.env['ALIBABA_CLOUD_ACCESS_KEY_ID'], + // 必填,请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_SECRET。 + accessKeySecret: process.env['ALIBABA_CLOUD_ACCESS_KEY_SECRET'], + }); + // Endpoint 请参考 https://api.aliyun.com/product/Dysmsapi + config.endpoint = `dysmsapi.aliyuncs.com`; + return new Dysmsapi20170525(config); + } + + static async main(SMSSendConfig): Promise { + try { + } catch (error) { + // 此处仅做打印展示,请谨慎对待异常处理,在工程项目中切勿直接忽略异常。 + // 错误 message + console.log(); + // 诊断地址 + console.log(error.data['Recommend']); + } + } +} diff --git a/apps/server/src/config/sms.ts b/apps/server/src/config/sms.ts deleted file mode 100644 index 42db5512..00000000 --- a/apps/server/src/config/sms.ts +++ /dev/null @@ -1,25 +0,0 @@ -export const SMSClientConfig = { - // ACCESS_KEY_ID/ACCESS_KEY_SECRET 根据实际申请的账号信息进行替换 - accessKeyId: 'yourAccessKeyId', - secretAccessKey: 'yourAccessKeySecret', - - //在云通信页面开通相应业务消息后,就能在页面上获得对应的queueName,不用填最后面一段 - queueName: 'Alicom-Queue-1092397003988387-', - - // vpc需要配置,华东1示例:请查看 https://help.aliyun.com/document_detail/68360.html - smsApiEndpoint: 'http://dysmsapi-vpc.cn-hangzhou.aliyuncs.com', - baseApiEndpoint: 'http://dybaseapi-vpc.cn-hangzhou.aliyuncs.com', - regionId: 'cn-hangzhou', - mnsVpc: { - secure: false, // use https or http - internal: true, // use internal endpoint - vpc: true, - }, - - options: { method: 'POST' }, -}; - -export const SMSSendConfig = { - SignName: '海报编辑器', - TemplateCode: 'SMS_301990296', -}; diff --git a/apps/server/src/sms/dto/sms.dto.ts b/apps/server/src/sms/dto/sms.dto.ts index ad7b5aec..90a42350 100644 --- a/apps/server/src/sms/dto/sms.dto.ts +++ b/apps/server/src/sms/dto/sms.dto.ts @@ -4,7 +4,7 @@ export class SendCodeBySMSDto { @ApiProperty({ description: '电话号码列表,这里仅为示例,实际可能支持多个号码', type: String, - example: '1500000000', + example: '14709723891', }) readonly phone: string; } diff --git a/apps/server/src/sms/sms.service.ts b/apps/server/src/sms/sms.service.ts index 5332a477..579b3b21 100644 --- a/apps/server/src/sms/sms.service.ts +++ b/apps/server/src/sms/sms.service.ts @@ -1,9 +1,11 @@ -import { HttpException, HttpStatus, Injectable } from '@nestjs/common'; -import SMSClient from '@alicloud/sms-sdk'; -import { SMSClientConfig, SMSSendConfig } from '../config/sms'; +import { Injectable } from '@nestjs/common'; import { SendCodeBySMSDto } from './dto/sms.dto'; import { generateVerificationCode } from 'src/utils'; import { CacheService } from 'src/cache/cache.service'; +import { ResponseData } from 'src/response/ResponseFormat'; +import Client from 'src/common/sms'; +import * as $Dysmsapi20170525 from '@alicloud/dysmsapi20170525'; +import * as $Util from '@alicloud/tea-util'; @Injectable() export class SmsService { @@ -11,20 +13,19 @@ export class SmsService { async sendCodeBySMS(dto: SendCodeBySMSDto) { try { const code = generateVerificationCode(); - const smsClient = new SMSClient(SMSClientConfig); this.cacheService.setCache(dto.phone, code); - const res = smsClient.sendSMS( - { - PhoneNumbers: dto.phone, - SignName: SMSSendConfig.SignName, - TemplateCode: SMSSendConfig.TemplateCode, - TemplateParam: JSON.stringify({ code }), - }, - { method: 'POST' }, - ); - return res.Code === 'OK' ? res : false; + let client = Client.createClient(); + let sendSmsRequest = new $Dysmsapi20170525.SendSmsRequest({ + signName: process.env.SignName, + templateCode: process.env.TemplateCode, + phoneNumbers: dto.phone, + templateParam: JSON.stringify({ code }), + }); + let runtime = new $Util.RuntimeOptions({}); + await client.sendSmsWithOptions(sendSmsRequest, runtime); + return ResponseData.ok(null, '短信发送成功'); } catch (error) { - new HttpException('sendCodeBySMS error', HttpStatus.BAD_REQUEST); + return ResponseData.fail(error.message); } } } diff --git a/apps/server/src/user/user.controller.ts b/apps/server/src/user/user.controller.ts index a2098fa4..4379a3c8 100644 --- a/apps/server/src/user/user.controller.ts +++ b/apps/server/src/user/user.controller.ts @@ -1,7 +1,34 @@ -import { Body, Controller, Get, Patch, Post, UseGuards } from '@nestjs/common'; +import { + Body, + Controller, + Get, + Inject, + Patch, + Post, + UseGuards, +} from '@nestjs/common'; import { UserService } from './user.service'; +import { ApiBody, ApiOperation } from '@nestjs/swagger'; +import { DefaultLoginDto } from 'src/auth/dto/auth.dto'; +import { CreateUserDto } from './dto/user.dto'; +import { DB, DbType } from 'src/global/providers/db.provider'; +import { user } from '@poster-craft/schema'; +import { ResponseData } from 'src/response/ResponseFormat'; @Controller('user') export class UserController { - constructor(private readonly userService: UserService) {} + constructor( + private readonly userService: UserService, + @Inject(DB) private db: DbType, + ) {} + + @Post('test') + @ApiOperation({ summary: '测试', description: '测试' }) + async testAdd() { + const [res] = await this.db.insert(user).values({ + phone: '14709723891', + username: 'demo', + }); + return ResponseData.ok(res); + } } diff --git a/apps/server/src/utils/index.ts b/apps/server/src/utils/index.ts index c098efff..a3f52494 100644 --- a/apps/server/src/utils/index.ts +++ b/apps/server/src/utils/index.ts @@ -1,8 +1,13 @@ import crypto from 'crypto'; /** 生成随机验证码 */ -export function generateVerificationCode(): string { - return crypto.randomInt(100000, 1000000).toString().slice(0, 6); +export function generateVerificationCode() { + let code = ''; + for (let i = 0; i < 6; i++) { + // 生成 0-9 之间的数字,并将其转换为字符串后追加到 code + code += Math.floor(Math.random() * 10); + } + return code; } /** 生成随机用户名 */ diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4dc881f3..22508a9e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -126,9 +126,24 @@ importers: specifier: ^8.1.2 version: 8.1.2 devDependencies: + '@alicloud/dysmsapi20170525': + specifier: 3.0.0 + version: 3.0.0 + '@alicloud/openapi-client': + specifier: ^0.4.8 + version: 0.4.10 '@alicloud/sms-sdk': specifier: ^1.1.6 version: 1.1.6 + '@alicloud/tea-console': + specifier: ^1.0.0 + version: 1.0.0 + '@alicloud/tea-typescript': + specifier: ^1.7.1 + version: 1.8.0 + '@alicloud/tea-util': + specifier: ^1.4.7 + version: 1.4.8 '@nestjs/cli': specifier: ^10.0.0 version: 10.4.2(esbuild@0.21.5) @@ -291,8 +306,6 @@ importers: specifier: ^1.2.3 version: 1.3.0(@algolia/client-search@4.24.0)(@types/node@20.14.10)(search-insights@2.15.0)(typescript@5.5.3) - packages/eslint-config: {} - packages/schema: dependencies: '@paralleldrive/cuid2': @@ -301,8 +314,6 @@ importers: packages/shared: {} - packages/tsconfig: {} - packages/ui: {} packages: @@ -457,6 +468,17 @@ packages: '@algolia/requester-common': 4.24.0 dev: false + /@alicloud/credentials@2.3.1: + resolution: {integrity: sha512-FK8N1YNVqUGOl7qOFn8h3zTwv2Tj8ON3459XXnJkAa08YBECj8o/V81D/ubxpX0yZub4RVKjknxNSHEbrASc+A==} + dependencies: + '@alicloud/tea-typescript': 1.8.0 + httpx: 2.3.2 + ini: 1.3.8 + kitx: 2.1.0 + transitivePeerDependencies: + - supports-color + dev: true + /@alicloud/dybaseapi@1.0.0: resolution: {integrity: sha512-4KEDgqES7IL60T/TWGSkLQkN6BYeHEw8smnPgac2J2MTES5v1ieCWvbLSuUUWi5SAXi7cydKoD4HUOmX7xwM+A==} dependencies: @@ -473,6 +495,36 @@ packages: - supports-color dev: true + /@alicloud/dysmsapi20170525@3.0.0: + resolution: {integrity: sha512-d2Wp5Cxx30As8STvUFys8L6aPTVm2U+xhDLDRMPEB3H5lYFlREixHPn4vu6s8kaTGUNPHuCOD0I940Z9jaApSA==} + dependencies: + '@alicloud/endpoint-util': 0.0.1 + '@alicloud/openapi-client': 0.4.10 + '@alicloud/openapi-util': 0.3.2 + '@alicloud/tea-typescript': 1.8.0 + '@alicloud/tea-util': 1.4.8 + transitivePeerDependencies: + - supports-color + dev: true + + /@alicloud/endpoint-util@0.0.1: + resolution: {integrity: sha512-+pH7/KEXup84cHzIL6UJAaPqETvln4yXlD9JzlrqioyCSaWxbug5FUobsiI6fuUOpw5WwoB3fWAtGbFnJ1K3Yg==} + dependencies: + '@alicloud/tea-typescript': 1.8.0 + kitx: 2.1.0 + transitivePeerDependencies: + - supports-color + dev: true + + /@alicloud/gateway-spi@0.0.8: + resolution: {integrity: sha512-KM7fu5asjxZPmrz9sJGHJeSU+cNQNOxW+SFmgmAIrITui5hXL2LB+KNRuzWmlwPjnuA2X3/keq9h6++S9jcV5g==} + dependencies: + '@alicloud/credentials': 2.3.1 + '@alicloud/tea-typescript': 1.8.0 + transitivePeerDependencies: + - supports-color + dev: true + /@alicloud/mns@1.0.0: resolution: {integrity: sha512-SUJYM8+x3iPy6thIy5Wa/5lw7+RodeDDIPcI3QQ3bZPNCSq+yEC3jMtfVlS3vxGPq+dGjAysI9RGeM7NByeHlw==} dependencies: @@ -484,6 +536,30 @@ packages: - supports-color dev: true + /@alicloud/openapi-client@0.4.10: + resolution: {integrity: sha512-AarOnkQzVscj33eWwIqe5BN+snE/Q3d+s+wzJnRvnldO/E9yiGdZ8UbQQCltzBVoUpuZfu9tVBg60dYvX7wIhg==} + dependencies: + '@alicloud/credentials': 2.3.1 + '@alicloud/gateway-spi': 0.0.8 + '@alicloud/openapi-util': 0.3.2 + '@alicloud/tea-typescript': 1.8.0 + '@alicloud/tea-util': 1.4.8 + '@alicloud/tea-xml': 0.0.3 + transitivePeerDependencies: + - supports-color + dev: true + + /@alicloud/openapi-util@0.3.2: + resolution: {integrity: sha512-EC2JvxdcOgMlBAEG0+joOh2IB1um8CPz9EdYuRfTfd1uP8Yc9D8QRUWVGjP6scnj6fWSOaHFlit9H6PrJSyFow==} + dependencies: + '@alicloud/tea-typescript': 1.8.0 + '@alicloud/tea-util': 1.4.8 + kitx: 2.1.0 + sm3: 1.0.3 + transitivePeerDependencies: + - supports-color + dev: true + /@alicloud/pop-core@1.7.13: resolution: {integrity: sha512-agzr4DU+aAGW7/2mp2hP1JcNJkn/zBS0jUGQt5etIASN0MVq1tMdudVqvWbExUG0mUouo/n2VgdnjOHjswvrlA==} engines: {node: '>=8.0.0'} @@ -508,6 +584,42 @@ packages: - supports-color dev: true + /@alicloud/tea-console@1.0.0: + resolution: {integrity: sha512-kkdhu/iZRUzZBh58XPaKw+fsKlUAznPRD21wgHSUN+R85ODM66h3+a//hK9dsX3zUbfZ7DqDjZf53zu5ecKk6g==} + dependencies: + '@alicloud/tea-typescript': 1.8.0 + transitivePeerDependencies: + - supports-color + dev: true + + /@alicloud/tea-typescript@1.8.0: + resolution: {integrity: sha512-CWXWaquauJf0sW30mgJRVu9aaXyBth5uMBCUc+5vKTK1zlgf3hIqRUjJZbjlwHwQ5y9anwcu18r48nOZb7l2QQ==} + dependencies: + '@types/node': 12.20.55 + httpx: 2.3.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@alicloud/tea-util@1.4.8: + resolution: {integrity: sha512-CPmRUAWhUMewZXLVZ8HTCrqRzzcT6F3o/1sB3IY27oU8RLjFj3FMpZe423pJoC/noNXo4Ja3FTTEFF5k8asQBw==} + dependencies: + '@alicloud/tea-typescript': 1.8.0 + kitx: 2.1.0 + transitivePeerDependencies: + - supports-color + dev: true + + /@alicloud/tea-xml@0.0.3: + resolution: {integrity: sha512-+/9GliugjrLglsXVrd1D80EqqKgGpyA0eQ6+1ZdUOYCaRguaSwz44trX3PaxPu/HhIPJg9PsGQQ3cSLXWZjbAA==} + dependencies: + '@alicloud/tea-typescript': 1.8.0 + '@types/xml2js': 0.4.14 + xml2js: 0.6.2 + transitivePeerDependencies: + - supports-color + dev: true + /@alloc/quick-lru@5.2.0: resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} engines: {node: '>=10'} @@ -2925,6 +3037,10 @@ packages: resolution: {integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==} dev: true + /@types/node@12.20.55: + resolution: {integrity: sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==} + dev: true + /@types/node@20.14.10: resolution: {integrity: sha512-MdiXf+nDuMvY0gJKxyfZ7/6UFsETO7mGKF54MVD/ekJS6HdFtpZFBgrh6Pseu64XTb2MLyFPlbW6hj8HYRQNOQ==} dependencies: @@ -3001,6 +3117,12 @@ packages: resolution: {integrity: sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow==} dev: false + /@types/xml2js@0.4.14: + resolution: {integrity: sha512-4YnrRemBShWRO2QjvUin8ESA41rH+9nQGLUGZV/1IDhi3SL9OhdpNC/MrulTWuptXKwhx/aDxE7toV0f/ypIXQ==} + dependencies: + '@types/node': 20.14.10 + dev: true + /@types/yargs-parser@21.0.3: resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==} dev: true @@ -6489,6 +6611,10 @@ packages: /inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + /ini@1.3.8: + resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} + dev: true + /inquirer@8.2.6: resolution: {integrity: sha512-M1WuAmb7pn9zdFRtQYk26ZBoY043Sse0wVDdk4Bppr+JOXyQYybdtvK+l9wUibhtjdjvtoiNy8tk+EgsYIUqKg==} engines: {node: '>=12.0.0'} @@ -7551,6 +7677,12 @@ packages: resolution: {integrity: sha512-fhBqFlXd0GkKTB+8ayLfpzPUw+LHxZlPAukPNBD1Om7JMeInT+/PxCAf1yLagvD+VKoyWhXtJR68xQkX/a0wOQ==} dev: true + /kitx@2.1.0: + resolution: {integrity: sha512-C/5v9MtIX7aHGOjwn5BmrrbNkJSf7i0R5mRzmh13GSAdRqQ7bYQo/Su2pTYNylFicqKNTVX3HML9k1u8k51+pQ==} + dependencies: + '@types/node': 12.20.55 + dev: true + /kleur@3.0.3: resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} engines: {node: '>=6'} @@ -9310,6 +9442,10 @@ packages: is-fullwidth-code-point: 5.0.0 dev: true + /sm3@1.0.3: + resolution: {integrity: sha512-KyFkIfr8QBlFG3uc3NaljaXdYcsbRy1KrSfc4tsQV8jW68jAktGeOcifu530Vx/5LC+PULHT0Rv8LiI8Gw+c1g==} + dev: true + /source-map-js@1.2.0: resolution: {integrity: sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==} engines: {node: '>=0.10.0'} @@ -10831,6 +10967,14 @@ packages: xmlbuilder: 11.0.1 dev: true + /xml2js@0.6.2: + resolution: {integrity: sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==} + engines: {node: '>=4.0.0'} + dependencies: + sax: 1.4.1 + xmlbuilder: 11.0.1 + dev: true + /xmlbuilder@11.0.1: resolution: {integrity: sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==} engines: {node: '>=4.0'}