admin
2021-05-06 42f05d2b835ed1ee41ca32cf76fe11849a890cb4
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
182
183
package com.ks.goldcorn.service.remote;
 
import com.ks.goldcorn.exception.GoldAppException;
import com.ks.goldcorn.exception.GoldRecordException;
import com.ks.goldcorn.exception.GoldTradeException;
import com.ks.goldcorn.exception.GoldUserException;
import com.ks.goldcorn.manager.RedisManager;
import com.ks.goldcorn.mapper.GoldCornAppInfoMapper;
import com.ks.goldcorn.mapper.GoldCornBalanceMapper;
import com.ks.goldcorn.mapper.GoldCornConsumeSourceMapper;
import com.ks.goldcorn.mapper.GoldCornGetSourceMapper;
import com.ks.goldcorn.pojo.DO.*;
import com.ks.goldcorn.service.GoldCornBalanceManager;
import com.ks.goldcorn.service.GoldCornRecordManager;
import org.apache.dubbo.config.annotation.Service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.transaction.annotation.Transactional;
 
import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;
 
@Service(version = "1.0")
public class GoldCornTradeServiceImpl implements GoldCornTradeService {
 
    Logger logger = LoggerFactory.getLogger(GoldCornTradeService.class);
 
    @Resource
    private GoldCornAppInfoMapper goldCornAppInfoMapper;
 
    @Resource
    private GoldCornBalanceMapper goldCornBalanceMapper;
 
    @Resource
    private GoldCornConsumeSourceMapper goldCornConsumeSourceMapper;
 
    @Resource
    private GoldCornBalanceManager goldCornBalanceManager;
 
    @Resource
    private GoldCornGetSourceMapper goldCornGetSourceMapper;
 
    @Resource
    private GoldCornRecordManager goldCornRecordManager;
 
    @Resource
    private RedisTemplate<String, Object> redisTemplate;
 
    @Resource
    private RedisManager redisManager;
 
    /**
     * 验证系统与用户
     *
     * @param appCode
     * @param uid
     * @return
     * @throws GoldAppException
     * @throws GoldUserException
     */
    private Long validateAppAndUser(String appCode, String uid) throws GoldAppException, GoldUserException {
        GoldCornAppInfo appInfo = goldCornAppInfoMapper.selectByAppCode(appCode);
        if (appInfo == null) {
            throw new GoldAppException(GoldAppException.CODE_NOT_EXIST, "app is not exist");
        }
 
        GoldCornBalance balance = goldCornBalanceMapper.selectByAppIdAndUid(appInfo.getId(), uid);
        if (balance == null) {
            throw new GoldUserException(GoldUserException.CODE_NOT_EXIST, "uid is not exist");
        }
 
        return appInfo.getId();
    }
 
    @Override
    public long getNextDoTaskTime(String appCode, String uid, String sourceCode) {
        long time = redisManager.getCanAddCornExpireTime(appCode, uid, sourceCode);
        if (time <= 0) {
            return -1;
        }
 
        return System.currentTimeMillis() + 1000 * time;
    }
 
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void addGoldCorn(String appCode, String uid, String sourceCode, Integer goldCornCount, String title, String desc) throws GoldAppException, GoldUserException, GoldTradeException {
        Long appId = validateAppAndUser(appCode, uid);
        GoldCornGetSource source = goldCornGetSourceMapper.selectByAppIdAndSourceCode(appId, sourceCode);
        if (source == null) {
            throw new GoldUserException(GoldTradeException.CODE_NOT_EXIST, "source is not exist");
        }
 
 
        String key = appCode + "-" + uid + "-" + sourceCode;
        if (!redisTemplate.opsForValue().setIfAbsent(key, 1, 60 * 2, TimeUnit.SECONDS)) {
            throw new GoldTradeException(GoldTradeException.CODE_FREQUENCY_LIMIT, "请求频率过高,请稍后再试");
        }
        try {
            int count = redisManager.getGoldCornAddRecordCount(appCode, uid, sourceCode);
            if (count >= source.getMaxDayCount()) {
                throw new GoldTradeException(GoldTradeException.CODE_COUNT_LIMIT, "添加次数超限,请明日再试");
            }
 
            if (!redisManager.canAddCornWithTime(appCode, uid, sourceCode)) {
                throw new GoldTradeException(GoldTradeException.CODE_FREQUENCY_LIMIT, "添加时间间隔过小");
            }
            //加记录
            GoldCornRecord record = new GoldCornRecord();
            record.setAppId(appId);
            record.setGoldCorn(goldCornCount == null ? source.getGoldCorn() : goldCornCount);
            record.setSourceCode(source.getSourceCode());
            record.setType(GoldCornRecord.TYPE_GET);
            record.setUid(uid);
            if (title != null) {
                record.setTitle(title);
            } else {
                record.setTitle(source.getSourceName());
            }
            if (desc != null) {
                record.setDesc(desc);
            } else {
                record.setDesc(source.getSourceDesc());
            }
            try {
                goldCornRecordManager.addRecord(record);
            } catch (GoldRecordException e) {
                throw new GoldTradeException(GoldTradeException.CODE_ADD_RECORD_FAIL, "添加记录失败");
            }
            //加余额
            goldCornBalanceManager.addMoney(appId, uid, record.getGoldCorn());
 
            redisManager.addCornSuccess(appCode, uid, sourceCode, source.getMinTimeSpan());
        } catch (GoldUserException e) {
            throw e;
        } catch (GoldTradeException e) {
            throw e;
        } catch (Exception e) {
            logger.error("添加金币未知异常:{}", e);
        } finally {
            redisTemplate.delete(key);
        }
    }
 
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void consumeGoldCorn(String appCode, String uid, String sourceCode, Integer goldCornCount, String title, String desc) throws GoldAppException, GoldUserException, GoldTradeException {
        Long appId = validateAppAndUser(appCode, uid);
        GoldCornConsumeSource source = goldCornConsumeSourceMapper.selectByAppIdAndSourceCode(appId, sourceCode);
        if (source == null) {
            throw new GoldUserException(GoldTradeException.CODE_NOT_EXIST, "source is not exist");
        }
 
        int goldCorn = goldCornCount == null ? source.getGoldCorn() : goldCornCount;
 
        //减余额
        goldCornBalanceManager.subMoney(appId, uid, goldCorn);
 
        //加记录
        GoldCornRecord record = new GoldCornRecord();
        record.setAppId(appId);
        record.setGoldCorn(goldCorn);
        record.setSourceCode(source.getSourceCode());
        record.setType(GoldCornRecord.TYPE_CONSUME);
        record.setUid(uid);
        if (title != null) {
            record.setTitle(title);
        } else {
            record.setTitle(source.getSourceName());
        }
        if (desc != null) {
            record.setDesc(desc);
        } else {
            record.setDesc(source.getSourceDesc());
        }
        try {
            goldCornRecordManager.addRecord(record);
        } catch (GoldRecordException e) {
            throw new GoldTradeException(GoldTradeException.CODE_ADD_RECORD_FAIL, "添加记录失败");
        }
    }
}