新版仿ok交易所-后端
zyy
2026-02-06 2948af6d6886466a46fd728a5226d5e636fb742f
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
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
package com.yami.trading.api.controller;
 
import com.yami.trading.bean.c2c.C2cAdvert;
import com.yami.trading.bean.c2c.C2cOrder;
import com.yami.trading.bean.model.C2cPaymentMethod;
import com.yami.trading.bean.model.User;
import com.yami.trading.common.constants.Constants;
import com.yami.trading.common.constants.RedisKeys;
import com.yami.trading.common.domain.Result;
import com.yami.trading.common.exception.BusinessException;
import com.yami.trading.common.exception.YamiShopBindException;
import com.yami.trading.common.util.*;
import com.yami.trading.security.common.util.SecurityUtils;
import com.yami.trading.service.SessionTokenService;
import com.yami.trading.service.c2c.C2cAdvertService;
import com.yami.trading.service.c2c.C2cOrderService;
import com.yami.trading.service.c2c.C2cPaymentMethodService;
import com.yami.trading.service.syspara.SysparaService;
import com.yami.trading.service.user.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
 
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
 
@RestController
@Slf4j
public class ApiC2cOrderController {
 
    @Autowired
    private C2cOrderService c2cOrderService;
    private final String action = "/api/c2cOrder!";
 
    @Autowired
    SessionTokenService sessionTokenService;
 
    @Autowired
    C2cAdvertService c2cAdvertService;
    @Autowired
    SysparaService sysparaService;
 
    @Autowired
    RedisTemplate redisTemplate;
 
    @Autowired
    UserService userService;
 
    @Autowired
    C2cPaymentMethodService c2cPaymentMethodService;
 
