huliguo
2025-07-03 e3a2245265516fef78b4737d6fffc939e7c5e0af
pt-errand/src/main/java/com/ruoyi/errand/service/impl/AppUserServiceImpl.java
@@ -4,6 +4,7 @@
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
@@ -11,16 +12,10 @@
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.errand.constant.*;
import com.ruoyi.errand.domain.AppUser;
import com.ruoyi.errand.domain.*;
import com.ruoyi.errand.domain.Order;
import com.ruoyi.errand.domain.UserCancellationLog;
import com.ruoyi.errand.domain.VipOrder;
import com.ruoyi.errand.mapper.AppUserMapper;
import com.ruoyi.errand.mapper.*;
import com.ruoyi.errand.mapper.OrderMapper;
import com.ruoyi.errand.mapper.UserCancellationLogMapper;
import com.ruoyi.errand.mapper.VipOrderMapper;
import com.ruoyi.errand.object.dto.app.AppletLogin;
import com.ruoyi.errand.object.dto.app.BirthDayDTO;
import com.ruoyi.errand.object.dto.app.MobileLoginDTO;
@@ -35,7 +30,11 @@
import com.ruoyi.errand.object.vo.sys.OrderPageListVO;
import com.ruoyi.errand.object.vo.sys.UserStatsVO;
import com.ruoyi.errand.service.AppUserService;
import com.ruoyi.errand.service.CommunityCourierService;
import com.ruoyi.errand.utils.*;
import com.ruoyi.errand.utils.sms.AliyunSmsService;
import com.ruoyi.errand.utils.wx.RefundCallbackResult;
import com.ruoyi.errand.utils.wx.WechatPayService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
@@ -43,9 +42,11 @@
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.lang.reflect.Array;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalUnit;
@@ -68,6 +69,21 @@
    private OrderMapper orderMapper;
    @Autowired
    private VipOrderMapper vipOrderMapper;
    @Autowired
    private WechatPayService wechatPayService;
    @Autowired
    private AppUserService appUserService;
    @Autowired
    private CommunityCourierMapper communityCourierMapper;
    @Autowired
    private CommunityCourierService communityCourierService;
    @Autowired
    private CourierMapper courierMapper;
    @Autowired
    private CommunityMapper communityMapper;
    @Autowired
    private TokenBlacklistService blacklistService;
    @Override
@@ -100,7 +116,7 @@
        for (int i = 0; i < 6; i++) {
            code += Double.valueOf(Math.random() * 10).intValue();
        }
        SMSUtil.sendSms("[\"" + code + "\"]", phone, "8824121211029", "39533d100b2b4aee8ed198aa49fe99dd");
        AliyunSmsService.sendVerificationCode(phone,code);
        redisService.setCacheObject(phone, code, 300L, TimeUnit.SECONDS);
    }
