| | |
| | | package com.taoke.autopay.service.impl; |
| | | |
| | | import com.taoke.autopay.dao.KeyOrderMapper; |
| | | import com.taoke.autopay.entity.KeyOrder; |
| | | import com.taoke.autopay.entity.OrderDistributeCountInfo; |
| | | import com.taoke.autopay.dao.WxUserSettingsMapper; |
| | | import com.taoke.autopay.dto.ChannelOrderStatistic; |
| | | import com.taoke.autopay.dto.DYOrderDto; |
| | | import com.taoke.autopay.entity.*; |
| | | import com.taoke.autopay.entity.agent.ChannelAgent; |
| | | import com.taoke.autopay.entity.agent.ChannelAgentSettings; |
| | | import com.taoke.autopay.exception.KeyOrderException; |
| | | import com.taoke.autopay.exception.KeyVerifyException; |
| | | import com.taoke.autopay.exception.WxOrderCountException; |
| | | import com.taoke.autopay.factory.OrderFactory; |
| | | import com.taoke.autopay.service.KeyOrderService; |
| | | import com.taoke.autopay.service.*; |
| | | import com.taoke.autopay.service.agent.ChannelAgentService; |
| | | import com.taoke.autopay.service.agent.ChannelAgentSettingService; |
| | | import com.taoke.autopay.service.agent.ChannelAgentSharingRatioService; |
| | | import com.taoke.autopay.utils.*; |
| | | import com.taoke.autopay.utils.order.DYOrderApi; |
| | | import com.taoke.autopay.utils.order.OrderChannelUtil; |
| | | import com.taoke.autopay.vo.SubmitKeyInfo; |
| | | import net.sf.json.JSONArray; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | |
| | | import javax.annotation.Resource; |
| | | import java.util.Comparator; |
| | | import java.util.Date; |
| | | import java.util.List; |
| | | import java.math.BigDecimal; |
| | | import java.net.URI; |
| | | import java.util.*; |
| | | import java.util.regex.Matcher; |
| | | import java.util.regex.Pattern; |
| | | |
| | | /** |
| | | * @author hxh |
| | |
| | | @Resource |
| | | private KeyOrderMapper keyOrderMapper; |
| | | |
| | | @Resource |
| | | private WxUserSettingService wxUserSettingService; |
| | | |
| | | @Resource |
| | | private WxUserOrderCountService wxUserOrderCountService; |
| | | |
| | | @Resource |
| | | private SystemConfigService systemConfigService; |
| | | |
| | | @Resource |
| | | private ChannelAgentService channelAgentService; |
| | | |
| | | @Resource |
| | | private ChannelAgentSharingRatioService channelAgentSharingRatioService; |
| | | |
| | | @Resource |
| | | private ChannelAgentSettingService channelAgentSettingService; |
| | | |
| | | @Resource |
| | | private ClientInfoService clientInfoService; |
| | | |
| | | @Resource |
| | | private PayMoneySettingService payMoneySettingService; |
| | | |
| | | |
| | | @Override |
| | | public KeyOrder selectById(String id) { |
| | | return keyOrderMapper.selectById(id); |
| | | } |
| | | |
| | | @Transactional(rollbackFor = Exception.class) |
| | | @Override |
| | | public KeyOrder addKeyOrder(String key) throws KeyOrderException { |
| | | String id = OrderFactory.createId(key); |
| | | KeyOrder order = keyOrderMapper.selectById(id); |
| | | if(order!=null){ |
| | | throw new KeyOrderException("请勿重复提交口令"); |
| | | public KeyOrder addKeyOrder(SubmitKeyInfo keyInfo, Long uid, String day, Integer orderType, DYOrderDto orderDto) throws KeyOrderException, WxOrderCountException { |
| | | // 判断提交次数是否过量 |
| | | if (uid != null) { |
| | | WxUserSettings settings = wxUserSettingService.getUserSettings(uid); |
| | | OrderCountTypeEnum countType = OrderCountTypeEnum.SUBMIT_TOKEN_COUNT; |
| | | wxUserOrderCountService.addOrderCount(uid, countType,null, day, 1, settings.getTotalOrderCountPerDay()); |
| | | } |
| | | order =new KeyOrder(); |
| | | String id = OrderFactory.createId(keyInfo.getKey()); |
| | | KeyOrder order = keyOrderMapper.selectById(id); |
| | | if (order != null) { |
| | | throw new KeyOrderException("请勿重复提交口令"); |
| | | } |
| | | order = new KeyOrder(); |
| | | // 解析referer中的链接 |
| | | if (!StringUtil.isNullOrEmpty(keyInfo.getReferer())) { |
| | | Map<String, String> paramsMap = HttpUtil.getPramsFromUrl(keyInfo.getReferer()); |
| | | if (paramsMap.containsKey("a")) { |
| | | String alias = paramsMap.get("a"); |
| | | ChannelAgent agent = channelAgentService.selectByAlias(alias); |
| | | if (agent == null) { |
| | | throw new KeyOrderException("渠道不存在"); |
| | | } |
| | | |
| | | if (agent.getStatus() != ChannelAgent.STATUS_NOMAL) { |
| | | throw new KeyOrderException("渠道受限"); |
| | | } |
| | | // 验证渠道时间 |
| | | ChannelAgentSettings settings = channelAgentSettingService.selectByAgentId(agent.getId()); |
| | | if(settings!=null&&!StringUtil.isNullOrEmpty(settings.getStartSubmitTime())&&!StringUtil.isNullOrEmpty(settings.getEndSubmitTime())){ |
| | | String now = TimeUtil.getGernalTime(System.currentTimeMillis(), "HHmmss"); |
| | | String startTime = settings.getStartSubmitTime().replace(":",""); |
| | | String endTime = settings.getEndSubmitTime().replace(":",""); |
| | | if (Integer.parseInt(now) < Integer.parseInt(startTime) || Integer.parseInt(now) > Integer.parseInt(endTime)) { |
| | | throw new KeyOrderException(String.format("口令提交时间段为:%s-%s",settings.getStartSubmitTime(), settings.getEndSubmitTime())); |
| | | } |
| | | } |
| | | |
| | | order.setAgentId(agent.getId()); |
| | | } |
| | | } |
| | | |
| | | |
| | | order.setId(id); |
| | | order.setKey(key); |
| | | order.setKey(keyInfo.getKey()); |
| | | if (!StringUtil.isNullOrEmpty(keyInfo.getMoney())) { |
| | | order.setOrderMoney(new BigDecimal(keyInfo.getMoney())); |
| | | } |
| | | order.setUid(uid); |
| | | order.setState(KeyOrder.STATE_NOT_PROCESS); |
| | | order.setStateDesc("尚未处理"); |
| | | order.setCreateTime(new Date()); |
| | | if(orderType!=Constant.ORDER_TYPE_UNKNOWN){ |
| | | order.setOrderType(orderType); |
| | | } |
| | | if (orderDto != null) { |
| | | order.setOrderNo(orderDto.getOrder_id()); |
| | | } |
| | | |
| | | keyOrderMapper.insertSelective(order); |
| | | |
| | | |
| | | return order; |
| | | } |
| | | |
| | |
| | | |
| | | @Transactional(rollbackFor = Exception.class) |
| | | @Override |
| | | public void setOrderInfo(String id,String orderNo, int orderState) throws KeyOrderException{ |
| | | public void paySuccess(String id, String stateDesc, String day,String payMerchant) throws WxOrderCountException { |
| | | KeyOrder old = keyOrderMapper.selectByPrimaryKeyForUpdate(id); |
| | | if (old == null) { |
| | | throw new KeyOrderException("口令不存在"); |
| | | return; |
| | | } |
| | | KeyOrder keyOrder=new KeyOrder(); |
| | | if (old.getState() == KeyOrder.STATE_PAY) { |
| | | return; |
| | | } |
| | | if (old.getUid() != null) { |
| | | Integer orderType = old.getOrderType(); |
| | | wxUserOrderCountService.addOrderCount(old.getUid(), (orderType==null||orderType==Constant.ORDER_TYPE_DY)? OrderCountTypeEnum.DY_ORDER_PAY:OrderCountTypeEnum.KS_ORDER_PAY, OrderChannelUtil.getChannelByKey( old.getOrderChannel()), day, 1, null); |
| | | } |
| | | KeyOrder orderUpdate = new KeyOrder(); |
| | | orderUpdate.setId(id); |
| | | orderUpdate.setState(KeyOrder.STATE_PAY); |
| | | orderUpdate.setStateDesc(stateDesc); |
| | | orderUpdate.setPayMerchant(payMerchant); |
| | | if (old.getPayTime() == null) { |
| | | orderUpdate.setPayTime(new Date()); |
| | | } |
| | | update(orderUpdate); |
| | | } |
| | | |
| | | @Transactional(rollbackFor = Exception.class) |
| | | @Override |
| | | public void setOrderInfo(String id, String orderNo, int orderState) throws KeyOrderException { |
| | | KeyOrder old = keyOrderMapper.selectByPrimaryKeyForUpdate(id); |
| | | if (old == null) { |
| | | throw new KeyOrderException("口令不存在"); |
| | | } |
| | | KeyOrder keyOrder = new KeyOrder(); |
| | | keyOrder.setId(id); |
| | | // 默认1抖音 |
| | | keyOrder.setOrderType(1); |
| | |
| | | } |
| | | |
| | | @Override |
| | | public Long getCanDistributeUid() { |
| | | List<OrderDistributeCountInfo> list = keyOrderMapper.listDistributeUids(); |
| | | if(list==null||list.size()==0){ |
| | | public List<KeyOrder> listWithUser(KeyOrderMapper.DaoQuery query) { |
| | | return keyOrderMapper.listWithUser(query); |
| | | } |
| | | |
| | | @Override |
| | | public long countWithUser(KeyOrderMapper.DaoQuery query) { |
| | | return keyOrderMapper.countWithUser(query); |
| | | } |
| | | |
| | | @Override |
| | | public ChannelOrderStatistic statisticWithUser(KeyOrderMapper.DaoQuery query) { |
| | | Map<OrderChannelEnum, BigDecimal> shareMoneyMap = channelAgentSharingRatioService.getShareMoneyMap(query.agentId); |
| | | List<ChannelOrderStatistic> channelOrderStatisticList = keyOrderMapper.statisticChannelOrders(query); |
| | | BigDecimal totalMoney = new BigDecimal(0); |
| | | long totalOrderCount = 0; |
| | | for (ChannelOrderStatistic s : channelOrderStatisticList) { |
| | | |
| | | for (OrderChannelEnum channel : OrderChannelEnum.values()) { |
| | | if (channel.getKey().equalsIgnoreCase(s.getOrderChannel())) { |
| | | |
| | | if (shareMoneyMap.containsKey(channel)) { |
| | | totalMoney = totalMoney.add(shareMoneyMap.get(channel).multiply(new BigDecimal(s.getCount()))); |
| | | } |
| | | break; |
| | | } |
| | | } |
| | | totalOrderCount += s.getCount(); |
| | | } |
| | | long userCount = keyOrderMapper.countUser(query); |
| | | ChannelOrderStatistic statistic = new ChannelOrderStatistic(); |
| | | statistic.setUserCount(userCount); |
| | | statistic.setMoney(totalMoney); |
| | | statistic.setCount(totalOrderCount); |
| | | return statistic; |
| | | } |
| | | |
| | | @Override |
| | | public List<ChannelOrderStatistic> statisticChannelOrders(Long agentId, Date startTime, Date endTime) { |
| | | KeyOrderMapper.DaoQuery daoQuery = new KeyOrderMapper.DaoQuery(); |
| | | daoQuery.minCreateTime = startTime; |
| | | daoQuery.maxCreateTime = endTime; |
| | | daoQuery.agentId = agentId; |
| | | daoQuery.state = KeyOrder.STATE_PAY; |
| | | daoQuery.hasPayTime = true; |
| | | // 将数据拉出来 |
| | | long count = keyOrderMapper.count(daoQuery); |
| | | daoQuery.count = (int)count; |
| | | List<KeyOrder> orderList = keyOrderMapper.list(daoQuery); |
| | | Map<String,Set<Long>> uidsMap = new HashMap<>(); |
| | | Map<String,Integer> countMap = new HashMap<>(); |
| | | Map<String,BigDecimal> moneyMap = new HashMap<>(); |
| | | |
| | | Set<String> orderIds=new HashSet<>(); |
| | | for(KeyOrder order:orderList){ |
| | | String orderId=order.getOrderType()+"#"+ order.getOrderNo(); |
| | | if(!StringUtil.isNullOrEmpty(order.getOrderNo())){ |
| | | if(orderIds.contains(orderId)){ |
| | | continue; |
| | | } |
| | | orderIds.add(orderId); |
| | | } |
| | | String orderChannel = order.getOrderChannel(); |
| | | |
| | | if(!uidsMap.containsKey(orderChannel)){ |
| | | uidsMap.put(orderChannel, new HashSet<>()); |
| | | } |
| | | uidsMap.get(orderChannel).add(order.getUid()); |
| | | |
| | | if(!countMap.containsKey(orderChannel)){ |
| | | countMap.put(orderChannel,0); |
| | | } |
| | | countMap.put(orderChannel, countMap.get(orderChannel)+1); |
| | | |
| | | |
| | | if(!moneyMap.containsKey(orderChannel)){ |
| | | moneyMap.put(orderChannel, new BigDecimal(0)); |
| | | } |
| | | moneyMap.put(orderChannel, moneyMap.get(orderChannel).add(order.getOrderMoney())); |
| | | } |
| | | |
| | | List<ChannelOrderStatistic> results=new ArrayList<>(); |
| | | for(String orderChannel: moneyMap.keySet()){ |
| | | ChannelOrderStatistic statistic=new ChannelOrderStatistic(); |
| | | statistic.setCount(countMap.get(orderChannel)); |
| | | statistic.setMoney(moneyMap.get(orderChannel)); |
| | | statistic.setUserCount(uidsMap.get(orderChannel).size()); |
| | | statistic.setOrderChannel(orderChannel); |
| | | results.add(statistic); |
| | | } |
| | | return results; |
| | | } |
| | | |
| | | |
| | | @Override |
| | | public Long getCanDistributeUid(int maxQueueSize) { |
| | | // 最近1小时有活跃,且不算12以上未执行的数据 |
| | | List<OrderDistributeCountInfo> list = keyOrderMapper.listDistributeUids(new Date(System.currentTimeMillis() - 1000 * 60 * 31L), new Date(System.currentTimeMillis() - 1000 * 60 * 60 * 12L)); |
| | | if (list == null || list.size() == 0) { |
| | | return null; |
| | | } |
| | | Comparator<OrderDistributeCountInfo> cm = (OrderDistributeCountInfo o1, OrderDistributeCountInfo o2)-> o1.getCount()-o2.getCount(); |
| | | list.sort(cm); |
| | | return list.get(0).getUid(); |
| | | // 排除重新分配的设备 |
| | | List<Long> excludeIds = clientInfoService.getRePayClientIds(); |
| | | for (int i = 0; i < list.size(); i++) { |
| | | if (excludeIds.contains(list.get(i).getUid())) { |
| | | list.remove(i); |
| | | i--; |
| | | } |
| | | } |
| | | List<OrderDistributeCountInfo> filterList = new ArrayList<>(); |
| | | // count小于2直接视为0 |
| | | for (OrderDistributeCountInfo info : list) { |
| | | if (info.getCount() >= maxQueueSize) { |
| | | continue; |
| | | } |
| | | filterList.add(info); |
| | | } |
| | | if (filterList.size() <= 0) { |
| | | return null; |
| | | } |
| | | |
| | | return ClientDistributeUtil.computeDistributeClient(filterList); |
| | | } |
| | | |
| | | @Override |
| | | public List<KeyOrder> listNotDistributed(int page, int pageSize) { |
| | | return keyOrderMapper.listNotDistributed((page-1)*pageSize,pageSize); |
| | | return keyOrderMapper.listNotDistributed((page - 1) * pageSize, pageSize); |
| | | } |
| | | |
| | | @Override |
| | | public void deleteAll(Date maxCreateTime) { |
| | | keyOrderMapper.deleteAll(maxCreateTime); |
| | | } |
| | | |
| | | @Override |
| | | public DYOrderDto verifyKey(String orderNoDesc, String orderStatus, String money, Long uid, String keyId) throws KeyVerifyException { |
| | | int orderType = AlipayOrderUtil.getOrderType(orderNoDesc); |
| | | if (uid != null) { |
| | | WxUserSettings settings = wxUserSettingService.getUserSettings(uid); |
| | | OrderCountTypeEnum orderCountType = OrderCountTypeEnum.SUBMIT_TOKEN_COUNT; |
| | | int maxCount = settings.getTotalOrderCountPerDay(); |
| | | switch (orderType) { |
| | | case Constant.ORDER_TYPE_DY: |
| | | orderCountType = OrderCountTypeEnum.DY_ORDER_PAY; |
| | | maxCount = settings.getDyOrderCountPerDay(); |
| | | break; |
| | | case Constant.ORDER_TYPE_KS: |
| | | orderCountType = OrderCountTypeEnum.KS_ORDER_PAY; |
| | | maxCount = settings.getKsOrderCountPerDay(); |
| | | break; |
| | | } |
| | | } |
| | | |
| | | |
| | | String orderNo = ""; |
| | | // 匹配连续的数字 |
| | | Pattern pattern = Pattern.compile("\\d+"); |
| | | Matcher matcher = pattern.matcher(orderNoDesc); |
| | | while (matcher.find()) { |
| | | // 获取匹配到的数字字符串 |
| | | String number = matcher.group(); |
| | | if (number.length() > 10) { |
| | | orderNo = number; |
| | | break; |
| | | } |
| | | } |
| | | |
| | | if (orderType == Constant.ORDER_TYPE_UNKNOWN) { |
| | | throw new KeyVerifyException(KeyVerifyException.CODE_ORDER_TYPE_ERROR, "未定义的订单类型"); |
| | | } |
| | | |
| | | if (!StringUtil.isNullOrEmpty(orderStatus) && !orderStatus.contains("未支付")) { |
| | | throw new KeyVerifyException(KeyVerifyException.CODE_ORDER_STATUS_ERROR, "订单状态:" + orderStatus); |
| | | } |
| | | DYOrderDto dyOrderDto = null; |
| | | // 先匹配订单 |
| | | try { |
| | | if (orderType == Constant.ORDER_TYPE_DY && !StringUtil.isNullOrEmpty(orderNo)) { |
| | | dyOrderDto = DYOrderApi.getOrderDetail(orderNo); |
| | | if (dyOrderDto != null && false) { |
| | | // 验证金额 |
| | | if (dyOrderDto.getPay_amount().intValue() != new BigDecimal(money).multiply(new BigDecimal(100)).setScale(0).intValue()) { |
| | | throw new KeyVerifyException(KeyVerifyException.CODE_ORDER_MONEY_NOT_MATCH, String.format("支付金额与订单金额不一致:%s-%d", money, dyOrderDto.getPay_amount())); |
| | | } |
| | | // 验证订单号是否已经存在 |
| | | KeyOrderMapper.DaoQuery query = new KeyOrderMapper.DaoQuery(); |
| | | query.orderNo = orderNo; |
| | | query.orderType = orderType; |
| | | if (count(query) > 1) { |
| | | throw new KeyVerifyException(KeyVerifyException.CODE_ORDER_NO_REPEAT, "订单号重复提交"); |
| | | } |
| | | } |
| | | } else { |
| | | throw new KeyOrderException("抖音订单获取失败"); |
| | | } |
| | | } catch (KeyOrderException e) { |
| | | // 抖音订单未验证通过,匹配金额 |
| | | // 验证提交的金额是否正确 |
| | | Set<String> moneySet =payMoneySettingService.listAllMoneyAsStr(); |
| | | // 匹配金额 |
| | | if (!moneySet.contains(money)) { |
| | | throw new KeyVerifyException(KeyVerifyException.CODE_KEY_MONEY_NOT_MATCH, String.format("金额未在系统设置中:%s", money)); |
| | | } |
| | | } |
| | | |
| | | return dyOrderDto; |
| | | } |
| | | |
| | | @Override |
| | | public void removeDistributedClient(String id) { |
| | | keyOrderMapper.removeDistributedClient(id); |
| | | } |
| | | |
| | | @Override |
| | | public List<Long> listAgentId(KeyOrderMapper.DaoQuery query) { |
| | | return keyOrderMapper.listAgentId(query); |
| | | } |
| | | |
| | | @Override |
| | | public long countAgentId(KeyOrderMapper.DaoQuery query) { |
| | | return keyOrderMapper.countAgentId(query); |
| | | } |
| | | } |