| | |
| | | import com.netease.nim.server.sdk.core.YunxinApiHttpClient; |
| | | import com.netease.nim.server.sdk.core.YunxinApiResponse; |
| | | import com.netease.nim.server.sdk.core.exception.YunxinSdkException; |
| | | import com.ruoyi.common.core.domain.R; |
| | | import com.ruoyi.im.comm.Result; |
| | | import com.ruoyi.im.config.AppAuthConfig; |
| | | import com.ruoyi.system.domain.UserAccount; |
| | |
| | | import com.ruoyi.im.dto.RegisterDto; |
| | | import com.ruoyi.system.service.UserAccountService; |
| | | import com.ruoyi.im.util.SymmetricCryptoUtil; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | import org.springframework.transaction.interceptor.TransactionAspectSupport; |
| | | import org.springframework.util.CollectionUtils; |
| | | |
| | | import javax.annotation.PostConstruct; |
| | |
| | | import java.util.concurrent.atomic.AtomicLong; |
| | | |
| | | @Service |
| | | @Slf4j |
| | | public class ImApiServcieImpl implements ImApiServcie { |
| | | @Autowired |
| | | private UserAccountService userAccountService; |
| | |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) // 添加事务注解确保操作原子性 |
| | | public Result register(RegisterDto dto) { |
| | | // 短信验证 TODO |
| | | |
| | | // 手机号是否存在 - 添加分布式锁或数据库唯一索引确保并发安全 |
| | | List<UserAccount> accounts = userAccountService.list( |
| | | new LambdaQueryWrapper<>(UserAccount.class) |
| | | .eq(UserAccount::getAccount, dto.getAccount()) |
| | | ); |
| | | |
| | | if(!CollectionUtils.isEmpty(accounts)){ |
| | | return Result.error("手机号已注册!"); |
| | | } |
| | | |
| | | // // 生成云信账号 |
| | | // long cloudMessageAccount; |
| | | // try { |
| | | // cloudMessageAccount = generateUniqueCloudMessageAccount(); |
| | | // } catch (RuntimeException e) { |
| | | // return Result.error("系统繁忙,请稍后重试"); |
| | | // } |
| | | |
| | | // 注册云信 |
| | | String path = "/user/create.action"; |
| | | Map<String, String> paramMap = new HashMap<>(); |
| | | paramMap.put("accid", String.valueOf(dto.getAccount())); |
| | | paramMap.put("token", dto.getPassword()); |
| | | |
| | | YunxinApiResponse response; |
| | | try { |
| | | response = yunxinClient.executeV1Api(path, paramMap); |
| | | } catch (YunxinSdkException e) { |
| | | System.err.println("register error, traceId = " + e.getTraceId()); |
| | | return Result.error("注册失败,系统异常"); |
| | | } |
| | | // 验证手机号是否已存在(数据库唯一索引提供最终保障) |
| | | List<UserAccount> accounts = userAccountService.list( |
| | | new LambdaQueryWrapper<>(UserAccount.class) |
| | | .eq(UserAccount::getAccount, dto.getAccount()) |
| | | ); |
| | | |
| | | // 获取结果 |
| | | String data = response.getData(); |
| | | JSONObject json = JSONObject.parseObject(data); |
| | | int code = json.getIntValue("code"); |
| | | if (!CollectionUtils.isEmpty(accounts)) { |
| | | return Result.error("手机号已注册!"); |
| | | } |
| | | |
| | | if (code == 200) { |
| | | // 注册成功 |
| | | // 创建本地用户账户记录 |
| | | UserAccount userAccount = new UserAccount(); |
| | | userAccount.setAccount(dto.getAccount()); |
| | | userAccount.setPhoneNumber(dto.getAccount()); |
| | | userAccount.setCloudMessageAccount(dto.getAccount()); |
| | | userAccount.setPassword(SymmetricCryptoUtil.encryptPassword(dto.getPassword())); |
| | | |
| | | try { |
| | | userAccountService.save(userAccount); |
| | | return Result.success("注册成功"); |
| | | } catch (Exception e) { |
| | | // 处理数据库插入异常,可能需要回滚云信账号 |
| | | if (!userAccountService.save(userAccount)) { |
| | | return Result.error("注册失败,请重试"); |
| | | } |
| | | } else if (code == 414) { |
| | | return Result.error("账号已被注册!"); |
| | | } else { |
| | | System.err.println("register fail, response = " + data + ", traceId=" + response.getTraceId()); |
| | | return Result.error("注册失败,错误码: " + code); |
| | | |
| | | // 注册云信账号(远程调用) |
| | | String path = "/user/create.action"; |
| | | Map<String, String> paramMap = new HashMap<>(); |
| | | paramMap.put("accid", dto.getAccount()); |
| | | paramMap.put("token", dto.getPassword()); |
| | | |
| | | YunxinApiResponse response = yunxinClient.executeV1Api(path, paramMap); |
| | | |
| | | // 处理云信响应 |
| | | String data = response.getData(); |
| | | JSONObject json = JSONObject.parseObject(data); |
| | | int code = json.getIntValue("code"); |
| | | |
| | | if (code == 200) { |
| | | return Result.success("注册成功"); |
| | | } else if (code == 414) { |
| | | // 手动触发回滚(事务注解会自动处理) |
| | | TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); |
| | | return Result.error("账号已被注册!"); |
| | | } else { |
| | | // 其他错误码同样触发回滚 |
| | | TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); |
| | | log.error("云信注册失败,响应: {}, traceId: {}", data, response.getTraceId()); |
| | | return Result.error("注册失败,错误码: " + code); |
| | | } |
| | | |
| | | } catch (YunxinSdkException e) { |
| | | // 云信调用异常时回滚事务 |
| | | TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); |
| | | log.error("云信服务调用异常 traceId: {}", e.getTraceId(), e); |
| | | return Result.error("注册失败,系统异常"); |
| | | } catch (Exception e) { |
| | | // 其他异常同样回滚 |
| | | TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); |
| | | log.error("注册过程发生未知异常", e); |
| | | return Result.error("注册失败,请重试"); |
| | | } |
| | | } |
| | | |
| | |
| | | try { |
| | | Thread.sleep(ThreadLocalRandom.current().nextInt(10, 50)); |
| | | } catch (InterruptedException e) { |
| | | e.printStackTrace(); |
| | | Thread.currentThread().interrupt(); |
| | | throw new RuntimeException("生成账号被中断", e); |
| | | } |