MintOrderService.java 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530
  1. package com.izouma.nineth.service;
  2. import com.alibaba.fastjson.JSON;
  3. import com.alibaba.fastjson.JSONObject;
  4. import com.alibaba.fastjson.serializer.SerializerFeature;
  5. import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult;
  6. import com.github.binarywang.wxpay.bean.order.WxPayMwebOrderResult;
  7. import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
  8. import com.github.binarywang.wxpay.constant.WxPayConstants;
  9. import com.github.binarywang.wxpay.exception.WxPayException;
  10. import com.github.binarywang.wxpay.service.WxPayService;
  11. import com.huifu.adapay.core.exception.BaseAdaPayException;
  12. import com.huifu.adapay.model.AdapayCommon;
  13. import com.huifu.adapay.model.Payment;
  14. import com.izouma.nineth.config.AdapayProperties;
  15. import com.izouma.nineth.config.GeneralProperties;
  16. import com.izouma.nineth.config.RedisKeys;
  17. import com.izouma.nineth.config.WxPayProperties;
  18. import com.izouma.nineth.domain.*;
  19. import com.izouma.nineth.dto.PageQuery;
  20. import com.izouma.nineth.enums.AssetStatus;
  21. import com.izouma.nineth.enums.MintOrderStatus;
  22. import com.izouma.nineth.enums.PayMethod;
  23. import com.izouma.nineth.event.OrderNotifyEvent;
  24. import com.izouma.nineth.exception.BusinessException;
  25. import com.izouma.nineth.repo.*;
  26. import com.izouma.nineth.utils.JpaUtils;
  27. import com.izouma.nineth.utils.SecurityUtils;
  28. import com.izouma.nineth.utils.SnowflakeIdWorker;
  29. import lombok.AllArgsConstructor;
  30. import lombok.extern.slf4j.Slf4j;
  31. import org.apache.commons.codec.EncoderException;
  32. import org.apache.commons.codec.net.URLCodec;
  33. import org.apache.commons.collections.MapUtils;
  34. import org.apache.commons.lang3.StringUtils;
  35. import org.apache.rocketmq.spring.core.RocketMQTemplate;
  36. import org.springframework.core.env.Environment;
  37. import org.springframework.data.domain.Page;
  38. import org.springframework.data.redis.core.BoundSetOperations;
  39. import org.springframework.data.redis.core.BoundValueOperations;
  40. import org.springframework.data.redis.core.RedisTemplate;
  41. import org.springframework.scheduling.annotation.Scheduled;
  42. import org.springframework.stereotype.Service;
  43. import javax.transaction.Transactional;
  44. import java.math.BigDecimal;
  45. import java.math.RoundingMode;
  46. import java.time.LocalDateTime;
  47. import java.time.format.DateTimeFormatter;
  48. import java.util.*;
  49. import java.util.concurrent.TimeUnit;
  50. import java.util.stream.Collectors;
  51. @Slf4j
  52. @Service
  53. @AllArgsConstructor
  54. public class MintOrderService {
  55. private MintOrderRepo mintOrderRepo;
  56. private UserRepo userRepo;
  57. private AssetService assetService;
  58. private AssetRepo assetRepo;
  59. private MintActivityRepo mintActivityRepo;
  60. private UserAddressRepo userAddressRepo;
  61. private GeneralProperties generalProperties;
  62. private Environment env;
  63. private AdapayProperties adapayProperties;
  64. private SnowflakeIdWorker snowflakeIdWorker;
  65. private WxPayProperties wxPayProperties;
  66. private WxPayService wxPayService;
  67. private MintMaterialRepo mintMaterialRepo;
  68. private MintActivityService mintActivityService;
  69. private RedisTemplate<String, Object> redisTemplate;
  70. private RocketMQTemplate rocketMQTemplate;
  71. public Page<MintOrder> all(PageQuery pageQuery) {
  72. return mintOrderRepo.findAll(JpaUtils.toSpecification(pageQuery, MintOrder.class), JpaUtils.toPageRequest(pageQuery));
  73. }
  74. @Transactional
  75. public void create(Long userId, List<Long> assetIds) {
  76. User user = userRepo.findByIdAndDelFalse(userId).orElseThrow(new BusinessException("用户不存在"));
  77. User blackHole = userRepo.findByIdAndDelFalse(1435297L).orElseThrow(new BusinessException("无法铸造"));
  78. if (assetIds.size() != 3) {
  79. throw new BusinessException("数量不正确,请重新选择");
  80. }
  81. List<Asset> assets = assetRepo.findAllByIdInAndUserId(assetIds, userId);
  82. assets = assets.stream()
  83. .filter(asset -> asset.getName().contains("尼尔斯") && AssetStatus.NORMAL.equals(asset.getStatus()))
  84. .collect(Collectors.toList());
  85. if (assets.size() != 3) {
  86. throw new BusinessException("有藏品不符合,请重新选择");
  87. }
  88. // 铸造订单
  89. MintOrder order = mintOrderRepo.save(MintOrder.builder()
  90. .userId(userId)
  91. .phone(user.getPhone())
  92. // .material(materials)
  93. .consume(true)
  94. .status(MintOrderStatus.AIR_DROP)
  95. .build());
  96. // 铸造资产
  97. List<MintMaterial> materials = assets.stream().map(asset -> {
  98. MintMaterial material = new MintMaterial();
  99. material.setAssetId(asset.getId());
  100. material.setCollectionId(asset.getCollectionId());
  101. material.setName(asset.getName());
  102. material.setNumber(asset.getNumber());
  103. material.setPic(asset.getPic());
  104. material.setCategory(asset.getCategory());
  105. material.setOrderId(order.getId());
  106. return material;
  107. }).collect(Collectors.toList());
  108. mintMaterialRepo.saveAll(materials);
  109. // 改为转赠
  110. assets.forEach(asset -> assetService.transfer(asset, asset.getPrice(), blackHole, "转赠", null));
  111. }
  112. /**
  113. * 订单
  114. *
  115. * @param id 编号
  116. */
  117. public void finish(Long id) {
  118. MintOrder mintOrder = mintOrderRepo.findById(id).orElseThrow(new BusinessException("铸造订单不存在"));
  119. mintOrder.setStatus(MintOrderStatus.FINISH);
  120. mintOrderRepo.save(mintOrder);
  121. }
  122. /**
  123. * 发货
  124. *
  125. * @param id 编号
  126. * @param courierId 快递单号
  127. */
  128. public void dispatch(Long id, String courierId) {
  129. MintOrder mintOrder = mintOrderRepo.findById(id).orElseThrow(new BusinessException("铸造订单不存在"));
  130. mintOrder.setStatus(MintOrderStatus.RECEIVE);
  131. mintOrder.setCourierId(courierId);
  132. mintOrderRepo.save(mintOrder);
  133. }
  134. /**
  135. * @param user 用户
  136. * @param assetId 资产
  137. * @param mintActivityId 铸造活动
  138. * @param addressId 地址
  139. */
  140. // @Transactional
  141. public MintOrder create(User user, List<Long> assetId, Long mintActivityId, Long addressId) {
  142. try {
  143. // 参加的活动
  144. MintActivity mintActivity = mintActivityRepo.findByIdAndDelFalse(mintActivityId)
  145. .orElseThrow(new BusinessException("无此铸造活动"));
  146. int stock = Optional.ofNullable(mintActivityService.decreaseStock(mintActivityId, 1))
  147. .map(Math::toIntExact)
  148. .orElseThrow(new BusinessException("很遗憾,藏品已售罄"));
  149. if (stock < 0) {
  150. throw new BusinessException("铸造活动已无库存");
  151. }
  152. if (mintActivity.getNum() > 0) {
  153. if (assetId.size() != mintActivity.getNum()) {
  154. throw new BusinessException("数量不正确,请重新选择");
  155. }
  156. }
  157. List<Asset> assets = assetRepo.findAllByIdInAndUserId(assetId, user.getId());
  158. // 资产产品是否符合铸造活动的名称
  159. assets = assets.stream()
  160. .filter(asset -> asset.getName()
  161. .contains(mintActivity.getCollectionName()) && AssetStatus.NORMAL.equals(asset.getStatus()))
  162. .collect(Collectors.toList());
  163. if (mintActivity.getNum() > 0 && (assets.size() != mintActivity.getNum())) {
  164. throw new BusinessException("有藏品不符合,请重新选择");
  165. }
  166. Map<Long, Long> privilegeIds = new HashMap<>();
  167. // 铸造特权
  168. if (!mintActivity.isConsume()) {
  169. assets.forEach(asset -> {
  170. List<Privilege> privileges = asset.getPrivileges()
  171. .stream()
  172. .filter(p -> p.getName().equals("铸造"))
  173. .collect(Collectors.toList());
  174. if (privileges.size() == 0) {
  175. throw new BusinessException("无铸造特权");
  176. } else {
  177. boolean flag = false;
  178. for (Privilege privilege : privileges) {
  179. // 打开多次 或者 可打开一次但未使用
  180. if (!privilege.isOnce() || (privilege.isOnce() && !privilege
  181. .isOpened())) {
  182. flag = true;
  183. privilegeIds.put(asset.getId(), privilege.getId());
  184. break;
  185. }
  186. }
  187. if (!flag) {
  188. throw new BusinessException("铸造特权已使用");
  189. }
  190. }
  191. });
  192. assets.forEach(asset -> {
  193. asset.getPrivileges()
  194. .stream()
  195. .filter(p -> p.getId().equals(privilegeIds.get(asset.getId())))
  196. .forEach(p -> {
  197. p.setOpened(true);
  198. p.setOpenTime(LocalDateTime.now());
  199. p.setOpenedBy(SecurityUtils.getAuthenticatedUser().getId());
  200. });
  201. assetRepo.save(asset);
  202. });
  203. } else {
  204. // 消耗改为转赠
  205. assets.forEach(asset -> {
  206. asset.setStatus(AssetStatus.MINTING);
  207. assetRepo.save(asset);
  208. });
  209. // 转让的用户
  210. userRepo.findByIdAndDelFalse(1435297L).orElseThrow(new BusinessException("无法铸造"));
  211. }
  212. UserAddress userAddress = null;
  213. if (addressId != null) {
  214. userAddress = userAddressRepo.findById(addressId).orElseThrow(new BusinessException("地址信息不存在"));
  215. }
  216. // 铸造订单
  217. MintOrder mintOrder = mintOrderRepo.save(MintOrder.builder()
  218. .userId(user.getId())
  219. .phone(user.getPhone())
  220. .consume(mintActivity.isConsume())
  221. .status(MintOrderStatus.NOT_PAID)
  222. .airDrop(mintActivity.isAirDrop())
  223. .gasPrice(mintActivity.getGasPrice())
  224. .mintActivityId(mintActivityId)
  225. .contactName(Optional.ofNullable(userAddress).map(UserAddress::getName).orElse(null))
  226. .contactPhone(Optional.ofNullable(userAddress).map(UserAddress::getPhone).orElse(null))
  227. .address(Optional.ofNullable(userAddress).map(u ->
  228. u.getProvinceName() + " " + u.getCityName() + " " + u.getDistrictName() + " " + u.getAddress())
  229. .orElse(null))
  230. .build());
  231. // 铸造资产
  232. List<MintMaterial> materials = assets.stream().map(asset -> {
  233. MintMaterial material = new MintMaterial();
  234. material.setAssetId(asset.getId());
  235. material.setCollectionId(asset.getCollectionId());
  236. material.setName(asset.getName());
  237. material.setPrivilegeId(privilegeIds.get(asset.getId()));
  238. material.setNumber(asset.getNumber());
  239. material.setPic(asset.getPic());
  240. material.setCategory(asset.getCategory());
  241. material.setOrderId(mintOrder.getId());
  242. return material;
  243. }).collect(Collectors.toList());
  244. mintMaterialRepo.saveAll(materials);
  245. //库存
  246. // mintActivity.setStock(mintActivity.getStock() - 1);
  247. // mintActivityRepo.save(mintActivity);
  248. //销量
  249. // mintActivityService.increaseSale(mintActivityId, 1);
  250. return mintOrder;
  251. } catch (Exception e) {
  252. // 错了加库存
  253. mintActivityService.increaseStock(mintActivityId, 1);
  254. throw e;
  255. }
  256. }
  257. public Object payOrderWeixin(Long id, String tradeType, String openId) throws WxPayException, EncoderException {
  258. MintOrder order = mintOrderRepo.findById(id).orElseThrow(new BusinessException("订单不存在"));
  259. if (order.getStatus() != MintOrderStatus.NOT_PAID) {
  260. throw new BusinessException("订单状态错误");
  261. }
  262. WxPayUnifiedOrderRequest request = new WxPayUnifiedOrderRequest();
  263. request.setBody("铸造GAS费");
  264. request.setOutTradeNo(String.valueOf(new SnowflakeIdWorker(1, 1).nextId()));
  265. request.setTotalFee(order.getGasPrice().multiply(BigDecimal.valueOf(100)).intValue());
  266. if (Arrays.stream(env.getActiveProfiles()).noneMatch(s -> s.equals("prod"))) {
  267. // 测试环境设为1分
  268. // request.setTotalFee(1);
  269. }
  270. request.setSpbillCreateIp("180.102.110.170");
  271. request.setNotifyUrl(wxPayProperties.getNotifyUrl());
  272. request.setTradeType(tradeType);
  273. request.setOpenid(openId);
  274. request.setSignType("MD5");
  275. JSONObject body = new JSONObject();
  276. body.put("action", "payMintOrder");
  277. body.put("userId", order.getUserId());
  278. body.put("orderId", order.getId());
  279. request.setAttach(body.toJSONString());
  280. if (WxPayConstants.TradeType.MWEB.equals(tradeType)) {
  281. WxPayMwebOrderResult result = wxPayService.createOrder(request);
  282. return result.getMwebUrl() + "&redirect_url=" + new URLCodec().encode(wxPayProperties.getReturnUrl());
  283. } else if (WxPayConstants.TradeType.JSAPI.equals(tradeType)) {
  284. return wxPayService.<WxPayMpOrderResult>createOrder(request);
  285. }
  286. throw new BusinessException("不支持此付款方式");
  287. }
  288. public Object payAdapay(Long id, String payChannel, String openId) throws BaseAdaPayException {
  289. List<String> aliChannels = Arrays.asList("alipay", "alipay_qr", "alipay_wap");
  290. List<String> wxChannels = Arrays.asList("wx_pub", "wx_lite");
  291. if (!aliChannels.contains(payChannel) && !wxChannels.contains(payChannel)) {
  292. throw new BusinessException("不支持此渠道");
  293. }
  294. MintOrder order = mintOrderRepo.findById(id).orElseThrow(new BusinessException("订单不存在"));
  295. if (order.getStatus() != MintOrderStatus.NOT_PAID) {
  296. throw new BusinessException("订单状态错误");
  297. }
  298. Map<String, Object> paymentParams = new HashMap<>();
  299. paymentParams.put("order_no", String.valueOf(snowflakeIdWorker.nextId()));
  300. paymentParams.put("pay_amt", order.getGasPrice().setScale(2, RoundingMode.HALF_UP).toPlainString());
  301. paymentParams.put("app_id", adapayProperties.getAppId());
  302. paymentParams.put("pay_channel", payChannel);
  303. paymentParams.put("goods_title", "铸造GAS费");
  304. paymentParams.put("goods_desc", "铸造GAS费");
  305. paymentParams.put("time_expire", DateTimeFormatter.ofPattern("yyyyMMddHHmmss")
  306. .format(LocalDateTime.now().plusMinutes(5)));
  307. paymentParams.put("notify_url", adapayProperties.getNotifyUrl() + "/mintOrder/" + order.getId());
  308. Map<String, Object> expend = new HashMap<>();
  309. paymentParams.put("expend", expend);
  310. if ("wx_pub".equals(payChannel)) {
  311. if (StringUtils.isBlank(openId)) {
  312. throw new BusinessException("缺少openId");
  313. }
  314. expend.put("open_id", openId);
  315. expend.put("limit_pay", "1");
  316. }
  317. Map<String, Object> response;
  318. if ("wx_lite".equals(payChannel)) {
  319. paymentParams.put("adapay_func_code", "wxpay.createOrder");
  320. paymentParams.put("callback_url", generalProperties.getHost() + "/9th/orders");
  321. response = AdapayCommon.requestAdapayUits(paymentParams);
  322. log.info("createOrderResponse {}", JSON.toJSONString(response, SerializerFeature.PrettyFormat));
  323. } else {
  324. response = Payment.create(paymentParams);
  325. log.info("createOrderResponse {}", JSON.toJSONString(response, SerializerFeature.PrettyFormat));
  326. AdapayService.checkSuccess(response);
  327. // adapay 同步
  328. BoundSetOperations<String, Object> ops = redisTemplate.boundSetOps(RedisKeys.ACTIVITY_PAY_RECORD + order.getId());
  329. ops.add(MapUtils.getString(response, "id"));
  330. ops.expire(7, TimeUnit.DAYS);
  331. }
  332. switch (payChannel) {
  333. case "alipay_wap":
  334. case "alipay":
  335. return MapUtils.getString(MapUtils.getMap(response, "expend"), "pay_info");
  336. case "alipay_qr":
  337. return MapUtils.getString(MapUtils.getMap(response, "expend"), "qrcode_url");
  338. case "wx_pub":
  339. JSONObject payParams = JSON.parseObject(MapUtils.getString(MapUtils.getMap(response, "expend"), "pay_info"));
  340. payParams.put("timestamp", payParams.get("timeStamp"));
  341. payParams.remove("timeStamp");
  342. return payParams;
  343. default:
  344. return MapUtils.getMap(response, "expend");
  345. }
  346. }
  347. @Transactional
  348. public void mintNotify(Long orderId, PayMethod payMethod, String transactionId) {
  349. log.info("铸造订单回调 orderId: {}, payMethod: {}, transactionId: {}", orderId, payMethod, transactionId);
  350. if (!getOrderLock(orderId)) {
  351. log.info("铸造订单回调失败 orderId: {} redis锁定, 重新发送到队列", orderId);
  352. rocketMQTemplate.syncSend(generalProperties.getOrderNotifyTopic(),
  353. new OrderNotifyEvent(orderId, payMethod, transactionId, System.currentTimeMillis()));
  354. return;
  355. }
  356. try {
  357. MintOrder mintOrder = mintOrderRepo.findById(orderId).orElseThrow(new BusinessException("订单不存在"));
  358. List<MintMaterial> materials = mintMaterialRepo.findAllByOrderIdAndDelFalse(orderId);
  359. List<Asset> assets = assetRepo.findAllById(materials
  360. .stream()
  361. .map(MintMaterial::getAssetId)
  362. .collect(Collectors.toList()));
  363. mintOrder.setPayMethod(payMethod);
  364. if (mintOrder.isAirDrop()) {
  365. mintOrder.setStatus(MintOrderStatus.AIR_DROP);
  366. } else {
  367. mintOrder.setStatus(MintOrderStatus.DELIVERY);
  368. }
  369. mintOrder.setTransactionId(transactionId);
  370. mintOrder.setPayAt(LocalDateTime.now());
  371. if (mintOrder.isConsume()) {
  372. User newOwner = userRepo.findByIdAndDelFalse(1435297L).orElseThrow(new BusinessException("无法铸造"));
  373. assets.forEach(asset -> assetService.transfer(asset, asset.getPrice(), newOwner, "转赠", null));
  374. }
  375. mintOrderRepo.save(mintOrder);
  376. } catch (Exception e) {
  377. if (e instanceof BusinessException) {
  378. log.error("铸造订单回调出错 orderId: {} {}", orderId, e.getMessage());
  379. } else {
  380. log.error("铸造订单回调出错 orderId: " + orderId, e);
  381. }
  382. }
  383. releaseOrderLock(orderId);
  384. }
  385. @Scheduled(fixedRate = 60000)
  386. public void batchCancel() {
  387. if (generalProperties.isNotifyServer()) {
  388. return;
  389. }
  390. if (Arrays.asList(env.getActiveProfiles()).contains("dev")) {
  391. return;
  392. }
  393. List<MintOrder> orders = mintOrderRepo.findByStatusAndCreatedAtBeforeAndDelFalse(MintOrderStatus.NOT_PAID,
  394. LocalDateTime.now().minusMinutes(5));
  395. orders.forEach(o -> {
  396. try {
  397. cancel(o);
  398. } catch (Exception ignored) {
  399. }
  400. });
  401. }
  402. public void cancel(MintOrder order) {
  403. if (!getOrderLock(order.getId())) {
  404. log.error("订单取消失败 {}, redis锁了", order.getId());
  405. return;
  406. }
  407. try {
  408. if (order.getStatus() != MintOrderStatus.NOT_PAID) {
  409. throw new BusinessException("已支付订单无法取消");
  410. }
  411. Set<Object> transactionIds = redisTemplate.opsForSet()
  412. .members(RedisKeys.ACTIVITY_PAY_RECORD + order.getId());
  413. if (transactionIds != null && transactionIds.size() > 0) {
  414. if (transactionIds.parallelStream().anyMatch(transactionId -> {
  415. try {
  416. Map<String, Object> map = Payment.query(transactionId.toString());
  417. return "succeeded".equalsIgnoreCase(MapUtils.getString(map, "status")) ||
  418. "pending".equalsIgnoreCase(MapUtils.getString(map, "status"));
  419. } catch (BaseAdaPayException e) {
  420. e.printStackTrace();
  421. }
  422. return false;
  423. })) {
  424. throw new BusinessException("订单已经支付成功或待支付,不能取消 " + order.getId());
  425. }
  426. }
  427. List<MintMaterial> materials = mintMaterialRepo.findAllByOrderIdAndDelFalse(order.getId());
  428. List<Asset> assets = assetRepo.findAllById(materials.stream()
  429. .map(MintMaterial::getAssetId)
  430. .collect(Collectors.toList()));
  431. if (order.isConsume()) {
  432. assets.forEach(asset -> {
  433. asset.setStatus(AssetStatus.NORMAL);
  434. assetRepo.save(asset);
  435. });
  436. } else {
  437. Map<Long, Long> privilegeIds = materials.stream()
  438. .collect(Collectors.toMap(MintMaterial::getAssetId, MintMaterial::getPrivilegeId));
  439. assets.forEach(asset -> {
  440. asset.getPrivileges()
  441. .stream()
  442. .filter(p -> p.getId().equals(privilegeIds.get(asset.getId())))
  443. .forEach(p -> {
  444. p.setOpened(false);
  445. p.setOpenTime(null);
  446. p.setOpenedBy(null);
  447. });
  448. assetRepo.save(asset);
  449. });
  450. }
  451. log.info("set normal mintOrder {}", order.getId());
  452. order.setStatus(MintOrderStatus.CANCELLED);
  453. order.setCancelTime(LocalDateTime.now());
  454. mintOrderRepo.save(order);
  455. // 加库存
  456. // mintActivityRepo.addStock(order.getMintActivityId());
  457. mintActivityService.increaseStock(order.getMintActivityId(), 1);
  458. // mintActivityService.decreaseSale(order.getMintActivityId(), 1);
  459. rocketMQTemplate.syncSend(generalProperties.getUpdateStockTopic(), order.getMintActivityId(), 10000);
  460. log.info("取消订单{}", order.getId());
  461. } catch (Exception e) {
  462. log.error("订单取消错误 orderId: " + order.getId(), e);
  463. }
  464. releaseOrderLock(order.getId());
  465. }
  466. public boolean getOrderLock(Long orderId) {
  467. BoundValueOperations<String, Object> ops = redisTemplate.boundValueOps(RedisKeys.MINT_ORDER_LOCK + orderId);
  468. Boolean flag = ops.setIfAbsent(1, 1, TimeUnit.DAYS);
  469. return Boolean.TRUE.equals(flag);
  470. }
  471. public void releaseOrderLock(Long orderId) {
  472. redisTemplate.delete(RedisKeys.MINT_ORDER_LOCK + orderId);
  473. }
  474. }