    /**
     * 首次进入下单页面,传递session_token
     */
    @RequestMapping(action + "order_open.action")
    public Object order_open(HttpServletRequest request) throws IOException {
        String currency = request.getParameter("currency");
        if (StringUtils.isEmptyString(currency)) {
            throw new YamiShopBindException("支付币种不正确");
        }
        String partyId = SecurityUtils.getCurrentUserId();
        String session_token = sessionTokenService.savePut(partyId);
        Map<String, String> allPrice = c2cAdvertService.getAllSymbolPrice(currency);
        Map<String, Object> data = new HashMap<String, Object>();
        data.put("session_token", session_token);
        data.put("all_price", allPrice);
        return Result.succeed(data);
    }
 
 
    /**
     * 自选区下单:购买、出售
     *
     * safe_password 资金密码
     * c2c_advert_id 广告id
     * payment_method_id 支付方式ID:购买为承兑商收款方式ID,出售为用户收款方式ID
     * order_type 订单类型:by_amount按支付金额/by_num按币种数量
     * amount 支付金额
     * coin_amount 币种数量
     * remark 备注
     */
    @RequestMapping(action + "open.action")
    public Object open(HttpServletRequest request) {
        String session_token = request.getParameter("session_token");
//        String safe_password = request.getParameter("safe_password");
        String c2c_advert_id = request.getParameter("c2c_advert_id");
        String payment_method_id = request.getParameter("payment_method_id");
        String order_type = request.getParameter("order_type");
        String direction = request.getParameter("direction");
        String amount = request.getParameter("amount");
        String coin_amount = request.getParameter("coin_amount");
        String remark = request.getParameter("remark");
 
 
 
        String partyId =SecurityUtils.getCurrentUserId();
 
        Result resultObject=new Result();
        boolean lock = false;
        User   party=null;
        String orderNo = DateUtil.getToday("yyMMddHHmmss") + RandomUtil.getRandomNum(8);
        try {
 
               party = userService.getById(partyId);
            log.error("用户"+direction+"开始当前用户uid:"+party.getUserCode()+"当前用户名:"+party.getUserName()+"生成的订单号:"+orderNo);
            if (Constants.SECURITY_ROLE_TEST.equals(party.getRoleName())) {
                throw new YamiShopBindException("无权限");
            }
 
            if (!C2cLock.add(partyId)) {
                throw new YamiShopBindException("Please try again later");
            }
            lock = true;
 
            Object object = this.sessionTokenService.cacheGet(session_token);
            this.sessionTokenService.del(session_token);
            if (null == object || !partyId.equals((String) object)) {
                throw new YamiShopBindException("请稍后再试");
            }
 
            if (!party.isEnabled()) {
 
                return Result.succeed("User is locked");
            }
 
            // C2C用户未结束订单最大数量
            Long nofinishOrderCount = c2cOrderService.getNofinishOrderCount(partyId);
            String c2c_sell_only_one = sysparaService.find("c2c_sell_only_one").getSvalue();
            if(StringUtils.isNotEmpty(c2c_sell_only_one)&&"1".equals(c2c_sell_only_one)) {
                if(nofinishOrderCount >= 1) {
                    throw new YamiShopBindException("提交失败,当前有未处理订单");
                }
                Long.valueOf(c2c_sell_only_one).longValue();
            }
            Object obj2 = this.sysparaService.find("c2c_nofinish_order_count_max");
            if (null != obj2) {
                if (nofinishOrderCount >= Long.valueOf(this.sysparaService.find("c2c_nofinish_order_count_max").getSvalue()).longValue()) {
                    throw new YamiShopBindException("用户未结束订单数量已达上限");
                }
            }
 
            // C2C用户下单是否需要基础认证(true:是,false:否)
            Object obj = this.sysparaService.find("c2c_order_need_kyc");
            if (null != obj) {
                if (!party.isRealNameAuthority() && "true".equals(this.sysparaService.find("c2c_order_need_kyc").getSvalue())) {
                    return Result.succeed("未实名认证,是否认证?");
                }
            }
 
            // C2C每日订单取消最大次数
            int orderCancelDayTimes = 0;
            Map<String, Integer> map = (Map<String, Integer>)redisTemplate.opsForValue() .get(RedisKeys.C2C_ORDER_CANCEL_DAY_TIMES);
            if (null != map && null != map.get(partyId)) {
                orderCancelDayTimes = map.get(partyId);
            }
            Object obj1 = this.sysparaService.find("c2c_order_cancel_day_times");
            if (null != obj1) {
                if (orderCancelDayTimes >= Integer.valueOf(this.sysparaService.find("c2c_order_cancel_day_times").getSvalue()).intValue()) {
                    throw new YamiShopBindException("今日取消订单次数太多了,请明日再试");
                }
            }
 
            C2cAdvert c2cAdvert = this.c2cAdvertService.getById(c2c_advert_id);
            if (null == c2cAdvert) {
                throw new YamiShopBindException("广告不存在");
            }
 
            C2cPaymentMethod method =c2cPaymentMethodService.get(payment_method_id);
            if (null == method) {
                throw new YamiShopBindException("支付方式不存在");
            }
 
            if (StringUtils.isEmptyString(order_type) || !Arrays.asList("by_amount", "by_num").contains(order_type)) {
                throw new YamiShopBindException("订单类型不正确");
            }
 
            if (C2cOrder.ORDER_TYPE_BY_AMOUNT.equals(order_type)) {
                // 按支付金额支付
                if (StringUtils.isEmptyString(amount) || !StringUtils.isDouble(amount) || Double.valueOf(amount).doubleValue() <= 0) {
                    throw new YamiShopBindException("支付金额不正确");
                }
                coin_amount = "0";
            } else {
                // 按币种数量支付
                if (StringUtils.isEmptyString(coin_amount) || !StringUtils.isDouble(coin_amount) || Double.valueOf(coin_amount).doubleValue() <= 0) {
                    throw new YamiShopBindException("币种数量不正确");
                }
                amount = "0";
            }
 
            Map<String, Object> data = new HashMap<String, Object>();
 
            C2cOrder c2cOrder = new C2cOrder();
            c2cOrder.setPartyId(partyId);
            c2cOrder.setC2cUserId(c2cAdvert.getC2cUserId());
            c2cOrder.setC2cAdvertId(c2c_advert_id);
            c2cOrder.setPaymentMethodId(payment_method_id);
            c2cOrder.setOrderType(order_type);
            c2cOrder.setOrderNo(orderNo);
            // 0未付款
            c2cOrder.setState("0");
            c2cOrder.setAmount(StringUtils.isEmptyString(amount) ? 0 : Double.valueOf(amount).doubleValue());
            c2cOrder.setCoinAmount(StringUtils.isEmptyString(coin_amount) ? 0 : Double.valueOf(coin_amount).doubleValue());
            c2cOrder.setRemark(remark);
            String remarks = "name:"+party.getUserName()+"code:"+party.getUserCode()+"direction:"+direction+"orderNo:"+orderNo;
            this.c2cOrderService.saveOpen(c2cOrder,remarks);
            data.put("order_no", c2cOrder.getOrderNo());
            resultObject.setData(data);
            resultObject.setCode(0);
        } catch (BusinessException e) {
            log.error("用户"+direction+"执行异常1当前用户uid:"+party.getUserCode()+"当前用户名:"+party.getUserName()+"生成的订单号:"+orderNo);
            resultObject.setCode(1);
            resultObject.setMsg(e.getMessage());
            log.error("error:"+e.getMessage());
        } catch (Throwable t) {
            log.error("用户"+direction+"执行异常2当前用户uid:"+party.getUserCode()+"当前用户名:"+party.getUserName()+"生成的订单号:"+orderNo);
            resultObject.setCode(1);
            //resultObject.setMsg("程序错误");
            resultObject.setMsg(t.getMessage());
            log.error("error:", t);
        }  finally {
            if (lock) {
                C2cLock.remove(partyId);
            }
        }
 
        return resultObject;
    }
 