@@ -113,26 +129,16 @@
            }
        }
        //查看用户是否存在
        AppUser appUser = this.getOne(new LambdaQueryWrapper<AppUser>().eq(AppUser::getPhone, mobileLogin.getPhone()));
        if (null == appUser || appUser.getDelFlag().equals(DelFlagConstant.DELETE)) {
        AppUser appUser = this.getOne(new LambdaQueryWrapper<AppUser>().eq(AppUser::getPhone, mobileLogin.getPhone())
                .ne(AppUser::getStatus,AppUserStatusConstant.LOGOUT)
                .eq(AppUser::getDelFlag,DelFlagConstant.UNDELETE));
        if (null == appUser || null == appUser.getWxOpenid()) {
            //用户不存在
            //使用jscode获取微信openid
            Map<String, Object> map = weChatUtil.code2Session(mobileLogin.getJscode());
            Integer errcode = Integer.valueOf(map.get("errcode").toString());
            if(0 != errcode){
                throw new ServiceException(map.get("msg").toString());
            }
            String openid = map.get("openid").toString();
            //注册一个
            appUser = new AppUser();
            appUser.setPhone(mobileLogin.getPhone());
            appUser.setDelFlag(DelFlagConstant.UNDELETE);
            appUser.setStatus(AppUserStatusConstant.NORMAL);
            appUser.setWxOpenid(openid);
            appUser.setAvatar(DEFAULT_AVATAR_URL);
            appUser.setFirstLogin(IsFirstLoginConstant.YES);
            appUser.setFirstOrder(IsFirstOrder.YES);
            this.save(appUser);
            //跳转注册页面
            LoginVO loginVo = new LoginVO();
            loginVo.setSkipPage(2);
            loginVo.setPhone(mobileLogin.getPhone());
            return R.ok(loginVo);
        }
        if (Objects.equals(appUser.getStatus(), AppUserStatusConstant.FREEZE)) {
            throw new ServiceException("该账户已被冻结");
@@ -152,7 +158,7 @@
        loginVO.setToken("app:" + jwt.get("token").toString());
        loginVO.setFailureTime(TimeUnit.MILLISECONDS.toSeconds((long)jwt.get("exp")));
        loginVO.setPhone(appUser.getPhone());
        loginVO.setSkipPage(appUser.getFirstLogin());
        loginVO.setSkipPage(1);
        loginVO.setIsCourier(appUser.getCourierId()!=null);
        return R.ok(loginVO);
    }
@@ -167,29 +173,21 @@
        }
        String openid = map.get("openid").toString();
        String sessionKey = map.get("sessionKey").toString();
        //查询用户是否注册,没有注册则注册
        AppUser appUser = this.getOne(new LambdaQueryWrapper<AppUser>().eq(AppUser::getWxOpenid, openid));
        if(null == appUser|| appUser.getDelFlag().equals(DelFlagConstant.DELETE)){
            appUser = new AppUser();
            //注册
            //获取手机号
            String decrypt = WXCore.decrypt(appletLogin.getEncryptedData_phone(), sessionKey, appletLogin.getIv_phone());
            if (StringUtils.isEmpty(decrypt)) {
                return R.fail("获取手机信息失败");
            }
            JSONObject phone = JSON.parseObject(decrypt);
            String purePhoneNumber = phone.getString("phoneNumber");
            //新用户默认信息
            appUser = new AppUser();
            appUser.setPhone(purePhoneNumber);
            appUser.setDelFlag(DelFlagConstant.UNDELETE);
            appUser.setStatus(AppUserStatusConstant.NORMAL);
            appUser.setWxOpenid(openid);
            appUser.setAvatar(DEFAULT_AVATAR_URL);
            appUser.setFirstLogin(IsFirstLoginConstant.YES);
            appUser.setFirstOrder(IsFirstOrder.YES);
            this.save(appUser);
        //获取手机号
        String decrypt = WXCore.decrypt(appletLogin.getEncryptedData_phone(), sessionKey, appletLogin.getIv_phone());
        if (StringUtils.isEmpty(decrypt)) {
            return R.fail("获取手机信息失败");
        }
        JSONObject phoneJson = JSON.parseObject(decrypt);
        String phone = phoneJson.getString("phoneNumber");
        //查询用户是否存在
        AppUser appUser = this.getOne(new LambdaQueryWrapper<AppUser>().eq(AppUser::getPhone, phone).ne(AppUser::getStatus, AppUserStatusConstant.LOGOUT).eq(AppUser::getDelFlag,DelFlagConstant.UNDELETE));
        if(null == appUser || null == appUser.getWxOpenid()){
            //跳转到注册界面
            LoginVO loginVo = new LoginVO();
            loginVo.setSkipPage(2);
            loginVo.setPhone(phone);
            return R.ok(loginVo);
        }
        if (Objects.equals(appUser.getStatus(), AppUserStatusConstant.FREEZE)) {
@@ -200,7 +198,7 @@
        }
        //构建token
        Map<String,Object> tokenMap = new HashMap<>();
        map.put("userId",appUser.getId());
        tokenMap.put("userId",appUser.getId());
        Map<String, Object> jwt = JwtUtil.createJWT(tokenMap);
@@ -208,18 +206,59 @@
        loginVO.setToken("app:" + jwt.get("token").toString());
        loginVO.setFailureTime(TimeUnit.MILLISECONDS.toSeconds((long)jwt.get("exp")));
        loginVO.setPhone(appUser.getPhone());
        loginVO.setSkipPage(appUser.getFirstLogin());
        loginVO.setSkipPage(1);
        loginVO.setIsCourier(appUser.getCourierId()!=null);
        return R.ok(loginVO);
    }
    @Override
    public void register(RegisterDTO registerDTO) {
        //注册 修改用户信息
        AppUser appUser = (AppUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        appUser.setName(registerDTO.getUsername());
        appUser.setFirstLogin(IsFirstLoginConstant.NO);
        appUser.setCommunityId(registerDTO.getCommunityId());
        this.updateById(appUser);
    public LoginVO register(RegisterDTO registerDTO) {
        //使用jscode获取微信openid
        Map<String, Object> map = weChatUtil.code2Session(registerDTO.getJscode());
        Integer errcode = Integer.valueOf(map.get("errcode").toString());
        if(0 != errcode){
            throw new ServiceException(map.get("msg").toString());
        }
        String openid = map.get("openid").toString();
        AppUser appUser2 = this.getOne(new LambdaQueryWrapper<AppUser>().eq(AppUser::getPhone, registerDTO.getPhone()).ne(AppUser::getStatus, AppUserStatusConstant.LOGOUT).eq(AppUser::getDelFlag,DelFlagConstant.UNDELETE));
        if (null != appUser2 && appUser2.getWxOpenid() !=null) {
            throw new ServiceException("手机号已注册,请直接登录!");
        }
        if (appUser2 ==null) {
            appUser2 = new AppUser();
            //注册一个
            appUser2.setPhone(registerDTO.getPhone());
            appUser2.setDelFlag(DelFlagConstant.UNDELETE);
            appUser2.setStatus(AppUserStatusConstant.NORMAL);
            appUser2.setWxOpenid(openid);
            appUser2.setFirstLogin(IsFirstLoginConstant.YES);
            appUser2.setFirstOrder(IsFirstOrder.YES);
        }
        //修改
        appUser2.setName(registerDTO.getUsername());
        appUser2.setAvatar(registerDTO.getAvatar()==null?DEFAULT_AVATAR_URL:registerDTO.getAvatar());
        appUser2.setCommunityId(registerDTO.getCommunityId());
        appUser2.setWxOpenid(openid);
        appUser2.setPhone(registerDTO.getPhone());
        appUser2.setCreateTime(LocalDateTime.now());
        appUser2.setRegionExtend(registerDTO.getRegionExtend());
        this.saveOrUpdate(appUser2);
        //构建token
        Map<String,Object> tokenMap = new HashMap<>();
        tokenMap.put("userId",appUser2.getId());
        Map<String, Object> jwt = JwtUtil.createJWT(tokenMap);
        LoginVO loginVO=new LoginVO();
        loginVO.setToken("app:" + jwt.get("token").toString());
        loginVO.setFailureTime(TimeUnit.MILLISECONDS.toSeconds((long)jwt.get("exp")));
        loginVO.setPhone(appUser2.getPhone());
        loginVO.setSkipPage(1);
        loginVO.setIsCourier(appUser2.getCourierId()!=null);
        return loginVO;
    }
@@ -227,19 +266,55 @@
    public OrderPageVO getOrderPage(Integer communityId) {
        AppUser appUser = (AppUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        //更换绑定的小区
        if (communityId!=null){
        if (communityId!=null&& !Objects.equals(appUser.getCommunityId(), communityId)){
            appUser.setCommunityId(communityId);
            this.updateById(appUser);
        }
        List<OrderPageVO> orderPage = this.getBaseMapper().getOrderPage(appUser.getId());
        Community community = communityMapper.selectById(appUser.getCommunityId());
        String regionFullName = getRegionFullName(community.getRegionId());
        orderPage.get(0).setRegionName(regionFullName);
        orderPage.get(0).setRegionId(community.getRegionId());
        return orderPage.get(0);
    }
    @Autowired
    private RegionMapper regionMapper;
    /**
     * 根据区ID查询完整的省市区名称
     */
    public String getRegionFullName(Integer districtId) {
        Region district = regionMapper.selectById(districtId);
        if (district == null) {
            return "";
        }
        Region city = regionMapper.selectById(district.getParentId());
        if (city == null) {
            return district.getName();
        }
        Region province = regionMapper.selectById(city.getParentId());
        if (province == null) {
            return city.getName()  + district.getName();
        }
        return province.getName()  + city.getName()  + district.getName();
    }
    @Override
    public AppUserInfoVO getMyInfo() {
        AppUser appUser = (AppUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        return this.getBaseMapper().getMyInfo(appUser.getId());
        AppUserInfoVO myInfo = this.getBaseMapper().getMyInfo(appUser.getId());
        myInfo.setEndTimeStamp(myInfo.getEndTime() != null ?
                myInfo.getEndTime().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli() :
                null);
        if (myInfo.getEndTime() != null) {
            if(myInfo.getEndTime().isBefore(LocalDateTime.now())){
                myInfo.setVipId(null);
            }
        }
        return myInfo;
    }
    @Override
@@ -265,16 +340,44 @@
     * 注销账号
     */
    @Override
    public void delete() {
    public void delete(String token) {
        AppUser appuser = (AppUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        appuser.setDelFlag(DelFlagConstant.DELETE);
        appuser.setStatus(AppUserStatusConstant.LOGOUT);
        this.updateById(appuser);
        //跑腿员 订单是否完成
        if (appuser.getCourierId()!=null){
            //跑腿员
            Courier courier = courierMapper.selectById(appuser.getCourierId());
            if (null != courier && courier.getDelFlag().equals(DelFlagConstant.UNDELETE)) {
                //查订单是否完成
                Long count = orderMapper.selectCount(new LambdaUpdateWrapper<Order>().eq(Order::getCourierId, appuser.getCourierId())
                        .eq(Order::getDelFlag, DelFlagConstant.UNDELETE)
                        .eq(Order::getOrderStatus, 2));
                if (count > 0) {
                    throw new ServiceException("您还有订单未完成,无法注销");
                }
            }
            //与小区关系删除
            CommunityCourier communityCourier = communityCourierMapper.selectOne(new LambdaQueryWrapper<CommunityCourier>().eq(CommunityCourier::getCourierId, appuser.getCourierId()));
            if (null != communityCourier) {
                communityCourierMapper.deleteById(communityCourier.getId());
            }
            //跑腿员删除
            courier.setDelFlag(DelFlagConstant.DELETE);
            courierMapper.updateById(courier);
        }
        UpdateWrapper<AppUser> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("id", appuser.getId())
                .set("courier_id", null)
                .set("del_flag", DelFlagConstant.DELETE)
                        .set("status",AppUserStatusConstant.LOGOUT);
        this.getBaseMapper().update(null, updateWrapper);
        UserCancellationLog userCancellationLog=new UserCancellationLog();
        userCancellationLog.setApp_user_id(appuser.getId());
        userCancellationLog.setDel_flag(DelFlagConstant.DELETE);
        userCancellationLog.setCreate_time(LocalDateTime.now());
        userCancellationLogMapper.insert(userCancellationLog);
        blacklistService.addToBlacklist(token);
    }
    @Override
@@ -329,12 +432,15 @@
    }
    @Override
    public AppUserSysDetailVO detail(Integer id) {
    public AppUserSysDetailVO detail(String id) {
        // 获取本月的开始时间和结束时间
        LocalDate now = LocalDate.now();
        LocalDateTime startOfMonth = now.withDayOfMonth(1).atStartOfDay();
        LocalDateTime endOfMonth = now.withDayOfMonth(now.lengthOfMonth()).atTime(23, 59, 59);
        AppUser appUser = this.getBaseMapper().selectById(id);
        if (null == appUser || appUser.getDelFlag() == DelFlagConstant.DELETE) {
            throw new ServiceException("用户不存在");
        }
        AppUserSysDetailVO vo = new AppUserSysDetailVO();
        BeanUtils.copyProperties(appUser, vo);
        int isVip =0;
@@ -360,7 +466,7 @@
    }
    @Override
    public void froze(Integer id) {
    public void froze(String id) {
        AppUser appUser = this.getBaseMapper().selectById(id);
        if (appUser==null|| Objects.equals(appUser.getDelFlag(), DelFlagConstant.DELETE)) {
            throw new ServiceException("用户不存在");
@@ -377,13 +483,14 @@
    }
    @Override
    public void refund(Integer id) {
    public void refund(String id) {
        // 1. 查询用户所有未退费的VIP订单(状态为4-已完成且未删除)
        List<VipOrder> orders = vipOrderMapper.selectList(new LambdaQueryWrapper<VipOrder>()
                .eq(VipOrder::getAppUserId, id)
                .eq(VipOrder::getOrderStatus, 4) // 4-已完成
                .eq(VipOrder::getDelFlag, DelFlagConstant.UNDELETE)     // 0-未删除
                .isNull(VipOrder::getRefundTime) // 未退款的
                        .eq(VipOrder::getPayStatus,2)
                .orderByDesc(VipOrder::getOrderTime));
        // 2. 计算每个订单的有效期结束时间
@@ -405,29 +512,55 @@
            //退款
            log.info("开始会员退费,被退款人员id:{},退款订单:{}",vipOrder.getAppUserId(),vipOrder.getId());
            R r = refundPayMoney(vipOrder);//退款
            if (200 == r.getCode()) {
                //退款成功取消用户的会员,将用户状态改变
                AppUser appUser = this.getById(id);
                appUser.setStartTime(LocalDateTime.now());
                appUser.setEndTime(LocalDateTime.now());
                appUser.setVipId(null);
            if (200 != r.getCode()) {
                throw new ServiceException("退款失败,msg:"+ r.getMsg()+" 订单id:"+vipOrder.getId());
            }
        });
        UpdateWrapper<AppUser> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("id", id)
                .set("vip_id", null)        // 显式设置vip_id为null
                .set("end_time", LocalDateTime.now());  // 设置结束时间
        appUserService.update(null, updateWrapper);
    }
    @Override
    public R refundPayMoneyCallback(RefundCallbackResult refundCallbackResult) {
        String code = refundCallbackResult.getR3_RefundOrderNo().substring(1);
        VipOrder vipOrder = vipOrderMapper.selectOne(new LambdaQueryWrapper<VipOrder>().eq(VipOrder::getOrderNumber, code));
    public R refundPayMoneyCallback(String xmlData) {
        RefundCallbackResult result = wechatPayService.processRefundCallback(xmlData);
        if (!result.isSuccess()) {
            System.out.println("会员退费错误:"+result.getMsg());
            return R.fail(result.getMsg());
        }
        VipOrder vipOrder = vipOrderMapper.selectOne(new LambdaQueryWrapper<VipOrder>().eq(VipOrder::getOrderNumber,  result.getOrderNo()));
        if (null == vipOrder || vipOrder.getPayStatus() == 1 || vipOrder.getOrderStatus() == 6) {
            return R.ok();
        }
        vipOrder.setRefundCode(refundCallbackResult.getR5_RefundTrxNo());
        vipOrder.setRefundCode(result.getRefundNo());
        vipOrder.setRefundStatus(2);
        vipOrder.setRefundTime(LocalDateTime.now());
        vipOrder.setOrderStatus(6);//已退费
        vipOrderMapper.updateById(vipOrder);
        //退款成功取消用户的会员,将用户状态改变
        UpdateWrapper<AppUser> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("id", vipOrder.getAppUserId())
                .set("vip_id", null)        // 显式设置vip_id为null
                .set("end_time", LocalDateTime.now());  // 设置结束时间
        appUserService.update(null, updateWrapper);
        return R.ok();
    }
    @Override
    public void setName(String name) {
        AppUser appuser = (AppUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        appuser.setName(name);
        this.updateById(appuser);
    }
    @Override
    public void setAvatar(String avatar) {
        AppUser appuser = (AppUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        appuser.setAvatar(avatar);
        this.updateById(appuser);
    }
    private Map<Long, LocalDateTime> calculateOrderEndTimes(List<VipOrder> orders) {
@@ -479,11 +612,14 @@
        BigDecimal paymentAmount = order.getPaymentAmount();
        if (BigDecimal.ZERO.compareTo(order.getPaymentAmount()) < 0) {//支付的金额是否大于0
            //微信退款
            RefundResult refund = PaymentUtil.refund(order.getOrderNumber(), "R" + order.getOrderNumber(), paymentAmount.doubleValue(),
                    "/app/user/refundPayMoneyCallback");
            if (!"100".equals(refund.getRa_Status())) {
                return R.fail(refund.getRc_CodeMsg());//退款失败
            Map<String,String> map = wechatPayService.refund(order.getOrderNumber(), order.getOrderNumber(), order.getPaymentAmount().toString(), order.getPaymentAmount().toString(), "会员退款", "/app/user/refundPayMoneyCallback");
            if (!"SUCCESS".equals(map.get("return_code"))) {
                return R.fail(map.get("return_msg"));//退款失败
            }
            //这里申请成功后先返回,等待微信退款成功再取消用户会员
            order.setRefundStatus(1);
            vipOrderMapper.updateById(order);
            return R.ok();
        }
        return R.ok();
    }