|  | @@ -0,0 +1,243 @@
 | 
	
		
			
				|  |  | +package com.zanxiang.game.module.sdk.service.impl;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 | 
	
		
			
				|  |  | +import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
 | 
	
		
			
				|  |  | +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 | 
	
		
			
				|  |  | +import com.github.sd4324530.jtuple.Tuple2;
 | 
	
		
			
				|  |  | +import com.zanxiang.game.back.base.ServerInfo;
 | 
	
		
			
				|  |  | +import com.zanxiang.game.back.base.pojo.dto.TtAppOrderBackQueryRpcDTO;
 | 
	
		
			
				|  |  | +import com.zanxiang.game.back.base.pojo.vo.OrderBackQueryRpcVO;
 | 
	
		
			
				|  |  | +import com.zanxiang.game.back.base.rpc.ITtAppBackRpc;
 | 
	
		
			
				|  |  | +import com.zanxiang.game.module.mybatis.entity.Agent;
 | 
	
		
			
				|  |  | +import com.zanxiang.game.module.mybatis.entity.GameBackLogMediaSdk;
 | 
	
		
			
				|  |  | +import com.zanxiang.game.module.mybatis.entity.User;
 | 
	
		
			
				|  |  | +import com.zanxiang.game.module.mybatis.entity.UserEvent;
 | 
	
		
			
				|  |  | +import com.zanxiang.game.module.mybatis.mapper.GameBackLogMediaSdkMapper;
 | 
	
		
			
				|  |  | +import com.zanxiang.game.module.sdk.constant.RedisKeyConstant;
 | 
	
		
			
				|  |  | +import com.zanxiang.game.module.sdk.enums.CallBackTypeEnum;
 | 
	
		
			
				|  |  | +import com.zanxiang.game.module.sdk.pojo.dto.PlatformOrderDTO;
 | 
	
		
			
				|  |  | +import com.zanxiang.game.module.sdk.pojo.param.BackLogMediaSdkParam;
 | 
	
		
			
				|  |  | +import com.zanxiang.game.module.sdk.pojo.param.CallBackControlParam;
 | 
	
		
			
				|  |  | +import com.zanxiang.game.module.sdk.pojo.param.UserData;
 | 
	
		
			
				|  |  | +import com.zanxiang.game.module.sdk.service.*;
 | 
	
		
			
				|  |  | +import com.zanxiang.module.redis.service.IDistributedLockComponent;
 | 
	
		
			
				|  |  | +import com.zanxiang.module.util.JsonUtil;
 | 
	
		
			
				|  |  | +import lombok.extern.slf4j.Slf4j;
 | 
	
		
			
				|  |  | +import org.apache.dubbo.config.annotation.DubboReference;
 | 
	
		
			
				|  |  | +import org.apache.logging.log4j.util.Strings;
 | 
	
		
			
				|  |  | +import org.springframework.beans.factory.annotation.Autowired;
 | 
	
		
			
				|  |  | +import org.springframework.stereotype.Service;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +import java.time.LocalDateTime;
 | 
	
		
			
				|  |  | +import java.util.*;
 | 
	
		
			
				|  |  | +import java.util.concurrent.TimeUnit;
 | 
	
		
			
				|  |  | +import java.util.stream.Collectors;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/**
 | 
	
		
			
				|  |  | + * @author : lingfeng
 | 
	
		
			
				|  |  | + * @time : 2022-11-10
 | 
	
		
			
				|  |  | + * @description : 媒体sdk回传日志
 | 
	
		
			
				|  |  | + */
 | 
	
		
			
				|  |  | +@Slf4j
 | 
	
		
			
				|  |  | +@Service
 | 
	
		
			
				|  |  | +public class GameBackLogMediaSdkServiceImpl extends ServiceImpl<GameBackLogMediaSdkMapper, GameBackLogMediaSdk> implements IGameBackLogMediaSdkService {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    @DubboReference(providedBy = ServerInfo.SERVER_DUBBO_NAME)
 | 
	
		
			
				|  |  | +    private ITtAppBackRpc ttAppBackRpc;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    @Autowired
 | 
	
		
			
				|  |  | +    private IAgentService agentService;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    @Autowired
 | 
	
		
			
				|  |  | +    private IUserService userService;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    @Autowired
 | 
	
		
			
				|  |  | +    private IOrderService orderService;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    @Autowired
 | 
	
		
			
				|  |  | +    private IDistributedLockComponent distributedLockComponent;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    @Autowired
 | 
	
		
			
				|  |  | +    private IUserEventService userEventService;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    @Override
 | 
	
		
			
				|  |  | +    public Map<String, Object> callBackJudge(CallBackControlParam param, UserData userData) {
 | 
	
		
			
				|  |  | +        Map<String, Object> resultMap = new HashMap<>(7);
 | 
	
		
			
				|  |  | +        resultMap.put("callBackTypeEnum", param.getCallBackTypeEnum().getValue());
 | 
	
		
			
				|  |  | +        resultMap.put("userId", userData.getUserId());
 | 
	
		
			
				|  |  | +        resultMap.put("gameId", userData.getGameId());
 | 
	
		
			
				|  |  | +        resultMap.put("callBack", Boolean.FALSE);
 | 
	
		
			
				|  |  | +        //参数判断是否齐全
 | 
	
		
			
				|  |  | +        Tuple2<Boolean, String> backParamCheck = this.callBackParamCheck(param, resultMap);
 | 
	
		
			
				|  |  | +        if (!backParamCheck.first) {
 | 
	
		
			
				|  |  | +            resultMap.put("backMsg", backParamCheck.second);
 | 
	
		
			
				|  |  | +            return resultMap;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        //判断是否过事件行为, 全量回传
 | 
	
		
			
				|  |  | +        Tuple2<Boolean, List<Integer>> userEventTuple = this.userEventTest(userData, param.getOrderId());
 | 
	
		
			
				|  |  | +        if (userEventTuple.first) {
 | 
	
		
			
				|  |  | +            resultMap.put("callBack", Boolean.TRUE);
 | 
	
		
			
				|  |  | +            if (CollectionUtils.isNotEmpty(userEventTuple.second)) {
 | 
	
		
			
				|  |  | +                resultMap.put("amount", userEventTuple.second);
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            return resultMap;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        //查询玩家, 判断玩家是否存在渠道, 不存在渠道则不回传
 | 
	
		
			
				|  |  | +        User user = userService.getById(userData.getUserId());
 | 
	
		
			
				|  |  | +        Agent agent = agentService.getById(user.getAgentId());
 | 
	
		
			
				|  |  | +        if (agent == null) {
 | 
	
		
			
				|  |  | +            return resultMap;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        //线程锁
 | 
	
		
			
				|  |  | +        String lockKey = this.getLockKey(param, userData.getUserId());
 | 
	
		
			
				|  |  | +        //上锁
 | 
	
		
			
				|  |  | +        if (!distributedLockComponent.doLock(lockKey, 0L, 1L, TimeUnit.MINUTES)) {
 | 
	
		
			
				|  |  | +            log.error("重复请求触发线程锁, 直接返回false, lockKey : {}", lockKey);
 | 
	
		
			
				|  |  | +            return resultMap;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        try {
 | 
	
		
			
				|  |  | +            //判断回传
 | 
	
		
			
				|  |  | +            this.checkCallBack(user.getId(), agent, param.getCallBackTypeEnum(), resultMap, param);
 | 
	
		
			
				|  |  | +        } catch (Exception e) {
 | 
	
		
			
				|  |  | +            log.error("事件回传判断, 出现异常, param : {},  userData : {}, e : {}", JsonUtil.toString(param),
 | 
	
		
			
				|  |  | +                    JsonUtil.toString(userData), e.getMessage(), e);
 | 
	
		
			
				|  |  | +        } finally {
 | 
	
		
			
				|  |  | +            distributedLockComponent.unlock(lockKey);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        //返回结果
 | 
	
		
			
				|  |  | +        return resultMap;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    private String getLockKey(CallBackControlParam param, Long userId) {
 | 
	
		
			
				|  |  | +        //回传枚举
 | 
	
		
			
				|  |  | +        CallBackTypeEnum callBackTypeEnum = param.getCallBackTypeEnum();
 | 
	
		
			
				|  |  | +        //线程锁
 | 
	
		
			
				|  |  | +        String lockKey = RedisKeyConstant.CALL_BACK_JUDGE_LOCK + callBackTypeEnum.getValue() + "_" + userId;
 | 
	
		
			
				|  |  | +        if (Strings.isNotBlank(param.getRoleId())) {
 | 
	
		
			
				|  |  | +            lockKey = lockKey + "_" + param.getRoleId();
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        if (Strings.isNotBlank(param.getOrderId())) {
 | 
	
		
			
				|  |  | +            lockKey = lockKey + "_" + param.getOrderId();
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        return lockKey;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    private Tuple2<Boolean, String> callBackParamCheck(CallBackControlParam param, Map<String, Object> resultMap) {
 | 
	
		
			
				|  |  | +        CallBackTypeEnum callBackTypeEnum = param.getCallBackTypeEnum();
 | 
	
		
			
				|  |  | +        //创角和新手引导回传, 必须传角色id
 | 
	
		
			
				|  |  | +        if (Objects.equals(callBackTypeEnum, CallBackTypeEnum.CALL_BACK_ACTIVATE)
 | 
	
		
			
				|  |  | +                || Objects.equals(callBackTypeEnum, CallBackTypeEnum.CALL_BACK_TUTORIAL_FINISH)) {
 | 
	
		
			
				|  |  | +            if (Strings.isBlank(param.getRoleId())) {
 | 
	
		
			
				|  |  | +                return Tuple2.with(Boolean.FALSE, "参数错误, 创角或新手引导回传, 必须传角色id");
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            resultMap.put("roleId", param.getRoleId());
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        //付费回传, 必须传订单id
 | 
	
		
			
				|  |  | +        if (Objects.equals(callBackTypeEnum, CallBackTypeEnum.CALL_BACK_PAY_ORDER)) {
 | 
	
		
			
				|  |  | +            if (Strings.isBlank(param.getOrderId())) {
 | 
	
		
			
				|  |  | +                return Tuple2.with(Boolean.FALSE, "参数错误, 付费回传, 必须传订单id");
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            resultMap.put("orderId", param.getOrderId());
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        return Tuple2.with(Boolean.TRUE, null);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    private Tuple2<Boolean, List<Integer>> userEventTest(UserData userData, String orderId) {
 | 
	
		
			
				|  |  | +        Boolean callBack = Boolean.FALSE;
 | 
	
		
			
				|  |  | +        List<Integer> amountList = null;
 | 
	
		
			
				|  |  | +        //查询玩家
 | 
	
		
			
				|  |  | +        User user = userService.getById(userData.getUserId());
 | 
	
		
			
				|  |  | +        //判断是否测试过事件用户
 | 
	
		
			
				|  |  | +        if (userEventService.count(new LambdaQueryWrapper<UserEvent>()
 | 
	
		
			
				|  |  | +                .eq(UserEvent::getGameId, userData.getGameId())
 | 
	
		
			
				|  |  | +                .and(qw -> qw.eq(UserEvent::getUsername, user.getUsername())
 | 
	
		
			
				|  |  | +                        .or().eq(UserEvent::getUsername, user.getOpenId())
 | 
	
		
			
				|  |  | +                        .or().eq(UserEvent::getMobile, user.getMobile())
 | 
	
		
			
				|  |  | +                )
 | 
	
		
			
				|  |  | +        ) > 0) {
 | 
	
		
			
				|  |  | +            callBack = Boolean.TRUE;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        //判断是否订单回传
 | 
	
		
			
				|  |  | +        if (callBack && Strings.isNotBlank(orderId)) {
 | 
	
		
			
				|  |  | +            PlatformOrderDTO platformOrderDTO = orderService.getByOrderId(orderId);
 | 
	
		
			
				|  |  | +            if (platformOrderDTO != null) {
 | 
	
		
			
				|  |  | +                amountList = Collections.singletonList(platformOrderDTO.getAmount().intValue());
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        //返回结果
 | 
	
		
			
				|  |  | +        return Tuple2.with(callBack, amountList);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    private void checkCallBack(Long userId, Agent agent, CallBackTypeEnum callBackTypeEnum, Map<String, Object> resultMap,
 | 
	
		
			
				|  |  | +                               CallBackControlParam param) {
 | 
	
		
			
				|  |  | +        switch (callBackTypeEnum) {
 | 
	
		
			
				|  |  | +            case CALL_BACK_LOGIN_IN:
 | 
	
		
			
				|  |  | +                break;
 | 
	
		
			
				|  |  | +            case CALL_BACK_REGISTER:
 | 
	
		
			
				|  |  | +            case CALL_BACK_ACTIVATE:
 | 
	
		
			
				|  |  | +            case CALL_BACK_CREATE_ROLE:
 | 
	
		
			
				|  |  | +            case CALL_BACK_UPDATE_LEVEL:
 | 
	
		
			
				|  |  | +            case CALL_BACK_ADD_TO_WISHLIST:
 | 
	
		
			
				|  |  | +            case CALL_BACK_ON_SHARE_TIME_LINE:
 | 
	
		
			
				|  |  | +            case CALL_BACK_ON_SHARE_APP_MESSAGE:
 | 
	
		
			
				|  |  | +            case CALL_BACK_VIEW_CONTENT_MALL:
 | 
	
		
			
				|  |  | +            case CALL_BACK_VIEW_CONTENT_ACTIVITY:
 | 
	
		
			
				|  |  | +                resultMap.put("callBack", Boolean.TRUE);
 | 
	
		
			
				|  |  | +                break;
 | 
	
		
			
				|  |  | +            case CALL_BACK_RE_ACTIVE:
 | 
	
		
			
				|  |  | +                //沉默唤起
 | 
	
		
			
				|  |  | +                resultMap.put("callBack", Boolean.TRUE);
 | 
	
		
			
				|  |  | +                break;
 | 
	
		
			
				|  |  | +            case CALL_BACK_TUTORIAL_FINISH:
 | 
	
		
			
				|  |  | +                //完成新手引导
 | 
	
		
			
				|  |  | +                resultMap.put("callBack", Boolean.TRUE);
 | 
	
		
			
				|  |  | +                break;
 | 
	
		
			
				|  |  | +            case CALL_BACK_PAY_ORDER:
 | 
	
		
			
				|  |  | +                TtAppOrderBackQueryRpcDTO orderTransform = this.transform(userId, param.getOrderId(), agent);
 | 
	
		
			
				|  |  | +                OrderBackQueryRpcVO orderBackQueryRpcVO = ttAppBackRpc.orderBackQuery(orderTransform).getData();
 | 
	
		
			
				|  |  | +                resultMap.put("orderId", param.getOrderId());
 | 
	
		
			
				|  |  | +                resultMap.put("callBack", orderBackQueryRpcVO.getDoBack());
 | 
	
		
			
				|  |  | +                resultMap.put("backMsg", orderBackQueryRpcVO.getBackMsg());
 | 
	
		
			
				|  |  | +                if (Objects.equals(orderBackQueryRpcVO.getDoBack(), Boolean.TRUE)) {
 | 
	
		
			
				|  |  | +                    //传过来的金额是分, 换算成元, 存在小数直接舍弃
 | 
	
		
			
				|  |  | +                    List<Long> backMoney = orderBackQueryRpcVO.getBackMoney()
 | 
	
		
			
				|  |  | +                            .stream().map(money -> money / 100)
 | 
	
		
			
				|  |  | +                            .collect(Collectors.toList());
 | 
	
		
			
				|  |  | +                    resultMap.put("amount", backMoney);
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +                break;
 | 
	
		
			
				|  |  | +            default:
 | 
	
		
			
				|  |  | +                resultMap.put("backMsg", "未知的回传类型");
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    @Override
 | 
	
		
			
				|  |  | +    public boolean addMediaSdkBackLog(BackLogMediaSdkParam param, UserData userData) {
 | 
	
		
			
				|  |  | +        return super.save(this.transform(param, userData));
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    private GameBackLogMediaSdk transform(BackLogMediaSdkParam param, UserData userData) {
 | 
	
		
			
				|  |  | +        return GameBackLogMediaSdk.builder()
 | 
	
		
			
				|  |  | +                .gameId(userData.getGameId())
 | 
	
		
			
				|  |  | +                .userId(userData.getUserId())
 | 
	
		
			
				|  |  | +                .callBackTypeEnum(param.getCallBackTypeEnum().getValue())
 | 
	
		
			
				|  |  | +                .callBackJudgeResult(JsonUtil.toString(param.getCallBackJudgeResult()))
 | 
	
		
			
				|  |  | +                .callBackParam(JsonUtil.toString(param.getCallBackParam()))
 | 
	
		
			
				|  |  | +                .errorMsg(param.getErrorMsg())
 | 
	
		
			
				|  |  | +                .createTime(LocalDateTime.now())
 | 
	
		
			
				|  |  | +                .build();
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    private TtAppOrderBackQueryRpcDTO transform(Long userId, String orderId, Agent agent) {
 | 
	
		
			
				|  |  | +        return TtAppOrderBackQueryRpcDTO.builder()
 | 
	
		
			
				|  |  | +                .gameId(agent.getGameId())
 | 
	
		
			
				|  |  | +                .userId(userId.toString())
 | 
	
		
			
				|  |  | +                .orderId(orderId)
 | 
	
		
			
				|  |  | +                .agentKey(agent.getAgentKey())
 | 
	
		
			
				|  |  | +                .build();
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 |