| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468 |
- package com.zsElectric.boot.app.api;
- import cn.hutool.core.img.ImgUtil;
- import cn.hutool.core.util.ObjectUtil;
- import cn.hutool.extra.qrcode.QrCodeUtil;
- import com.fasterxml.jackson.databind.JsonNode;
- import com.fasterxml.jackson.databind.ObjectMapper;
- import com.zsElectric.boot.app.model.entity.*;
- import com.zsElectric.boot.app.service.*;
- import com.zsElectric.boot.core.web.Result;
- import jakarta.servlet.http.HttpServletRequest;
- import jakarta.servlet.http.HttpServletResponse;
- import lombok.RequiredArgsConstructor;
- import lombok.extern.slf4j.Slf4j;
- import okhttp3.MediaType;
- import okhttp3.OkHttpClient;
- import okhttp3.Request;
- import org.springframework.beans.factory.annotation.Value;
- import org.springframework.data.redis.core.RedisTemplate;
- import org.springframework.transaction.annotation.Transactional;
- import org.springframework.web.bind.annotation.*;
- import org.springframework.web.multipart.MultipartFile;
- import java.time.LocalDateTime;
- import java.util.*;
- import java.util.concurrent.TimeUnit;
- /**
- * 用户API接口 - 面向小程序/APP
- */
- @Slf4j
- @RestController
- @RequestMapping("/userApi")
- @RequiredArgsConstructor
- public class UserApiController {
- private final UserInfoService userInfoService;
- private final UserAccountService userAccountService;
- private final BannerInfoService bannerInfoService;
- private final UserFeedbackService userFeedbackService;
- private final NewUserDiscountService newUserDiscountService;
- private final ChargeOrderInfoService chargeOrderInfoService;
- private final UserFirmService userFirmService;
- private final FirmInfoService firmInfoService;
- private final AdvertisingService advertisingService;
- private final RedisTemplate<String, Object> redisTemplate;
- private final OkHttpClient okHttpClient = new OkHttpClient();
- private final ObjectMapper objectMapper = new ObjectMapper();
- private final String TOKEN_PREFIX = "user:token:";
- @Value("${wx.miniapp.app-id:}")
- private String wxAppid;
- @Value("${wx.miniapp.app-secret:}")
- private String wxAppSecret;
- /**
- * 新用户活动信息查询
- */
- @PostMapping("/checkNewUser")
- @Transactional(rollbackFor = Exception.class)
- public Result<?> checkNewUser(@RequestBody Map<String, Object> data, HttpServletRequest request) {
- UserInfo cacheUser = getUserFromToken(request);
- if (cacheUser == null) {
- return Result.failed("登录已过期");
- }
- List<NewUserDiscount> list = newUserDiscountService.lambdaQuery()
- .eq(NewUserDiscount::getStatus, 1)
- .le(NewUserDiscount::getBeginTime, LocalDateTime.now())
- .ge(NewUserDiscount::getEndTime, LocalDateTime.now())
- .list();
- if (list == null || list.isEmpty()) {
- return Result.success("暂无新用户活动");
- }
- NewUserDiscount discountInfo = list.get(0);
- long orderCount = chargeOrderInfoService.lambdaQuery()
- .eq(ChargeOrderInfo::getUserId, cacheUser.getId())
- .count();
- if (orderCount > 0) {
- return Result.success("不是新用户");
- }
- Map<String, Object> result = new HashMap<>();
- result.put("discountInfo", discountInfo);
- return Result.success(result);
- }
- /**
- * 微信小程序登录
- */
- @PostMapping("/login")
- @Transactional(rollbackFor = Exception.class)
- public Result<?> login(@RequestBody Map<String, Object> data, HttpServletRequest request) {
- UserInfo cacheUser = getUserFromToken(request);
- // 检查是否已登录
- if (cacheUser != null && cacheUser.getId() != null) {
- String token = request.getHeader("token");
- if (token == null) {
- return Result.failed("token不能为空");
- }
- if (data.get("checkStatus") != null) {
- UserInfo userInfo = userInfoService.getById(cacheUser.getId());
- saveUserToCache(token, userInfo);
- Map<String, Object> result = new HashMap<>();
- result.put("userInfo", userInfo);
- result.put("token", token);
- return Result.success(result);
- }
- Map<String, Object> result = new HashMap<>();
- result.put("userInfo", cacheUser);
- result.put("token", token);
- return Result.success(result);
- }
- String code = (String) data.get("code");
- log.info("[微信登录]code:{}", code);
- log.info("[微信登录]wxAppid:{}", wxAppid);
- try {
- // 调用微信接口获取openid
- String url = "https://api.weixin.qq.com/sns/jscode2session?appid=" + wxAppid +
- "&secret=" + wxAppSecret +
- "&grant_type=authorization_code&js_code=" + code;
- String body = okHttpClient.newCall(new Request.Builder().url(url).get().build())
- .execute().body().string();
- log.info("[微信登录]回复报文:{}", body);
- JsonNode jsonNode = objectMapper.readTree(body);
- String openid = jsonNode.has("openid") ? jsonNode.get("openid").asText() : null;
- if (openid == null) {
- log.error("[微信登录]失败,回复报文:{}", body);
- return Result.failed("登录失败,请稍后再试");
- }
- // 查询或创建用户
- UserInfo userInfo = userInfoService.lambdaQuery()
- .eq(UserInfo::getWechat, openid)
- .one();
- if (userInfo == null) {
- userInfo = new UserInfo();
- userInfo.setWechat(openid);
- userInfoService.save(userInfo);
- // 创建账户
- UserAccount userAccount = new UserAccount();
- userAccount.setUserId(userInfo.getId());
- userAccountService.save(userAccount);
- }
- // 生成token并保存到缓存
- String loginToken = UUID.randomUUID().toString().replace("-", "");
- saveUserToCache(loginToken, userInfo);
- Map<String, Object> result = new HashMap<>();
- result.put("userInfo", userInfo);
- result.put("token", loginToken);
- return Result.success(result);
- } catch (Exception e) {
- log.error("[微信登录]异常", e);
- return Result.failed("登录失败,请稍后再试");
- }
- }
- /**
- * 获取手机号
- */
- @PostMapping("/getPhone")
- @Transactional(rollbackFor = Exception.class)
- public Result<?> getPhone(@RequestBody Map<String, Object> data, HttpServletRequest request) {
- UserInfo cacheUser = getUserFromToken(request);
- if (cacheUser == null) {
- return Result.failed("登录已过期");
- }
- String code = (String) data.get("code");
- try {
- // 获取access_token
- String tokenUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" +
- wxAppid + "&secret=" + wxAppSecret;
- String tokenBody = okHttpClient.newCall(new Request.Builder().url(tokenUrl).get().build())
- .execute().body().string();
- log.info("[获取token]回复报文:{}", tokenBody);
- JsonNode tokenNode = objectMapper.readTree(tokenBody);
- String accessToken = tokenNode.has("access_token") ? tokenNode.get("access_token").asText() : null;
- if (accessToken == null) {
- log.error("[获取token]失败,回复报文:{}", tokenBody);
- return Result.failed("获取失败,请稍后再试");
- }
- // 获取手机号
- Map<String, Object> phoneParams = new HashMap<>();
- phoneParams.put("code", code);
- okhttp3.RequestBody requestBody = okhttp3.RequestBody.create(
- MediaType.parse("application/json"), objectMapper.writeValueAsString(phoneParams));
- String phoneUrl = "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=" + accessToken;
- String phoneBody = okHttpClient.newCall(new Request.Builder().url(phoneUrl).post(requestBody).build())
- .execute().body().string();
- log.info("[获取手机号]回复报文:{}", phoneBody);
- JsonNode phoneNode = objectMapper.readTree(phoneBody);
- Integer errcode = phoneNode.has("errcode") ? phoneNode.get("errcode").asInt() : -1;
- if (errcode != 0) {
- log.error("[获取手机号]失败,回复报文:{}", phoneBody);
- return Result.failed("获取失败,请稍后再试");
- }
- JsonNode phoneInfo = phoneNode.get("phone_info");
- String phone = phoneInfo.has("phoneNumber") ? phoneInfo.get("phoneNumber").asText() : null;
- // 检查手机号是否已存在
- UserInfo existUser = userInfoService.lambdaQuery()
- .eq(UserInfo::getPhone, phone)
- .ne(UserInfo::getGroupId, -1L)
- .one();
- if (existUser != null) {
- // 删除原账户的微信绑定
- UserInfo oldUser = new UserInfo();
- oldUser.setId(cacheUser.getId());
- oldUser.setWechat(cacheUser.getId() + "_" + cacheUser.getWechat());
- userInfoService.updateById(oldUser);
- // 更新现有用户的微信id
- existUser.setWechat(cacheUser.getWechat());
- userInfoService.updateById(existUser);
- String token = request.getHeader("token");
- saveUserToCache(token, existUser);
- Map<String, Object> result = new HashMap<>();
- result.put("userInfo", existUser);
- return Result.success(result);
- }
- // 更新当前用户的手机号
- UserInfo updateUser = new UserInfo();
- updateUser.setId(cacheUser.getId());
- updateUser.setPhone(phone);
- userInfoService.updateById(updateUser);
- UserInfo userInfo = userInfoService.getById(cacheUser.getId());
- String token = request.getHeader("token");
- saveUserToCache(token, userInfo);
- Map<String, Object> result = new HashMap<>();
- result.put("userInfo", userInfo);
- return Result.success(result);
- } catch (Exception e) {
- log.error("[获取手机号]异常", e);
- return Result.failed("获取失败,请稍后再试");
- }
- }
- /**
- * 获取用户账户信息
- */
- @PostMapping("/getUserAccount")
- public Result<?> getUserAccount(HttpServletRequest request) {
- UserInfo cacheUser = getUserFromToken(request);
- if (cacheUser == null) {
- return Result.failed("登录已过期");
- }
- UserInfo user = userInfoService.getById(cacheUser.getId());
- if (user == null) {
- return Result.failed("未查询到用户信息");
- }
- if (ObjectUtil.isNotEmpty(user.getFirmId())) {
- FirmInfo firmInfo = firmInfoService.getById(user.getFirmId());
- if (ObjectUtil.isNotEmpty(firmInfo)) {
- user.setFirmInfoName(firmInfo.getName());
- user.setFirmType(firmInfo.getStatus());
- }
- }
- Map<String, Object> result = new HashMap<>();
- result.put("accountInfo", user);
- return Result.success(result);
- }
- /**
- * 获取Banner列表
- */
- @PostMapping("/getBanners")
- public Result<?> getBanners() {
- List<BannerInfo> banners = bannerInfoService.lambdaQuery()
- .eq(BannerInfo::getStatus, 1)
- .orderByAsc(BannerInfo::getSort)
- .list();
- Map<String, Object> result = new HashMap<>();
- result.put("banners", banners);
- return Result.success(result);
- }
- /**
- * 获取广告位
- */
- @PostMapping("/getAdvertising")
- public Result<?> getAdvertising() {
- List<Advertising> banners = advertisingService.lambdaQuery()
- .eq(Advertising::getStatus, 1)
- .orderByAsc(Advertising::getSort)
- .list();
- Map<String, Object> result = new HashMap<>();
- result.put("banners", banners);
- return Result.success(result);
- }
- /**
- * 新增用户反馈
- */
- @PostMapping("/addUserFeedback")
- @Transactional(rollbackFor = Exception.class)
- public Result<?> addUserFeedback(@RequestBody UserFeedback data, HttpServletRequest request) {
- UserInfo cacheUser = getUserFromToken(request);
- if (cacheUser == null) {
- return Result.failed("登录已过期");
- }
- data.setUserId(cacheUser.getId());
- boolean saved = userFeedbackService.save(data);
- if (!saved) {
- return Result.failed("提交失败");
- }
- return Result.success();
- }
- /**
- * 查看用户反馈
- */
- @PostMapping("/getMyFeekBack")
- public Result<?> getMyFeekBack(HttpServletRequest request) {
- UserInfo cacheUser = getUserFromToken(request);
- if (cacheUser == null) {
- return Result.failed("登录已过期");
- }
- List<UserFeedback> list = userFeedbackService.lambdaQuery()
- .eq(UserFeedback::getUserId, cacheUser.getId())
- .orderByDesc(UserFeedback::getCreateTime)
- .list();
- Map<String, Object> result = new HashMap<>();
- result.put("list", list);
- return Result.success(result);
- }
- /**
- * 上传文件
- */
- @PostMapping("/upFile")
- public Result<?> upFile(@RequestParam("file") MultipartFile file) {
- try {
- // TODO: 实现文件上传逻辑,使用ossProperties配置
- String fileUrl = "/uploads/" + file.getOriginalFilename();
- Map<String, Object> result = new HashMap<>();
- result.put("fileUrl", fileUrl);
- return Result.success(result);
- } catch (Exception e) {
- log.error("文件上传失败", e);
- return Result.failed("文件上传失败");
- }
- }
- /**
- * 获取邀请员工的二维码
- */
- @GetMapping("/get-invite-qr")
- public void getInviteQr(HttpServletRequest request, HttpServletResponse response) {
- try {
- UserInfo cacheUser = getUserFromToken(request);
- if (cacheUser == null) {
- return;
- }
- UserFirm firm = userFirmService.lambdaQuery()
- .eq(UserFirm::getUserId, cacheUser.getId())
- .one();
- if (ObjectUtil.isEmpty(firm)) {
- return;
- }
- if (firm.getUserType() == 2) {
- return;
- }
- String content = "https://cd.api.zswlgz.com/deviceid?frimId=" + firm.getFirmId();
- QrCodeUtil.generate(content, 300, 300, ImgUtil.IMAGE_TYPE_PNG, response.getOutputStream());
- } catch (Exception e) {
- log.error("生成二维码失败", e);
- }
- }
- /**
- * 邀请员工加入企业
- */
- @PostMapping("/add-firm-user")
- public Result<?> addFirmUser(HttpServletRequest request, @RequestParam("firmId") Long firmId) {
- UserInfo cacheUser = getUserFromToken(request);
- if (cacheUser == null) {
- return Result.failed("登录已过期");
- }
- UserFirm userFirm = new UserFirm();
- userFirm.setUserId(cacheUser.getId());
- userFirm.setFirmId(firmId);
- userFirm.setUserType(2L);
- try {
- boolean saved = userFirmService.save(userFirm);
- if (saved) {
- FirmInfo firmInfo = firmInfoService.getById(firmId);
- return Result.success("你已经成功加入" + firmInfo.getName() + ",现在充电享受企业专享价");
- }
- } catch (Exception e) {
- return Result.failed(e.getMessage());
- }
- return Result.failed("加入失败");
- }
- /**
- * 从请求头获取token并从缓存中获取用户信息
- */
- private UserInfo getUserFromToken(HttpServletRequest request) {
- String token = request.getHeader("token");
- if (token == null) {
- return null;
- }
- Object obj = redisTemplate.opsForValue().get(TOKEN_PREFIX + token);
- if (obj instanceof UserInfo) {
- // 刷新token过期时间
- redisTemplate.expire(TOKEN_PREFIX + token, 30, TimeUnit.MINUTES);
- return (UserInfo) obj;
- }
- return null;
- }
- /**
- * 保存用户信息到缓存
- */
- private void saveUserToCache(String token, UserInfo userInfo) {
- redisTemplate.opsForValue().set(TOKEN_PREFIX + token, userInfo, 30, TimeUnit.MINUTES);
- }
- }
|