| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400 |
- package com.izouma.nineth.service;
- import cn.hutool.core.collection.CollUtil;
- import com.alibaba.excel.EasyExcel;
- import com.alibaba.fastjson.JSON;
- import com.alibaba.fastjson.JSONObject;
- import com.alibaba.fastjson.serializer.SerializerFeature;
- import com.alipay.api.AlipayClient;
- import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult;
- import com.github.binarywang.wxpay.bean.order.WxPayMwebOrderResult;
- import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
- import com.github.binarywang.wxpay.constant.WxPayConstants;
- import com.github.binarywang.wxpay.exception.WxPayException;
- import com.github.binarywang.wxpay.service.WxPayService;
- import com.google.common.base.Splitter;
- import com.huifu.adapay.core.exception.BaseAdaPayException;
- import com.huifu.adapay.model.AdapayCommon;
- import com.huifu.adapay.model.Payment;
- import com.izouma.nineth.config.*;
- import com.izouma.nineth.domain.Collection;
- import com.izouma.nineth.domain.*;
- import com.izouma.nineth.domain.netease.NeteaseMessage;
- import com.izouma.nineth.domain.nftdomain.Cart;
- import com.izouma.nineth.dto.MarketSettlement;
- import com.izouma.nineth.dto.PageQuery;
- import com.izouma.nineth.dto.UserBankCard;
- import com.izouma.nineth.dto.nftdomain.DomainOrderDTO;
- import com.izouma.nineth.enums.*;
- import com.izouma.nineth.event.*;
- import com.izouma.nineth.exception.BusinessException;
- import com.izouma.nineth.repo.*;
- import com.izouma.nineth.repo.nftdomain.CartRepo;
- import com.izouma.nineth.security.Authority;
- import com.izouma.nineth.service.netease.NeteaseMessageService;
- import com.izouma.nineth.service.sms.SmsService;
- import com.izouma.nineth.utils.*;
- import com.sun.xml.bind.v2.runtime.NameBuilder;
- import io.github.bucket4j.Bandwidth;
- import io.github.bucket4j.Bucket;
- import io.github.bucket4j.BucketConfiguration;
- import io.github.bucket4j.Refill;
- import io.github.bucket4j.distributed.proxy.ProxyManager;
- import lombok.extern.slf4j.Slf4j;
- import org.apache.commons.codec.EncoderException;
- import org.apache.commons.codec.net.URLCodec;
- import org.apache.commons.collections.MapUtils;
- import org.apache.commons.lang3.ObjectUtils;
- import org.apache.commons.lang3.RandomStringUtils;
- import org.apache.commons.lang3.RandomUtils;
- import org.apache.commons.lang3.StringUtils;
- import org.apache.rocketmq.client.producer.SendResult;
- import org.apache.rocketmq.spring.core.RocketMQTemplate;
- import org.springframework.cache.annotation.Cacheable;
- import org.springframework.context.event.EventListener;
- import org.springframework.core.env.Environment;
- import org.springframework.data.domain.Page;
- import org.springframework.data.domain.PageImpl;
- import org.springframework.data.domain.Pageable;
- import org.springframework.data.redis.core.BoundSetOperations;
- import org.springframework.data.redis.core.BoundValueOperations;
- import org.springframework.data.redis.core.RedisTemplate;
- import org.springframework.scheduling.annotation.Async;
- import org.springframework.scheduling.annotation.Scheduled;
- import org.springframework.stereotype.Service;
- import javax.crypto.interfaces.PBEKey;
- import javax.persistence.criteria.Join;
- import javax.transaction.Transactional;
- import java.io.OutputStream;
- import java.math.BigDecimal;
- import java.math.BigInteger;
- import java.math.RoundingMode;
- import java.time.Duration;
- import java.time.LocalDateTime;
- import java.time.format.DateTimeFormatter;
- import java.util.*;
- import java.util.concurrent.ExecutionException;
- import java.util.concurrent.ForkJoinPool;
- import java.util.concurrent.TimeUnit;
- import java.util.concurrent.atomic.AtomicInteger;
- import java.util.stream.Collectors;
- @Service
- @Slf4j
- public class OrderService {
- private final OrderRepo orderRepo;
- private final CollectionRepo collectionRepo;
- private final UserAddressRepo userAddressRepo;
- private final UserRepo userRepo;
- private final Environment env;
- private final AlipayClient alipayClient;
- private final AlipayProperties alipayProperties;
- private final WxPayService wxPayService;
- private final WxPayProperties wxPayProperties;
- private final AssetService assetService;
- private final SysConfigService sysConfigService;
- private final AssetRepo assetRepo;
- private final UserCouponRepo userCouponRepo;
- private final CollectionService collectionService;
- private final CommissionRecordRepo commissionRecordRepo;
- private final AdapayProperties adapayProperties;
- private final GeneralProperties generalProperties;
- private final RocketMQTemplate rocketMQTemplate;
- private final RedisTemplate<String, Object> redisTemplate;
- private final SnowflakeIdWorker snowflakeIdWorker;
- private final SmsService smsService;
- private final ErrorOrderRepo errorOrderRepo;
- private final ShowCollectionRepo showCollectionRepo;
- private final ShowroomService showroomService;
- private final CollectionPrivilegeRepo collectionPrivilegeRepo;
- private final UserBankCardRepo userBankCardRepo;
- private final CacheService cacheService;
- private final UserPropertyRepo userPropertyRepo;
- private final UserBalanceService userBalanceService;
- private final ProxyManager<String> buckets;
- private final HeatInfoRepo heatInfoRepo;
- private final ShowroomRepo showroomRepo;
- private final NeteaseMessageService neteaseMessageService;
- private final CartRepo cartRepo;
- // private final RiceRepo riceRepo;
- private final RiceService riceService;
- // private RiceOperationRecordRepo riceOperationRecordRepo;
- // private RiceOperationRecordService riceOperationRecordService;
- public OrderService(OrderRepo orderRepo, CollectionRepo collectionRepo, UserAddressRepo userAddressRepo,
- UserRepo userRepo, Environment env, AlipayClient alipayClient,
- AlipayProperties alipayProperties, WxPayService wxPayService, WxPayProperties wxPayProperties,
- AssetService assetService, SysConfigService sysConfigService, AssetRepo assetRepo,
- UserCouponRepo userCouponRepo, CollectionService collectionService,
- CommissionRecordRepo commissionRecordRepo, AdapayProperties adapayProperties,
- GeneralProperties generalProperties, RocketMQTemplate rocketMQTemplate,
- RedisTemplate<String, Object> redisTemplate, SnowflakeIdWorker snowflakeIdWorker,
- SmsService smsService, ErrorOrderRepo errorOrderRepo, ShowCollectionRepo showCollectionRepo,
- ShowroomService showroomService, CollectionPrivilegeRepo collectionPrivilegeRepo,
- UserBankCardRepo userBankCardRepo, CacheService cacheService, UserPropertyRepo userPropertyRepo,
- UserBalanceService userBalanceService, ProxyManager<String> proxyManager,
- HeatInfoRepo heatInfoRepo, ShowroomRepo showroomRepo, NeteaseMessageService neteaseMessageService,
- CartRepo cartRepo, RiceService riceService) {
- this.orderRepo = orderRepo;
- this.collectionRepo = collectionRepo;
- this.userAddressRepo = userAddressRepo;
- this.userRepo = userRepo;
- this.env = env;
- this.alipayClient = alipayClient;
- this.alipayProperties = alipayProperties;
- this.wxPayService = wxPayService;
- this.wxPayProperties = wxPayProperties;
- this.assetService = assetService;
- this.sysConfigService = sysConfigService;
- this.assetRepo = assetRepo;
- this.userCouponRepo = userCouponRepo;
- this.collectionService = collectionService;
- this.commissionRecordRepo = commissionRecordRepo;
- this.adapayProperties = adapayProperties;
- this.generalProperties = generalProperties;
- this.rocketMQTemplate = rocketMQTemplate;
- this.redisTemplate = redisTemplate;
- this.snowflakeIdWorker = snowflakeIdWorker;
- this.smsService = smsService;
- this.errorOrderRepo = errorOrderRepo;
- this.showCollectionRepo = showCollectionRepo;
- this.showroomService = showroomService;
- this.collectionPrivilegeRepo = collectionPrivilegeRepo;
- this.userBankCardRepo = userBankCardRepo;
- this.cacheService = cacheService;
- this.userPropertyRepo = userPropertyRepo;
- this.userBalanceService = userBalanceService;
- this.buckets = proxyManager;
- this.heatInfoRepo = heatInfoRepo;
- this.showroomRepo = showroomRepo;
- this.neteaseMessageService = neteaseMessageService;
- this.cartRepo = cartRepo;
- this.riceService = riceService;
- }
- public Page<Order> all(PageQuery pageQuery) {
- Page<Order> all = orderRepo
- .findAll(JpaUtils.toSpecification(pageQuery, Order.class), JpaUtils.toPageRequest(pageQuery));
- List<Order> content = all.getContent();
- content.forEach(order -> {
- Long userId = orderRepo.selectUserId(order.getAssetId());
- order.setSellerId(userId);
- });
- return orderRepo.findAll(JpaUtils.toSpecification(pageQuery, Order.class), JpaUtils.toPageRequest(pageQuery));
- }
- public String mqCreate(Long userId, Long collectionId, int qty, Long addressId, Long userCouponId, Long invitor,
- String sign, boolean vip, boolean safeFlag, Long showroomId, OrderType orderType, String collectionIds) {
- String qs = null;
- try {
- qs = AESEncryptUtil.decrypt(sign);
- } catch (Exception e) {
- throw new BusinessException("签名错误");
- }
- final Map<String, String> map = Splitter.on('&').trimResults().withKeyValueSeparator('=').split(qs);
- if (Math.abs(MapUtils.getLong(map, "ts") - System.currentTimeMillis()) > 90000) {
- throw new BusinessException("签名已过期");
- }
- if (redisTemplate.opsForValue().get(RedisKeys.BLACK_LIST + userId) != null) {
- throw new BusinessException("频繁操作,请稍后再试");
- }
- BoundValueOperations<String, Object> ops = redisTemplate.boundValueOps(RedisKeys.LIMIT_USER + userId);
- ops.setIfAbsent(0, Duration.ofSeconds(10));
- long val = Optional.ofNullable(ops.increment()).orElse(0L);
- if (val > 5) {
- if (val > 10) {
- redisTemplate.opsForValue().set(RedisKeys.BLACK_LIST + userId, 1, Duration.ofSeconds(60 * 10));
- }
- throw new BusinessException("频繁操作,请稍后再试");
- }
- limitReq(collectionId);
- if (orderType != null) {
- if (!orderType.equals(OrderType.MIX)) {
- Integer stock = collectionService.getStock(collectionId);
- if (stock == null || stock <= 0) {
- throw new BusinessException("藏品已售罄", ErrorCode.SOLD_OUT);
- }
- }
- } else {
- orderType = OrderType.NORMAL;
- }
- Long id = snowflakeIdWorker.nextId();
- redisTemplate.opsForValue().set("safeFlag::" + id, safeFlag, 10, TimeUnit.MINUTES);
- SendResult result = rocketMQTemplate.syncSend(generalProperties.getCreateOrderTopic(),
- new CreateOrderEvent(id, userId, collectionId, qty, addressId, userCouponId, invitor, vip, showroomId, orderType, collectionIds),
- 100000);
- log.info("发送订单到队列: {}, userId={}, result={}", id, userId, result);
- return String.valueOf(id);
- }
- private void batchCreateOrder() {
- }
- public void limitReq(Long collectionId) {
- Bucket bucket = buckets.builder().build("limit::" + collectionId, () -> (BucketConfiguration.builder()
- .addLimit(Bandwidth
- .classic(3000, Refill
- .intervally(3000, Duration
- .ofSeconds(3000))))
- .build()));
- if (!bucket.tryConsume(1)) {
- throw new BusinessException("前方拥堵,请稍后再试");
- }
- }
- public Order create(Long userId, Long collectionId, int qty, Long addressId, Long userCouponId, Long invitor,
- Long id, boolean vip, Long showroomId, OrderType orderType, Long parentOrderId, String collectionIds, Long newId) {
- if (orderType.equals(OrderType.MIX)) {
- Collection collection = collectionRepo.findById(collectionId).orElseThrow(new BusinessException("暂无藏品"));
- // Cart cart = cartRepo
- // .findFirstByCollectionIdAndUserIdAndDel(collectionId, userId, false);
- // if (cart != null)
- // cartRepo.delete(cart);
- User minter = userRepo.findById(collection.getMinterId()).orElseThrow(new BusinessException("铸造者不存在"));
- Order order = Order.builder()
- .id(Optional.ofNullable(id).orElse(snowflakeIdWorker.nextId()))
- .userId(userId)
- .collectionId(collectionId)
- .name(collection.getName())
- .pic(collection.getPic())
- .detail(collection.getDetail())
- .properties(collection.getProperties())
- .category(collection.getCategory())
- .canResale(collection.isCanResale())
- .royalties(collection.getRoyalties())
- .serviceCharge(collection.getServiceCharge())
- .type(collection.getType())
- .source(collection.getSource())
- .minterId(collection.getMinterId())
- .minter(minter.getNickname())
- .minterAvatar(minter.getAvatar())
- .qty(qty)
- // .price(collection.getPrice())
- // .gasPrice(gasFee)
- // .totalPrice(collection.getPrice().multiply(BigDecimal.valueOf(qty)).add(gasFee))
- // .contactName(Optional.ofNullable(userAddress).map(UserAddress::getName).orElse(null))
- // .contactPhone(Optional.ofNullable(userAddress).map(UserAddress::getPhone).orElse(null))
- // .address(Optional.ofNullable(userAddress).map(u ->
- // u.getProvinceName() + " " + u.getCityName() + " " + u.getDistrictName() + " " + u
- // .getAddress())
- // .orElse(null))
- .status(OrderStatus.NOT_PAID)
- // .assetId(collection.getAssetId())
- .couponId(userCouponId)
- .invitor(invitor)
- // .countId(collection.getCountId())
- .vip(vip)
- .vipPoint(0)
- .companyId(1L)
- .orderType(OrderType.MIX)
- .collectionIds(collectionIds)
- .build();
- return orderRepo.save(order);
- } else {
- long t = System.currentTimeMillis();
- qty = 1;
- int stock = Optional.ofNullable(collectionService.decreaseStock(collectionId, qty))
- .map(Math::toIntExact)
- .orElseThrow(new BusinessException("很遗憾,藏品已售罄", ErrorCode.SOLD_OUT));
- int usePoint = 0;
- // 创建订单出错后需要回滚库存,所以需要try-catch
- try {
- if (stock < 0) {
- throw new BusinessException("很遗憾,藏品已售罄", ErrorCode.SOLD_OUT);
- }
- Collection collection = collectionRepo.findById(collectionId)
- .orElseThrow(new BusinessException("藏品不存在"));
- if (collection.isInPaying()) {
- throw new BusinessException("当然藏品正在支付中");
- }
- if (collection.getAssetId() != null && collection.getAssetId().equals(778359L)) {
- throw new BusinessException("很遗憾,藏品已售罄", ErrorCode.SOLD_OUT);
- }
- if (collection.getSource() == CollectionSource.TRANSFER) {
- Asset asset = assetRepo.findById(collection.getAssetId())
- .orElseThrow(new BusinessException("藏品不存在"));
- if (Objects.equals(asset.getUserId(), userId)) {
- throw new BusinessException("不能购买自己的藏品");
- }
- if (asset.getStatus() != AssetStatus.NORMAL) {
- throw new BusinessException("藏品已下架");
- }
- if (asset.getLockTo() != null && asset.getLockTo().isAfter(LocalDateTime.now())) {
- throw new BusinessException("此藏品已锁仓");
- }
- }
- User minter = userRepo.findById(collection.getMinterId()).orElseThrow(new BusinessException("铸造者不存在"));
- UserCoupon coupon = null;
- if (collection.isCouponPayment()) {
- if (userCouponId == null) {
- throw new BusinessException("必须使用优惠券支付");
- }
- coupon = userCouponRepo.findById(userCouponId).orElseThrow(new BusinessException("兑换券不存在"));
- if (!coupon.getUserId().equals(userId)) {
- throw new BusinessException("兑换券不属于您");
- }
- if (coupon.isUsed()) {
- throw new BusinessException("该兑换券已使用");
- }
- if (coupon.isLimited() && !coupon.getCollectionIds().contains(collectionId)) {
- throw new BusinessException("该兑换券不可用");
- }
- }
- if (collection.isScheduleSale()) {
- if (collection.getStartTime().isAfter(LocalDateTime.now())) {
- throw new BusinessException("当前还未开售");
- }
- }
- if (!collection.isOnShelf()) {
- if (!collection.isScanCode()) {
- throw new BusinessException("藏品已下架");
- }
- }
- if (!collection.isSalable()) {
- throw new BusinessException("该藏品当前不可购买");
- }
- if (collection.getMaxCount() > 0) {
- int userMax = userPropertyRepo.findById(userId)
- .map(UserProperty::getMaxCount)
- .orElse(collection.getMaxCount());
- int count;
- if (StringUtils.isNotBlank(collection.getCountId())) {
- count = orderRepo.countByUserIdAndCountIdAndStatusIn(userId, collection.getCountId(),
- Arrays.asList(OrderStatus.FINISH, OrderStatus.NOT_PAID, OrderStatus.PROCESSING));
- } else {
- count = orderRepo.countByUserIdAndCollectionIdAndStatusIn(userId, collectionId,
- Arrays.asList(OrderStatus.FINISH, OrderStatus.NOT_PAID, OrderStatus.PROCESSING));
- }
- if (count >= userMax) {
- throw new BusinessException("限购" + userMax + "件");
- }
- }
- User user = userRepo.findById(userId).orElseThrow(new BusinessException("用户不存在"));
- //设置了最低消费
- if (ObjectUtils.isNotEmpty(collection.getMinimumCharge()) && collection.getMinimumCharge()
- .compareTo(BigDecimal.ZERO) > 0) {
- if (!user.isCanSale()) {
- throw new BusinessException("绿洲石不足");
- }
- }
- //查询是否有拉新任务,只算官方购买
- if (collection.getSource() != CollectionSource.TRANSFER && collection.getAssignment() > 0) {
- //延迟销售
- if (!vip && collection.getTimeDelay()) {
- if (collection.getSaleTime().isAfter(LocalDateTime.now())) {
- throw new BusinessException("当前还未开售");
- }
- }
- if (vip) {
- if (user.getVipPurchase() < 1) {
- throw new BusinessException("非vip!");
- }
- } else {
- if (user.getVipPoint() < 1) {
- throw new BusinessException("没有购买名额");
- }
- usePoint = 1;
- }
- }
- UserAddress userAddress = null;
- if (addressId != null) {
- userAddress = userAddressRepo.findById(addressId).orElseThrow(new BusinessException("地址信息不存在"));
- }
- BigDecimal gasFee = sysConfigService.getBigDecimal("gas_fee");
- Order order = Order.builder()
- .id(Optional.ofNullable(id).orElse(snowflakeIdWorker.nextId()))
- .userId(userId)
- .collectionId(collectionId)
- .name(collection.getName())
- .pic(collection.getPic())
- .detail(collection.getDetail())
- .properties(collection.getProperties())
- .category(collection.getCategory())
- .canResale(collection.isCanResale())
- .royalties(collection.getRoyalties())
- .serviceCharge(collection.getServiceCharge())
- .type(collection.getType())
- .source(collection.getSource())
- .minterId(collection.getMinterId())
- .minter(minter.getNickname())
- .minterAvatar(minter.getAvatar())
- .qty(qty)
- .price(collection.getPrice())
- .gasPrice(gasFee)
- .totalPrice(collection.getPrice().multiply(BigDecimal.valueOf(qty)).add(gasFee))
- .contactName(Optional.ofNullable(userAddress).map(UserAddress::getName).orElse(null))
- .contactPhone(Optional.ofNullable(userAddress).map(UserAddress::getPhone)
- .orElse(null))
- .address(Optional.ofNullable(userAddress).map(u ->
- u.getProvinceName() + " " + u.getCityName() + " " + u
- .getDistrictName() + " " + u
- .getAddress())
- .orElse(null))
- .status(OrderStatus.NOT_PAID)
- .assetId(collection.getAssetId())
- .couponId(userCouponId)
- .invitor(invitor)
- .countId(collection.getCountId())
- .vip(vip)
- .vipPoint(usePoint)
- .companyId(collection.getCompanyId())
- .build();
- if (orderType == OrderType.SUB) {
- order.setId(newId);
- order.setOrderType(orderType);
- order.setParentOrderId(parentOrderId);
- }
- if (coupon != null) {
- coupon.setUsed(true);
- coupon.setUseTime(LocalDateTime.now());
- if (coupon.isNeedGas()) {
- order.setTotalPrice(order.getGasPrice());
- } else {
- order.setTotalPrice(BigDecimal.ZERO);
- }
- userCouponRepo.save(coupon);
- }
- if (collection.getSource() == CollectionSource.TRANSFER) {
- Asset asset = assetRepo.findById(collection.getAssetId())
- .orElseThrow(new BusinessException("资产不存在"));
- asset.setStatus(AssetStatus.TRADING);
- assetRepo.save(asset);
- // collectionRepo.setOnShelf(collectionId, false);
- collectionRepo.setInPaying(collectionId, true);
- //拥有指定藏品降税
- Long sellerId = asset.getUserId();
- order.setRoyalties(assetService.getRoyalties(minter.getId(), collection.getRoyalties(), sellerId));
- if (asset.getType().equals(CollectionType.DOMAIN)) {
- order.setServiceCharge(assetService.getDomainServiceCharge(sellerId));
- } else {
- order.setServiceCharge(assetService.getServicecharge(collection.getServiceCharge(), sellerId));
- }
- }
- order = orderRepo.save(order);
- if (order.getTotalPrice().compareTo(BigDecimal.ZERO) == 0) {
- notifyOrder(order.getId(), PayMethod.WEIXIN, null);
- }
- // if (usePoint > 0) {
- // // 扣除积分
- // userRepo.addVipPoint(userId, -usePoint);
- // cacheService.clearUserMy(userId);
- // }
- cacheService.clearPrefixNameCount(collection.getPrefixName());
- if (ObjectUtils.isNotEmpty(showroomId)) {
- //通过展厅的购买数量
- heatInfoRepo.save(HeatInfo.builder()
- .showroomId(showroomId)
- .userId(userId)
- .type(HeatType.BUY)
- .value(0)
- .orderId(order.getId())
- .build());
- }
- // Cart cart = cartRepo
- // .findFirstByCollectionIdAndUserIdAndDel(collectionId, userId, false);
- // if (cart != null)
- // cartRepo.delete(cart);
- rocketMQTemplate.syncSend(generalProperties.getUpdateStockTopic(), collectionId, 10000);
- log.info("订单创建完成, id={}, {}ms", order.getId(), System.currentTimeMillis() - t);
- return order;
- } catch (Exception e) {
- collectionService.increaseStock(collectionId, qty);
- // if (usePoint > 0) {
- // // 扣除积分
- // userRepo.addVipPoint(userId, usePoint);
- // cacheService.clearUserMy(userId);
- // log.info("订单失败加积分用户ID:{}, 积分:{}", userId, usePoint);
- // }
- // if (vip) {
- // collectionService.decreaseQuota(collectionId, 1);
- // log.info("订单失败加藏品额度CollectionId:{}", collectionId);
- // }
- throw e;
- }
- }
- }
- public Object checkLimit(Long collectionId, Long userId) {
- Collection collection = collectionRepo.findById(collectionId).orElseThrow(new BusinessException("藏品不存在"));
- int count = 0;
- AtomicInteger userMax = new AtomicInteger();
- userPropertyRepo.findById(userId).ifPresent(userProperty -> userMax.set(userProperty.getMaxCount()));
- if (collection.getMaxCount() > 0) {
- if (StringUtils.isNotBlank(collection.getCountId())) {
- count = orderRepo.countByUserIdAndCountIdAndStatusIn(userId, collection.getCountId(),
- Arrays.asList(OrderStatus.FINISH, OrderStatus.NOT_PAID, OrderStatus.PROCESSING));
- } else {
- count = orderRepo.countByUserIdAndCollectionIdAndStatusIn(userId, collectionId,
- Arrays.asList(OrderStatus.FINISH, OrderStatus.NOT_PAID, OrderStatus.PROCESSING));
- }
- }
- Map<String, Object> map = new HashMap<>();
- map.put("limit", userMax.get() > 0 ? userMax.get() : collection.getMaxCount());
- map.put("count", count);
- return map;
- }
- public Object payOrderWeixin(Long id, String tradeType, String openId) throws WxPayException, EncoderException {
- Order order = orderRepo.findByIdAndDelFalse(id).orElseThrow(new BusinessException("订单不存在"));
- if (order.getStatus() != OrderStatus.NOT_PAID) {
- throw new BusinessException("订单状态错误");
- }
- WxPayUnifiedOrderRequest request = new WxPayUnifiedOrderRequest();
- request.setBody(order.getName());
- request.setOutTradeNo(String.valueOf(new SnowflakeIdWorker(1, 1).nextId()));
- request.setTotalFee(order.getTotalPrice().multiply(BigDecimal.valueOf(100)).intValue());
- if (Arrays.stream(env.getActiveProfiles()).noneMatch(s -> s.equals("prod"))) {
- // 测试环境设为1分
- // request.setTotalFee(1);
- }
- request.setSpbillCreateIp("180.102.110.170");
- request.setNotifyUrl(wxPayProperties.getNotifyUrl());
- request.setTradeType(tradeType);
- request.setOpenid(openId);
- request.setSignType("MD5");
- JSONObject body = new JSONObject();
- body.put("action", "payOrder");
- body.put("userId", order.getUserId());
- body.put("orderId", order.getId());
- request.setAttach(body.toJSONString());
- if (WxPayConstants.TradeType.MWEB.equals(tradeType)) {
- WxPayMwebOrderResult result = wxPayService.createOrder(request);
- return result.getMwebUrl() + "&redirect_url=" + new URLCodec().encode(wxPayProperties.getReturnUrl());
- } else if (WxPayConstants.TradeType.JSAPI.equals(tradeType)) {
- return wxPayService.<WxPayMpOrderResult>createOrder(request);
- }
- throw new BusinessException("不支持此付款方式");
- }
- @Cacheable(value = "adapay", key = "#id+'_'+#payChannel")
- public Object payAdapay(Long id, String payChannel, String openId) throws BaseAdaPayException {
- List<String> aliChannels = Arrays.asList("alipay", "alipay_qr", "alipay_wap");
- List<String> wxChannels = Arrays.asList("wx_pub", "wx_lite");
- if (!aliChannels.contains(payChannel) && !wxChannels.contains(payChannel)) {
- throw new BusinessException("不支持此渠道");
- }
- Order order = orderRepo.findByIdAndDelFalse(id).orElseThrow(new BusinessException("订单不存在"));
- if (SecurityUtils.getAuthenticatedUser() != null
- && !SecurityUtils.getAuthenticatedUser().getId().equals(order.getUserId())) {
- log.error("payAdapay userId错误 requestUserId={} orderUserId={}",
- SecurityUtils.getAuthenticatedUser().getId(), order.getUserId());
- }
- Collection collection = collectionRepo.findById(order.getCollectionId())
- .orElseThrow(new BusinessException("藏品不存在"));
- User invitor = null;
- if (order.getInvitor() != null) {
- invitor = userRepo.findById(order.getInvitor()).orElse(null);
- }
- if (invitor != null && StringUtils.isBlank(invitor.getSettleAccountId())) {
- invitor = null;
- }
- if (order.getStatus() != OrderStatus.NOT_PAID) {
- throw new BusinessException("订单状态错误");
- }
- Map<String, Object> paymentParams = new HashMap<>();
- paymentParams.put("order_no", String.valueOf(snowflakeIdWorker.nextId()));
- paymentParams.put("pay_amt", order.getTotalPrice().setScale(2, RoundingMode.HALF_UP).toPlainString());
- paymentParams.put("app_id", adapayProperties.getAppId());
- paymentParams.put("pay_channel", payChannel);
- paymentParams.put("goods_title", collection.getName());
- paymentParams.put("goods_desc", collection.getName());
- paymentParams.put("time_expire", DateTimeFormatter.ofPattern("yyyyMMddHHmmss")
- .format(LocalDateTime.now().plusMinutes(3)));
- paymentParams.put("notify_url", adapayProperties.getNotifyUrl() + "/order/" + adapayProperties
- .getMerchant() + "/" + order.getId());
- List<Map<String, Object>> divMembers = new ArrayList<>();
- BigDecimal totalAmount = order.getTotalPrice().subtract(order.getGasPrice());
- BigDecimal restAmount = order.getTotalPrice().multiply(BigDecimal.valueOf(1));
- if (collection.getSource().equals(CollectionSource.TRANSFER)) {
- Asset asset = assetRepo.findById(collection.getAssetId()).orElseThrow(new BusinessException("无记录"));
- User owner = userRepo.findById(asset.getUserId()).orElseThrow(new BusinessException("拥有者用户不存在"));
- if (collection.getServiceCharge() + collection.getRoyalties() > 0) {
- // 扣除手续费、服务费、GAS费
- restAmount = divMoney(totalAmount, restAmount, divMembers, owner.getMemberId(),
- 100 - (collection.getServiceCharge() + collection.getRoyalties()), false);
- }
- restAmount = divMoney(restAmount, divMembers, "0", restAmount, true);
- } else {
- if (invitor != null && invitor.getShareRatio() != null
- && invitor.getShareRatio().compareTo(BigDecimal.ZERO) > 0) {
- restAmount = divMoney(totalAmount, restAmount, divMembers, invitor.getMemberId(),
- invitor.getShareRatio().intValue(), false);
- }
- restAmount = divMoney(restAmount, divMembers, "0", restAmount, true);
- }
- if (restAmount.compareTo(BigDecimal.ZERO) != 0) {
- log.error("分账出错 {}", JSON.toJSONString(divMembers, SerializerFeature.PrettyFormat));
- throw new BusinessException("分账出错");
- }
- if (divMembers.size() > 1) {
- paymentParams.put("div_members", divMembers);
- }
- Map<String, Object> expend = new HashMap<>();
- paymentParams.put("expend", expend);
- if ("wx_pub" .equals(payChannel)) {
- if (StringUtils.isBlank(openId)) {
- throw new BusinessException("缺少openId");
- }
- expend.put("open_id", openId);
- expend.put("limit_pay", "1");
- }
- Map<String, Object> response;
- if ("wx_lite" .equals(payChannel)) {
- paymentParams.put("adapay_func_code", "wxpay.createOrder");
- paymentParams.put("callback_url", generalProperties.getHost() + "/9th/orders");
- response = AdapayCommon.requestAdapayUits(paymentParams);
- log.info("createOrderResponse {}", JSON.toJSONString(response, SerializerFeature.PrettyFormat));
- } else {
- response = Payment.create(paymentParams);
- log.info("createOrderResponse {}", JSON.toJSONString(response, SerializerFeature.PrettyFormat));
- AdapayService.checkSuccess(response);
- // 保存adapay的订单id,用于后续取消订单时的查询
- BoundSetOperations<String, Object> ops = redisTemplate.boundSetOps(RedisKeys.PAY_RECORD + order.getId());
- ops.add(adapayProperties.getMerchant() + "#" + MapUtils.getString(response, "id"));
- ops.expire(7, TimeUnit.DAYS);
- }
- switch (payChannel) {
- case "alipay_wap":
- case "alipay":
- return MapUtils.getString(MapUtils.getMap(response, "expend"), "pay_info");
- case "alipay_qr":
- return MapUtils.getString(MapUtils.getMap(response, "expend"), "qrcode_url");
- case "wx_pub":
- JSONObject payParams = JSON
- .parseObject(MapUtils.getString(MapUtils.getMap(response, "expend"), "pay_info"));
- payParams.put("timestamp", payParams.get("timeStamp"));
- payParams.remove("timeStamp");
- return payParams;
- default:
- return MapUtils.getMap(response, "expend");
- }
- }
- public static BigDecimal divMoney(BigDecimal totalAmount, BigDecimal restAmount, List<Map<String, Object>> divMembers,
- String memberId, double ratio, boolean feeFlag) {
- if (ratio == -1 || (ratio > 0 && ratio < 100)) {
- BigDecimal divAmount = ratio == -1 ? restAmount :
- totalAmount.multiply(BigDecimal.valueOf(ratio))
- .divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP);
- Map<String, Object> divMem = new HashMap<>();
- divMem.put("member_id", memberId);
- divMem.put("amount", divAmount.toPlainString());
- divMem.put("fee_flag", feeFlag ? "Y" : "N");
- divMembers.add(divMem);
- return restAmount.subtract(divAmount);
- } else {
- throw new BusinessException("分账比例错误");
- }
- }
- public Order fixMainOrder(Order mainOrder, BigDecimal total, BigDecimal gas, BigDecimal price, List<FileObject> count, String collectionIds, String subOrderIds) {
- mainOrder.setTotalPrice(total);
- mainOrder.setPic(count);
- mainOrder.setPrice(price);
- mainOrder.setGasPrice(gas);
- mainOrder.setPayTime(LocalDateTime.now());
- mainOrder.setCollectionIds(collectionIds);
- mainOrder.setSubOrderIds(subOrderIds);
- return orderRepo.save(mainOrder);
- }
- public static BigDecimal divMoney(BigDecimal restAmount, List<Map<String, Object>> divMembers,
- String memberId, BigDecimal divAmount, boolean feeFlag) {
- if (divAmount.compareTo(BigDecimal.ZERO) > 0) {
- Map<String, Object> divMem = new HashMap<>();
- divMem.put("member_id", memberId);
- divMem.put("amount", divAmount.toPlainString());
- divMem.put("fee_flag", feeFlag ? "Y" : "N");
- divMembers.add(divMem);
- }
- return restAmount.subtract(divAmount);
- }
- @Transactional
- public void notifyOrder(Long orderId, PayMethod payMethod, String transactionId) {
- log.info("订单回调 orderId: {}, payMethod: {}, transactionId: {}", orderId, payMethod, transactionId);
- // 取消订单与订单回调不能同时进行,需要抢锁
- if (!getOrderLock(orderId)) {
- log.info("订单回调失败 orderId: {} redis锁定, 重新发送到队列", orderId);
- rocketMQTemplate.syncSend(generalProperties.getOrderNotifyTopic(),
- new OrderNotifyEvent(orderId, payMethod, transactionId, System.currentTimeMillis()));
- return;
- }
- try {
- Order order = orderRepo.findById(orderId).orElseThrow(new BusinessException("订单不存在"));
- if (order.getOrderType() == null) {
- order.setOrderType(OrderType.NORMAL);
- }
- if (order.getOrderType().equals(OrderType.MIX)) {
- List<String> orderIds = Arrays.asList(order.getSubOrderIds().split(","));
- orderIds.forEach(subOrder -> {
- notifyOrder(Long.valueOf(subOrder), payMethod, transactionId);
- });
- order.setStatus(OrderStatus.FINISH);
- order.setPayMethod(payMethod);
- order.setTransactionId(transactionId);
- } else {
- Collection collection = collectionRepo.findDetailById(order.getCollectionId())
- .orElseThrow(new BusinessException("藏品不存在"));
- Cart cart = cartRepo
- .findFirstByCollectionIdAndUserIdAndDel(order.getCollectionId(), order.getUserId(), false);
- if (cart != null)
- cartRepo.delete(cart);
- User user = userRepo.findById(order.getUserId()).orElseThrow(new BusinessException("用户不存在"));
- if (order.getStatus() == OrderStatus.NOT_PAID) {
- order.setStatus(OrderStatus.PROCESSING);
- order.setPayTime(LocalDateTime.now());
- order.setTransactionId(transactionId);
- order.setPayMethod(payMethod);
- if (order.getType() == CollectionType.BLIND_BOX) {
- log.info("开始盲盒抽卡 orderId: {}, collectionId: {}", orderId, collection.getId());
- BlindBoxItem winItem = collectionService.draw(order.getUserId(), collection.getId());
- log.info("抽卡成功 orderId: {}, collectionId: {}, winCollectionId: {}", orderId, collection
- .getId(), winItem.getCollectionId());
- order.setWinCollectionId(winItem.getCollectionId());
- orderRepo.save(order);
- //藏品其他信息/是否vip
- CollectionPrivilege collectionPrivilege = collectionPrivilegeRepo
- .findByCollectionId(order.getCollectionId());
- if (ObjectUtils.isNotEmpty(collectionPrivilege)) {
- if (collectionPrivilege.isVip()) {
- //更新vip信息
- userRepo.updateVipPurchase(order.getUserId(), 1);
- }
- }
- Collection winCollection = collectionRepo.findById(winItem.getCollectionId())
- .orElseThrow(new BusinessException("藏品不存在"));
- assetService.createAsset(winItem, user, order.getId(), order.getPrice(), "出售",
- winItem.getTotal() > 1 ? collectionService
- .getNextNumber(winItem.getCollectionId()) : null,
- winCollection.getHoldDays(), false);
- } else {
- if (collection.getSource() == CollectionSource.TRANSFER) {
- orderRepo.save(order);
- Asset asset = assetRepo.findById(collection.getAssetId()).orElse(null);
- Set<Tag> tags = new HashSet<>(asset.getTags());
- boolean safeFlag = Objects
- .equals(true, redisTemplate.opsForValue().get("safeFlag::" + orderId));
- assetService.transfer(asset, order.getPrice(), user, TransferReason.TRANSFER,
- order.getId(), safeFlag, tags);
- order.setStatus(OrderStatus.FINISH);
- orderRepo.save(order);
- collectionRepo.delete(collection);
- cacheService.clearPrefixNameCount(collection.getPrefixName());
- // 如果展厅有此藏品
- showCollectionRepo.deleteAllByCollectionId(order.getCollectionId());
- // 发送短信提醒用户转让成功
- if (asset != null && asset.getUserId() != null) {
- smsService.sellOut(userRepo.findPhoneById(asset.getUserId()), order.getCompanyId());
- }
- riceService.addScoreInOrder(order.getUserId());
- userBalanceService.realtimeSettleOrder(order);
- if (collection.getType().equals(CollectionType.DOMAIN)) {
- NeteaseMessage neteaseMessage = new NeteaseMessage();
- neteaseMessage.setFromId("7209");
- neteaseMessage.setToId("9626109603");
- neteaseMessage.setType(0);
- neteaseMessage.setOpe(1);
- neteaseMessage
- .setFromAvatar("https://cdn.raex.vip/image/2022-12-22-11-08-11fdBrwzSL.png");
- neteaseMessage.setFromNickName("RID交易official");
- Map<String, String> object = new HashMap<>();
- DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
- String localDateTimeNowStr = order.getPayTime().format(formatter);
- // String info = "<div style=\"line-height: 40px;background: #06c04f;border-radius: 4px;padding: 0 20px;margin-bottom: 12px;\">RAEX绿洲:RID元域名称交易监控</div><div style=\"display: flex\"><img style=\"width: 18px; height: 18px; margin: 5px 10px 0 0\"src=\"https://cdn.raex.vip/image/2023-04-06-14-32-07vINcTaZP.png\"alt=\"\"/><span> RID:" + collection
- // .getName()
- // .substring(9) + "【已出售】</span></div><div style=\"display: flex\"><img style=\"width: 18px; height: 18px; margin: 5px 10px 0 0\"src=\"https://cdn.raex.vip/image/2023-04-06-14-28-32HcaKTDYb.png\"alt=\"\"/><span>分类:【RID元域名】</span></div><div style=\"display: flex\"><img style=\"width: 18px; height: 18px; margin: 5px 10px 0 0\"src=\"https://cdn.raex.vip/image/2023-04-06-14-31-49lldhGaqC.png\"alt=\"\"/><span>销售价格:【" + order
- // .getTotalPrice() + "】</span></div><div style=\"display: flex\"><img style=\"width: 18px; height: 18px; margin: 5px 10px 0 0\"src=\"https://cdn.raex.vip/image/2023-04-06-14-32-21ciilInpO.png\"alt=\"\"/><span>交易时间:<br/>【" + localDateTimeNowStr + "】</span></div>";
- String info = "<div style=\"padding: 4px 0\">" +
- " <div" +
- " style=\"" +
- " line-height: 40px;" +
- " background: #06c04f;" +
- " border-radius: 4px;" +
- " padding: 0 12px;" +
- " margin-bottom: 12px;" +
- " font-weight: bold;" +
- " \"" +
- " >" +
- " RAEX绿洲:RID元域名称交易监控" +
- " </div>" +
- " <div style=\"display: flex; margin-bottom: 8px\">" +
- " <img" +
- " style=\"width: 18px; height: 18px; margin: 5px 10px 0 0\"" +
- " src=\"https://cdn.raex.vip/image/2023-04-06-14-32-07vINcTaZP.png\"" +
- " alt=\"\"" +
- " />" +
- " <span> RID:"
- + collection
- .getName()
- .substring(9)
- + "【已出售】</span>" +
- " </div>" +
- " <div style=\"display: flex; margin-bottom: 8px\">" +
- " <img" +
- " style=\"width: 18px; height: 18px; margin: 5px 10px 0 0\"" +
- " src=\"https://cdn.raex.vip/image/2023-04-06-14-28-32HcaKTDYb.png\"" +
- " alt=\"\"" +
- " />" +
- " <span>分类: 【RID元域名】</span>" +
- " </div>" +
- " <div style=\"display: flex; margin-bottom: 8px\">" +
- " <img" +
- " style=\"width: 18px; height: 18px; margin: 5px 10px 0 0\"" +
- " src=\"https://cdn.raex.vip/image/2023-04-06-14-31-49lldhGaqC.png\"" +
- " alt=\"\"" +
- " />" +
- " <span>销售价格: 【" + order
- .getTotalPrice() + " 】</span>" +
- " </div>" +
- " <div style=\"display: flex\">" +
- " <img" +
- " style=\"width: 18px; height: 18px; margin: 5px 10px 0 0\"" +
- " src=\"https://cdn.raex.vip/image/2023-04-06-14-32-21ciilInpO.png\"" +
- " alt=\"\"" +
- " />" +
- " <span>交易时间:<br />【" + localDateTimeNowStr + "】</span>" +
- " </div>" +
- " </div>";
- // String info = "元域名:\"" + collection.getName().substring(9)
- // .replace(".nft", "") + "\"\n" +
- // "持有人:\"" + collection.getOwner() + "\"\n" +
- // "购买人:\"" + user.getNickname() + "\"\n" +
- // "时间:\"" + localDateTimeNowStr + "\"\n" +
- // "成交价:\"" + order.getTotalPrice() + "\"\n";
- object.put("msg", info);
- String news = JSONObject.toJSONString(object);
- neteaseMessage.setBody(news);
- neteaseMessageService.sendMessage(neteaseMessage);
- }
- } else {
- orderRepo.save(order);
- //藏品其他信息/是否vip
- CollectionPrivilege collectionPrivilege = collectionPrivilegeRepo
- .findByCollectionId(order.getCollectionId());
- if (ObjectUtils.isNotEmpty(collectionPrivilege)) {
- if (collectionPrivilege.isVip()) {
- //更新vip信息
- userRepo.updateVipPurchase(order.getUserId(), 1);
- }
- }
- Asset asset = assetService
- .createAsset(collection, user, order.getId(), order.getPrice(),
- "出售", collectionService.getNextNumber(collection), false);
- if (collection.getType() == CollectionType.SHOWROOM) {
- showroomService.save(asset);
- }
- }
- }
- commission(order);
- if (collection.getAssetId() == null) {
- collectionService.increaseSale(order.getCollectionId(), order.getQty());
- }
- //通过展厅购买加热力值
- List<HeatInfo> heatInfos = heatInfoRepo
- .findByUserIdAndOrderIdAndType(order.getUserId(), orderId, HeatType.BUY);
- if (CollUtil.isNotEmpty(heatInfos)) {
- HeatInfo heatInfo = heatInfos.get(0);
- int weight = sysConfigService.getInt("heat_buy_weight");
- heatInfo.setValue(weight);
- heatInfoRepo.save(heatInfo);
- showroomRepo.addHeat(heatInfo.getShowroomId(), weight);
- }
- } else {
- throw new BusinessException("状态错误 " + order.getStatus());
- }
- }
- } catch (Exception e) {
- ErrorOrder errorOrder = ErrorOrder.builder()
- .orderId(orderId)
- .transactionId(transactionId)
- .payMethod(payMethod)
- .build();
- if (e instanceof BusinessException) {
- log.error("订单回调出错 orderId: {} {}", orderId, e.getMessage());
- } else {
- log.error("订单回调出错 orderId: " + orderId, e);
- }
- errorOrder.setErrorMessage(e.getMessage());
- errorOrderRepo.save(errorOrder);
- }
- releaseOrderLock(orderId);
- }
- @EventListener
- public void onCreateAsset(CreateAssetEvent event) {
- Asset asset = event.getAsset();
- if (asset.getOrderId() != null) {
- Order order = orderRepo.findById(asset.getOrderId()).orElse(null);
- if (event.isSuccess() && order != null) {
- order.setTxHash(asset.getTxHash());
- order.setGasUsed(asset.getGasUsed());
- order.setBlockNumber(asset.getBlockNumber());
- order.setStatus(OrderStatus.FINISH);
- orderRepo.save(order);
- }
- }
- }
- @EventListener
- public void onHcMinted(MintedEvent event) {
- Asset asset = assetRepo.findById(event.getAssetId()).orElse(null);
- if (asset != null && asset.getOrderId() != null) {
- orderRepo.findById(asset.getOrderId()).ifPresent(order -> {
- order.setHcTxHash(asset.getTxHash());
- order.setHcGasUsed(asset.getGasUsed());
- order.setHcBlockNumber(asset.getBlockNumber());
- orderRepo.save(order);
- });
- }
- }
- @EventListener
- public void onTransferAsset(TransferAssetEvent event) {
- Asset asset = event.getAsset();
- Order order = orderRepo.findById(asset.getOrderId()).orElseThrow(new BusinessException("订单不存在"));
- if (event.isSuccess()) {
- order.setTxHash(asset.getTxHash());
- order.setGasUsed(asset.getGasUsed());
- order.setBlockNumber(asset.getBlockNumber());
- order.setStatus(OrderStatus.FINISH);
- orderRepo.save(order);
- } else {
- log.error("创建asset失败");
- }
- }
- public void cancel(Long id) {
- Order order = orderRepo.findById(id).orElseThrow(new BusinessException("订单不存在"));
- cancel(order);
- }
- public void cancel(Order order) {
- log.info("尝试取消订单 {}", order.getId());
- // 取消订单与订单回调不能同时进行,需要抢锁
- if (!getOrderLock(order.getId())) {
- log.error("订单取消失败 {}, redis锁了", order.getId());
- return;
- }
- try {
- if (order.getOrderType() == null) {
- order.setOrderType(OrderType.NORMAL);
- }
- if (order.getOrderType().equals(OrderType.MIX)) {
- order.setStatus(OrderStatus.CANCELLED);
- orderRepo.save(order);
- } else {
- if (order.getStatus() != OrderStatus.NOT_PAID) {
- throw new BusinessException("当前订单状态无法取消[" + order.getStatus().name() + "]");
- }
- CollectionSource source = Optional.ofNullable(order.getSource()).orElseGet(() ->
- collectionRepo.findById(order.getCollectionId()).map(Collection::getSource).orElse(null));
- if (source == CollectionSource.TRANSFER) {
- Asset asset = assetRepo.findById(order.getAssetId()).orElse(null);
- if (asset != null) {
- log.info("恢复藏品状态 assetId={}", asset.getId());
- asset.setStatus(AssetStatus.NORMAL);
- assetRepo.save(asset);
- }
- // collectionRepo.setOnShelf(order.getCollectionId(), true);
- log.info("取消支付中状态 collectionId={}", order.getId());
- collectionRepo.setInPaying(order.getCollectionId(), false);
- cacheService.clearPrefixNameCount(asset.getPrefixName());
- }
- collectionService.increaseStock(order.getCollectionId(), order.getQty());
- log.info("设置订单状态为取消 orderId={}", order.getId());
- order.setStatus(OrderStatus.CANCELLED);
- order.setCancelTime(LocalDateTime.now());
- orderRepo.save(order);
- if (order.getCouponId() != null) {
- userCouponRepo.findById(order.getCouponId()).ifPresent(coupon -> {
- log.info("恢复优惠券状态 couponId={}", coupon.getId());
- coupon.setUsed(false);
- coupon.setUseTime(null);
- userCouponRepo.save(coupon);
- });
- }
- //加上积分
- if (ObjectUtils.isNotEmpty(order.getVipPoint()) && order.getVipPoint() > 0) {
- userRepo.addVipPoint(order.getUserId(), order.getVipPoint());
- cacheService.clearUserMy(order.getUserId());
- log.info("取消加积分用户ID:{},订单ID:{},积分:{}", order.getUserId(), order.getId(), order.getVipPoint());
- }
- if (order.isVip()) {
- collectionService.decreaseQuota(order.getCollectionId(), 1);
- log.info("取消加藏品额度CollectionId:{}", order.getCollectionId());
- }
- rocketMQTemplate.syncSend(generalProperties.getUpdateQuotaTopic(), order.getCollectionId(), 10000);
- log.info("取消订单完成 orderId={}", order.getId());
- }
- } catch (Exception e) {
- if (e instanceof BusinessException) {
- log.error(e.getMessage());
- } else {
- log.error("订单取消错误 orderId: " + order.getId(), e);
- }
- }
- releaseOrderLock(order.getId());
- }
- public void refundCancelled(Order order) {
- }
- public void setNumber() {
- for (Collection collection : collectionRepo.findAll()) {
- if (collection.getSource() != CollectionSource.OFFICIAL) continue;
- collection.setCurrentNumber(0);
- collectionRepo.save(collection);
- for (Asset asset : assetRepo.findByCollectionId(collection.getId())) {
- if (asset.getStatus() == AssetStatus.GIFTED || asset.getStatus() == AssetStatus.TRANSFERRED) {
- } else {
- asset.setNumber(collectionService.getNextNumber(collection.getId()));
- assetRepo.save(asset);
- }
- }
- }
- }
- public void setNumberRecursive(Asset asset) {
- }
- @Scheduled(cron = "0 0 4 * * ?")
- public void setSales() {
- if (generalProperties.isNotifyServer()) {
- return;
- }
- List<User> minters = userRepo.findByAuthoritiesContains(Authority.get(AuthorityName.ROLE_MINTER));
- for (User minter : minters) {
- userRepo.setSales(minter.getId(), (int) orderRepo.countSales(minter.getId()));
- }
- }
- public void commission(Order order) {
- if (order.getInvitor() != null) {
- userRepo.findById(order.getInvitor()).ifPresent(user -> {
- BigDecimal shareRatio = user.getShareRatio();
- if (StringUtils.isNotBlank(user.getSettleAccountId()) &&
- shareRatio != null && shareRatio.compareTo(BigDecimal.ZERO) > 0) {
- BigDecimal totalPrice = order.getTotalPrice().subtract(order.getGasPrice());
- commissionRecordRepo.save(CommissionRecord.builder()
- .orderId(order.getId())
- .collectionId(order.getCollectionId())
- .name(order.getName())
- .totalPrice(totalPrice)
- .nickname(user.getNickname())
- .userId(user.getId())
- .shareRatio(user.getShareRatio())
- .phone(user.getPhone())
- .shareAmount(totalPrice.multiply(shareRatio)
- .divide(BigDecimal
- .valueOf(100), 2, RoundingMode.HALF_UP))
- .type(InviteType.NORMAL)
- .build());
- }
- });
- }
- }
- public Object queryCreateOrder(String id) {
- Object res = redisTemplate.opsForValue().get(RedisKeys.CREATE_ORDER + id);
- if (res != null) {
- if (res instanceof Map) {
- if (MapUtils.getBooleanValue((Map) res, "success", false)) {
- Order order = (Order) MapUtils.getObject((Map) res, "data");
- if (!SecurityUtils.getAuthenticatedUser().getId().equals(order.getUserId())) {
- log.error("queryCreateOrder userId错误 requestUserId={} orderUserId={}",
- SecurityUtils.getAuthenticatedUser().getId(), order.getUserId());
- return null;
- }
- }
- }
- }
- return res;
- }
- // 获取订单锁,有效时间1小时
- public boolean getOrderLock(Long orderId) {
- BoundValueOperations<String, Object> ops = redisTemplate.boundValueOps(RedisKeys.ORDER_LOCK + orderId);
- Boolean flag = ops.setIfAbsent(1, 1, TimeUnit.HOURS);
- return Boolean.TRUE.equals(flag);
- }
- // 释放订单锁
- public void releaseOrderLock(Long orderId) {
- redisTemplate.delete(RedisKeys.ORDER_LOCK + orderId);
- }
- public void calcSettle(LocalDateTime start, LocalDateTime end, OutputStream outputStream) {
- List<Order> orders = orderRepo
- .findByCreatedAtBetweenAndSourceAndStatusIn(start, end, CollectionSource.TRANSFER, Arrays
- .asList(OrderStatus.PROCESSING, OrderStatus.FINISH));
- List<Asset> assets = assetRepo.findAllById(orders.stream().map(Order::getAssetId).collect(Collectors.toSet()));
- List<UserBankCard> bankCards = userBankCardRepo
- .findByUserIdIn(assets.stream().map(Asset::getUserId).collect(Collectors.toSet()));
- List<MarketSettlement> settlements = new ArrayList<>();
- for (Order order : orders) {
- BigDecimal amount = order.getTotalPrice()
- .subtract(order.getGasPrice())
- .multiply(new BigDecimal("100")
- .subtract(BigDecimal.valueOf(order.getServiceCharge()))
- .subtract(BigDecimal.valueOf(order.getRoyalties()))
- .divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP))
- .setScale(2, RoundingMode.HALF_UP);
- Long userId = assets.stream().filter(a -> a.getId().equals(order.getAssetId())).map(Asset::getUserId)
- .findAny().orElse(null);
- if (userId != null) {
- UserBankCard userBankCard = bankCards.stream().filter(b -> b.getUserId().equals(userId)).findAny()
- .orElse(null);
- MarketSettlement marketSettlement = settlements.stream().filter(s -> s.getUserId().equals(userId))
- .findAny().orElse(null);
- if (marketSettlement == null) {
- marketSettlement = new MarketSettlement(userId,
- Optional.ofNullable(userBankCard).map(UserBankCard::getRealName).orElse(null),
- Optional.ofNullable(userBankCard).map(UserBankCard::getBankNo).orElse(null),
- amount);
- settlements.add(marketSettlement);
- } else {
- marketSettlement.setAmount(marketSettlement.getAmount()
- .add(amount));
- }
- }
- }
- EasyExcel.write(outputStream, MarketSettlement.class).sheet("sheet").doWrite(settlements);
- }
- @Scheduled(cron = "0 0/3 * * * ?")
- public void setBlackList() {
- List<Long> userIds = orderRepo
- .checkBlackList(LocalDateTime.now(), LocalDateTime.now().minusMinutes(30));
- userIds.forEach(userId -> {
- if (redisTemplate.opsForValue().get(RedisKeys.BLACK_LIST + userId) == null) {
- redisTemplate.opsForValue().set(RedisKeys.BLACK_LIST + userId, 1, Duration.ofSeconds(60 * 180));
- }
- });
- }
- public List<Order> addOrder(Long collectionId, List<Long> userIds, LocalDateTime time, boolean notify) {
- Collection collection = collectionRepo.findById(collectionId).orElseThrow(new BusinessException("藏品不存在"));
- User minter = userRepo.findById(collection.getMinterId()).orElseThrow(new BusinessException("用户不存在"));
- int i = 0;
- List<Order> list = new ArrayList<>();
- for (Long userId : userIds) {
- time = time.plusSeconds(i++);
- BigDecimal gasFee = new BigDecimal("1");
- Order order = Order.builder()
- .id(snowflakeIdWorker.nextId())
- .userId(userId)
- .collectionId(collectionId)
- .name(collection.getName())
- .pic(collection.getPic())
- .detail(collection.getDetail())
- .properties(collection.getProperties())
- .category(collection.getCategory())
- .canResale(collection.isCanResale())
- .royalties(collection.getRoyalties())
- .serviceCharge(collection.getServiceCharge())
- .type(collection.getType())
- .source(collection.getSource())
- .minterId(collection.getMinterId())
- .minter(minter.getNickname())
- .minterAvatar(minter.getAvatar())
- .qty(1)
- .price(collection.getPrice())
- .gasPrice(gasFee)
- .totalPrice(collection.getPrice().multiply(BigDecimal.valueOf(1)).add(gasFee))
- .status(notify ? OrderStatus.NOT_PAID : OrderStatus.FINISH)
- .assetId(collection.getAssetId())
- .countId(collection.getCountId())
- .build();
- orderRepo.saveAndFlush(order);
- String txHash = RandomStringUtils.randomAlphanumeric(64).toLowerCase(Locale.ROOT);
- String transactionId = DateTimeUtils.format(LocalDateTime.now(), "yyyyMMdd") +
- RandomStringUtils.randomNumeric(24);
- BigInteger gas = new BigInteger("157377");
- if (notify) {
- rocketMQTemplate.syncSend(generalProperties.getOrderNotifyTopic(),
- new OrderNotifyEvent(order.getId(), PayMethod.ALIPAY, order.getTransactionId()
- , System.currentTimeMillis()));
- } else {
- order.setCreatedAt(ObjectUtils.clone(time));
- order.setPayTime(time.plusSeconds(RandomUtils.nextInt(5, 50)));
- order.setTransactionId(transactionId);
- order.setTxHash(txHash);
- order.setGasUsed(gas);
- order.setPayMethod(PayMethod.ALIPAY);
- order.setStatus(OrderStatus.FINISH);
- order.setModifiedAt(order.getPayTime());
- order.setModifiedBy("system");
- order.setCreatedBy("system");
- orderRepo.save(order);
- }
- list.add(order);
- }
- return list;
- }
- public Page<Order> byTag(Long tagId, List<Long> excludeUserId, Pageable pageable) {
- if (excludeUserId.isEmpty()) {
- excludeUserId.add(0L);
- }
- return orderRepo.findAll((root, query, criteriaBuilder) -> {
- Join join = root.join("tags");
- return criteriaBuilder.and(criteriaBuilder.equal(join.get("id"), tagId),
- criteriaBuilder.equal(root.get("status"), OrderStatus.FINISH),
- criteriaBuilder.equal(root.get("source"), CollectionSource.TRANSFER),
- criteriaBuilder.not(root.get("ownerId").in(excludeUserId)));
- }, pageable);
- }
- @Async
- public void refundGas() throws ExecutionException, InterruptedException {
- new ForkJoinPool(500).submit(() -> {
- List<Order> list = orderRepo.findByCollectionId(8657801L).stream()
- .filter(o -> o.getStatus() == OrderStatus.FINISH || o
- .getStatus() == OrderStatus.PROCESSING)
- .collect(Collectors.toList());
- list.parallelStream().forEach(o -> {
- log.info("refundGas {}", o.getId());
- userBalanceService
- .modifyBalance(o.getUserId(), new BigDecimal(1), BalanceType.REFUND, null, false, null);
- });
- }).get();
- }
- public Map<String, Object> domainTransferInfo(int type) {
- Set<String> prefixNames = new HashSet<>();
- switch (type) {
- case 0:
- prefixNames.add("RIDCX");
- break;
- case 1:
- prefixNames.add("RID");
- prefixNames.add("RID1");
- prefixNames.add("RID2");
- prefixNames.add("RID3");
- prefixNames.add("RID4");
- prefixNames.add("RID5");
- break;
- case 2:
- prefixNames.add("RIDN1");
- prefixNames.add("RIDN2");
- prefixNames.add("RIDN3");
- prefixNames.add("RIDN4");
- prefixNames.add("RIDN5");
- prefixNames.add("RIDN6");
- break;
- }
- //流通量
- int transferringCount = assetRepo.countAllByPrefixNameInAndStatusAndDel(prefixNames, AssetStatus.NORMAL, false);
- //寄售中
- int consignment = assetRepo
- .countAllByPrefixNameInAndStatusAndConsignmentAndDel(prefixNames, AssetStatus.NORMAL, true, false);
- //仅展示
- int publicShow = assetRepo
- .countAllByPrefixNameInAndStatusAndConsignmentAndPublicShowAndDel(prefixNames, AssetStatus.NORMAL, false, true, false);
- Map<String, Object> result = new HashMap<>();
- result.put("transferringCount", transferringCount);
- result.put("consignment", consignment);
- result.put("publicShow", publicShow);
- return result;
- }
- public Page<DomainOrderDTO> newestDomainTransfer(int type, Pageable pageable) {
- Set<String> prefixNames = new HashSet<>();
- switch (type) {
- case 0:
- prefixNames.add("RIDCX");
- break;
- case 1:
- prefixNames.add("RID");
- prefixNames.add("RID1");
- prefixNames.add("RID2");
- prefixNames.add("RID3");
- prefixNames.add("RID4");
- prefixNames.add("RID5");
- break;
- case 2:
- prefixNames.add("RIDN1");
- prefixNames.add("RIDN2");
- prefixNames.add("RIDN3");
- prefixNames.add("RIDN4");
- prefixNames.add("RIDN5");
- prefixNames.add("RIDN6");
- break;
- }
- Page<Order> orders = orderRepo.queryDomainOrder(prefixNames, pageable);
- List<Order> orderContent = orders.getContent();
- List<DomainOrderDTO> domainOrderDTOS = new ArrayList<>();
- orderContent.forEach(order -> {
- Asset asset = assetRepo.findById(order.getAssetId()).orElse(null);
- if (asset != null) {
- DomainOrderDTO domainOrderDTO = new DomainOrderDTO();
- domainOrderDTO.setName(order.getName());
- domainOrderDTO.setOwner(asset.getOwner());
- domainOrderDTO.setOwnerAvatar(asset.getOwnerAvatar());
- domainOrderDTO.setPrice(order.getPrice());
- domainOrderDTO.setPayTime(order.getPayTime().toLocalDate());
- domainOrderDTO.setPic(order.getPic());
- domainOrderDTOS.add(domainOrderDTO);
- }
- });
- return new PageImpl<>(domainOrderDTOS, orders.getPageable(), orders.getTotalElements());
- }
- }
|