From 5d7b65670282a4fad015e37d567cfa171b162052 Mon Sep 17 00:00:00 2001
From: huliguo <2023611923@qq.com>
Date: 星期二, 20 五月 2025 12:25:19 +0800
Subject: [PATCH] 基础代码

---
 pt-errand/src/main/java/com/ruoyi/errand/service/impl/VipOrderServiceImpl.java |  181 +++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 181 insertions(+), 0 deletions(-)

diff --git a/pt-errand/src/main/java/com/ruoyi/errand/service/impl/VipOrderServiceImpl.java b/pt-errand/src/main/java/com/ruoyi/errand/service/impl/VipOrderServiceImpl.java
new file mode 100644
index 0000000..849a970
--- /dev/null
+++ b/pt-errand/src/main/java/com/ruoyi/errand/service/impl/VipOrderServiceImpl.java
@@ -0,0 +1,181 @@
+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();
+    }
+
+}

--
Gitblit v1.7.1