auth.service.js 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. "use strict";
  2. var __importDefault = (this && this.__importDefault) || function (mod) {
  3. return (mod && mod.__esModule) ? mod : { "default": mod };
  4. };
  5. Object.defineProperty(exports, "__esModule", { value: true });
  6. exports.generateSmsCode = generateSmsCode;
  7. exports.verifySmsCode = verifySmsCode;
  8. exports.generateToken = generateToken;
  9. exports.loginWithPhone = loginWithPhone;
  10. exports.getUserInfo = getUserInfo;
  11. const jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
  12. const models_1 = require("../../models");
  13. // 验证码存储(生产环境应使用 Redis)
  14. const smsCodes = new Map();
  15. // 生成验证码
  16. function generateSmsCode(phone) {
  17. const code = Math.random().toString().slice(2, 6);
  18. smsCodes.set(phone, {
  19. code,
  20. expireAt: Date.now() + 5 * 60 * 1000, // 5分钟有效
  21. });
  22. console.log(`📱 验证码已生成: ${phone} -> ${code}`);
  23. return code;
  24. }
  25. // 验证验证码
  26. function verifySmsCode(phone, code) {
  27. const stored = smsCodes.get(phone);
  28. if (!stored)
  29. return false;
  30. if (Date.now() > stored.expireAt) {
  31. smsCodes.delete(phone);
  32. return false;
  33. }
  34. if (stored.code !== code)
  35. return false;
  36. smsCodes.delete(phone);
  37. return true;
  38. }
  39. // 生成 JWT Token
  40. function generateToken(userId, phone) {
  41. const secret = 'my-jwt-secret-key-2024';
  42. const payload = { userId, phone };
  43. return jsonwebtoken_1.default.sign(payload, secret, {
  44. expiresIn: '7d',
  45. });
  46. }
  47. // 手机号登录/注册
  48. async function loginWithPhone(phone, code) {
  49. // 免密登录:开发环境下,code 为空或为"123456"时直接登录
  50. const isDev = process.env.NODE_ENV === 'development';
  51. const skipVerify = isDev && (!code || code === '123456');
  52. if (!skipVerify) {
  53. // 验证验证码
  54. const isValid = verifySmsCode(phone, code || '');
  55. if (!isValid) {
  56. throw new Error('验证码错误或已过期');
  57. }
  58. }
  59. // 查找或创建用户
  60. let user = await models_1.prisma.user.findFirst({ where: { phone } });
  61. let isNewUser = false;
  62. if (!user) {
  63. user = await models_1.prisma.user.create({
  64. data: {
  65. phone,
  66. nickname: `用户${phone.slice(-4)}`,
  67. avatar: `https://api.dicebear.com/7.x/avataaars/svg?seed=${phone}`,
  68. memberLevel: 0,
  69. dailyUsage: 0,
  70. lastUsageDate: '',
  71. },
  72. });
  73. isNewUser = true;
  74. }
  75. const token = generateToken(user.id.toString(), phone);
  76. return {
  77. token,
  78. user: {
  79. id: user.id.toString(),
  80. phone: user.phone,
  81. nickname: user.nickname,
  82. avatar: user.avatar,
  83. memberLevel: user.memberLevel,
  84. isNewUser,
  85. },
  86. };
  87. }
  88. // 获取用户信息
  89. async function getUserInfo(userId) {
  90. const user = await models_1.prisma.user.findUnique({ where: { id: parseInt(userId) } });
  91. if (!user) {
  92. throw new Error('用户不存在');
  93. }
  94. return {
  95. id: user.id.toString(),
  96. phone: user.phone,
  97. nickname: user.nickname,
  98. avatar: user.avatar,
  99. memberLevel: user.memberLevel,
  100. memberExpireAt: user.memberExpireAt,
  101. dailyUsage: user.dailyUsage,
  102. };
  103. }