| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450 |
- package com.izouma.nineth.service;
- import com.alibaba.fastjson.JSON;
- import com.alibaba.fastjson.JSONObject;
- import com.alibaba.fastjson.serializer.SerializerFeature;
- 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.huifu.adapay.core.exception.BaseAdaPayException;
- import com.huifu.adapay.model.AdapayCommon;
- import com.huifu.adapay.model.Payment;
- import com.izouma.nineth.config.AdapayProperties;
- import com.izouma.nineth.config.GeneralProperties;
- import com.izouma.nineth.config.WxPayProperties;
- import com.izouma.nineth.domain.*;
- import com.izouma.nineth.dto.PageQuery;
- import com.izouma.nineth.enums.AssetStatus;
- import com.izouma.nineth.enums.MintOrderStatus;
- import com.izouma.nineth.enums.PayMethod;
- import com.izouma.nineth.exception.BusinessException;
- import com.izouma.nineth.repo.*;
- import com.izouma.nineth.utils.JpaUtils;
- import com.izouma.nineth.utils.SecurityUtils;
- import com.izouma.nineth.utils.SnowflakeIdWorker;
- import lombok.AllArgsConstructor;
- 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.StringUtils;
- import org.springframework.core.env.Environment;
- import org.springframework.data.domain.Page;
- import org.springframework.scheduling.annotation.Scheduled;
- import org.springframework.stereotype.Service;
- import javax.transaction.Transactional;
- import java.math.BigDecimal;
- import java.math.RoundingMode;
- import java.time.LocalDateTime;
- import java.time.format.DateTimeFormatter;
- import java.util.*;
- import java.util.stream.Collectors;
- @Slf4j
- @Service
- @AllArgsConstructor
- public class MintOrderService {
- private MintOrderRepo mintOrderRepo;
- private UserRepo userRepo;
- private AssetService assetService;
- private AssetRepo assetRepo;
- private MintActivityRepo mintActivityRepo;
- private UserAddressRepo userAddressRepo;
- private GeneralProperties generalProperties;
- private Environment env;
- private AdapayProperties adapayProperties;
- private SnowflakeIdWorker snowflakeIdWorker;
- private WxPayProperties wxPayProperties;
- private WxPayService wxPayService;
- private MintMaterialRepo mintMaterialRepo;
- private MintActivityService mintActivityService;
- public Page<MintOrder> all(PageQuery pageQuery) {
- return mintOrderRepo.findAll(JpaUtils.toSpecification(pageQuery, MintOrder.class), JpaUtils.toPageRequest(pageQuery));
- }
- @Transactional
- public void create(Long userId, List<Long> assetIds) {
- User user = userRepo.findByIdAndDelFalse(userId).orElseThrow(new BusinessException("用户不存在"));
- User blackHole = userRepo.findByIdAndDelFalse(1435297L).orElseThrow(new BusinessException("无法铸造"));
- if (assetIds.size() != 3) {
- throw new BusinessException("数量不正确,请重新选择");
- }
- List<Asset> assets = assetRepo.findAllByIdInAndUserId(assetIds, userId);
- assets = assets.stream()
- .filter(asset -> asset.getName().contains("尼尔斯") && AssetStatus.NORMAL.equals(asset.getStatus()))
- .collect(Collectors.toList());
- if (assets.size() != 3) {
- throw new BusinessException("有藏品不符合,请重新选择");
- }
- // 铸造订单
- MintOrder order = mintOrderRepo.save(MintOrder.builder()
- .userId(userId)
- .phone(user.getPhone())
- // .material(materials)
- .consume(true)
- .status(MintOrderStatus.AIR_DROP)
- .build());
- // 铸造资产
- List<MintMaterial> materials = assets.stream().map(asset -> {
- MintMaterial material = new MintMaterial();
- material.setAssetId(asset.getId());
- material.setCollectionId(asset.getCollectionId());
- material.setName(asset.getName());
- material.setNumber(asset.getNumber());
- material.setPic(asset.getPic());
- material.setCategory(asset.getCategory());
- material.setOrderId(order.getId());
- return material;
- }).collect(Collectors.toList());
- mintMaterialRepo.saveAll(materials);
- // 改为转赠
- assets.forEach(asset -> assetService.transfer(asset, asset.getPrice(), blackHole, "转赠", null));
- }
- /**
- * 订单
- *
- * @param id 编号
- */
- public void finish(Long id) {
- MintOrder mintOrder = mintOrderRepo.findById(id).orElseThrow(new BusinessException("铸造订单不存在"));
- mintOrder.setStatus(MintOrderStatus.FINISH);
- mintOrderRepo.save(mintOrder);
- }
- /**
- * 发货
- *
- * @param id 编号
- * @param courierId 快递单号
- */
- public void dispatch(Long id, String courierId) {
- MintOrder mintOrder = mintOrderRepo.findById(id).orElseThrow(new BusinessException("铸造订单不存在"));
- mintOrder.setStatus(MintOrderStatus.RECEIVE);
- mintOrder.setCourierId(courierId);
- mintOrderRepo.save(mintOrder);
- }
- /**
- * @param user 用户
- * @param assetId 资产
- * @param mintActivityId 铸造活动
- * @param addressId 地址
- */
- @Transactional
- public MintOrder create(User user, List<Long> assetId, Long mintActivityId, Long addressId) {
- // 参加的活动
- MintActivity mintActivity = mintActivityRepo.findByIdAndDelFalse(mintActivityId)
- .orElseThrow(new BusinessException("无此铸造活动"));
- int stock = Optional.ofNullable(mintActivityService.decreaseStock(mintActivityId, 1))
- .map(Math::toIntExact)
- .orElseThrow(new BusinessException("很遗憾,藏品已售罄"));
- if (stock < 0) {
- throw new BusinessException("铸造活动已无库存");
- }
- if (mintActivity.getNum() > 0) {
- if (assetId.size() != mintActivity.getNum()) {
- throw new BusinessException("数量不正确,请重新选择");
- }
- }
- List<Asset> assets = assetRepo.findAllByIdInAndUserId(assetId, user.getId());
- // 资产产品是否符合铸造活动的名称
- assets = assets.stream()
- .filter(asset -> asset.getName()
- .contains(mintActivity.getCollectionName()) && AssetStatus.NORMAL.equals(asset.getStatus()))
- .collect(Collectors.toList());
- if (mintActivity.getNum() > 0 && (assets.size() != mintActivity.getNum())) {
- throw new BusinessException("有藏品不符合,请重新选择");
- }
- Map<Long, Long> privilegeIds = new HashMap<>();
- // 铸造特权
- if (!mintActivity.isConsume()) {
- assets.forEach(asset -> {
- List<Privilege> privileges = asset.getPrivileges()
- .stream()
- .filter(p -> p.getName().equals("铸造"))
- .collect(Collectors.toList());
- if (privileges.size() == 0) {
- throw new BusinessException("无铸造特权");
- } else {
- boolean flag = false;
- for (Privilege privilege : privileges) {
- // 打开多次 或者 可打开一次但未使用
- if (!privilege.isOnce() || (privilege.isOnce() && !privilege
- .isOpened())) {
- flag = true;
- privilegeIds.put(asset.getId(), privilege.getId());
- break;
- }
- }
- if (!flag) {
- throw new BusinessException("铸造特权已使用");
- }
- }
- });
- assets.forEach(asset -> {
- asset.getPrivileges()
- .stream()
- .filter(p -> p.getId().equals(privilegeIds.get(asset.getId())))
- .forEach(p -> {
- p.setOpened(true);
- p.setOpenTime(LocalDateTime.now());
- p.setOpenedBy(SecurityUtils.getAuthenticatedUser().getId());
- });
- assetRepo.save(asset);
- });
- } else {
- // 消耗改为转赠
- assets.forEach(asset -> {
- asset.setStatus(AssetStatus.MINTING);
- assetRepo.save(asset);
- });
- // 转让的用户
- userRepo.findByIdAndDelFalse(1435297L).orElseThrow(new BusinessException("无法铸造"));
- }
- UserAddress userAddress = null;
- if (addressId != null) {
- userAddress = userAddressRepo.findById(addressId).orElseThrow(new BusinessException("地址信息不存在"));
- }
- // 铸造订单
- MintOrder mintOrder = mintOrderRepo.save(MintOrder.builder()
- .userId(user.getId())
- .phone(user.getPhone())
- // .material(materials)
- .consume(mintActivity.isConsume())
- .status(MintOrderStatus.NOT_PAID)
- .airDrop(mintActivity.isAirDrop())
- .gasPrice(mintActivity.getGasPrice())
- .mintActivityId(mintActivityId)
- .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))
- .build());
- // 铸造资产
- List<MintMaterial> materials = assets.stream().map(asset -> {
- MintMaterial material = new MintMaterial();
- material.setAssetId(asset.getId());
- material.setCollectionId(asset.getCollectionId());
- material.setName(asset.getName());
- material.setPrivilegeId(privilegeIds.get(asset.getId()));
- material.setNumber(asset.getNumber());
- material.setPic(asset.getPic());
- material.setCategory(asset.getCategory());
- material.setOrderId(mintOrder.getId());
- return material;
- }).collect(Collectors.toList());
- mintMaterialRepo.saveAll(materials);
- //库存
- // mintActivity.setStock(mintActivity.getStock() - 1);
- // mintActivityRepo.save(mintActivity);
- mintActivityService.increaseSale(mintActivityId, 1);
- return mintOrder;
- }
- public Object payOrderWeixin(Long id, String tradeType, String openId) throws WxPayException, EncoderException {
- MintOrder order = mintOrderRepo.findById(id).orElseThrow(new BusinessException("订单不存在"));
- if (order.getStatus() != MintOrderStatus.NOT_PAID) {
- throw new BusinessException("订单状态错误");
- }
- WxPayUnifiedOrderRequest request = new WxPayUnifiedOrderRequest();
- request.setBody("铸造GAS费");
- request.setOutTradeNo(String.valueOf(new SnowflakeIdWorker(1, 1).nextId()));
- request.setTotalFee(order.getGasPrice().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", "payMintOrder");
- 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("不支持此付款方式");
- }
- 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("不支持此渠道");
- }
- MintOrder order = mintOrderRepo.findById(id).orElseThrow(new BusinessException("订单不存在"));
- if (order.getStatus() != MintOrderStatus.NOT_PAID) {
- throw new BusinessException("订单状态错误");
- }
- Map<String, Object> paymentParams = new HashMap<>();
- paymentParams.put("order_no", String.valueOf(snowflakeIdWorker.nextId()));
- paymentParams.put("pay_amt", order.getGasPrice().setScale(2, RoundingMode.HALF_UP).toPlainString());
- paymentParams.put("app_id", adapayProperties.getAppId());
- paymentParams.put("pay_channel", payChannel);
- paymentParams.put("goods_title", "铸造GAS费");
- paymentParams.put("goods_desc", "铸造GAS费");
- paymentParams.put("time_expire", DateTimeFormatter.ofPattern("yyyyMMddHHmmss")
- .format(LocalDateTime.now().plusMinutes(5)));
- paymentParams.put("notify_url", adapayProperties.getNotifyUrl() + "/mintOrder/" + order.getId());
- 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);
- }
- 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");
- }
- }
- @Transactional
- public void mintNotify(Long orderId, PayMethod payMethod, String transactionId) {
- MintOrder mintOrder = mintOrderRepo.findById(orderId).orElseThrow(new BusinessException("订单不存在"));
- // List<MintMaterial> materials = mintOrder.getMaterial();
- List<MintMaterial> materials = mintMaterialRepo.findAllByOrderIdAndDelFalse(orderId);
- List<Asset> assets = assetRepo.findAllById(materials
- .stream()
- .map(MintMaterial::getAssetId)
- .collect(Collectors.toList()));
- mintOrder.setPayMethod(payMethod);
- if (mintOrder.isAirDrop()) {
- mintOrder.setStatus(MintOrderStatus.AIR_DROP);
- } else {
- mintOrder.setStatus(MintOrderStatus.DELIVERY);
- }
- mintOrder.setTransactionId(transactionId);
- mintOrder.setPayAt(LocalDateTime.now());
- if (mintOrder.isConsume()) {
- User newOwner = userRepo.findByIdAndDelFalse(1435297L).orElseThrow(new BusinessException("无法铸造"));
- assets.forEach(asset -> assetService.transfer(asset, asset.getPrice(), newOwner, "转赠", null));
- }
- mintOrderRepo.save(mintOrder);
- }
- @Scheduled(fixedRate = 60000)
- public void batchCancel() {
- if (generalProperties.isNotifyServer()) {
- return;
- }
- if (Arrays.asList(env.getActiveProfiles()).contains("dev")) {
- return;
- }
- List<MintOrder> orders = mintOrderRepo.findByStatusAndCreatedAtBeforeAndDelFalse(MintOrderStatus.NOT_PAID,
- LocalDateTime.now().minusMinutes(5));
- orders.forEach(o -> {
- try {
- cancel(o);
- } catch (Exception ignored) {
- }
- });
- }
- public void cancel(MintOrder order) {
- if (order.getStatus() != MintOrderStatus.NOT_PAID) {
- throw new BusinessException("已支付订单无法取消");
- }
- // List<MintMaterial> materials = order.getMaterial();
- List<MintMaterial> materials = mintMaterialRepo.findAllByOrderIdAndDelFalse(order.getId());
- List<Asset> assets = assetRepo.findAllById(materials.stream()
- .map(MintMaterial::getAssetId)
- .collect(Collectors.toList()));
- if (order.isConsume()) {
- assets.forEach(asset -> {
- asset.setStatus(AssetStatus.NORMAL);
- assetRepo.save(asset);
- });
- } else {
- Map<Long, Long> privilegeIds = materials.stream()
- .collect(Collectors.toMap(MintMaterial::getAssetId, MintMaterial::getPrivilegeId));
- assets.forEach(asset -> {
- asset.getPrivileges()
- .stream()
- .filter(p -> p.getId().equals(privilegeIds.get(asset.getId())))
- .forEach(p -> {
- p.setOpened(false);
- p.setOpenTime(null);
- p.setOpenedBy(null);
- });
- assetRepo.save(asset);
- });
- }
- log.info("set normal mintOrder {}", order.getId());
- order.setStatus(MintOrderStatus.CANCELLED);
- order.setCancelTime(LocalDateTime.now());
- mintOrderRepo.save(order);
- // 加库存
- // mintActivityRepo.addStock(order.getMintActivityId());
- mintActivityService.increaseStock(order.getMintActivityId(), 1);
- }
- }
|