phone-decrypt.route.ts 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. import { createRoute, OpenAPIHono } from '@hono/zod-openapi';
  2. import { MiniAuthService } from '../services';
  3. import { AppDataSource, redisUtil } from '@d8d/shared-utils';
  4. import { ErrorSchema } from '@d8d/shared-utils';
  5. import { UserEntity } from '@d8d/user-module';
  6. import { authMiddleware } from '../middleware';
  7. import { AuthContext } from '@d8d/shared-types';
  8. import { PhoneDecryptSchema, PhoneDecryptResponseSchema } from '../schemas';
  9. const phoneDecryptRoute = createRoute({
  10. method: 'post',
  11. path: '/phone-decrypt',
  12. middleware: [authMiddleware],
  13. request: {
  14. body: {
  15. content: {
  16. 'application/json': {
  17. schema: PhoneDecryptSchema
  18. }
  19. }
  20. }
  21. },
  22. responses: {
  23. 200: {
  24. description: '手机号解密成功',
  25. content: {
  26. 'application/json': {
  27. schema: PhoneDecryptResponseSchema
  28. }
  29. }
  30. },
  31. 400: {
  32. description: '参数错误或解密失败',
  33. content: {
  34. 'application/json': {
  35. schema: ErrorSchema
  36. }
  37. }
  38. },
  39. 401: {
  40. description: '未授权访问',
  41. content: {
  42. 'application/json': {
  43. schema: ErrorSchema
  44. }
  45. }
  46. },
  47. 404: {
  48. description: '用户不存在',
  49. content: {
  50. 'application/json': {
  51. schema: ErrorSchema
  52. }
  53. }
  54. },
  55. 500: {
  56. description: '服务器错误',
  57. content: {
  58. 'application/json': {
  59. schema: ErrorSchema
  60. }
  61. }
  62. }
  63. }
  64. });
  65. const app = new OpenAPIHono<AuthContext>().openapi(phoneDecryptRoute, async (c) => {
  66. try {
  67. const { encryptedData, iv } = c.req.valid('json');
  68. const user = c.get('user');
  69. if (!user) {
  70. return c.json({ code: 401, message: '未授权访问' }, 401);
  71. }
  72. // 获取用户信息
  73. const userRepository = AppDataSource.getRepository(UserEntity);
  74. const userEntity = await userRepository.findOne({
  75. where: { id: user.id },
  76. relations: ['avatarFile']
  77. });
  78. if (!userEntity) {
  79. return c.json({ code: 404, message: '用户不存在' }, 404);
  80. }
  81. // 创建 MiniAuthService 实例
  82. const miniAuthService = new MiniAuthService(AppDataSource);
  83. // 从Redis获取用户的sessionKey
  84. const sessionKey = await redisUtil.getSessionKey(user.id);
  85. if (!sessionKey) {
  86. return c.json({ code: 400, message: 'sessionKey已过期,请重新登录' }, 400);
  87. }
  88. // 使用 MiniAuthService 进行手机号解密
  89. const decryptedPhoneNumber = await miniAuthService.decryptPhoneNumber(
  90. encryptedData,
  91. iv,
  92. sessionKey
  93. );
  94. // 更新用户手机号
  95. userEntity.phone = decryptedPhoneNumber;
  96. await userRepository.save(userEntity);
  97. return c.json({
  98. phoneNumber: decryptedPhoneNumber,
  99. user: {
  100. id: userEntity.id,
  101. username: userEntity.username,
  102. nickname: userEntity.nickname,
  103. phone: userEntity.phone,
  104. email: userEntity.email,
  105. avatarFileId: userEntity.avatarFileId,
  106. registrationSource: userEntity.registrationSource
  107. }
  108. }, 200);
  109. } catch (error) {
  110. const { code = 500, message = '手机号解密失败' } = error as Error & { code?: number };
  111. return c.json({ code, message }, code as 400 | 401 | 404 | 500);
  112. }
  113. });
  114. export default app;