    @RequestMapping(action + "pay_finish.action")
    public Object pay_finish(HttpServletRequest request) {
        String order_no = request.getParameter("order_no");
        String safe_password = request.getParameter("safe_password");
 
        Result resultObject = new Result();
 
        boolean lock = false;
 
        try {
 
            String partyId = SecurityUtils.getCurrentUserId();
            if (null == partyId) {
                throw new BusinessException("请重新登录");
            }
 
            User party = userService.getById(partyId);
            if (Constants.SECURITY_ROLE_TEST.equals(party.getRoleName())) {
                throw new BusinessException("无权限");
            }
 
            if (!userService.checkLoginSafeword(partyId, safe_password)) {
                throw new BusinessException("资金密码错误");
            }
 
            if (!party.isEnabled()) {
                return Result.succeed("User is locked");
            }
 
            C2cOrder order = this.c2cOrderService.get(order_no);
            if (null == order) {
                throw new BusinessException("订单不存在");
            }
 
            if (partyId.equals(order.getPartyId())) {
                // 用户操作
                if (!"buy".equals(order.getDirection())) {
                    throw new BusinessException("用户不能支付卖单");
                }
            } else if (partyId.equals(order.getC2cUserPartyId())) {
                // 承兑商操作
                if (!"sell".equals(order.getDirection())) {
                    throw new BusinessException("承兑商不能支付买单");
                }
            } else {
                throw new BusinessException("无权限");
            }
 
            if (!"0".equals(order.getState())) {
                throw new BusinessException("订单不是未付款状态");
            }
 
            if (!C2cOrderLock.add(order_no)) {
                throw new BusinessException(1, "请稍后再试");
            }
 
            lock = true;
 
            order.setState("1");
            order.setPayTime(new Date());
            this.c2cOrderService.updateById(order);
 
            if (Arrays.asList("0", "1").contains(order.getState())) {
                // 只有未付款和已付款的订单存入redis
                redisTemplate.opsForValue().set(RedisKeys.C2C_ORDER_NO + order.getOrderNo(), order);
            } else {
                redisTemplate.delete(RedisKeys.C2C_ORDER_NO + order.getOrderNo());
            }
 
            // 订单自动取消时间和确认收款超时时间(0未付款/1已付款)
            Map<String, Long> map = (Map<String, Long>) redisTemplate.opsForValue().get(RedisKeys.C2C_ORDER_NO_EXPIRE_TIME);
            if (null == map) {
                map = new ConcurrentHashMap<String, Long>();
            }
            if (!Arrays.asList("0", "1").contains(order.getState())) {
                map.remove(order.getOrderNo() + "_auto_cancel");
                map.remove(order.getOrderNo() + "_expire");
            } else {
                if (Arrays.asList("0").contains(order.getState())) {
                    map.put(order.getOrderNo() + "_auto_cancel", order.getCreateTime().getTime() + (long) order.getExpireTime() * 60 * 1000);
                    map.put(order.getOrderNo() + "_expire", order.getCreateTime().getTime() + (long) order.getExpireTime() * 60 * 1000 * 2);
                } else if (Arrays.asList("1").contains(order.getState())) {
                    map.put(order.getOrderNo() + "_auto_cancel", order.getCreateTime().getTime() + (long) order.getExpireTime() * 60 * 1000);
                    map.put(order.getOrderNo() + "_expire", order.getPayTime().getTime() + (long) order.getExpireTime() * 60 * 1000);
                }
            }
            this.redisTemplate.opsForValue().set(RedisKeys.C2C_ORDER_NO_EXPIRE_TIME, map);
 
            resultObject.setCode(0);
        } catch (BusinessException e) {
            resultObject.setCode(1);
            resultObject.setMsg(e.getMessage());
            log.error("error: {}", e.getMessage());
        } catch (Throwable t) {
            resultObject.setCode(1);
            //resultObject.setMsg("程序错误");
            resultObject.setMsg(t.getMessage());
            log.error("error:", t);
        } finally {
            if (lock) {
                ThreadUtils.sleep(100);
                C2cOrderLock.remove(order_no);
            }
        }
 
        return resultObject;
    }
 
