package com.ruoyi.errand.service.impl;
|
|
import com.alibaba.fastjson2.JSON;
|
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;
|
import com.ruoyi.common.core.domain.R;
|
import com.ruoyi.common.exception.ServiceException;
|
import com.ruoyi.common.utils.StringUtils;
|
import com.ruoyi.errand.constant.*;
|
import com.ruoyi.errand.domain.*;
|
|
import com.ruoyi.errand.mapper.*;
|
|
import com.ruoyi.errand.object.dto.app.AppletLogin;
|
import com.ruoyi.errand.object.dto.app.BirthDayDTO;
|
import com.ruoyi.errand.object.dto.app.MobileLoginDTO;
|
import com.ruoyi.errand.object.dto.app.RegisterDTO;
|
import com.ruoyi.errand.object.dto.sys.AppUserPageListDTO;
|
import com.ruoyi.errand.object.vo.app.AppUserInfoVO;
|
import com.ruoyi.errand.object.vo.app.OrderPageVO;
|
import com.ruoyi.errand.object.vo.app.UserTopInfoVO;
|
import com.ruoyi.errand.object.vo.login.LoginVO;
|
import com.ruoyi.errand.object.vo.sys.AppUserPageListVO;
|
import com.ruoyi.errand.object.vo.sys.AppUserSysDetailVO;
|
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;
|
import org.springframework.security.core.context.SecurityContextHolder;
|
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;
|
import java.util.*;
|
import java.util.concurrent.TimeUnit;
|
import java.util.stream.Collectors;
|
|
@Slf4j
|
@Service
|
public class AppUserServiceImpl extends ServiceImpl<AppUserMapper, AppUser> implements AppUserService {
|
@Resource
|
private RedisService redisService;
|
|
@Resource
|
private WeChatUtil weChatUtil;
|
private static final String DEFAULT_AVATAR_URL = "http://qijishenghuiyuan.obs.cn-southwest-2.myhuaweicloud.com/admin/aedfbbb41280471f8d9fa7905298b65f.png";
|
@Autowired
|
private UserCancellationLogMapper userCancellationLogMapper;
|
@Autowired
|
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
|
public void getSMSCode(String phone) {
|
//校验验证码获取频率(1分钟5次)
|
String key = "app" + "&" + phone;
|
Map<String, Object> cacheMap = redisService.getCacheMap(key);
|
if(null != cacheMap && cacheMap.size() > 0){
|
Integer number = Integer.valueOf(cacheMap.get("number").toString()) + 1;
|
Long startTime = Long.valueOf(cacheMap.get("startTime").toString());
|
if(number > 5 && (System.currentTimeMillis() - startTime) < 60000){
|
throw new ServiceException("获取验证码太频繁,请稍后重试!");
|
}
|
if(number <= 5){
|
cacheMap.put("number", number);
|
}else{
|
cacheMap.put("number", 1);
|
cacheMap.put("startTime", System.currentTimeMillis());
|
}
|
}else{
|
cacheMap = new HashMap<>();
|
cacheMap.put("number", 1);
|
cacheMap.put("startTime", System.currentTimeMillis());
|
}
|
//存储计数器到缓存中,5分钟有效期
|
redisService.setCacheMap(key, cacheMap, 300);
|
|
//开始构建验证码内容
|
String code = "";
|
for (int i = 0; i < 6; i++) {
|
code += Double.valueOf(Math.random() * 10).intValue();
|
}
|
AliyunSmsService.sendVerificationCode(phone,code);
|
redisService.setCacheObject(phone, code, 300L, TimeUnit.SECONDS);
|
}
|
|
@Override
|
public R<LoginVO> mobileLogin(MobileLoginDTO mobileLogin) {
|
String code = redisService.getCacheObject(mobileLogin.getPhone());
|
if(!"999999".equals(mobileLogin.getCode())){
|
if(null == code || !code.equals(mobileLogin.getCode())){
|
throw new ServiceException("验证码错误");
|
}
|
}
|
//查看用户是否存在
|
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()) {
|
//用户不存在
|
//跳转注册页面
|
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("该账户已被冻结");
|
}
|
if (Objects.equals(appUser.getStatus(), AppUserStatusConstant.LOGOUT)) {
|
throw new ServiceException("该账户已被注销");
|
}
|
appUser.setLastLoginTime(LocalDateTime.now());
|
this.updateById(appUser);
|
//构建token
|
Map<String,Object> map = new HashMap<>();
|
map.put("userId",appUser.getId());
|
Map<String, Object> jwt = JwtUtil.createJWT(map);
|
|
|
LoginVO loginVO=new LoginVO();
|
loginVO.setToken("app:" + jwt.get("token").toString());
|
loginVO.setFailureTime(TimeUnit.MILLISECONDS.toSeconds((long)jwt.get("exp")));
|
loginVO.setPhone(appUser.getPhone());
|
loginVO.setSkipPage(1);
|
loginVO.setIsCourier(false);
|
if (appUser.getCourierId()!=null){
|
Courier courier = courierMapper.selectById(appUser.getCourierId());
|
if (courier!=null && courier.getDelFlag().equals(0) && courier.getStatus().equals(1)){
|
loginVO.setIsCourier(true);
|
}
|
}
|
return R.ok(loginVO);
|
}
|
|
@Override
|
public R<LoginVO> appletLogin(AppletLogin appletLogin) {
|
//使用jscode获取微信openid
|
Map<String, Object> map = weChatUtil.code2Session(appletLogin.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();
|
String sessionKey = map.get("sessionKey").toString();
|
//获取手机号
|
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)) {
|
throw new ServiceException("该账户已被冻结");
|
}
|
if (Objects.equals(appUser.getStatus(), AppUserStatusConstant.LOGOUT)) {
|
throw new ServiceException("该账户已被注销");
|
}
|
//构建token
|
Map<String,Object> tokenMap = new HashMap<>();
|
tokenMap.put("userId",appUser.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(appUser.getPhone());
|
loginVO.setSkipPage(1);
|
loginVO.setIsCourier(false);
|
if (appUser.getCourierId()!=null){
|
Courier courier = courierMapper.selectById(appUser.getCourierId());
|
if (courier!=null && courier.getDelFlag().equals(0) && courier.getStatus().equals(1)){
|
loginVO.setIsCourier(true);
|
}
|
}
|
|
|
return R.ok(loginVO);
|
}
|
|
@Override
|
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(false);
|
if (appUser2.getCourierId()!=null){
|
Courier courier = courierMapper.selectById(appUser2.getCourierId());
|
if (courier!=null && courier.getDelFlag().equals(0) && courier.getStatus().equals(1)){
|
loginVO.setIsCourier(true);
|
}
|
}
|
return loginVO;
|
|
}
|
|
@Override
|
public OrderPageVO getOrderPage(Integer communityId,String regionExtend) {
|
AppUser appUser = (AppUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
//更换绑定的小区
|
if (communityId!=null&& !Objects.equals(appUser.getCommunityId(), communityId)){
|
appUser.setCommunityId(communityId);
|
this.updateById(appUser);
|
}
|
if (regionExtend!=null&& !Objects.equals(appUser.getRegionExtend(), regionExtend)){
|
appUser.setRegionExtend(regionExtend);
|
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();
|
AppUserInfoVO myInfo = this.getBaseMapper().getMyInfo(appUser.getId());
|
myInfo.setIsCourier(false);
|
if (myInfo.getCourierId()!=null){
|
Courier courier = courierMapper.selectById(myInfo.getCourierId());
|
if (courier!=null && courier.getDelFlag().equals(0) && courier.getStatus().equals(1)){
|
myInfo.setIsCourier(true);
|
}
|
}
|
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
|
public void setSex(Integer sex) {
|
AppUser appUser = (AppUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
if (appUser.getSex().equals(sex)) {
|
throw new ServiceException("修改的性别与当前性别重复");
|
}
|
appUser.setSex(sex);
|
|
updateById(appUser);
|
|
}
|
|
@Override
|
public void setBirthDay(BirthDayDTO birth) {
|
AppUser appUser = (AppUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
appUser.setBirthday(birth.getBirthday());
|
updateById(appUser);
|
}
|
|
/**
|
* 注销账号
|
*/
|
@Override
|
public void delete(String token) {
|
AppUser appuser = (AppUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
//跑腿员 订单是否完成
|
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
|
public UserStatsVO getUserStats(LocalDateTime start, LocalDateTime end, String datePattern) {
|
UserStatsVO vo = new UserStatsVO();
|
// 1. 查询按时间分组的用户数
|
List<Map<String, Object>> stats = this.getBaseMapper().countGroupByDate(start, end, datePattern);
|
|
// 2. 生成完整的日期序列并填充数据
|
fillDateAndValue(vo, start, end, datePattern, stats);
|
|
return vo;
|
}
|
|
@Override
|
public UserTopInfoVO userTopInfo(LocalDateTime start, LocalDateTime end) {
|
UserTopInfoVO userTopInfoVO = new UserTopInfoVO();
|
// 1. 查询总用户数
|
userTopInfoVO.setTotalUsers(this.getBaseMapper().countByCreateTimeBefore(end));
|
|
// 2. 查询新增用户数
|
userTopInfoVO.setInsertUsers(this.getBaseMapper().countByCreateTimeBetween(start, end));
|
return userTopInfoVO;
|
}
|
|
@Override
|
public IPage<AppUserPageListVO> getAppUserPageList(AppUserPageListDTO dto) {
|
// 获取本月的开始时间和结束时间
|
LocalDate now = LocalDate.now();
|
LocalDateTime startOfMonth = now.withDayOfMonth(1).atStartOfDay();
|
LocalDateTime endOfMonth = now.withDayOfMonth(now.lengthOfMonth()).atTime(23, 59, 59);
|
|
IPage<AppUserPageListVO> page = new Page<>(dto.getPageNum(),dto.getPageSize());
|
IPage<AppUserPageListVO> iPage = this.getBaseMapper().getAppUserPageList(page, dto);
|
iPage.getRecords().forEach((record) -> {
|
//当月下单量
|
Long mouth = orderMapper.selectCount(new LambdaUpdateWrapper<Order>()
|
.eq(Order::getAppUserId, record.getId())
|
.eq(Order::getDelFlag, DelFlagConstant.UNDELETE)
|
.between(Order::getOrderTime, startOfMonth, endOfMonth)
|
);
|
record.setMouth(mouth.intValue());
|
|
//总共下单量
|
Long total = orderMapper.selectCount(new LambdaUpdateWrapper<Order>()
|
.eq(Order::getAppUserId, record.getId())
|
.eq(Order::getDelFlag, DelFlagConstant.UNDELETE)
|
);
|
record.setTotal(total.intValue());
|
});
|
return iPage;
|
}
|
|
@Override
|
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;
|
if (appUser.getEndTime() != null) {
|
isVip = appUser.getEndTime().isAfter(LocalDateTime.now())?1:0;
|
}
|
vo.setIsVip(isVip);
|
//当月下单量
|
Long mouth = orderMapper.selectCount(new LambdaUpdateWrapper<Order>()
|
.eq(Order::getAppUserId, id)
|
.eq(Order::getDelFlag, DelFlagConstant.UNDELETE)
|
.between(Order::getOrderTime, startOfMonth, endOfMonth)
|
);
|
vo.setMouth(mouth.intValue());
|
|
//总共下单量
|
Long total = orderMapper.selectCount(new LambdaUpdateWrapper<Order>()
|
.eq(Order::getAppUserId,id)
|
.eq(Order::getDelFlag, DelFlagConstant.UNDELETE)
|
);
|
vo.setTotal(total.intValue());
|
return vo;
|
}
|
|
@Override
|
public void froze(String id) {
|
AppUser appUser = this.getBaseMapper().selectById(id);
|
if (appUser==null|| Objects.equals(appUser.getDelFlag(), DelFlagConstant.DELETE)) {
|
throw new ServiceException("用户不存在");
|
}
|
|
if (appUser.getStatus()==1 || appUser.getStatus()==2) {
|
appUser.setStatus(appUser.getStatus()==1?2:1);
|
}else {
|
throw new ServiceException("用户状态错误");
|
}
|
|
this.getBaseMapper().updateById(appUser);
|
|
}
|
|
@Override
|
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. 计算每个订单的有效期结束时间
|
Map<Long, LocalDateTime> orderEndTimes = calculateOrderEndTimes(orders);
|
|
// 3. 筛选出仍在有效期内的订单
|
LocalDateTime now = LocalDateTime.now();
|
List<VipOrder> refundVipOrderList = orders.stream()
|
.filter(order -> {
|
LocalDateTime endTime = orderEndTimes.get(order.getId());
|
return endTime != null && endTime.isAfter(now);
|
})
|
.collect(Collectors.toList());
|
if(refundVipOrderList.isEmpty()){
|
return;
|
}
|
// 4.对每个订单进行退款操作
|
refundVipOrderList.forEach(vipOrder -> {
|
//退款
|
log.info("开始会员退费,被退款人员id:{},退款订单:{}",vipOrder.getAppUserId(),vipOrder.getId());
|
R r = refundPayMoney(vipOrder);//退款
|
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(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(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) {
|
Map<Long, LocalDateTime> result = new HashMap<>();
|
LocalDateTime currentEndTime = null;
|
|
// 按购买时间升序处理,计算叠加后的有效期
|
List<VipOrder> sortedOrders = orders.stream()
|
.sorted(Comparator.comparing(VipOrder::getOrderTime))
|
.collect(Collectors.toList());
|
|
for (VipOrder order : sortedOrders) {
|
int daysToAdd = getVipDays(order.getVipId());
|
if (daysToAdd == 0) continue;
|
|
LocalDateTime orderTime = order.getOrderTime();
|
LocalDateTime orderEndTime = orderTime.plusDays(daysToAdd)
|
.withHour(23).withMinute(59).withSecond(59);
|
|
// 如果当前订单购买时间在上一个有效期之后,则重新计算
|
if (currentEndTime == null || orderTime.isAfter(currentEndTime)) {
|
currentEndTime = orderEndTime;
|
} else {
|
// 否则叠加有效期
|
currentEndTime = currentEndTime.plusDays(daysToAdd)
|
.withHour(23).withMinute(59).withSecond(59);
|
}
|
|
result.put(order.getId(), currentEndTime);
|
}
|
|
return result;
|
}
|
|
private int getVipDays(Integer vipId) {
|
switch (vipId) {
|
case 1: return 31;
|
case 2: return 90;
|
case 3: return 180;
|
case 4: return 365;
|
default: return 0;
|
}
|
}
|
/**
|
* 返回订单支付金额
|
*/
|
public R refundPayMoney(VipOrder order) {
|
//开始退款
|
BigDecimal paymentAmount = order.getPaymentAmount();
|
if (BigDecimal.ZERO.compareTo(order.getPaymentAmount()) < 0) {//支付的金额是否大于0
|
//微信退款
|
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();
|
}
|
|
private void fillDateAndValue(UserStatsVO vo, LocalDateTime start, LocalDateTime end,
|
String datePattern, List<Map<String, Object>> stats) {
|
List<String> allDates = generateDateRange(start, end, datePattern);
|
Map<String, Integer> statMap = convertStatsToMap(stats);
|
|
List<String> dates = new ArrayList<>();
|
List<Integer> values = new ArrayList<>();
|
|
for (String date : allDates) {
|
dates.add(date);
|
values.add(statMap.getOrDefault(date, 0)); // 无数据的日期补0
|
}
|
|
vo.setDate(dates);
|
vo.setValue(values);
|
}
|
|
private Map<String, Integer> convertStatsToMap(List<Map<String, Object>> stats) {
|
return stats.stream()
|
.collect(Collectors.toMap(
|
stat -> String.valueOf(stat.get("date")),
|
stat -> Integer.valueOf(String.valueOf(stat.get("count")))
|
));
|
}
|
|
private List<String> generateDateRange(LocalDateTime start, LocalDateTime end, String datePattern) {
|
List<String> dates = new ArrayList<>();
|
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(datePattern);
|
|
TemporalUnit unit = getTemporalUnit(datePattern);
|
LocalDateTime current = getInitialDateTime(start, datePattern);
|
|
while (!current.isAfter(end)) {
|
dates.add(current.format(formatter));
|
current = incrementDateTime(current, unit);
|
}
|
|
return dates;
|
}
|
|
private TemporalUnit getTemporalUnit(String datePattern) {
|
switch (datePattern) {
|
case "HH时": return ChronoUnit.HOURS;
|
case "EEEE":
|
case "dd日":
|
case "yyyy-MM-dd": return ChronoUnit.DAYS;
|
case "MM月": return ChronoUnit.MONTHS;
|
default: return ChronoUnit.DAYS;
|
}
|
}
|
|
private LocalDateTime getInitialDateTime(LocalDateTime datetime, String datePattern) {
|
switch (datePattern) {
|
case "HH时": return datetime.withMinute(0).withSecond(0).withNano(0);
|
case "MM月": return datetime.withDayOfMonth(1);
|
default: return datetime;
|
}
|
}
|
|
private LocalDateTime incrementDateTime(LocalDateTime current, TemporalUnit unit) {
|
if (unit == ChronoUnit.HOURS) return current.plusHours(1);
|
if (unit == ChronoUnit.DAYS) return current.plusDays(1);
|
if (unit == ChronoUnit.MONTHS) return current.plusMonths(1);
|
return current.plusDays(1);
|
}
|
|
}
|