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.extension.service.impl.ServiceImpl;
|
import com.ruoyi.common.core.domain.R;
|
import com.ruoyi.common.exception.ServiceException;
|
import com.ruoyi.errand.constant.DelFlagConstant;
|
import com.ruoyi.errand.domain.AppUser;
|
import com.ruoyi.errand.domain.VipOrder;
|
import com.ruoyi.errand.domain.VipSetting;
|
import com.ruoyi.errand.mapper.AppUserMapper;
|
import com.ruoyi.errand.mapper.VipOrderMapper;
|
import com.ruoyi.errand.mapper.VipSettingMapper;
|
import com.ruoyi.errand.object.dto.app.VipPaymentDTO;
|
import com.ruoyi.errand.object.vo.sys.OrderSysDetailVO;
|
import com.ruoyi.errand.service.VipOrderService;
|
import com.ruoyi.errand.utils.CloseOrderResult;
|
import com.ruoyi.errand.utils.PaymentUtil;
|
import com.ruoyi.errand.utils.UniPayCallbackResult;
|
import com.ruoyi.errand.utils.UniPayResult;
|
import com.ruoyi.errand.utils.wx.PayResult;
|
import com.ruoyi.errand.utils.wx.WechatPayService;
|
import lombok.extern.slf4j.Slf4j;
|
import org.springframework.data.redis.core.RedisTemplate;
|
import org.springframework.security.core.context.SecurityContextHolder;
|
import org.springframework.stereotype.Service;
|
|
import javax.annotation.Resource;
|
import java.math.BigDecimal;
|
import java.text.SimpleDateFormat;
|
import java.time.LocalDateTime;
|
import java.time.ZoneOffset;
|
import java.util.*;
|
|
@Service
|
@Slf4j
|
public class VipOrderServiceImpl extends ServiceImpl<VipOrderMapper, VipOrder> implements VipOrderService {
|
@Resource
|
private VipSettingMapper vipSettingMapper;
|
@Resource
|
private RedisTemplate redisTemplate;
|
@Resource
|
private AppUserMapper appUserMapper;
|
@Resource
|
private WechatPayService wechatPayService;
|
|
@Override
|
public R vipPayment(VipPaymentDTO vipPaymentDTO) {
|
AppUser appuser = (AppUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
VipOrder vipOrder = new VipOrder();
|
vipOrder.setAppUserId(appuser.getId());
|
|
VipSetting vipSetting = vipSettingMapper.selectById(vipPaymentDTO.getId());
|
vipOrder.setOrderAmount(vipSetting.getVipPrice());
|
vipOrder.setPaymentAmount(vipSetting.getVipPrice());
|
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
|
vipOrder.setOrderNumber("QJS" + getNumber(3) + sdf.format(new Date()));
|
vipOrder.setPayStatus(1);
|
vipOrder.setVipId(vipPaymentDTO.getId());
|
this.save(vipOrder);
|
//判断需要支付的金额是否大于0
|
BigDecimal paymentMoney = vipOrder.getOrderAmount();
|
if ( BigDecimal.ZERO.compareTo(paymentMoney) < 0){
|
//调起微信支付
|
String vipName = vipSetting.getVipName();
|
try {
|
R r = wechatPayService.unifiedOrder(vipOrder.getId().toString(), vipOrder.getOrderNumber(), paymentMoney.toString(), "购买"+vipName,appuser.getWxOpenid(),"/app/vipOrder/orderPaymentCallback");
|
if (null == r || 200 != r.getCode()) {
|
//支付失败 删除订单
|
vipOrder.setDelFlag(1);
|
this.updateById(vipOrder);
|
//返回报错信息
|
return R.fail(null == r ? "支付失败" : r.getMsg());
|
}
|
//将支付数据添加到redis队列中,便于定时任务去校验是否完成支付,没有完成支付支付,15分钟后关闭订单。
|
long second = LocalDateTime.now().plusMinutes(15).toEpochSecond(ZoneOffset.UTC);
|
redisTemplate.opsForZSet().add("VipOrderPayment", vipOrder.getOrderNumber(), second);
|
return r;
|
} catch (Exception e) {
|
throw new RuntimeException(e);
|
}
|
}
|
//设置vipOrder信息
|
vipOrder.setPayStatus(2);//已支付
|
vipOrder.setOrderTime(LocalDateTime.now());//下单时间
|
vipOrder.setOrderStatus(4);
|
this.updateById(vipOrder);
|
//更新用户信息
|
Long appUserId = vipOrder.getAppUserId();
|
AppUser appUser = appUserMapper.selectById(appUserId);
|
appUser.setVipId(vipOrder.getVipId());
|
if (appUser.getEndTime().isBefore(LocalDateTime.now())) {
|
appUser.setStartTime(LocalDateTime.now());
|
}
|
// 根据 vipId 计算会员到期时间
|
LocalDateTime endTime = calculateEndTime(appUser.getEndTime(), vipOrder.getVipId());
|
appUser.setEndTime(endTime);
|
appUserMapper.updateById(appUser);
|
return R.ok();
|
|
}
|
|
@Override
|
public R orderPaymentCallback(PayResult payResult) {
|
VipOrder vipOrder = this.getBaseMapper().selectOne(new LambdaQueryWrapper<VipOrder>().eq(VipOrder::getOrderNumber, payResult.getOrderNumber()));
|
if(null == vipOrder || vipOrder.getPayStatus() == 2){
|
return R.ok();
|
}
|
//设置vipOrder信息
|
vipOrder.setPayStatus(2);//已支付
|
vipOrder.setOrderTime(LocalDateTime.now());//下单时间
|
String r7TrxNo = payResult.getTransactionId();
|
vipOrder.setSerialNumber(r7TrxNo);
|
vipOrder.setOrderStatus(4);
|
this.updateById(vipOrder);
|
//更新用户信息
|
//检查是否续期的
|
Long appUserId = vipOrder.getAppUserId();
|
AppUser appUser = appUserMapper.selectById(appUserId);
|
appUser.setVipId(vipOrder.getVipId());
|
LocalDateTime now = LocalDateTime.now();
|
appUser.setEndTime(appUser.getEndTime()==null?now:appUser.getEndTime());
|
if (appUser.getEndTime().isBefore(now)) {
|
appUser.setStartTime(now);
|
}
|
// 根据 vipId 计算会员到期时间
|
LocalDateTime endTime = calculateEndTime(appUser.getEndTime(), vipOrder.getVipId());
|
appUser.setEndTime(endTime);
|
|
appUserMapper.updateById(appUser);
|
return R.ok();
|
}
|
|
@Override
|
public void closeOrder() {
|
//订单支付数据
|
long second = LocalDateTime.now().toEpochSecond(ZoneOffset.UTC);
|
Set<String> orderPayment = redisTemplate.opsForZSet().rangeByScore("VipOrderPayment", 0, second);
|
if(orderPayment.size() > 0){
|
List<VipOrder> list = this.getBaseMapper().selectList(new LambdaQueryWrapper<VipOrder>().in(VipOrder::getOrderNumber, orderPayment));
|
for (VipOrder order : list) {
|
if(null == order || order.getPayStatus() != 1){
|
//不在待支付中的,移除
|
redisTemplate.opsForZSet().remove("VipOrderPayment", order.getOrderNumber());
|
continue;
|
}
|
//开始执行关闭订单操作
|
Map<String, String> map = wechatPayService.closeOrder(order.getOrderNumber());
|
if((null == map || !map.get("return_code").equals("SUCCESS"))){
|
redisTemplate.opsForZSet().add("VipOrderPayment", order.getOrderNumber(), 0);
|
log.error("关闭订单失败:{}---->{}", order.getOrderNumber(), map.get("return_msg"));
|
}
|
redisTemplate.opsForZSet().remove("VipOrderPayment", order.getOrderNumber());
|
//删除订单
|
order.setDelFlag(DelFlagConstant.DELETE);
|
this.updateById(order);
|
|
}
|
}
|
}
|
|
@Override
|
public OrderSysDetailVO detail(Integer id) {
|
|
return this.getBaseMapper().detail(id);
|
}
|
|
|
private LocalDateTime calculateEndTime(LocalDateTime startTime, Integer vipId) {
|
switch (vipId) {
|
case 1: // 月卡
|
return startTime.plusDays(31).withHour(23).withMinute(59).withSecond(59);
|
case 2: // 季卡
|
return startTime.plusDays(90).withHour(23).withMinute(59).withSecond(59);
|
case 3: // 半年卡
|
return startTime.plusDays(180).withHour(23).withMinute(59).withSecond(59);
|
case 4: // 年卡
|
return startTime.plusDays(365).withHour(23).withMinute(59).withSecond(59);
|
default:
|
// 处理无效的 vipId 情况,例如抛出异常或记录日志
|
throw new ServiceException("无效的 vipId: " + vipId);
|
}
|
}
|
|
public String getNumber(Integer size){
|
StringBuilder str = new StringBuilder();
|
for (int i = 0; i < size; i++) {
|
str.append(Double.valueOf(Math.random() * 10).intValue());
|
}
|
return str.toString();
|
}
|
|
}
|