    /**
     * 订单放行
     */
    @RequestMapping(action + "order_pass.action")
    public Object order_pass(HttpServletRequest request) {
        String order_no = request.getParameter("order_no");
        String safe_password = request.getParameter("safe_password");
 
        Result resultObject = new Result();
        boolean lock = false;
        try {
 
            String partyId = SecurityUtils.getCurrentUserId();
            if (null == partyId) {
                throw new BusinessException("请重新登录");
            }
 
            User party = userService.getById(partyId);
            if (Constants.SECURITY_ROLE_TEST.equals(party.getRoleName())) {
                throw new BusinessException("无权限");
            }
 
            if (!C2cOrderLock.add(order_no)) {
                throw new BusinessException(1, "请稍后再试");
            }
 
            lock = true;
 
            if (!userService.checkLoginSafeword(partyId, safe_password)) {
                throw new BusinessException("资金密码错误");
            }
            if (!party.isEnabled()) {
                return Result.succeed("User is locked");
            }
 
            C2cOrder order = this.c2cOrderService.get(order_no);
            if (null == order || !order.getPartyId().equals(partyId)) {
                throw new BusinessException("订单不存在");
            }
            if ("0".equals(order.getState())) {
                throw new BusinessException("待付款的订单无法放行");
            }
            if ("3".equals(order.getState())) {
                resultObject.setCode(0);
                return resultObject;
                //throw new BusinessException("订单已完成,无法放行");
            }
            if ("4".equals(order.getState())) {
                throw new BusinessException("订单已取消,无法放行");
            }
 
            this.c2cOrderService.saveOrderPass(order);
            resultObject.setCode(0);
        } catch (BusinessException e) {
            resultObject.setCode(1);
            resultObject.setMsg(e.getMessage());
            log.error("error:{}", e.getMessage());
        } catch (Throwable t) {
            resultObject.setCode(1);
            //resultObject.setMsg("程序错误");
            resultObject.setMsg(t.getMessage());
            log.error("error:", t);
        } finally {
            if (lock) {
                ThreadUtils.sleep(100);
                C2cOrderLock.remove(order_no);
            }
        }
 
        return resultObject;
    }
 
 
}