Browse Source

feat: 添加文件

bianzhenhua123 4 weeks ago
parent
commit
201582dfdd

+ 2091 - 0
tzy-sportcard/src/main/java/com/tzy/sportcard/group/service/impl/CardGroupOrderInfoServiceImpl.java

@@ -0,0 +1,2091 @@
+package com.tzy.sportcard.group.service.impl;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.github.pagehelper.PageHelper;
+import com.github.pagehelper.PageInfo;
+import com.google.common.collect.ImmutableMap;
+import com.tzy.app.domain.AppUserDetailInfo;
+import com.tzy.app.domain.AppUserPoint;
+import com.tzy.app.domain.order.OrderListDTO;
+import com.tzy.app.domain.order.PayRecord;
+import com.tzy.app.dto.*;
+import com.tzy.app.dto.group.CourierDTO;
+import com.tzy.app.mapper.AppUserDetailInfoMapper;
+import com.tzy.app.mapper.OrderListMapper;
+import com.tzy.app.mapper.PayRecordMapper;
+import com.tzy.common.annotation.RedisLock;
+import com.tzy.common.constant.Constants;
+import com.tzy.common.constant.MqConstans;
+import com.tzy.common.constant.MsgConstants;
+import com.tzy.common.constant.NoticeMsgModel;
+import com.tzy.common.core.domain.entity.SysDictData;
+import com.tzy.common.dto.*;
+import com.tzy.common.dto.UserInfo;
+import com.tzy.common.dto.group.NonEmptyQuery;
+import com.tzy.common.dto.group.OrderQuery;
+import com.tzy.common.dto.group.RefundReqDTO;
+import com.tzy.common.dto.invoice.InvoiceMerchantDTO;
+import com.tzy.common.dto.invoice.InvoiceMerchantQuery;
+import com.tzy.common.dto.invoice.InvoiceOrderQuery;
+import com.tzy.common.dto.invoice.SimpleOrderDTO;
+import com.tzy.common.dto.order.CostOrderDTO;
+import com.tzy.common.dto.order.OrderStatusDTO;
+import com.tzy.common.dto.order.ShippingPayParam;
+import com.tzy.common.dto.order.ShippingPayResult;
+import com.tzy.common.dto.pay.AllocatePayChannels;
+import com.tzy.common.dto.pay.PayResultDTO;
+import com.tzy.common.dto.pay.PaymentChannel;
+import com.tzy.common.dto.pay.PaymentParam;
+import com.tzy.common.exception.AppAssert;
+import com.tzy.common.exception.ServiceException;
+import com.tzy.common.utils.DateUtils;
+import com.tzy.common.utils.StringUtils;
+import com.tzy.common.utils.bean.BeanUtils;
+import com.tzy.common.utils.bean.JSONTools;
+import com.tzy.common.utils.http.HttpClientUtil;
+import com.tzy.common.utils.http.HttpMethod;
+import com.tzy.common.utils.http.forest.CommonForestClient;
+import com.tzy.coupon.card.domain.AppUserCardRecord;
+import com.tzy.coupon.card.domain.TzyCardBaseInfo;
+import com.tzy.coupon.card.mapper.AppUserCardRecordMapper;
+import com.tzy.coupon.card.service.IAppUserCardRecordService;
+import com.tzy.coupon.card.service.ITzyCardBaseInfoService;
+import com.tzy.dto.LimitAmountConfig;
+import com.tzy.dto.UserAmountDTO;
+import com.tzy.dto.UserPayNoticeDTO;
+import com.tzy.express.ExpressUtils;
+import com.tzy.framework.util.RedisUtils;
+import com.tzy.ierp.dto.ChecklistConfigDto;
+import com.tzy.mapper.QuestionnaireMapper;
+import com.tzy.pojo.question.Questionnaire;
+import com.tzy.sportcard.api.bean.MerchantPayInfo;
+import com.tzy.sportcard.api.bean.act.UserActTimes;
+import com.tzy.sportcard.api.bean.goods.SimpleSku;
+import com.tzy.sportcard.api.bean.invoice.AppUserInvoice;
+import com.tzy.sportcard.api.bean.invoice.AppUserInvoiceRecord;
+import com.tzy.sportcard.api.bean.param.ShippingQuery;
+import com.tzy.sportcard.api.domain.*;
+import com.tzy.sportcard.api.dto.ExpressResult;
+import com.tzy.sportcard.api.dto.GroupPriceDTO;
+import com.tzy.sportcard.api.dto.ReceiveGoodsDTO;
+import com.tzy.sportcard.api.dto.ResourceData;
+import com.tzy.sportcard.api.dto.merchant.ActGoods;
+import com.tzy.sportcard.api.mapper.AppUserInvoiceRecordMapper;
+import com.tzy.sportcard.api.mapper.MerchantApiMapper;
+import com.tzy.sportcard.api.mapper.OrderCourierRecordMapper;
+import com.tzy.sportcard.api.mapper.UserActTimesMapper;
+import com.tzy.sportcard.api.service.AsyncAppService;
+import com.tzy.sportcard.api.service.GroupApiService;
+import com.tzy.sportcard.api.service.MineApiService;
+import com.tzy.sportcard.base.service.CommonCacheService;
+import com.tzy.sportcard.enums.GroupInfoStatusEnums;
+import com.tzy.sportcard.group.domain.*;
+import com.tzy.sportcard.group.dto.ExpressCourierNumDTO;
+import com.tzy.sportcard.group.dto.ExpressInfoDetailDTO;
+import com.tzy.sportcard.group.mapper.AppCategoryPaymentMapper;
+import com.tzy.sportcard.group.mapper.CardGroupGoodsMapper;
+import com.tzy.sportcard.group.mapper.CardGroupInfoMapper;
+import com.tzy.sportcard.group.mapper.CardGroupOrderInfoMapper;
+import com.tzy.sportcard.group.service.ICardGroupGoodsIdxService;
+import com.tzy.sportcard.group.service.ICardGroupInfoService;
+import com.tzy.sportcard.group.service.ICardGroupOrderInfoService;
+import com.tzy.sportcard.point.domain.AppUserPointRecord;
+import com.tzy.system.domain.TzyShippingAddress;
+import com.tzy.system.service.ISysDictDataService;
+import com.tzy.system.service.ITzyShippingAddressService;
+import com.tzy.util.ExpressInfoUtil;
+import com.tzy.util.RandomUtil;
+import com.tzy.util.bean.ObjectUtil;
+import com.tzy.util.mq.MqUtils;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.amqp.rabbit.core.RabbitTemplate;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Lazy;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Isolation;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.CollectionUtils;
+import org.teasoft.bee.osql.SuidRich;
+
+import javax.annotation.Resource;
+import java.math.BigDecimal;
+import java.text.ParseException;
+import java.time.LocalDate;
+import java.time.ZoneId;
+import java.time.temporal.ChronoUnit;
+import java.time.temporal.Temporal;
+import java.util.*;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+
+/**
+ * 用户组团订单Service业务层处理
+ *
+ * @author tencheer
+ * @date 2021-07-09
+ */
+@Service
+@Slf4j
+public class CardGroupOrderInfoServiceImpl implements ICardGroupOrderInfoService {
+	@Resource
+	private CardGroupOrderInfoMapper cardGroupOrderInfoMapper;
+	@Autowired
+	private ICardGroupInfoService cardGroupInfoService;
+	@Autowired
+	private GroupApiService groupApiService;
+	@Autowired
+	private ITzyShippingAddressService tzyShippingAddressService;
+	@Autowired
+	private MineApiService mineApiService;
+	@Autowired
+	private ICardGroupGoodsIdxService cardGroupGoodsIdxService;
+	@Autowired
+	private RedisUtils redisUtils;
+	@Resource
+	private CardGroupGoodsMapper cardGroupGoodsMapper;
+	@Resource
+	private CardGroupInfoMapper cardGroupInfoMapper;
+	@Autowired
+	private ISysDictDataService dictDataService;
+	@Resource
+	private AppUserCardRecordMapper appUserCardRecordMapper;
+	@Resource
+	private PayRecordMapper payRecordMapper;
+	@Resource
+	private OrderListMapper orderListMapper;
+	@Autowired
+	private ITzyCardBaseInfoService cardBaseInfoService;
+	@Autowired
+	private RabbitTemplate rabbitTemplate;
+	@Resource
+	private MerchantApiMapper merchantApiMapper;
+	@Autowired
+	private CommonCacheService commonCacheService;
+	@Autowired
+	private SuidRich suidRich;
+	@Resource
+	private AppUserInvoiceRecordMapper userInvoiceRecordMapper;
+	@Autowired
+	private IAppUserCardRecordService appUserCardRecordService;
+	@Resource
+	private UserActTimesMapper userActTimesMapper;
+	@Resource
+	private ExpressInfoUtil expressInfoUtil;
+	@Resource private AppCategoryPaymentMapper appCategoryPaymentMapper;
+	@Autowired
+	@Lazy
+	private AsyncAppService asyncAppService;
+	@Resource
+	private OrderCourierRecordMapper orderCourierRecordMapper;
+	@Value("${pay.server.payType:http://localhost:8082/p1/api/remotePayChannel/list}")
+	private String payTypeUrl;
+	@Value("${pay.server.unified:http://localhost:8082/p1/v2/unified}")
+	private String unifiedV2Uri;
+	@Resource
+	private QuestionnaireMapper questionnaireMapper;
+	@Resource
+	private CommonForestClient commonForestClient;
+	@Resource
+	private AppUserDetailInfoMapper appUserDetailInfoMapper;
+
+	/**
+	 * 查询用户组团订单
+	 *
+	 * @param id 用户组团订单ID
+	 * @return 用户组团订单
+	 */
+	@Override
+	public CardGroupOrderInfo selectCardGroupOrderInfoById(Long id) {
+		return cardGroupOrderInfoMapper.selectCardGroupOrderInfoById(id);
+	}
+
+	/**
+	 * 查询用户组团订单列表
+	 *
+	 * @param cardGroupOrderInfo 用户组团订单
+	 * @return 用户组团订单
+	 */
+	@Override
+	public List<CardGroupOrderInfo> selectCardGroupOrderInfoList(CardGroupOrderInfo cardGroupOrderInfo) {
+		return cardGroupOrderInfoMapper.selectCardGroupOrderInfoList(cardGroupOrderInfo);
+	}
+
+	/**
+	 * 新增用户组团订单
+	 *
+	 * @param cardGroupOrderInfo 用户组团订单
+	 * @return 自增id
+	 */
+	@Override
+	@Transactional(isolation = Isolation.READ_COMMITTED, rollbackFor = Exception.class)
+	public Long insertCardGroupOrderInfo(CardGroupOrderInfo cardGroupOrderInfo) {
+		cardGroupOrderInfo.setCreateTime(new Date());
+		cardGroupOrderInfoMapper.insertCardGroupOrderInfo(cardGroupOrderInfo);
+		return cardGroupOrderInfo.getId();
+	}
+
+	/**
+	 * 修改用户组团订单
+	 *
+	 * @param cardGroupOrderInfo 用户组团订单
+	 * @return 结果
+	 */
+	@Override
+	public int updateCardGroupOrderInfo(CardGroupOrderInfo cardGroupOrderInfo) {
+		cardGroupOrderInfo.setUpdateTime(DateUtils.getNowDate());
+		return cardGroupOrderInfoMapper.updateCardGroupOrderInfo(cardGroupOrderInfo);
+	}
+
+	//更新取消支付状态【支付超时】
+	@Override
+	public int cancelOutDateGroupOrder(Integer id) {
+		return cardGroupOrderInfoMapper.cancelOutDateGroupOrder(id);
+	}
+
+	//查询未付款的总数
+	@Override
+	public int selectUnPaymentCount(CardGroupOrderInfo cardGroupOrderInfo) {
+		return cardGroupOrderInfoMapper.selectUnPaymentCount(cardGroupOrderInfo);
+	}
+
+	@Override
+	public Long getOrderMarkUserPoint() {
+		Object o = redisUtils.get(Constants.ORDER_MARK_USER_POINT);
+		if (o == null) {
+			SysDictData dictData = new SysDictData();
+			dictData.setDictType(Constants.ORDER_MARK_USER_POINT);
+			dictData.setStatus(Constants.STATUS_OK);
+			List<SysDictData> list = dictDataService.selectDictDataList(dictData);
+			if (list.isEmpty()) {
+				return 500000L;
+			}
+			Long point = Long.valueOf(list.get(0).getDictValue());
+			redisUtils.set(Constants.ORDER_MARK_USER_POINT, point, 60);
+			return point;
+		}
+		return Long.valueOf(o.toString());
+	}
+
+	@Override
+	public int getPayCountOfDay(Long userId) {
+		return cardGroupOrderInfoMapper.getPayCountOfDay(userId);
+	}
+
+	public List<PaymentParam> getAllPaySubTypesByCat(String payCat, String category) {
+		PayTypeParamDTO payTypeParamDTO = new PayTypeParamDTO(payCat, category);
+		try {
+			String response = commonForestClient.sendPost(payTypeUrl, Constants.JSON_HEADS, payTypeParamDTO);
+			if (StringUtils.isNotEmpty(response)) {
+				PayResultDTO payResult = JSONTools.jsonStr2obj(response, PayResultDTO.class);
+				if (payResult != null && !CollectionUtils.isEmpty(payResult.getData())) {
+					return payResult.getData();
+				}
+			}
+		} catch (Exception e) {
+			log.error("获取支付类型失败", e);
+		}
+		log.error("获取支付类型异常,返回为空");
+		return new ArrayList<>();
+	}
+
+
+	public List<PaymentParam> getAllPaySubTypesByCatV2(String payCat, String category,String orderNo, BigDecimal amount) {
+		PayTypeParamDTO payTypeParamDTO = new PayTypeParamDTO(payCat, category, orderNo, amount);
+		try {
+			String response = commonForestClient.sendPost(payTypeUrl, Constants.JSON_HEADS, payTypeParamDTO);
+			if (StringUtils.isNotEmpty(response)) {
+				PayResultDTO payResult = JSONTools.jsonStr2obj(response, PayResultDTO.class);
+				if (payResult != null && !CollectionUtils.isEmpty(payResult.getData())) {
+					return payResult.getData();
+				}
+			}
+		} catch (Exception e) {
+			log.error("获取支付类型失败", e);
+		}
+		log.error("获取支付类型异常,返回为空");
+		return new ArrayList<>();
+	}
+
+	/**
+	 * 根据用户标签选择支付子类型
+	 * @param payTypes
+	 * @return
+	 */
+	private String getPaySubTypeByUserAppCat(Integer userId, String payCat, List<PaymentParam> payTypes) {
+		// 指定标签用户
+		List<UserCatPayDTO> userCatPayTypes = appCategoryPaymentMapper.selectUserCatPayById(userId.longValue(), payCat);
+		if (!CollectionUtils.isEmpty(userCatPayTypes)) {
+			Set<String> userCatPaySubTypes = userCatPayTypes.stream().map(UserCatPayDTO::getPaySubType).collect(Collectors.toSet());
+			List<PaymentParam> userPaySubTypes = payTypes.stream().filter(pt -> userCatPaySubTypes.contains(pt.getCode())).collect(Collectors.toList());
+			if (!CollectionUtils.isEmpty(userPaySubTypes)) {
+				int size = userPaySubTypes.size();
+				if (size == 1) {
+					return userPaySubTypes.get(0).getCode();
+				}
+				return userPaySubTypes.get(RandomUtil.getRandomNum(size)).getCode();
+			}
+		}
+		return null;
+	}
+
+
+	private String getMerchantExclusivePayType(boolean isAbroad, boolean isExclusive, Long merchantId, String payCat, String category, Integer archivesId, List<PaymentParam> payTypes) {
+		if (isExclusive && !isAbroad) {
+			// 获取商户支付通道
+			List<MerchantPayInfo> merchantPayWays = merchantApiMapper.getPayTypeByMerchant(merchantId, payCat, category);
+			if (!CollectionUtils.isEmpty(merchantPayWays)) {
+				// 处理是否存在正常配置 如果不存在则使用默认分配
+				List<String> codes = payTypes.stream().map(PaymentParam::getCode).collect(Collectors.toList());
+				List<MerchantPayInfo> merchantPaysByArchives = merchantPayWays.stream().filter(item -> checkMerchantPayByArchives(archivesId, item)).collect(Collectors.toList());
+				if (!CollectionUtils.isEmpty(merchantPaysByArchives)) {
+					return merchantPaysByArchives.get(RandomUtil.getRandomNum(merchantPaysByArchives.size())).getPaySubType();
+				}
+				// 非拼团类型
+				if (!Constants.ORDER_TYPE_GROUP.equals(category)) {
+					List<MerchantPayInfo> payInfoByNoArchives1 = merchantPayWays.stream().filter(item -> codes.contains(item.getPaySubType()))
+							.collect(Collectors.toList());
+					log.debug("未关联主体 且不为拼团,随机分配一个");
+					if (!CollectionUtils.isEmpty(payInfoByNoArchives1)) {
+						return payInfoByNoArchives1.get(RandomUtil.getRandomNum(payInfoByNoArchives1.size())).getPaySubType();
+					}
+				}
+			}
+		}
+		return null;
+	}
+
+	private boolean checkMerchantPayByArchives(Integer archivesId, MerchantPayInfo item) {
+		if (archivesId == null && item.getMerchantArchivesId() == null) {
+			return true;
+		}
+		return archivesId != null && archivesId.equals(item.getMerchantArchivesId());
+	}
+
+
+	private boolean isNewAppUser(Date registerTime) {
+		Temporal temporal1 = registerTime.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
+		Temporal temporal2 = LocalDate.now();
+		// 方法返回为相差月份
+		long l = ChronoUnit.MONTHS.between(temporal1, temporal2);
+		return l <= 0;
+	}
+
+	@Override
+	public String getPayTypeByUserNew(String payType, AppUserInfoDto user, boolean isExclusive, Long merchantId, Integer archivesId, String category) {
+		boolean isLimitNew = payType.contains("alipay");
+		// 支付大类型
+		String payCat = getPayCat(payType);
+		List<PaymentParam> allPayTypes = getAllPaySubTypesByCat(payCat, category);
+		if (CollectionUtils.isEmpty(allPayTypes)) {
+			return getDefaultPayType();
+		}
+		// 是否指定标签用户,优先级最高
+		String paySubType = getPaySubTypeByUserAppCat(user.getId(), payCat, allPayTypes);
+		if (StringUtils.isNotEmpty(paySubType)) {
+			return paySubType;
+		}
+		// 过滤不符合条件的通道
+		boolean isAbroad = isAbroad();
+		int point = (int) Math.max((user.getGrowthNum() / 100), 0);
+		List<PaymentParam> payTypes = allPayTypes.stream().filter(t -> checkPaySubTypeByUser(t, isAbroad, point)).collect(Collectors.toList());
+		// 商家专属通道判断
+		String merchantExclusivePayType = getMerchantExclusivePayType(isAbroad, isExclusive, merchantId, payCat, category, archivesId, payTypes);
+		if (StringUtils.isNotEmpty(merchantExclusivePayType)) {
+			return merchantExclusivePayType;
+		}
+		// 排除商家专属通道
+		// 查询专属通道-所有商家
+		List<String> allPayType = merchantApiMapper.getAllPayType();
+		if (!CollectionUtils.isEmpty(allPayType)) {
+			payTypes = payTypes.stream().filter(i -> !allPayType.contains(i.getCode())).collect(Collectors.toList());
+		}
+		// 新用户限制通道
+		if (isLimitNew && isNewAppUser(user.getRegisterTime())) {
+			List<PaymentParam> newUserPays = payTypes.stream().filter(p -> p.getExclusiveOfNew() == 1).collect(Collectors.toList());
+			if (newUserPays.size() == 1) {
+				return newUserPays.get(0).getCode();
+			}
+			if (!newUserPays.isEmpty()) {
+				payTypes = newUserPays;
+			}
+		}
+		final String amountKey = Constants.PAY_AMOUNT_DAY_KEY + DateUtils.getDate();
+		List<PaymentParam> configList = payTypes.stream()
+				.filter(c -> c.getAmount() * 10000 > redisUtils.hincr(amountKey, c.getCode(), 0))
+				.collect(Collectors.toList());
+		if (configList.isEmpty()) {
+			log.info("所有支付方式达到限额,走默认支付");
+			return getDefaultPayType();
+		}
+		// 用户高频,仅用用户当前高频的支付方式
+		List<String> payLimitList = getUserCurrentPaySubType(user);
+		if (!CollectionUtils.isEmpty(payLimitList)) {
+			List<PaymentParam> payList = configList.stream().filter(c -> payLimitList.contains(c.getCode())).collect(Collectors.toList());
+			if (!CollectionUtils.isEmpty(payList)) {
+				configList = payList;
+			}
+		}
+		if (configList.size() == 1) {
+			return configList.get(0).getCode();
+		}
+		List<PaymentChannel> userChannels = configList.stream().map(PaymentChannel::toPaymentChannel).collect(Collectors.toList());
+		List<PaymentChannel> globalChannels = allPayTypes.stream().map(PaymentChannel::toPaymentChannel).collect(Collectors.toList());
+		String userPaySubType = AllocatePayChannels.allocatePaymentChannel(userChannels, globalChannels, payCat + category);
+		if (StringUtils.isNotEmpty(userPaySubType)) {
+			return userPaySubType;
+		}
+		log.debug("未能正常分配,随机分配一个");
+		return configList.get(RandomUtil.getRandomNum(configList.size())).getCode();
+	}
+
+	/**
+	 * 日期【2025年10月15日】 -----修改----  ----支持新通道规则限制---
+	 * @param payType
+	 * @param user
+	 * @param isExclusive
+	 * @param merchantId
+	 * @param archivesId
+	 * @param category
+	 * @param orderNo
+	 * @param amount
+	 * @return
+	 */
+	@Override
+	public String getPayTypeByUserV2(String payType, AppUserInfoDto user, boolean isExclusive, Long merchantId, Integer archivesId, String category, String orderNo , BigDecimal amount ) {
+		boolean isLimitNew = payType.contains("alipay");
+		// 支付大类型
+		String payCat = getPayCat(payType);
+		List<PaymentParam> allPayTypes = getAllPaySubTypesByCatV2(payCat, category,orderNo , amount);
+		if (CollectionUtils.isEmpty(allPayTypes)) {
+			return getDefaultPayType();
+		}
+		// 是否指定标签用户,优先级最高
+		String paySubType = getPaySubTypeByUserAppCat(user.getId(), payCat, allPayTypes);
+		if (StringUtils.isNotEmpty(paySubType)) {
+			return paySubType;
+		}
+		// 过滤不符合条件的通道
+		boolean isAbroad = isAbroad();
+		int point = (int) Math.max((user.getGrowthNum() / 100), 0);
+		List<PaymentParam> payTypes = allPayTypes.stream().filter(t -> checkPaySubTypeByUser(t, isAbroad, point)).collect(Collectors.toList());
+		// 商家专属通道判断
+		String merchantExclusivePayType = getMerchantExclusivePayType(isAbroad, isExclusive, merchantId, payCat, category, archivesId, payTypes);
+		if (StringUtils.isNotEmpty(merchantExclusivePayType)) {
+			return merchantExclusivePayType;
+		}
+		// 排除商家专属通道
+		// 查询专属通道-所有商家
+		List<String> allPayType = merchantApiMapper.getAllPayType();
+		if (!CollectionUtils.isEmpty(allPayType)) {
+			payTypes = payTypes.stream().filter(i -> !allPayType.contains(i.getCode())).collect(Collectors.toList());
+		}
+		// 新用户限制通道
+		if (isLimitNew && isNewAppUser(user.getRegisterTime())) {
+			List<PaymentParam> newUserPays = payTypes.stream().filter(p -> p.getExclusiveOfNew() == 1).collect(Collectors.toList());
+			if (newUserPays.size() == 1) {
+				return newUserPays.get(0).getCode();
+			}
+			if (!newUserPays.isEmpty()) {
+				payTypes = newUserPays;
+			}
+		}
+		final String amountKey = Constants.PAY_AMOUNT_DAY_KEY + DateUtils.getDate();
+		List<PaymentParam> configList = payTypes.stream()
+												.filter(c -> c.getAmount() * 10000 > redisUtils.hincr(amountKey, c.getCode(), 0))
+												.collect(Collectors.toList());
+		if (configList.isEmpty()) {
+			log.info("所有支付方式达到限额,走默认支付");
+			return getDefaultPayType();
+		}
+		// 用户高频,仅用用户当前高频的支付方式
+		List<String> payLimitList = getUserCurrentPaySubType(user);
+		if (!CollectionUtils.isEmpty(payLimitList)) {
+			List<PaymentParam> payList = configList.stream().filter(c -> payLimitList.contains(c.getCode())).collect(Collectors.toList());
+			if (!CollectionUtils.isEmpty(payList)) {
+				configList = payList;
+			}
+		}
+		if (configList.size() == 1) {
+			return configList.get(0).getCode();
+		}
+		List<PaymentChannel> userChannels = configList.stream().map(PaymentChannel::toPaymentChannel).collect(Collectors.toList());
+		List<PaymentChannel> globalChannels = allPayTypes.stream().map(PaymentChannel::toPaymentChannel).collect(Collectors.toList());
+		String userPaySubType = AllocatePayChannels.allocatePaymentChannel(userChannels, globalChannels, payCat + category);
+		if (StringUtils.isNotEmpty(userPaySubType)) {
+			return userPaySubType;
+		}
+		log.debug("未能正常分配,随机分配一个");
+		return configList.get(RandomUtil.getRandomNum(configList.size())).getCode();
+	}
+
+	private List<String> getUserCurrentPaySubType(AppUserInfoDto user) {
+		// 查询是否高频
+		List<SysDictData> payLimit = dictDataService.selectDictDataByCache(Constants.USER_PAY_LIMIT,null, Constants.STATUS_OK,true);
+		long count = 3;
+		int time = 1;
+		if (!payLimit.isEmpty()) {
+			count = payLimit.get(0).getDictSort();
+			time = Integer.parseInt(payLimit.get(0).getDictValue());
+		}
+		//统计短期内支付次数
+        return cardGroupOrderInfoMapper.getLimitPayWay(user.getId(), time, count);
+	}
+
+	private boolean checkPaySubTypeByUser(PaymentParam t, boolean isAbroad, int userPoint) {
+		int currentHour = DateUtils.getCurrentHour();
+		if (t.getStartTime() > currentHour) {
+			return false;
+		}
+		if (currentHour > t.getEndTime()) {
+			return false;
+		}
+		if (isAbroad && t.getAbroadStatus() == 0) {
+			return false;
+		}
+		if (!isAbroad && t.getAbroadStatus() == 1) {
+			return false;
+		}
+		if (userPoint < t.getPointMin()) {
+			return false;
+		}
+		return userPoint <= t.getPointMax();
+	}
+
+	public static String getPayCat(String payType) {
+		String payCat = "alipay";
+		if (payType.contains("alipay-hk")) {
+			payCat = "alipay-hk";
+		} else if (payType.contains("alipay")) {
+			payCat = "alipay";
+		} else if (payType.contains("wxpay-qm")) {
+			payCat = "wxpay-qm";
+		} else if (payType.contains("wxpay")) {
+			payCat = "wxpay";
+		} else if (payType.contains("uac")) {
+			payCat = "uac";
+		} else if (payType.contains("bank")) {
+			payCat = "bank";
+		} else if (payType.contains("agreement")) {
+			payCat = "agreement";
+		} else if (payType.contains("recharge")) {
+			payCat = "recharge";
+		}
+		return payCat;
+	}
+
+	private String getDefaultPayType() {
+		List<SysDictData> defaultPay = commonCacheService.getCommonDictData("default_pay_type", "default_pay_type", "1",
+																			"default_pay_type_cache", 600);
+		if (defaultPay.isEmpty()) {
+			return Constants.DEFAULT_PAY_TYPE;
+		}
+		String payType = defaultPay.get(0).getDictValue();
+		log.info("默认支付方式:{}", payType);
+		return payType;
+	}
+
+	@Override
+	public boolean isAbroad() {
+		boolean isAbroad = false;
+		IpAddrDTO ipAddress = commonCacheService.getIpAddr();
+		if (ipAddress != null && !Constants.CHINA.equalsIgnoreCase(ipAddress.getCountry())) {
+			isAbroad = true;
+		}
+		return isAbroad;
+	}
+
+	@Override
+	public OutDTO freeOrder(InDto inDto) {
+		return OutDTO.error(10041, "免单兑换异常,请重试");
+	}
+
+	private ResourceData buildFreeResourceData(CardGroupOrderInfo orderInfo) {
+		ResourceData resourceData = new ResourceData();
+		resourceData.setOut_trade_no(orderInfo.getOrderNo());
+		resourceData.setTrade_type("免单");//支付类型
+		resourceData.setSubPaymentType("免单");
+		resourceData.setTransaction_id(String.valueOf(System.currentTimeMillis()));//支付流水号,微信支付订单号
+		resourceData.setSuccess_time(DateUtils.dateTime(new Date()));//支付成功时间
+		resourceData.setTrade_state("TRADE_SUCCESS");//支付状态
+		resourceData.setTrade_state_desc("TRADE_SUCCESS");//支付状态说明
+		resourceData.setBank_type("免单");//付款银行
+		ResourceData.PayAmount payAmount = new ResourceData.PayAmount();
+		payAmount.setTotal(0);
+		payAmount.setPayer_total(0);
+		resourceData.setAmount(payAmount);
+		return resourceData;
+	}
+
+
+	private void buildOrderAddress(InDto inDto, CardGroupOrderInfo orderInfo) {
+		//收货地址id
+		Integer addrId = (Integer) inDto.get("shippingAddressId");
+		//选择默认的收货地址
+		TzyShippingAddress shippingAddress = tzyShippingAddressService.selectTzyShippingAddressById(addrId.longValue());
+		if (null != shippingAddress) {//添加收货地址
+			orderInfo.setShippingAddressId(shippingAddress.getId().longValue());
+			orderInfo.setShippingAddressLinkname(shippingAddress.getLinkname());
+			orderInfo.setShippingAddress(shippingAddress.getAddress() + shippingAddress.getAddressMore());
+			orderInfo.setShippingAddressPhone(shippingAddress.getPhone());
+		} else {
+			ShippingAddressDto shippingAddressDto = new ShippingAddressDto();
+			//shippingAddressDto.setId(addrId);
+			shippingAddressDto.setUserId(inDto.getUserId());
+			List<ShippingAddressDto> shippingAddressDtos = mineApiService.searchShippingAddress(shippingAddressDto);
+			if (!shippingAddressDtos.isEmpty()) {
+				ShippingAddressDto shippingAddressd = shippingAddressDtos.get(0);
+				orderInfo.setShippingAddressId(shippingAddressd.getId().longValue());
+				orderInfo.setShippingAddressLinkname(shippingAddressd.getLinkname());
+				orderInfo.setShippingAddress(shippingAddressd.getAddress() + shippingAddressd.getAddressMore());
+				orderInfo.setShippingAddressPhone(shippingAddressd.getPhone());
+			}
+		}
+	}
+
+	private void buildOrderAddress(Integer addressId, CardGroupOrderInfo orderInfo) {
+		if(addressId==null){
+			return;
+		}
+		TzyShippingAddress shippingAddress = tzyShippingAddressService.selectTzyShippingAddressById(addressId.longValue());
+		AppAssert.notNull(shippingAddress,"地址信息不存在,请核实!");
+		orderInfo.setShippingAddressId(shippingAddress.getId());
+		orderInfo.setShippingAddressLinkname(shippingAddress.getLinkname());
+		orderInfo.setShippingAddress(shippingAddress.getAddress() + shippingAddress.getAddressMore());
+		orderInfo.setShippingAddressPhone(shippingAddress.getPhone());
+	}
+
+	@Override
+	public CardGroupOrderInfo getByOrderNo(String no) {
+		return cardGroupOrderInfoMapper.getByOrderNo(no);
+	}
+
+	@Override
+	public void cancelOrder(CardGroupOrderInfo orderInfo) {
+		//加分布式锁
+		String lockKey = "BUY_LOCK_" + orderInfo.getGroupInfoId();
+		if (redisUtils.hasKey(Constants.ORDER_CALLBACK_LOCK_KEY + orderInfo.getTradeNo())) {
+			log.info("订单处于回调中,取消暂停,orderNo:{}", orderInfo.getOrderNo());
+			return;
+		}
+		if (orderInfo.getStatus() == 202) {
+			CardGroupOrderInfo order = new CardGroupOrderInfo();
+			order.setId(orderInfo.getId());
+			order.setStatus(202L);
+			order.setExpireTime(new Date());
+			updateCardGroupOrderInfo(order);
+		} else {
+			cancelOutDateGroupOrder(orderInfo.getId().intValue());
+		}
+
+		boolean isLock;
+		try {
+			isLock = redisUtils.tryLock(lockKey, TimeUnit.SECONDS, 30L, 15);
+			if (isLock) {
+				//释放库存和锁定的坐标
+				CardGroupInfo cardGroupInfo = cardGroupInfoService.selectCardGroupInfoById(orderInfo.getGroupInfoId());
+				boolean isNewGoods = cardGroupInfo.getGoodsType() == 1;
+				cardGroupInfo.setSoldCopies(orderInfo.getPurchaseCount());
+				if (Constants.INFO_TYPE_TEAM.equals(cardGroupInfo.getType())) {
+					cancelTeamSelected(orderInfo.getId(), orderInfo.getUserId());
+				} else if (StringUtils.isEmpty(cardGroupInfo.getChangeType()) && Constants.INFO_TYPE_BUY_TEAM.equals(cardGroupInfo.getType())) {
+					//买队玩法
+					if (StringUtils.isNotEmpty(orderInfo.getTeamFirst())) {
+						//包队数量重新查询
+						long count = getBuyTeamSoldCount(cardGroupInfo.getId(), orderInfo.getTeamFirst(), isNewGoods, orderInfo.getPurchaseCount());
+						if (!isNewGoods) {
+							cancelSelectedByTeam(orderInfo.getGroupInfoId(), orderInfo.getTeamFirst());
+						}
+						cardGroupInfo.setSoldCopies(count);
+					} else {
+						if (!isNewGoods) {
+							cancelSelectedByOrderId(orderInfo.getId());
+						}
+					}
+					//新版订单逻辑,需修改订单明细状态
+					orderListMapper.updateStatus(orderInfo.getId(), null, 201);
+				}
+				cardGroupInfoService.updateSold(cardGroupInfo);
+				if (Constants.INFO_TYPE_SELECT_TEAM.equals(cardGroupInfo.getType())) {
+					redisUtils.hdel(Constants.INFO_SELECT_TEAM_CACHE + cardGroupInfo.getId(), cardGroupInfo.getId().toString());
+				}
+				redisUtils.unlock(lockKey);
+			}
+		} catch (Exception e) {
+			log.error("定时任务修改异常:", e);
+		} finally {
+			try {
+				redisUtils.unlock(lockKey);
+			} catch (Exception e) {
+				log.debug("定时任务锁释放异常:", e);
+			}
+		}
+	}
+
+	private long getBuyTeamSoldCount(Long groupInfoId,String team,boolean isNewGoods,Long purchaseCount){
+		if(!isNewGoods){
+			return cardGroupGoodsMapper.getUnSelectOfBuyAllTeam(groupInfoId,team);
+		}
+		long unselected=cardGroupOrderInfoMapper.getSelectedOfBuyAllTeam(groupInfoId,team);
+		return purchaseCount-unselected;
+	}
+
+	private void cancelSelectedByTeam(Long groupInfoId, String team) {
+		cardGroupGoodsMapper.cancelSelectedByTeam(groupInfoId, team);
+		log.info("取消选中的卡密,groupInfoId:{},team:{}", groupInfoId, team);
+	}
+
+	@Override
+	public void cancelTeamSelected(Long orderId, Long userId) {
+		CardGroupGoodsIdx cardGroupGoodsIdx = new CardGroupGoodsIdx();
+		cardGroupGoodsIdx.setUserId(userId);
+		cardGroupGoodsIdx.setSelected(0L);
+		cardGroupGoodsIdx.setGroupOrderId(orderId);
+		cardGroupGoodsIdxService.updateUnSelectedIdx(cardGroupGoodsIdx);
+		log.info("取消选中的卡密,orderId:{},userId:{}", orderId, userId);
+	}
+
+	@Override
+	public void cancelSelectedByOrderId(Long orderId) {
+		cardGroupGoodsMapper.cancelSelectedByOrderId(orderId);
+		log.info("取消选中的卡密,orderId:{}", orderId);
+	}
+
+	@Override
+	public CardGroupOrderInfo selectUnPayOrderById(Long id) {
+		return cardGroupOrderInfoMapper.selectUnPayOrderById(id);
+	}
+
+	@Override
+	public void checkIsWaitShipping(String[] orderIds) {
+		CardGroupOrderInfo existOrder = selectCardGroupOrderInfoById(Long.valueOf(orderIds[0]));
+		AppUserInfoDto user = mineApiService.searchUserInfoById(existOrder.getUserId().intValue());
+		if (user != null && user.getRefusePickUp() == 1) {
+			throw new ServiceException(500, "此用户拒绝累积和自提,请及时发货!");
+		}
+		//int count =cardGroupOrderInfoMapper.getRefuseCount(Arrays.stream(orderIds).map(id -> Long.valueOf(id)).collect(Collectors.toList()));
+		//if(count>0){
+		//	throw new ServiceException(500,"此用户拒绝累积和自提方式,请及时发货!");
+		//}
+	}
+
+	@Override
+	public void useCard(CardGroupOrderInfo orderInfo) {
+		if (null == orderInfo || null == orderInfo.getCoupon()) {
+			return;
+		}
+		//优惠券使用核销
+		AppUserCardRecord appUserCardRecord = new AppUserCardRecord();
+		appUserCardRecord.setId(orderInfo.getCoupon());
+		appUserCardRecord.setOrderId(orderInfo.getId());
+		appUserCardRecord.setOrderNo(orderInfo.getOrderNo());
+		appUserCardRecord.setOriginalPrice(orderInfo.getAccountsPayable());
+		appUserCardRecord.setSpecialPrice(orderInfo.getActualPayment());
+		appUserCardRecord.setDiscount(orderInfo.getDiscount());
+		//已使用
+		appUserCardRecord.setStatus("1");
+		appUserCardRecordMapper.updateAppUserCardRecord(appUserCardRecord);
+	}
+
+	@Override
+	@RedisLock(lockKey = "gift_card_order_lock_+#{shipRecord.userId}",isUseTran = true,waitTime = 10,leaseTime = 20)
+	public OutDTO shippingPayV3(AppUserPoint shipRecord, BigDecimal totalCost, Integer shippingNum, String payType, Integer addressId) {
+        return new OutDTO();
+	}
+
+	private AppUserPoint getUserGiftRecord(AppUserPoint cond){
+		return suidRich.selectOne(cond);
+	}
+
+	@Override
+	public void exchangePoint(Long orderId) {
+		CardGroupOrderInfo orderInfo = selectCardGroupOrderInfoById(orderId);
+		if (orderInfo == null || orderInfo.getPointRate() == 0 || orderInfo.getRefuseStatus() != 3) {
+			return;
+		}
+		BigDecimal amount = orderInfo.getActualPayment().subtract(orderInfo.getRefundFee() == null ? BigDecimal.ZERO : orderInfo.getRefundFee());
+		int points = amount.multiply(new BigDecimal(orderInfo.getPointRate())).intValue();
+		addPoint(orderId, orderInfo, points, false);
+	}
+
+
+	private void addPoint(Long orderId, CardGroupOrderInfo orderInfo, Integer points, boolean isMediumCard) {
+		if (points == 0) {
+			return;
+		}
+		AppUserPointRecord pointRecord = new AppUserPointRecord();
+		pointRecord.setChangePoint(points.longValue());
+		pointRecord.setType(Constants.POINT_TYPE_MERCHANT);
+		pointRecord.setUserId(orderInfo.getUserId());
+		pointRecord.setOrderId(orderInfo.getId());
+		pointRecord.setOrderNo(orderInfo.getOrderNo());
+		pointRecord.setMerchantId(orderInfo.getMerchantId());
+		mineApiService.addUserPoint(pointRecord);
+		CardGroupOrderInfo order = new CardGroupOrderInfo();
+		order.setId(orderId);
+		order.setRefuseStatus(5);
+		if (!isMediumCard) {
+			order.setStatus(302L);
+		}
+		updateCardGroupOrderInfo(order);
+	}
+
+	@Override
+	public List<OrderListDTO> selectOrderList(Long orderId) {
+		return orderListMapper.selectByOrderId(orderId);
+	}
+
+	@Override
+	public OutDTO exchangeCouponById(Long couponId, Integer userId) {
+		TzyCardBaseInfo condition = new TzyCardBaseInfo();
+		condition.setId(couponId);
+		List<TzyCardBaseInfo> tzyCardBaseInfos = cardBaseInfoService.selectTzyCardBaseInfoList(condition);
+		if (tzyCardBaseInfos.isEmpty()) {
+			return OutDTO.error500("优惠劵不存在!");
+		}
+		return exchangeCoupon(tzyCardBaseInfos.get(0), userId);
+	}
+
+	public OutDTO exchangeCoupon(TzyCardBaseInfo cardBaseInfo, Integer userId) {
+		String cdkey = cardBaseInfo.getCdkey();
+		String userKey = Constants.GROUP_ORDER_LOCK + userId;
+		redisUtils.set(userKey, 1, 10);
+		String lockKey = "EXCHANGE_COUPON_LOCK_" + cardBaseInfo.getId();
+		try {
+			Boolean isLock = redisUtils.tryLock(lockKey, TimeUnit.SECONDS, 20L, 31L);
+			if (isLock) {
+				// 查询已兑换数量
+				int count = appUserCardRecordMapper.selectCouponExChangeCount(cardBaseInfo.getId(), null);
+				if (count >= cardBaseInfo.getMaxClaim()) {
+					redisUtils.unlock(lockKey);
+					return OutDTO.error500("已超过优惠劵最大数量!");
+				}
+				int userCount = appUserCardRecordMapper.selectCouponExChangeCount(cardBaseInfo.getId(), userId);
+				if (userCount >= 1) {
+					redisUtils.unlock(lockKey);
+					return OutDTO.error500("优惠劵仅能兑换一次!");
+				}
+				if (cardBaseInfo.getPointNum() != null && cardBaseInfo.getPointNum() > 0) {
+					AppUserInfoDto user = mineApiService.searchUserInfoById(userId);
+					int needPoint = 100 * cardBaseInfo.getPointNum().intValue();
+					if (user.getPoint() < needPoint) {
+						return OutDTO.error500("积分不足" + cardBaseInfo.getPointNum());
+					}
+					//兑换时需要扣除积分
+					CardGroupOrderInfo orderInfo = new CardGroupOrderInfo();
+					orderInfo.setUserId(userId.longValue());
+					orderInfo.setPoint(needPoint);
+					orderInfo.setId(0 - cardBaseInfo.getId());
+					orderInfo.setOrderNo(cardBaseInfo.getCode());
+					mineApiService.addUserPoint(orderInfo, false, Constants.POINT_TYPE_COMMON_SUB);
+				}
+				AppUserCardRecord userCardRecord = new AppUserCardRecord();
+				userCardRecord.setUserId(userId.longValue());
+				userCardRecord.setStatus(Constants.ZERO);
+				userCardRecord.setCardId(cardBaseInfo.getId());
+				userCardRecord.setCardName(cardBaseInfo.getName());
+				userCardRecord.setCardNo(cardBaseInfo.getCode());
+				userCardRecord.setCreateTime(new Date());
+				userCardRecord.setMerchantId(cardBaseInfo.getMerchantId());
+				userCardRecord.setFromCategory(cardBaseInfo.getFromCategory());
+				if (Constants.ONE.equals(cardBaseInfo.getUseType())) {
+					userCardRecord.setStartTime(cardBaseInfo.getUseStartTime());
+					userCardRecord.setExpiryTime(cardBaseInfo.getUseEndTime());
+				} else {
+					Date date = new Date();
+					userCardRecord.setStartTime(date);
+					userCardRecord.setExpiryTime(DateUtils.getFutureDate(date, Integer.valueOf(cardBaseInfo.getUseCycle())));
+				}
+				userCardRecord.setRemark("兑换码");
+				appUserCardRecordMapper.insertAppUserCardRecord(userCardRecord);
+				TzyCardBaseInfo updateMsg = new TzyCardBaseInfo();
+				updateMsg.setId(cardBaseInfo.getId());
+				updateMsg.setReceived(1L + count);
+				cardBaseInfoService.updateTzyCardBaseInfo(updateMsg);
+				redisUtils.unlock(lockKey);
+				redisUtils.del(userKey);
+			}
+		} catch (ServiceException e) {
+			log.error("兑换优惠劵失败失败,key:{},用户id:{}", cdkey, userId, e);
+			redisUtils.del(userKey);
+			throw e;
+		} catch (Exception e) {
+			log.error("兑换优惠劵失败失败,key:{},用户id:{}", cdkey, userId, e);
+			redisUtils.del(userKey);
+			return OutDTO.error500("兑换优惠劵失败失败,请重试!");
+		} finally {
+			try {
+				redisUtils.unlock(lockKey);
+			} catch (Exception e) {
+			}
+		}
+		redisUtils.del(userKey);
+		return OutDTO.ok();
+	}
+
+	@Override
+	public void addPayRecord(CardGroupOrderInfo orderInfo, String payType, String paymentSubType, String tradeNo) {
+		PayRecord payRecord = new PayRecord();
+		payRecord.setOrderId(orderInfo.getId());
+		payRecord.setPaymentType(payType);
+		payRecord.setPaymentSubType(paymentSubType);
+		payRecord.setPayAmount(orderInfo.getActualPayment());
+		payRecord.setActualPayment(orderInfo.getActualPayment());
+		payRecord.setCreateTime(new Date());
+		payRecord.setTradeNo(tradeNo);
+		payRecord.setOrderNo(orderInfo.getOrderNo());
+		payRecord.setAbroad_status(isAbroad()?1:0);
+		payRecordMapper.insertPayRecord(payRecord);
+		redisUtils.set(Constants.TRADE_NO_TO_PAY_RECORD + tradeNo, JSON.toJSONString(payRecord), 3600);
+	}
+
+	public void addPayRecord(String payType, String paymentSubType, String tradeNo, Long orderId, String orderNo, BigDecimal payAmount) {
+		PayRecord payRecord = new PayRecord();
+		payRecord.setOrderId(orderId);
+		payRecord.setPaymentType(payType);
+		payRecord.setPaymentSubType(paymentSubType);
+		payRecord.setPayAmount(payAmount);
+		payRecord.setActualPayment(payAmount);
+		payRecord.setCreateTime(new Date());
+		payRecord.setTradeNo(tradeNo);
+		payRecord.setOrderNo(orderNo);
+		payRecord.setAbroad_status(isAbroad() ? 1 : 0);
+		payRecordMapper.insertPayRecord(payRecord);
+		redisUtils.set(Constants.TRADE_NO_TO_PAY_RECORD + tradeNo, JSON.toJSONString(payRecord), 3600);
+	}
+
+	@Override
+	public List<PayRecord> findPayRecordByOrderId(Long orderId) {
+		return payRecordMapper.selectPayRecordByOrderId(orderId);
+	}
+
+	@Override
+	public PayRecord findPayRecord(Long orderId, Integer status) {
+		return payRecordMapper.selectLastPayRecordByOrderId(orderId, status);
+	}
+
+	@Override
+	public boolean checkOrderIsPay(Long orderId) {
+		List<PayRecord> unPayRecords = payRecordMapper.selectPayRecordByOrderId(orderId);
+		if (unPayRecords.isEmpty()) {
+			return false;
+		}
+		List<PayRecord> payRecords = unPayRecords.stream().filter(r -> r.getStatus() == 1).collect(Collectors.toList());
+		if (!payRecords.isEmpty()) {
+			return true;
+		}
+//		for (PayRecord record : unPayRecords) {
+//			PaymentInfoResponseDto result = paymentService.queryPaymentOrder(record.getPaymentSubType(), record.getTradeNo());
+//			if (result.isSuccess()) {
+//				return true;
+//			}
+//		}
+		return false;
+	}
+
+	@Override
+	public boolean checkIsUnPayOrder(Integer groupInfoId) {
+		return cardGroupInfoMapper.getOneUnPayOrderCount(groupInfoId) > 0;
+	}
+
+	@Override
+	public int findPayCountByOrderId(Long orderId) {
+		return payRecordMapper.findPayCountByOrderId(orderId);
+	}
+
+	@Override
+	public List<GroupPriceDTO> getGroupOrderInfoNew(CardGroupInfo cardGroupInfo) {
+		List<GroupPriceDTO> priceDTOS = new ArrayList<>();
+		if (Constants.INFO_TYPE_BUY_TEAM.equals(cardGroupInfo.getType())) {
+			// 买队玩法
+			CardGroupGoods goods = new CardGroupGoods();
+			goods.setGroupInfoId(cardGroupInfo.getId());
+			List<CardGroupGoods> cardGroupGoods = cardGroupGoodsMapper.selectCardGroupGoodsList(goods);
+			final List<GroupPriceDTO> priceList = new ArrayList<>();
+			cardGroupGoods.forEach(g -> {
+				GroupPriceDTO groupPriceDTO;
+				if (null != g.getUserOrderId()) {
+					CardGroupOrderInfo order = cardGroupOrderInfoMapper.selectCardGroupOrderInfoById(g.getUserOrderId().longValue());
+					if (g.getActPrice() != null) {
+						// 设置过活动价格
+						List<GoodsPriceJson> goodsPrices = JSONObject.parseArray(order.getGoodsPriceJson(), GoodsPriceJson.class);
+						List<GoodsPriceJson> list = goodsPrices.stream().filter(p -> g.getId().longValue() == p.getGoodsId()).collect(Collectors.toList());
+						GoodsPriceJson priceJson = list.get(0);
+						if (null == priceJson.getActPrice()) {
+							groupPriceDTO = new GroupPriceDTO(1, g.getPrice(), g.getPrice(), g.getPlayerName(), g.getTeam(), BigDecimal.ZERO,BigDecimal.ZERO);
+						} else {
+							groupPriceDTO = new GroupPriceDTO(1, priceJson.getActPrice(), priceJson.getActPrice(), g.getPlayerName(), g.getTeam(),  BigDecimal.ZERO,BigDecimal.ZERO);
+						}
+					} else {
+						groupPriceDTO = new GroupPriceDTO(1, g.getPrice(), g.getPrice(), g.getPlayerName(), g.getTeam(),  BigDecimal.ZERO,BigDecimal.ZERO);
+					}
+					priceList.add(groupPriceDTO);
+				}
+			});
+			priceDTOS.addAll(priceList);
+		} else {
+			priceDTOS = cardGroupOrderInfoMapper.getOrderDetailGroupActPrice(cardGroupInfo.getId());
+		}
+
+		return priceDTOS;
+	}
+
+	@Override
+	@Transactional(isolation = Isolation.READ_COMMITTED, rollbackFor = Exception.class)
+	public void giveawayGoods(AppUserInfoDto giveUser, Integer receiveUserId, List<Long> idsList, Integer groupInfoId) throws Exception {
+		AppUserInfoDto receiveUser = mineApiService.searchUserInfoById(receiveUserId);
+		if (receiveUser == null) {
+			throw new ServiceException(500, "被赠与人不存在!");
+		}
+		ShippingAddressDto shippingAddressDto = new ShippingAddressDto();
+		shippingAddressDto.setUserId(receiveUserId);
+		List<ShippingAddressDto> addressList = mineApiService.searchShippingAddress(shippingAddressDto);
+		if (CollectionUtils.isEmpty(addressList)) {
+			throw new ServiceException(500, "接收人名下无收货地址,请联系对方填写收货地址!");
+		}
+		CardGroupInfo cardGroupInfo=null;
+		if(groupInfoId!=null){
+			cardGroupInfo = cardGroupInfoService.selectCardGroupInfoById(groupInfoId.longValue());
+		}
+		GoodsQuery query = new GoodsQuery().setIds(idsList).setUserIdCond(giveUser.getId());
+		List<GoodsSerialDto> goods = cardGroupGoodsMapper.selectGoods(query);
+		if (goods.isEmpty()) {
+			throw new ServiceException(500, "赠送卡密不存在!");
+		}
+		Set<Long> giveOrderIds=goods.stream().map(g -> g.getUserOrderId().longValue()).collect(Collectors.toSet());
+		if (giveOrderIds.size() != 1) {
+			throw new ServiceException(500, "仅能赠送单笔订单下的卡密!");
+		}
+		Long giveOrderId = goods.get(0).getUserOrderId().longValue();
+		CardGroupOrderInfo giveOrder = selectCardGroupOrderInfoById(giveOrderId);
+		if (Constants.ORDER_SUB_TYPE_RECEIVE.equals(giveOrder.getOrderSubType())) {
+			throw new ServiceException(500, "被赠与卡密无法再次转赠!");
+		}
+		if (giveOrder.getUserId().intValue() == receiveUserId) {
+			throw new ServiceException(500, "卡密不能赠送自己!");
+		}
+		if(groupInfoId==null){
+			cardGroupInfo = cardGroupInfoService.selectCardGroupInfoById(giveOrder.getGroupInfoId());
+		}
+		if(StringUtils.isNotEmpty(cardGroupInfo.getHotTypeConfig())){
+			List<GoodsSerialDto> actGoods = goods.stream().filter(g -> StringUtils.isNotEmpty(g.getActType())).collect(Collectors.toList());
+			if(!actGoods.isEmpty()){
+				throw new ServiceException(500, "活动卡密不可赠送!");
+			}
+		}
+		if(Constants.INFO_TYPE_BUY_TEAM.equals(cardGroupInfo.getType())&&cardGroupInfo.getTeamFirst()==1){
+			throw new ServiceException(500, "此拼团不支持赠送玩法!");
+		}
+		if(cardGroupInfo.isPreSale()){
+			throw new ServiceException(500, "此拼团不支持赠送玩法!");
+		}
+		if (!(cardGroupInfo.getStatus() == 201 || cardGroupInfo.getStatus() == 203)) {
+			throw new ServiceException(500, "该拼团状态不符合赠送要求!");
+		}
+		if (Constants.ONE.equals(cardGroupInfo.getNonEmpty()) && cardGroupInfo.getStatus() == 203) {
+			throw new ServiceException(500, "该拼团状态不符合赠送要求!");
+		}
+		if (cardGroupInfo.getPaniniListId() != null && cardGroupInfo.getStatus() == 203 &&
+				!CollectionUtils.isEmpty(groupApiService.getUserListAct(cardGroupInfo.getPaniniListId()))) {
+			throw new ServiceException(500, "该拼团包含卡密活动,不支持赠送玩法!");
+		}
+		ShippingAddressDto receiveAddress=addressList.get(0);
+		log.info("卡密赠送开始,接受者id:{},赠送者id:{},卡密ids:{}", receiveUserId, giveUser.getId(), idsList);
+		//剩余卡密
+		int goodsCount = cardGroupGoodsMapper.selectGoodsByOrderId(giveOrderId);
+		CardGroupOrderInfo receiveOrder = buildReceiveOrder(receiveUserId, giveOrder,receiveAddress);
+		receiveOrder.setGiveUserCode(giveUser.getCode());
+		receiveOrder.setPurchaseCount((long) idsList.size());
+		cardGroupOrderInfoMapper.insertCardGroupOrderInfo(receiveOrder);
+		giveOrder.setOrderSubType(Constants.ORDER_SUB_TYPE_GIVE_AWAY);
+		List<OrderListDTO> receiveOrderList = buildGiveawayOrderList(idsList, receiveOrder, cardGroupInfo);
+		if (!receiveOrderList.isEmpty()) {
+			orderListMapper.insertOrderList(receiveOrderList);
+		}
+		List<GiveReceiveGoods> receiveGoods = buildGoodsRecord(goods, Constants.ORDER_SUB_TYPE_RECEIVE, receiveOrder.getId(),
+															   giveOrder.getId(), giveUser.getId(),cardGroupInfo.getGoodsType());
+		List<GiveReceiveGoods> giveGoods = buildGoodsRecord(goods, Constants.ORDER_SUB_TYPE_GIVE_AWAY, giveOrder.getId(),
+															receiveOrder.getId(), receiveUserId,cardGroupInfo.getGoodsType());
+		receiveGoods.addAll(giveGoods);
+		cardGroupGoodsMapper.batchInsertGiveGoods(receiveGoods);
+
+		CardGroupOrderInfo updateOrder = new CardGroupOrderInfo();
+		updateOrder.setId(giveOrder.getId());
+		updateOrder.setGiveNum(idsList.size());
+		//updateOrder.setOrderSubType(Constants.ORDER_SUB_TYPE_GIVE_AWAY);
+		updateOrder.setUpdateTime(new Date());
+		//全部赠送完毕,原订单删除
+		if (idsList.size() >= goodsCount) {
+			updateOrder.setDelFlg(1);
+			updateOrder.setStatus(302L);
+		}
+		cardGroupOrderInfoMapper.updateCardGroupOrderInfo(updateOrder);
+		CardGroupGoods cardGroupGoods = new CardGroupGoods();
+		cardGroupGoods.setUserId(receiveUserId);
+		cardGroupGoods.setUserOrderId(receiveOrder.getId().intValue());
+		cardGroupGoods.setUserNickname(receiveUser.getNickname());
+		cardGroupGoods.setUserAvatar(receiveUser.getAvatar());
+		cardGroupGoods.setLockStatus(1);
+		cardGroupGoods.setGiveFlag(1);
+		cardGroupGoodsMapper.updateByIds(cardGroupGoods, idsList);
+		log.info("卡密赠送成功记录,接受者id:{},赠送者id:{},卡密ids:{}", receiveUserId, giveUser.getId(), idsList);
+	}
+
+	private List<GiveReceiveGoods> buildGoodsRecord(List<GoodsSerialDto> goods, String type, Long orderId, Long refOrderId, Integer refUserId, Integer goodsType) {
+		List<GiveReceiveGoods> goodsList = new ArrayList<>(goods.size());
+		goods.forEach(g -> {
+			GiveReceiveGoods giveReceiveGoods = new GiveReceiveGoods();
+			giveReceiveGoods.setType(type);
+			giveReceiveGoods.setOrderId(orderId);
+			giveReceiveGoods.setCardGoodsId(g.getId().longValue());
+			giveReceiveGoods.setGoodsType(goodsType);
+			giveReceiveGoods.setRefUserId(refUserId);
+			giveReceiveGoods.setRefOrderId(refOrderId);
+			giveReceiveGoods.setSetName(g.getSetName());
+			giveReceiveGoods.setTeam(g.getTeam());
+			giveReceiveGoods.setPlayerName(g.getPlayerName());
+			giveReceiveGoods.setTeamZn(g.getTeam_zn());
+			giveReceiveGoods.setPlayerNameZn(g.getPlayerName_zn());
+			giveReceiveGoods.setSeq(g.getSeq());
+			giveReceiveGoods.setNum(g.getNum());
+			giveReceiveGoods.setNo(g.getNo());
+			goodsList.add(giveReceiveGoods);
+		});
+		return goodsList;
+	}
+
+	private List<OrderListDTO> buildGiveawayOrderList(List<Long> idsList, CardGroupOrderInfo order, CardGroupInfo cardGroupInfo) throws Exception {
+		List<OrderListDTO> orderListDTOS = new ArrayList<>(idsList.size());
+		//选队随机存在orderList子表数据
+		if (Constants.INFO_TYPE_SELECT_TEAM.equals(cardGroupInfo.getType()) && StringUtils.isEmpty(cardGroupInfo.getChangeType())) {
+			//查询orderList关联订单id
+			boolean isArea = Constants.INFO_SUB_TYPE_AREA_RANDOM.equals(cardGroupInfo.getSubType());
+			List<OrderListDTO> refOrderList = orderListMapper.selectByGoodsIds(order.getGiveOrderId(), idsList, isArea);
+			List<OrderListDTO> refOrderListDTOS = (List<OrderListDTO>) ObjectUtil.cloneList(refOrderList);
+			Map<String, OrderListDTO> orderListMap = refOrderListDTOS.stream().collect(Collectors.toMap(ol -> ol.getCardGoodsId().toString(), v -> v));
+			Map<String, OrderListDTO> orderListData = new HashMap<>();
+			idsList.forEach(id -> {
+				OrderListDTO orderListDTO = orderListMap.get(id.toString());
+				//区域随机与普通选队不一样,区域用sku_name区分,普通用skuId
+				String key = isArea ? orderListDTO.getSkuName() : orderListDTO.getSkuId().toString();
+				OrderListDTO existOrderListDTO = orderListData.get(key);
+				if (existOrderListDTO != null) {
+					existOrderListDTO.setQty(existOrderListDTO.getQty() + 1);
+				} else {
+					orderListDTO.setId(null);
+					orderListDTO.setOrderId(order.getId());
+					orderListDTO.setType(order.getOrderSubType());
+					orderListDTO.setOrderNo(order.getOrderNo());
+					orderListDTO.setQty(1L);
+					orderListDTO.setRetailPrice(BigDecimal.ZERO);
+					orderListDTO.setActPrice(BigDecimal.ZERO);
+					orderListDTO.setTotalAmount(BigDecimal.ZERO);
+					orderListDTO.setAccountsPayable(BigDecimal.ZERO);
+					orderListData.put(key, orderListDTO);
+					//orderListDTOS.add(orderListDTO);
+				}
+			});
+			orderListDTOS.addAll(orderListData.values());
+		}
+		return orderListDTOS;
+	}
+
+	private CardGroupOrderInfo buildReceiveOrder(Integer receiveUserId, CardGroupOrderInfo order, ShippingAddressDto shippingAddress) throws Exception {
+		CardGroupOrderInfo receiveOrder = ObjectUtil.clone(order);
+		receiveOrder.setId(null);
+		receiveOrder.setAppUserNickName(null);
+		receiveOrder.setAppUserAvatar(null);
+		receiveOrder.setGiveOrderId(order.getId());
+		receiveOrder.setOrderSubType(Constants.ORDER_SUB_TYPE_RECEIVE);
+		receiveOrder.setOrderNo(RandomUtil.getRandom(RandomUtil.GROUP_USER_ORDER));
+		receiveOrder.setActualPayment(BigDecimal.ZERO);
+		receiveOrder.setAccountsPayable(BigDecimal.ZERO);
+		receiveOrder.setTradeAmount(BigDecimal.ZERO);
+		receiveOrder.setCardPrice(BigDecimal.ZERO);
+		receiveOrder.setActPrice(BigDecimal.ZERO);
+		receiveOrder.setTradeNo(null);
+		receiveOrder.setUserId(receiveUserId.longValue());
+		receiveOrder.setCreateTime(new Date());
+		receiveOrder.setCoupon(null);
+		receiveOrder.setDiscount(null);
+		receiveOrder.setPaymentSubType("赠与");
+		receiveOrder.setPaymentType("赠与");
+		ShippingAddressDto shippingAddressDto = new ShippingAddressDto();
+		shippingAddressDto.setUserId(receiveUserId.intValue());
+		receiveOrder.setShippingAddressId(shippingAddress.getId().longValue());
+		receiveOrder.setShippingAddressLinkname(shippingAddress.getLinkname());
+		receiveOrder.setShippingAddress(shippingAddress.getAddress() + shippingAddress.getAddressMore());
+		receiveOrder.setShippingAddressPhone(shippingAddress.getPhone());
+		receiveOrder.setPoint(0);
+		receiveOrder.setPointType(order.getPointType());
+		return receiveOrder;
+	}
+
+	@Override
+	public AppUserInvoiceRecord openInvoiceV2(UserInfo user, Integer merchantId, Integer invoiceId, String orderIds) {
+		InvoiceOrderQuery query = new InvoiceOrderQuery().setMerchantId(merchantId).setUserId(user.getId()).setLimitTime(!checkUserInvoiceOpen(user.getId()));
+		if(StringUtils.isNotEmpty(orderIds)){
+			List<Long> orderIdList = Arrays.stream(orderIds.split(",")).map(Long::valueOf).collect(Collectors.toList());
+			query.setOrderIds(orderIdList);
+		}
+		List<SimpleOrderDTO> orderList = cardGroupOrderInfoMapper.getInvoiceOrder(query);
+		BigDecimal invoiceAmount = orderList.stream().map(SimpleOrderDTO::getInvoiceAmount).reduce(BigDecimal::add).get();
+		AppUserInvoice appUserInvoice = getAppUserInvoice(invoiceId);
+		MerchantInfo merchantInfo = merchantApiMapper.getMerchantInfo(merchantId, null);
+		AppUserInvoiceRecord invoiceRecord = new AppUserInvoiceRecord();
+		invoiceRecord.setAmount(invoiceAmount);
+		invoiceRecord.setStatus(0);
+		invoiceRecord.setMerchantId(merchantId);
+		invoiceRecord.setMerchantName(merchantInfo.getName());
+		invoiceRecord.setMerchantAvatar(merchantInfo.getAvatar());
+		invoiceRecord.setUserId(user.getId());
+		invoiceRecord.setUserName(user.getNickname());
+		invoiceRecord.setUserAvatar(user.getAvatar());
+		invoiceRecord.setInvoiceId(invoiceId);
+		invoiceRecord.setInvoiceName(appUserInvoice.getInvoiceName());
+		invoiceRecord.setTaxId(appUserInvoice.getTaxId());
+		invoiceRecord.setCreateTime(new Date());
+		userInvoiceRecordMapper.insertAppUserInvoiceRecord(invoiceRecord);
+		List<Long> invoiceOrderIds = orderList.stream().map(SimpleOrderDTO::getId).collect(Collectors.toList());
+		List<List<Long>> batchIds = BeanUtils.batchList(invoiceOrderIds, 1000);
+		batchIds.forEach(ids -> cardGroupOrderInfoMapper.updateOrderInvoiceId(ids, invoiceRecord.getId()));
+		invoiceRecord.setUserInvoice(appUserInvoice);
+		return invoiceRecord;
+	}
+
+	@Override
+	public AppUserInvoiceRecord openInvoiceV3(UserInfo user, Integer merchantId, Integer invoiceId, String orderIds, String orderType) {
+		InvoiceOrderQuery query = new InvoiceOrderQuery().setMerchantId(merchantId).setUserId(user.getId())
+				.setLimitTime(!checkUserInvoiceOpen(user.getId())).setOrderType(orderType);
+		if(StringUtils.isNotEmpty(orderIds)){
+			List<Long> orderIdList = Arrays.stream(orderIds.split(",")).map(Long::valueOf).collect(Collectors.toList());
+			query.setOrderIds(orderIdList);
+		}
+		List<SimpleOrderDTO> orderList = cardGroupOrderInfoMapper.getInvoiceOrderV3(query);
+		BigDecimal invoiceAmount = orderList.stream().map(SimpleOrderDTO::getInvoiceAmount).reduce(BigDecimal::add).get();
+		AppUserInvoice appUserInvoice = getAppUserInvoice(invoiceId);
+		MerchantInfo merchantInfo = merchantApiMapper.getMerchantInfo(merchantId, null);
+		AppUserInvoiceRecord invoiceRecord = new AppUserInvoiceRecord();
+		invoiceRecord.setAmount(invoiceAmount);
+		invoiceRecord.setStatus(0);
+		invoiceRecord.setMerchantId(merchantId);
+		invoiceRecord.setMerchantName(merchantInfo.getName());
+		invoiceRecord.setMerchantAvatar(merchantInfo.getAvatar());
+		invoiceRecord.setUserId(user.getId());
+		invoiceRecord.setUserName(user.getNickname());
+		invoiceRecord.setUserAvatar(user.getAvatar());
+		invoiceRecord.setInvoiceId(invoiceId);
+		invoiceRecord.setInvoiceName(appUserInvoice.getInvoiceName());
+		invoiceRecord.setTaxId(appUserInvoice.getTaxId());
+		invoiceRecord.setCreateTime(new Date());
+		userInvoiceRecordMapper.insertAppUserInvoiceRecord(invoiceRecord);
+		List<Long> invoiceOrderIds = orderList.stream().map(SimpleOrderDTO::getId).collect(Collectors.toList());
+		List<List<Long>> batchIds = BeanUtils.batchList(invoiceOrderIds, 1000);
+		batchIds.forEach(ids -> cardGroupOrderInfoMapper.updateOrderInvoiceId(ids, invoiceRecord.getId()));
+		invoiceRecord.setUserInvoice(appUserInvoice);
+		return invoiceRecord;
+	}
+
+	private AppUserInvoice getAppUserInvoice(Integer invoiceId) {
+		AppUserInvoice appUserInvoice = new AppUserInvoice();
+		appUserInvoice.setId(invoiceId.longValue());
+		appUserInvoice = suidRich.selectOne(appUserInvoice);
+		AppAssert.notNull(appUserInvoice, "发票信息不存在!");
+		return appUserInvoice;
+	}
+
+	@Override
+	public CardGroupOrderInfo getOrderByUserAndId(Integer userId, Long orderId) {
+		CardGroupOrderInfo order = cardGroupOrderInfoMapper.getOrderByUserAndId(userId, orderId);
+		if (StringUtils.isNotEmpty(order.getCourierNum()) && order.getRefuseStatus() != null && order.getRefuseStatus() == 4) {
+			OrderCourierRecord cond = new OrderCourierRecord();
+			cond.setOrderId(orderId);
+			cond.setStatus(103L);
+			List<OrderCourierRecord> courierRecords = orderCourierRecordMapper.selectOrderCourierRecordList(cond);
+			if (!CollectionUtils.isEmpty(courierRecords)) {
+				Set<CourierDTO> courierNumSet = courierRecords.stream().map(r -> new CourierDTO(r.getCourierCompany(), r.getCourierNum())).collect(Collectors.toSet());
+				courierNumSet.add(new CourierDTO(order.getCurierCompany(), order.getCourierNum()));
+				order.setCouriers(courierNumSet);
+			}
+		}
+		return order;
+	}
+
+	@Override
+	public CardGroupOrderInfo getOrderByUserAndGroupInfoId(Integer userId, Long groupInfoId) {
+		CardGroupOrderInfo order = cardGroupOrderInfoMapper.getOrderByUserAndGroupInfoId(userId, groupInfoId);
+		return order;
+	}
+
+	@Override
+	@Transactional(rollbackFor = Exception.class)
+	public void exchangeActGoods(List<ActGoods> goodsList, AppUserInfoDto userInfo) {
+		if (goodsList.isEmpty()) {
+			throw new ServiceException(500, "不存在兑换奖品");
+		}
+		String key = "exchange_act_goods_" + userInfo.getId();
+		if (redisUtils.hasKey(key)) {
+			throw new ServiceException(500, "操作频繁,请稍后再试!");
+		}
+		Set<Long> orderIds = goodsList.stream().map(g -> g.getUserOrderId()).collect(Collectors.toSet());
+		int receivedNums = cardGroupOrderInfoMapper.getActReceivedNum(orderIds);
+		if (receivedNums > 0) {
+			throw new ServiceException(500, "奖品已领取");
+		}
+		log.info("组团用户订单ID:{}", goodsList.get(0).getUserOrderId());
+		CardGroupOrderInfo userOrder = cardGroupOrderInfoMapper.selectCardGroupOrderInfoById(goodsList.get(0).getUserOrderId());
+		redisUtils.set(key, 1, 15);
+		List<OrderListDTO> orderLists = new ArrayList<>();
+		for (ActGoods actGoods : goodsList) {
+			if (Constants.GOODS_ACT_TYPE_GOODS.equals(actGoods.getActType())) {
+				orderLists.add(buildOrderList(actGoods));
+			} else if (Constants.GOODS_ACT_TYPE_COUPON.equals(actGoods.getActType())) {
+				appUserCardRecordService.addUserCoupon(actGoods.getActId().intValue(), userInfo.getId(), "卡密活动赠送");
+			} else if (Constants.GOODS_ACT_TYPE_TURNTABLE.equals(actGoods.getActType())) {
+				UserActTimes userActTimes = addActTimes(actGoods);
+				userActTimesMapper.insertUserActTimes(userActTimes);
+			}
+		}
+
+		List<Long> ids = goodsList.stream().map(g -> g.getId()).collect(Collectors.toList());
+		cardGroupOrderInfoMapper.updateActStatusByIds(ids);
+		if (orderLists.isEmpty()) {
+			return;
+		}
+		CardGroupOrderInfo orderInfo=buildActOrder(userOrder,(long)orderLists.size());
+		cardGroupOrderInfoMapper.insertCardGroupOrderInfo(orderInfo);
+		orderLists.forEach(orderList -> {
+			orderList.setOrderId(orderInfo.getId());
+			orderList.setOrderNo(orderInfo.getOrderNo());
+			orderList.setCreateTime(orderInfo.getCreateTime());
+			orderList.setMerchantId(orderInfo.getMerchantId());
+		});
+		orderListMapper.insertOrderList(orderLists);
+		CardGroupOrderInfo updateOrder = new CardGroupOrderInfo();
+		updateOrder.setRefundStatus(21);
+		updateOrder.setUpdateTime(orderInfo.getCreateTime());
+		cardGroupOrderInfoMapper.updateOrderByIds(updateOrder, orderIds);
+		redisUtils.del(key);
+	}
+
+	private CardGroupOrderInfo buildActOrder(CardGroupOrderInfo userOrder,Long purchaseCount){
+		CardGroupOrderInfo orderInfo = new CardGroupOrderInfo();
+		orderInfo.setOrderType(Constants.ORDER_TYPE_SHOP);
+		orderInfo.setUserId(userOrder.getUserId());
+		orderInfo.setPurchaseCount(purchaseCount);
+		orderInfo.setStatus(103L);
+		orderInfo.setMerchantId(userOrder.getMerchantId());
+		orderInfo.setOrderNo(RandomUtil.getRandom(RandomUtil.MALL_USER_ORDER));
+		orderInfo.setAccountsPayable(BigDecimal.ZERO);
+		orderInfo.setActualPayment(BigDecimal.ZERO);
+		orderInfo.setTradeAmount(BigDecimal.ZERO);
+		orderInfo.setPaymentStatus("支付成功");
+		orderInfo.setPaymentType("活动赠送");
+		orderInfo.setShippingAddressId(userOrder.getShippingAddressId());
+		orderInfo.setShippingAddressLinkname(userOrder.getShippingAddressLinkname());
+		orderInfo.setShippingAddress(userOrder.getShippingAddress());
+		orderInfo.setShippingAddressPhone(userOrder.getShippingAddressPhone());
+		orderInfo.setCreateTime(new Date());
+		orderInfo.setPaymentTime(orderInfo.getCreateTime());
+		orderInfo.setAppUserNickName(userOrder.getAppUserNickName());
+		orderInfo.setAppUserAvatar(userOrder.getAppUserAvatar());
+		return orderInfo;
+	}
+
+	private OrderListDTO buildOrderList(ActGoods actGoods) {
+		SimpleSku sku = new SimpleSku();
+		sku.setId(actGoods.getActId().longValue());
+		sku = suidRich.selectOne(sku);
+		if (sku == null) {
+			throw new ServiceException(500, "商品不存在,请联系管理员!");
+		}
+		OrderListDTO orderList = new OrderListDTO();
+		orderList.setSkuCode(sku.getCode());
+		orderList.setSkuId(sku.getId());
+		orderList.setSpuId(sku.getSpuId());
+		orderList.setSkuName(sku.getSkuName());
+		orderList.setSkuImg(sku.getCarouselImgUrl());
+		orderList.setQty(1L);
+		orderList.setBrandId(sku.getBrandId());
+		orderList.setBrandName(sku.getBrandName());
+		orderList.setSecondCatName(sku.getSecondCatName());
+		orderList.setStatus(103L);
+		orderList.setRetailPrice(BigDecimal.ZERO);
+		orderList.setActPrice(BigDecimal.ZERO);
+		orderList.setAccountsPayable(BigDecimal.ZERO);
+		orderList.setTotalAmount(BigDecimal.ZERO);
+		return orderList;
+	}
+
+	/**
+	 * 卡密增加抽奖次数
+	 * @param actGoods
+	 */
+	private UserActTimes addActTimes(ActGoods actGoods) {
+		UserActTimes userActTimes = new UserActTimes();
+		userActTimes.setActId(actGoods.getActId().longValue());
+		userActTimes.setRefType("goods");
+		userActTimes.setRefId(actGoods.getId());
+		userActTimes.setUserId(actGoods.getUserId());
+		userActTimes.setCreateTime(new Date());
+		userActTimes.setStatus(0);
+		return userActTimes;
+	}
+
+	@Override
+	public int updateOrderByIds(CardGroupOrderInfo updateOrder, Set<Long> orderIds) {
+		return cardGroupOrderInfoMapper.updateOrderByIds(updateOrder, orderIds);
+	}
+
+	@Override
+	public Map<String, BigDecimal> getActGroupAmount(Date startTime, Date endTime, Integer userId, String actType) {
+		List<String> actTypes = new ArrayList<>();
+		if (StringUtils.isNotEmpty(actType)) {
+			actTypes.add(actType);
+		}
+		return cardGroupOrderInfoMapper.getActGroupAmount(startTime, endTime, userId, actTypes);
+	}
+
+	@Override
+	public BigDecimal getActFrozenAmountV2(Date startTime, Date endTime, Integer userId) {
+		return cardGroupOrderInfoMapper.getActFrozenAmountV2(startTime, endTime, userId);
+	}
+
+	@Override
+	public BigDecimal getActConsumeAmountV2(Integer userId, String type) {
+		return cardGroupOrderInfoMapper.getActConsumeAmountV2(userId, type);
+	}
+
+	@Override
+	public Map<String, BigDecimal> getActGroupAmountByTypes(Date startTime, Date endTime, Integer userId, List<String> actTypes) {
+		return cardGroupOrderInfoMapper.getActGroupAmount(startTime, endTime,userId,actTypes);
+	}
+
+	@Override
+	public Map<String, BigDecimal> getActGroupPointByTypes(Date startTime, Date endTime, Integer userId, List<String> actTypes) {
+		return cardGroupOrderInfoMapper.getActGroupPointByTypes(startTime, endTime,userId,actTypes);
+	}
+
+	@Override
+	public List<ExpressCourierNumDTO> getExpressCourierNumDTOS(Integer orderId) {
+		OrderCourierRecord cond = new OrderCourierRecord();
+		cond.setOrderId(orderId.longValue());
+		cond.setStatus(103L);
+		List<OrderCourierRecord> courierRecords = orderCourierRecordMapper.selectOrderCourierRecordList(cond);
+		List<ExpressCourierNumDTO> courierNumDtoList;
+		if (!courierRecords.isEmpty()) {
+			courierNumDtoList = courierRecords.stream().map(r -> new ExpressCourierNumDTO(r.getId().intValue(), r.getCourierNum(), r.getCourierCompany(), r.getShippingPhone()))
+											  .collect(Collectors.toList());
+		} else {
+			courierNumDtoList = cardGroupOrderInfoMapper.getOrderExpressInfo(orderId);
+		}
+		return courierNumDtoList;
+	}
+
+	@Override
+	public JSONObject getOtherExpressInfo(ExpressCourierNumDTO courierDTO) {
+        /*courierDTO.setCurierCompanyCode(getExpressCode(courierDTO.getCurierCompany()));
+		List<ExpressInfoDetailDTO> expressInfo = expressInfoUtil.getExpressInfoNew(courierDTO);
+		if (!CollectionUtils.isEmpty(expressInfo)) {
+			return expressInfo.get(0);
+		}
+		return null;*/
+		String code = getExpressCode(courierDTO.getCurierCompany());
+		return expressInfoUtil.getExpressInfoNew(courierDTO.getId() ,courierDTO.getCourierNum(), code);
+	}
+
+	@Override
+	public List<ExpressTrailInfo> getSFExpressInfo(ExpressCourierNumDTO courierDTO) {
+		ExpressResult result = ExpressUtils.searchExpressTrail(courierDTO.getCurierCompany(), courierDTO.getCourierNum(), courierDTO.getPhone());
+		if (result.isSuccess()) {
+			List<ExpressTrailInfo> expressTrails = (List<ExpressTrailInfo>) result.get("expressTrails");
+			if (null != expressTrails) {
+				expressTrails = expressTrails.stream().sorted(Comparator.comparing(ExpressTrailInfo::getTime).reversed()).collect(Collectors.toList());
+			}
+			return expressTrails;
+		}
+		return null;
+	}
+
+	@Override
+	public ExpressInfoDetailDTO getOrderExpressInfo(Integer orderId) {
+		List<ExpressCourierNumDTO> courierNumDtoList = cardGroupOrderInfoMapper.getOrderExpressInfo(orderId);
+		if (CollectionUtils.isEmpty(courierNumDtoList)) {
+			return null;
+		}
+		courierNumDtoList.forEach(c -> c.setCurierCompanyCode(getExpressCode(c.getCurierCompany())));
+		List<ExpressInfoDetailDTO> detailDtoList = expressInfoUtil.getExpressInfo(courierNumDtoList);
+		if (CollectionUtils.isEmpty(detailDtoList)) {
+			return null;
+		}
+		return detailDtoList.get(0);
+	}
+
+
+	private String getExpressCode(String curierCompany) {
+		if (StringUtils.isEmpty(curierCompany)) {
+			return null;
+		}
+		SysDictData sysDictData = new SysDictData();
+		sysDictData.setDictType("Express");
+		sysDictData.setDictLabel(curierCompany);
+		List<SysDictData> codes = dictDataService.selectDictDataList(sysDictData);
+		if(CollectionUtils.isEmpty(codes)){
+			return null;
+		}
+		return codes.get(0).getDictValue();
+	}
+
+	//更新签收订单状态
+	@Override
+	public int confirmSignNew(Integer id, Date closePaymentTime){
+		CardGroupOrderInfo order = cardGroupOrderInfoMapper.selectCardGroupOrderInfoById(id.longValue());
+		if(Constants.ORDER_TYPE_SHOP.equals(order.getOrderType())){
+			List<Long> filterId = cardGroupOrderInfoMapper.checkVerifOrders(Collections.singletonList(id.longValue()));
+			if(!CollectionUtils.isEmpty(filterId)){
+				return 0;
+			}
+			asyncAppService.addPointByMallOrder(order);
+			//计算打款时间(签收后5个工作日)
+			if(!Constants.payment_type.contains(order.getPaymentType())) {
+				Date afterNumWorkDay = null;
+				try {
+					afterNumWorkDay = DateUtils.getNumWorkDayByNow(new Date(), 5);
+				} catch (ParseException e) {
+					e.printStackTrace();
+				}
+				return cardGroupOrderInfoMapper.confirmSignNew(id, afterNumWorkDay);
+			}
+			// 商城订单完结
+			Map<String, Object> param = ImmutableMap.of("type", Constants.TYPE_SHOP_POINT, "orderId", order.getId());
+			MqUtils.sendMq(MqConstans.QUEUE_ORDER_OVER, JSONTools.obj2json(param));
+		}
+		int i = cardGroupOrderInfoMapper.confirmSign(id);
+		if(i>0){
+			//签收成功 发送mq到 分佣服务
+			asyncAppService.sendPromotionOrderMq(Long.valueOf(id));
+		}
+		return i;
+	}
+
+
+	@Override
+	public CardGroupOrderInfo isHasEditAddress(List<Long> orderIds) {
+		return cardGroupOrderInfoMapper.isHasEditAddressOrder(orderIds);
+	}
+
+	@Override
+	public void updateAddressByIds(CardGroupOrderInfo orderInfo, List<Long> ids) {
+		cardGroupOrderInfoMapper.updateAddressByIds(orderInfo,ids);
+	}
+
+	@Override
+	public List<Long> getOrderIds(OrderQuery query) {
+		return cardGroupOrderInfoMapper.getOrderIds(query);
+	}
+
+	@Override
+	public PageInfo<ReceiveGoodsDTO> getGiveReceiveOrder(Integer userId, String type, String keyword, Integer pageNo, Integer pageSize) {
+		PageHelper.startPage(pageNo, pageSize,"grg.create_time desc");
+		List<ReceiveGoodsDTO> giveReceiveOrder=cardGroupOrderInfoMapper.getGiveReceiveOrder(userId,type,keyword);
+		return new PageInfo<>(giveReceiveOrder);
+	}
+
+	@Override
+	public void expireUnPayOrder(Long groupInfoId) {
+		cardGroupOrderInfoMapper.expireUnPayOrder(groupInfoId);
+	}
+
+	@Override
+	public Integer selectUserOrderNums(Integer userId, Long infoId) {
+		return cardGroupOrderInfoMapper.selectUserOrderNums(userId,infoId);
+	}
+
+	@Override
+	public List<SimpleUserShipDTO> getShippedCardByUser(NonEmptyQuery nonEmptyQuery) {
+		return cardGroupOrderInfoMapper.getShippedCardByUser(nonEmptyQuery);
+	}
+
+	@Override
+	public int returnCouponByOrderId(Long orderId) {
+		return appUserCardRecordMapper.returnCouponByOrderId(orderId);
+	}
+
+	@Override
+	public List<SimpleUserMerchant> getUserGiftCard(Integer userId, Integer pageSize, Integer offset) {
+		return cardGroupOrderInfoMapper.getUserGiftCard(userId,pageSize,offset);
+	}
+
+	@Override
+	public List<SimpleUserShipDTO> getNonEmptyCardByUserV3(NonEmptyQuery nonEmptyQuery) {
+		List<SimpleUserShipDTO> nonEmptyCardByUser = cardGroupOrderInfoMapper.getNonEmptyCardByUserV3(nonEmptyQuery);
+		nonEmptyCardByUser.forEach(u -> u.setOrderIds(cardGroupOrderInfoMapper.getNonEmptyOrderIdByUserV2(u.getId(),nonEmptyQuery.getMerchantId(),u.getAddressId(),u.getCardId())));
+		return nonEmptyCardByUser;
+	}
+
+	@Override
+	public int updateOrderCourierByOrderIds(CardGroupOrderInfo orderInfo, List<Long> orderIdList) {
+		return cardGroupOrderInfoMapper.updateOrderCourierByOrderIds(orderInfo,orderIdList);
+	}
+
+	@Override
+	public List<SimpleUserShipDTO> getWaitApplyUserCards(NonEmptyQuery query) {
+		return cardGroupOrderInfoMapper.getWaitApplyUserCards(query);
+	}
+
+	@Override
+	public CardGroupOrderInfo getRefShopOrderId(Long id) {
+		return cardGroupOrderInfoMapper.getRefShopOrderId(id);
+	}
+
+	@Override
+	public int changeMallOrderToShipment(Long infoId) {
+		return cardGroupOrderInfoMapper.changeMallOrderToShipment(infoId);
+	}
+
+	@Override
+	public boolean checkIsMerchantOrder(List<Long> orderIdList, Integer merchantId) {
+		return cardGroupOrderInfoMapper.checkIsMerchantOrder(orderIdList,merchantId)!=null;
+	}
+
+	@Override
+	public List<GroupUserOrderDto> getUserWaitShippingOrder(ShippingQuery query) {
+		return cardGroupOrderInfoMapper.getUserWaitShippingOrder(query);
+	}
+
+	@Override
+	public List<RefundReqDTO> getUserRefundReq(Integer userId) {
+		return cardGroupOrderInfoMapper.getUserRefundReq(userId);
+	}
+
+	@Override
+	@Transactional(rollbackFor = Exception.class,isolation = Isolation.READ_COMMITTED)
+	public int checkRefundReq(Integer userId, Integer groupInfoId, int serverStatus) {
+		return cardGroupOrderInfoMapper.checkOrderRefundReq(userId, groupInfoId, serverStatus);
+	}
+
+	@Override
+	public List<InvoiceMerchantDTO> getInvoiceMerchant(Integer userId,Integer merchantId, boolean isLimit) {
+		return cardGroupOrderInfoMapper.getInvoiceMerchant(userId,merchantId,isLimit);
+	}
+
+	@Override
+	public List<InvoiceMerchantDTO> getInvoiceMerchantV3(Integer userId, Integer merchantId, boolean isLimit, String orderType) {
+		return cardGroupOrderInfoMapper.getInvoiceMerchantV3(userId,merchantId,isLimit,orderType);
+	}
+
+	@Override
+	public PageInfo<InvoiceMerchantDTO> getInvoiceMerchantV4(InvoiceMerchantQuery invoiceMerchantQuery) {
+		PageHelper.startPage(invoiceMerchantQuery.getPageNo(),invoiceMerchantQuery.getPageSize());
+		List<InvoiceMerchantDTO> invoiceMerchantV4 = cardGroupOrderInfoMapper.getInvoiceMerchantV4(invoiceMerchantQuery);
+		return new PageInfo<>(invoiceMerchantV4);
+	}
+
+	@Override
+	public PageInfo<SimpleOrderDTO> getMerchantInvoiceOrderV3(InvoiceOrderQuery query) {
+		PageHelper.startPage(query.getPageNo(), query.getPageSize(),"id desc");
+		List<SimpleOrderDTO> orderList = cardGroupOrderInfoMapper.getInvoiceOrderV3(query);
+		return new PageInfo<>(orderList);
+	}
+
+	@Override
+	public PageInfo<SimpleOrderDTO> getMerchantInvoiceOrder(InvoiceOrderQuery query) {
+		PageHelper.startPage(query.getPageNo(), query.getPageSize(),"id desc");
+		List<SimpleOrderDTO> orderList = cardGroupOrderInfoMapper.getInvoiceOrder(query);
+		return new PageInfo<>(orderList);
+	}
+
+	@Override
+	public PageInfo<SimpleOrderDTO> getEcologyOrder(Integer pageNo, Integer pageSize, Integer userId) {
+		PageHelper.startPage(pageNo, pageSize, "id desc");
+		List<SimpleOrderDTO> orderList = cardGroupOrderInfoMapper.getEcologyOrder(userId);
+		return new PageInfo<>(orderList);
+	}
+
+	@Override
+	public BigDecimal getEcologyAmount(Integer userId) {
+		return cardGroupOrderInfoMapper.getEcologyAmount(userId);
+	}
+
+	/**
+	 * 用户开票限制
+	 * @param userId
+	 * @return
+	 */
+	@Override
+	public boolean checkUserInvoiceOpen(Integer userId) {
+		return checkUserHasAppCat(userId, "user_order", "open_invoice");
+	}
+
+	@Override
+	public boolean checkUserHasAppCat(Integer userId, String type, String containValue) {
+		String key = String.format(Constants.USER_CONTAINS_CAT_KEY_PRE, userId, type,containValue);
+		if (redisUtils.hasKey(key)) {
+			return true;
+		}
+		List<String> userCats = commonCacheService.getUserCatsByType(userId, type);
+		if (CollectionUtils.isEmpty(userCats)) {
+			return false;
+		}
+		boolean hasVal = userCats.contains(containValue);
+		if (hasVal) {
+			redisUtils.set(key, 1, Constants.dayForSecond);
+		}
+		return hasVal;
+	}
+
+	@Override
+	public String getPointTypeByOrderId(Long id) {
+		return cardGroupOrderInfoMapper.getPointTypeByOrderId(id);
+	}
+
+	@Override
+	public Long getArchivesIdByOrderId(Long id) {
+		return cardGroupOrderInfoMapper.getArchivesIdByOrderId(id);
+	}
+
+	@Override
+	public UserAmountDTO getUserOrderAmount(Integer userId) {
+		return cardGroupOrderInfoMapper.getUserOrderAmount(userId);
+	}
+
+	@Override
+	public UserPayNoticeDTO preOrderRecommendAmount(Integer userId) {
+		String dayNoticeKey = String.format(Constants.USER_LIMIT_PAY_NOTICE_KEY, DateUtils.getDate(), userId);
+		AppUserInfoDto user = mineApiService.searchUserInfoById(userId);
+		UserAmountDTO userAmount = getUserOrderAmount(userId);
+		boolean questionnaireAble = questionnaireMapper.hasUserQuestionnaire(userId, user.getMemberLevel()) == null;
+		Long questionnaireId=null;
+		if (questionnaireAble) {
+			Questionnaire questionnaire = questionnaireMapper.getLastQuestionnaire(Constants.TYPE_USER_INCR_AMOUNT, null,user.getMemberLevel());
+			questionnaireId = questionnaire != null ? questionnaire.getId() : null;
+		}
+		LimitAmountConfig.MemberAmount userExtraLimitAmount = getUserExtraLimitAmount(user.getMemberLevel(), user.getRegisterTime());
+		long monthlyLimit = (user.getMonthlyLimit() + userExtraLimitAmount.getAmount()) * 100L;
+		String mgs;
+		if (userAmount.getMonthAmount().doubleValue() >= monthlyLimit) {
+			mgs = questionnaireAble ? String.format(NoticeMsgModel.USER_PAY_QUESTION_NOTICE, userAmount.getMonthAmount()) :
+					String.format(NoticeMsgModel.USER_PAY_LIMIT_NOTICE, userAmount.getMonthAmount());
+			return new UserPayNoticeDTO(true,UserPayNoticeDTO.LIMIT_NOTICE, mgs, questionnaireAble,questionnaireId);
+		}
+		boolean isNoticeByDay = redisUtils.hasKey(dayNoticeKey);
+		if (isNoticeByDay) {
+			// 今日已提示
+			return new UserPayNoticeDTO();
+		}
+		long dailyLimit =  (user.getDailyLimit() + userExtraLimitAmount.getDailyLimit()) * 100L;
+		long weeklyLimit = (user.getWeeklyLimit() + userExtraLimitAmount.getWeeklyLimit()) * 100L;
+		boolean needNotice = (dailyLimit > 0 && userAmount.getDailyAmount().doubleValue() >= dailyLimit)
+				|| (weeklyLimit > 0 && userAmount.getWeekAmount().doubleValue() >= weeklyLimit);
+		if (needNotice && userAmount.getMonthAmount().compareTo(new BigDecimal(500)) >= 0) { // 月消费金额低于500不提醒
+			mgs = String.format(NoticeMsgModel.USER_PAY_NOTICE, userAmount.getMonthAmount());
+			redisUtils.set(dayNoticeKey, 1, Constants.dayForSecond);
+			return new UserPayNoticeDTO(true,UserPayNoticeDTO.DAY_NOTICE, mgs, questionnaireAble,questionnaireId);
+		}
+		return new UserPayNoticeDTO();
+	}
+
+	@Override
+	public UserPayNoticeDTO preOrderRecommendAmount2(Integer userId) {
+		UserAmountDTO userAmount = getUserOrderAmount(userId);
+		// 用户消费总额
+		double monthAmount = userAmount.getMonthAmount().doubleValue();
+		// 查询用户是否跳过答题固定额度
+		AppUserDetailInfo appUserDetailInfo = appUserDetailInfoMapper.getByUserId(userId);
+		// 设置了固定额度
+		if(appUserDetailInfo != null && appUserDetailInfo.getConsumeLimit() == 1){
+			// 查询最后一次提额
+			int newMonthlyLimit = questionnaireMapper.getLastNewMonthlyLimit(userId.longValue()) * 100;
+			// 用户月消费总额超过了固定额度
+			if(monthAmount >= newMonthlyLimit) {
+				String mgs = String.format(NoticeMsgModel.USER_PAY_LIMIT_NOTICE, newMonthlyLimit);
+				return new UserPayNoticeDTO(true, UserPayNoticeDTO.LIMIT_NOTICE, mgs, false, null);
+			}
+		}
+
+		String dayNoticeKey = String.format(Constants.USER_LIMIT_PAY_NOTICE_KEY, DateUtils.getDate(), userId);
+		AppUserInfoDto user = mineApiService.searchUserInfoById(userId);
+		LimitAmountConfig.MemberAmount userExtraLimitAmount = getUserExtraLimitAmount(user.getMemberLevel(), user.getRegisterTime());
+		// 月消费总额度
+		long monthlyLimit = (user.getMonthlyLimit() + userExtraLimitAmount.getAmount()) * 100L;
+		// 是否达到消费限额
+		boolean overLimit = monthAmount >= monthlyLimit;
+		String mgs;
+		Long questionnaireId = null;
+		boolean questionnaireAble = false;
+		if(overLimit){
+			questionnaireAble = questionnaireMapper.hasUserQuestionnaire(userId, user.getMemberLevel()) == null;
+			if (questionnaireAble) {
+				Questionnaire questionnaire = questionnaireMapper.getLastQuestionnaire(Constants.TYPE_USER_INCR_AMOUNT, null,user.getMemberLevel());
+				questionnaireId = questionnaire != null ? questionnaire.getId() : null;
+			}
+			mgs = questionnaireAble ? String.format(NoticeMsgModel.USER_PAY_QUESTION_NOTICE, monthAmount) :
+					String.format(NoticeMsgModel.USER_PAY_LIMIT_NOTICE, monthAmount);
+			return new UserPayNoticeDTO(true,UserPayNoticeDTO.LIMIT_NOTICE, mgs, questionnaireAble,questionnaireId);
+		}
+		boolean isNoticeByDay = redisUtils.hasKey(dayNoticeKey);
+		if (isNoticeByDay) {
+			// 今日已提示
+			return new UserPayNoticeDTO();
+		}
+		long dailyLimit =  (user.getDailyLimit() + userExtraLimitAmount.getDailyLimit()) * 100L;
+		long weeklyLimit = (user.getWeeklyLimit() + userExtraLimitAmount.getWeeklyLimit()) * 100L;
+		boolean needNotice = (dailyLimit > 0 && userAmount.getDailyAmount().doubleValue() >= dailyLimit)
+				|| (weeklyLimit > 0 && userAmount.getWeekAmount().doubleValue() >= weeklyLimit);
+		if (needNotice && userAmount.getMonthAmount().compareTo(new BigDecimal(500)) >= 0) { // 月消费金额低于500不提醒
+			mgs = String.format(NoticeMsgModel.USER_PAY_NOTICE, monthAmount);
+			redisUtils.set(dayNoticeKey, 1, Constants.dayForSecond);
+			return new UserPayNoticeDTO(true,UserPayNoticeDTO.DAY_NOTICE, mgs, questionnaireAble,questionnaireId);
+		}
+		return new UserPayNoticeDTO();
+	}
+
+	@Override
+	public LimitAmountConfig.MemberAmount getUserExtraLimitAmount(Integer memberLevel, Date registerTime) {
+		List<SysDictData> config = dictDataService.selectDictDataByCache(Constants.USER_LIMIT_PAY_CONFIG, null, "1", true);
+		if (CollectionUtils.isEmpty(config)) {
+			return new LimitAmountConfig.MemberAmount();
+		}
+		try {
+			LimitAmountConfig limitAmountConfig = JSONTools.jsonStr2obj(config.get(0).getDictValue(), LimitAmountConfig.class);
+			assert limitAmountConfig != null;
+			boolean isNewUser = isNewAppUser(registerTime);
+			LimitAmountConfig.MemberAmount memberAmount = limitAmountConfig.getMemberAmount().stream().filter(m -> memberLevel >= m.getMember())
+					.max(Comparator.comparing(LimitAmountConfig.MemberAmount::getMember)).orElse(new LimitAmountConfig.MemberAmount());
+			if (isNewUser) {
+				memberAmount.setAmount(memberAmount.getAmount() + limitAmountConfig.getNewUserAmount());
+				memberAmount.setDailyLimit(memberAmount.getDailyLimit() + limitAmountConfig.getNewUserDayAmount());
+				memberAmount.setWeeklyLimit(memberAmount.getWeeklyLimit() + limitAmountConfig.getNewUserWeekAmount());
+			}
+			return memberAmount;
+		} catch (Exception e) {
+			log.error("用户消费限额解析配置异常");
+		}
+		return new LimitAmountConfig.MemberAmount();
+	}
+
+	@Override
+	public List<SimpleMerchantInfo> getUserCostCardMerchant(Integer userId, boolean payed) {
+		return cardGroupOrderInfoMapper.selectPointCardMerchant(userId,payed);
+	}
+
+	@Override
+	public  PageInfo<CostOrderDTO> userCostCardOrders(OrderQuery orderQuery) {
+		PageHelper.startPage(orderQuery.getPageNo(), orderQuery.getPageSize()," o.id desc");
+		List<CostOrderDTO> orders=cardGroupOrderInfoMapper.selectPointCardOrders(orderQuery);
+		return new PageInfo<>(orders);
+	}
+
+	@Override
+	public int getCardNum(Integer userId, List<Long> idList) {
+		OrderQuery orderQuery = new OrderQuery().setUserId(userId).setOrderIds(idList).setPayed(false);
+		List<CostOrderDTO> orders = cardGroupOrderInfoMapper.selectPointCardOrders(orderQuery);
+		if(orders.size()!=idList.size()){
+			throw new ServiceException(MsgConstants.PARAM_EMPTY);
+		}
+		return orders.stream().mapToInt(CostOrderDTO::getPurchaseCount).sum();
+	}
+
+	@Override
+	@RedisLock(lockKey = "gift_card_order_lock_+#{payParam.userId}",isUseTran = true,waitTime = 1,leaseTime = 10)
+	public ShippingPayResult cardShippingPayNew(ShippingPayParam payParam) {
+		log.info("用户申请精美卡片发货,参数:{}", payParam);
+		if(ShippingPayParam.CARD_TYPE_GIFT.equals(payParam.getCardType())){
+			return giftCardShippingPay(payParam);
+		}
+		String shipOrderNo = RandomUtil.getRandom(RandomUtil.CARD_SHIPPING_ORDER);
+		BigDecimal totalCost = payParam.getTotalCost();
+		Long refOrderId = payParam.getOrderIds().get(0);
+
+		CardGroupOrderInfo orderInfo = new CardGroupOrderInfo();
+		orderInfo.setShippingTradeNo(shipOrderNo);
+		orderInfo.setShippingCost(totalCost);
+		ShippingPayResult result = new ShippingPayResult().setPrice(totalCost).setTotalCount(payParam.getShippingNum()).setOrderId(refOrderId);
+		return result;
+	}
+
+	private ShippingPayResult giftCardShippingPay(ShippingPayParam payParam) {
+		return null;
+	}
+
+
+	@Override
+	public boolean selectMerchantNoticePointOrder(Integer merchantId) {
+		return cardGroupOrderInfoMapper.selectMerchantNoticePointOrder(merchantId) != null;
+	}
+
+	@Override
+	public boolean selectUserNoticePointOrder(Integer id) {
+		return cardGroupOrderInfoMapper.selectUserNoticePointOrder(id) != null;
+	}
+
+	@Override
+	public void checkOrderInfoStatus(List<Long> idList) {
+		Long infoId = cardGroupOrderInfoMapper.selectUnPublicGroup(idList);
+		if (infoId != null) {
+			throw new ServiceException("存在未公示的拼团关联订单,请取消相关订单再申请");
+		}
+	}
+
+	@Override
+	public List<OrderStatusDTO> getOrderInfoStatus(List<Long> idList) {
+		List<OrderStatusDTO> orderStatusDTOS = cardGroupOrderInfoMapper.selectOrderStatusByIDs(idList);
+		for (OrderStatusDTO orderStatusDTO : orderStatusDTOS) {
+			orderStatusDTO.setStatusMsg(com.tzy.sportcard.enums.GroupOrderStatusEnums.getByCode(orderStatusDTO.getStatus()).name());
+			orderStatusDTO.setStatusDesc(com.tzy.sportcard.enums.GroupOrderStatusEnums.getMsg(orderStatusDTO.getStatus()));
+			if(orderStatusDTO.getGroupStatus()!=null){
+				orderStatusDTO.setGroupStatusMsg(GroupInfoStatusEnums.getByCode(orderStatusDTO.getGroupStatus()).name());
+				orderStatusDTO.setGroupStatusDesc(GroupInfoStatusEnums.getMsg(orderStatusDTO.getGroupStatus()));
+			}
+		}
+		return  orderStatusDTOS;
+	}
+
+	@Override
+	public ChecklistConfigDto getOneOrderSkuUnit(Long orderId) {
+		return cardGroupOrderInfoMapper.getOneOrderSkuUnit(orderId);
+	}
+
+	@Override
+	public int updateInvoice(Long userId) {
+		return cardGroupOrderInfoMapper.updateInvoice(userId);
+	}
+
+	@Override
+	public ShippingPayResult cardShippingPayV2(ShippingPayParam payParam) {
+		String shipOrderNo = RandomUtil.getRandom(RandomUtil.CARD_SHIPPING_ORDER);
+		BigDecimal totalCost = payParam.getTotalCost();
+		Long refOrderId = payParam.getOrderIds().get(0);
+		CardGroupOrderInfo orderInfo = new CardGroupOrderInfo();
+		orderInfo.setShippingTradeNo(shipOrderNo);
+		orderInfo.setShippingCost(totalCost);
+		ShippingPayResult result = new ShippingPayResult().setPrice(totalCost).setTotalCount(payParam.getShippingNum()).setOrderId(refOrderId);
+		if (totalCost.doubleValue() > 0) {
+			try {
+				String payType = payParam.getPayType();
+				String tradeNo = shipOrderNo;
+				payParam.setOrderNo(tradeNo);//设置订单编码
+				payParam.setAmount(totalCost);//设置支付金额
+				String paySubType = checkPayCat(payParam);
+				if(StringUtils.isBlank(paySubType)){
+					throw new ServiceException(500, "未配置支付方式!");
+				}
+				//获取支付参数
+				JSONObject payData = getPayData(tradeNo, totalCost, paySubType);
+				if (!payData.getBoolean("success")) {
+					throw new ServiceException(500, "唤起支付失败,请重试!");
+				}
+				JSONObject resultObject = payData.getJSONObject("result");
+				Object merOrderId = resultObject.get("merOrderId");
+				if (merOrderId != null && StringUtils.isNotEmpty(merOrderId.toString())) {
+					tradeNo = merOrderId.toString();
+				}
+				String paymentSubType = resultObject.get("paymentSubType") != null ? resultObject.get("paymentSubType")
+																								 .toString() : null;
+				addPayRecord(payType, paymentSubType, tradeNo, refOrderId, shipOrderNo, totalCost);
+				cardGroupOrderInfoMapper.updateOrderByIds(orderInfo, new HashSet<>(payParam.getOrderIds()));
+				//记录id集合,回调时用
+				String ids = payParam.getOrderIds()
+									 .stream()
+									 .map(String::valueOf)
+									 .collect(Collectors.joining(","));
+				redisUtils.set(Constants.COST_ORDER_RECORD + shipOrderNo, ids, 3600);
+				result.setPayWay(resultObject.get("payWay").toString())
+					  .setResult(resultObject.get("result"));
+			}catch (Exception e) {
+				log.error("[配送支付]配送支付异常:{}",e);
+				throw new ServiceException(500, "唤起支付失败,请重试!");
+			}
+		}else {
+			orderInfo.setStatus(103L);
+			orderInfo.setPaymentType("包邮");
+			orderInfo.setServeStatus(120);
+			cardGroupOrderInfoMapper.updateOrderByIds(orderInfo,new HashSet<>(payParam.getOrderIds()));
+			log.info("精美卡片申请发货订单编号:{},参数:{},",orderInfo.getOrderNo(),payParam);
+			result.setPayWay("free");
+		}
+		return result;
+	}
+
+	private JSONObject getPayData( String orderNo, BigDecimal price, String payType)  {
+		try {
+			JSONObject param = new JSONObject();
+			param.put("category", "gift_card");
+			param.put("userType", "App");
+			param.put("orderNo", orderNo);
+			param.put("totalAmount", price);
+			param.put("body", "快递费");
+			param.put("payWay", payType);
+			IpAddrDTO ipAddr = commonCacheService.getIpAddr();
+			param.put("createip", Objects.nonNull(ipAddr) ? ipAddr.getAddr() : "192.168.1.10");
+			param.put("createOrderTime", DateUtils.dateTimeNow(DateUtils.YYYY_MM_DD_HH_MM_SS));
+			param.put("expireTime", DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, DateUtils.addCalendar(new Date(), DateUtils.minute, 30)));//30分钟后过期
+			String ret = HttpClientUtil.create()
+									   .uri(unifiedV2Uri, HttpMethod.POST)
+									   .entity(param)
+									   .header(header())
+									   .build()
+									   .execute();
+			return JSONObject.parseObject(ret);
+		}catch (Exception e) {
+			log.error("[配送支付]获取支付参数异常:{}",e);
+			return new JSONObject().fluentPut("success", false);
+		}
+	}
+
+	private String checkPayCat(ShippingPayParam payParam){
+		String payType = "";
+		try {
+			//获取支付渠道列表
+			JSONObject payTypeParam = new JSONObject();
+			payTypeParam.put("payType", payParam.getPayType());
+			payTypeParam.put("category", "gift_card");
+//        payTypeParam.put("point",getAppUserInfo().getPoint());
+			payTypeParam.put("point", 100);
+			payTypeParam.put("currentHour", DateUtils.getCurrentHour());
+			String payTypeRet = HttpClientUtil.create()
+											  .uri(payTypeUrl, HttpMethod.POST)
+											  .entity(payTypeParam)
+											  .header(header())
+											  .build()
+											  .execute();
+			if (StringUtils.isBlank(payTypeRet)) {
+				return null;
+			}
+			JSONObject payTypeJson = JSONObject.parseObject(payTypeRet);
+			if (payTypeJson.getBoolean("success")) {
+				JSONArray data = payTypeJson.getJSONArray("data");
+				if (CollectionUtils.isEmpty(data)) {
+					throw new ServiceException("未设置支付配置!");
+				}
+				//获取支付通道
+				List<String> paySubTypes = (List<String>) data.stream()
+															  .map(obj -> JSONObject.parseObject(JSONObject.toJSONString(obj))
+																					.getString("code"))
+															  .filter(Objects::nonNull)
+															  .collect(Collectors.toList());
+				if (CollectionUtils.isEmpty(paySubTypes)) {
+					throw new ServiceException("未设置支付配置!");
+				}
+				Collections.shuffle(paySubTypes);
+				payType = paySubTypes.get(0);
+			} else {
+				return null;
+			}
+		}catch (Exception e) {
+			log.error("[配送支付]获取支付渠道异常:{}",e);
+			return null;
+		}
+		return payType;
+	}
+
+
+	private Map<String,String> header(){
+		Map<String,String> header = new HashMap<>();
+		header.put("Content-Type", "application/json");
+		return header;
+	}
+
+}