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.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 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.Arrays;
|
import java.util.Date;
|
import java.util.List;
|
import java.util.Set;
|
|
@Service
|
@Slf4j
|
public class VipOrderServiceImpl extends ServiceImpl<VipOrderMapper, VipOrder> implements VipOrderService {
|
@Resource
|
private VipSettingMapper vipSettingMapper;
|
@Resource
|
private RedisTemplate redisTemplate;
|
@Resource
|
private AppUserMapper appUserMapper;
|
|
@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.getVip_price());
|
vipOrder.setPaymentAmount(vipSetting.getVip_price());
|
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.getVip_name();
|
UniPayResult uniPayResult = PaymentUtil.uniPay(vipOrder.getOrderNumber(), paymentMoney.doubleValue(), "购买会员",
|
vipName, "", "/app/vipOrder/orderPaymentCallback", appuser.getWxOpenid(), null);
|
if(null == uniPayResult || !"100".equals(uniPayResult.getRa_Code())){
|
return R.fail(null == uniPayResult ? "支付失败" : uniPayResult.getRb_CodeMsg());
|
}
|
String rc_result = uniPayResult.getRc_Result();
|
JSONObject jsonObject = JSON.parseObject(rc_result);
|
jsonObject.put("orderId", vipOrder.getId().toString());
|
//将支付数据添加到redis队列中,便于定时任务去校验是否完成支付,没有完成支付支付,15分钟后关闭订单。
|
long second = LocalDateTime.now().plusMinutes(15).toEpochSecond(ZoneOffset.UTC);
|
redisTemplate.opsForZSet().add("VipOrderPayment", vipOrder.getOrderNumber(), second);
|
return R.ok(jsonObject.toJSONString());
|
}
|
//设置vipOrder信息
|
vipOrder.setPayStatus(2);//已支付
|
vipOrder.setOrderTime(LocalDateTime.now());//下单时间
|
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(UniPayCallbackResult uniPayCallbackResult) {
|
VipOrder vipOrder = this.getBaseMapper().selectOne(new LambdaQueryWrapper<VipOrder>().eq(VipOrder::getOrderNumber, uniPayCallbackResult.getR2_OrderNo()));
|
if(null == vipOrder || vipOrder.getPayStatus() == 2){
|
return R.ok();
|
}
|
//设置vipOrder信息
|
vipOrder.setPayStatus(2);//已支付
|
vipOrder.setOrderTime(LocalDateTime.now());//下单时间
|
String r7TrxNo = uniPayCallbackResult.getR9_BankTrxNo();
|
vipOrder.setSerialNumber(r7TrxNo);
|
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;
|
}
|
//开始执行关闭订单操作
|
CloseOrderResult closeOrderResult = PaymentUtil.closeOrder(order.getOrderNumber());
|
if((null == closeOrderResult || !closeOrderResult.getRa_Status().equals("100")) &&
|
Arrays.asList("0", "4", "101", "10080000", "10080002", "10083004", "10083005").contains(closeOrderResult.getRb_Code())){
|
redisTemplate.opsForZSet().add("VipOrderPayment", order.getOrderNumber(), 0);
|
log.error("关闭订单失败:{}---->{}",order.getOrderNumber(), JSON.toJSONString(closeOrderResult));
|
}
|
redisTemplate.opsForZSet().remove("VipOrderPayment", order.getOrderNumber());
|
//删除订单
|
order.setDelFlag(DelFlagConstant.DELETE);
|
this.updateById(order);
|
|
}
|
}
|
}
|
|
|
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();
|
}
|
|
}
|