huliguo
2 天以前 5d7b65670282a4fad015e37d567cfa171b162052
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
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();
    }
 
}