diff --git a/ff-base/src/main/java/com/ff/base/enums/ErrorCode.java b/ff-base/src/main/java/com/ff/base/enums/ErrorCode.java index ddb5bb7..89bfeb4 100644 --- a/ff-base/src/main/java/com/ff/base/enums/ErrorCode.java +++ b/ff-base/src/main/java/com/ff/base/enums/ErrorCode.java @@ -30,6 +30,7 @@ public enum ErrorCode { ACCOUNT_NOT_ONLINE(1014, "账号不在线"), FREQUENT_BALANCE_TRANSFER(1015, "当前游戏账号余额转移频繁"), PLATFORM_NOT_METHODS(1016, "游戏平台不支持的方法"), + DUPLICATE_ORDER_ID (1017, "重复的订单id"), ; // 获取错误码 diff --git a/ff-base/src/main/java/com/ff/base/enums/GameExchangeStep.java b/ff-base/src/main/java/com/ff/base/enums/GameExchangeStep.java index 2f13939..31257c4 100644 --- a/ff-base/src/main/java/com/ff/base/enums/GameExchangeStep.java +++ b/ff-base/src/main/java/com/ff/base/enums/GameExchangeStep.java @@ -15,10 +15,20 @@ import lombok.Getter; @AllArgsConstructor public enum GameExchangeStep { CREATE_ORDER(1, "创建订单"), - PLATFORM_TRANSACTION(2, "平台交易成功"), - PLATFORM_TRANSACTION_CONFIRM(3, "平台交易状态确认"), - TENANT_QUOTA_DEDUCTED(4, "租户额度扣减成功"); + DEDUCT_BALANCE(2, "转入提前扣租户余额"), + PLATFORM_TRANSACTION(3, "平台交易成功"), + TENANT_QUOTA_DEDUCTED(4, "转出租户额度增加成功"); - private final int code; + private final Integer code; private final String description; + + // 根据 code 获取对应的枚举 + public static GameExchangeStep getByCode(int code) { + for (GameExchangeStep step : GameExchangeStep.values()) { + if (step.getCode() == code) { + return step; + } + } + return null; + } } diff --git a/ff-base/src/main/java/com/ff/base/enums/GamePlatforms.java b/ff-base/src/main/java/com/ff/base/enums/GamePlatforms.java index 89a6973..5036923 100644 --- a/ff-base/src/main/java/com/ff/base/enums/GamePlatforms.java +++ b/ff-base/src/main/java/com/ff/base/enums/GamePlatforms.java @@ -1,5 +1,7 @@ package com.ff.base.enums; +import com.ff.base.exception.base.ApiException; + import java.util.ArrayList; import java.util.List; @@ -25,6 +27,20 @@ public enum GamePlatforms { this.info = info; } + /** + * 通过代码获取 + * + * @param code 代码 + * @return {@link GamePlatforms } + */ + public static GamePlatforms getByCode(String code) { + for (GamePlatforms platform : GamePlatforms.values()) { + if (platform.getCode().equals(code)) { + return platform; + } + } + throw new ApiException(ErrorCode.PLATFORM_NOT_EXIST.getCode()); + } public static List getCodes() { List result = new ArrayList<>(); diff --git a/ff-base/src/main/java/com/ff/base/enums/TimeOutType.java b/ff-base/src/main/java/com/ff/base/enums/TimeOutType.java new file mode 100644 index 0000000..d1ea786 --- /dev/null +++ b/ff-base/src/main/java/com/ff/base/enums/TimeOutType.java @@ -0,0 +1,25 @@ +package com.ff.base.enums; + +import com.alibaba.druid.filter.AutoLoad; +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * 超时类型 + * + * @author shi + * @date 2025/04/09 + */ +@AllArgsConstructor +@Getter +public enum TimeOutType { + GAME_EXCHANGE_MONEY("gameExchangeMoney", "游戏余额转移"); + /** + * 代码 + */ + private final String code; + /** + * 信息 + */ + private final String info; +} diff --git a/ff-base/src/main/java/com/ff/base/enums/TriggerType.java b/ff-base/src/main/java/com/ff/base/enums/TriggerType.java new file mode 100644 index 0000000..86edf54 --- /dev/null +++ b/ff-base/src/main/java/com/ff/base/enums/TriggerType.java @@ -0,0 +1,21 @@ +package com.ff.base.enums; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.Getter; + +/** + * 触发类型 + * + * @author shi + * @date 2025/04/09 + */ +@Getter +@AllArgsConstructor +public enum TriggerType { + MANUAL(1, "用户调用手动触发"), + TIMER(2, "定时器触发"); + + private final int code; + private final String description; +} diff --git a/ff-base/src/main/java/com/ff/base/manager/AsyncManager.java b/ff-base/src/main/java/com/ff/base/manager/AsyncManager.java index 4e2458f..c68be3c 100644 --- a/ff-base/src/main/java/com/ff/base/manager/AsyncManager.java +++ b/ff-base/src/main/java/com/ff/base/manager/AsyncManager.java @@ -2,11 +2,12 @@ package com.ff.base.manager; import com.ff.base.utils.Threads; import com.ff.base.utils.spring.SpringUtils; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; + +import java.util.ArrayList; +import java.util.List; import java.util.TimerTask; -import java.util.concurrent.Callable; -import java.util.concurrent.Future; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; +import java.util.concurrent.*; /** * 异步任务管理器 @@ -24,10 +25,33 @@ public class AsyncManager { */ private ScheduledExecutorService executor = SpringUtils.getBean("scheduledExecutorService"); + + /** + * 顺序执行线程池 + */ + private List orderedExecutor = new ArrayList<>(); + /** + * 最大线程数 + */ + public static final int MAX_THREAD_COUNT = 16; + + /** + * 线程池 + */ + private ThreadPoolTaskExecutor taskExecutor; + + + /** * 单例模式 */ private AsyncManager() { + for (int i = 0; i < MAX_THREAD_COUNT; i++) { + orderedExecutor.add(Executors.newSingleThreadExecutor()); + } + executor = SpringUtils.getBean("scheduledExecutorService"); + taskExecutor = SpringUtils.getBean("threadPoolTaskExecutor"); + } private static AsyncManager me = new AsyncManager(); @@ -36,6 +60,22 @@ public class AsyncManager { return me; } + + + + public void executeOrdered(String key, Runnable task) { + + if (null == key || key.isEmpty()) { + taskExecutor.execute(task); + return; + } + + int hash = key.hashCode(); + int index = Math.abs(hash % MAX_THREAD_COUNT); + orderedExecutor.get(index).execute(task); + } + + /** * 执行任务 * diff --git a/ff-game/src/main/java/com/ff/api/controller/ApiGameController.java b/ff-game/src/main/java/com/ff/api/controller/ApiGameController.java index 2cac157..8740bba 100644 --- a/ff-game/src/main/java/com/ff/api/controller/ApiGameController.java +++ b/ff-game/src/main/java/com/ff/api/controller/ApiGameController.java @@ -1,6 +1,7 @@ package com.ff.api.controller; +import cn.hutool.core.util.IdUtil; import com.ff.annotation.CheckHeader; import com.ff.api.request.*; import com.ff.api.response.*; @@ -8,9 +9,9 @@ import com.ff.base.constant.Constants; import com.ff.base.core.controller.BaseController; import com.ff.base.core.domain.AjaxResult; import com.ff.base.core.page.TableDataInfo; -import com.ff.base.enums.ErrorCode; -import com.ff.base.enums.TransferType; +import com.ff.base.enums.*; import com.ff.base.exception.base.ApiException; +import com.ff.base.manager.AsyncManager; import com.ff.base.system.domain.TenantSecretKey; import com.ff.base.utils.StringUtils; import com.ff.base.utils.bean.BeanUtils; @@ -19,6 +20,8 @@ import com.ff.common.service.ITenantGameQuotaFlowService; import com.ff.common.service.ITenantGameQuotaService; import com.ff.config.KeyConfig; import com.ff.game.api.IGamesService; +import com.ff.game.api.exchange.StepProcessorFactory; +import com.ff.game.api.exchange.dto.GameExchangeDTO; import com.ff.game.api.request.*; import com.ff.game.domain.*; import com.ff.game.dto.GameBettingDetailsDTO; @@ -30,8 +33,10 @@ import lombok.Data; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.http.ResponseEntity; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.Assert; import org.springframework.util.CollectionUtils; import org.springframework.util.ObjectUtils; import org.springframework.validation.annotation.Validated; @@ -39,12 +44,14 @@ import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.context.request.async.DeferredResult; import javax.annotation.Resource; import java.math.BigDecimal; import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.concurrent.CompletableFuture; /** * api控制器 @@ -94,6 +101,10 @@ public class ApiGameController extends BaseController { @Resource private IPlatformService platformService; + + @Resource + private StepProcessorFactory stepProcessorFactory; + /** * 列表 * @@ -185,8 +196,7 @@ public class ApiGameController extends BaseController { * @return {@link AjaxResult } */ @PostMapping("/exchange/balance") - @Transactional - public AjaxResult exchangeBalance(@Validated @RequestBody GameExchangeBalanceRequest gameExchangeBalanceRequest) { + public DeferredResult exchangeBalance(@Validated @RequestBody GameExchangeBalanceRequest gameExchangeBalanceRequest) { IGamesService iGamesService = gamesService.get(gameExchangeBalanceRequest.getPlatformCode() + Constants.SERVICE); ApiException.notNull(iGamesService, ErrorCode.PLATFORM_NOT_EXIST.getCode()); @@ -210,51 +220,77 @@ public class ApiGameController extends BaseController { } } ApiException.notNull(keyInfo, ErrorCode.CURRENCY_NOT_EXIST.getCode()); - BigDecimal quota = BigDecimal.ZERO; - //如果是扣钱提前扣 - if (TransferType.GAMES.getCode().equals(gameExchangeBalanceRequest.getTransferType())) { - quota = tenantGameQuotaService.gameBalanceExchange(GameBalanceExchange.builder() - .platformCode(gameExchangeBalanceRequest.getPlatformCode()) - .sourceId(gameExchangeBalanceRequest.getOrderId()) - .currencyCode(gameExchangeBalanceRequest.getCurrencyCode()) - .currency(targetCurrency) - .transferType(gameExchangeBalanceRequest.getTransferType()) - .amount(gameExchangeBalanceRequest.getAmount()) - .account(gameExchangeBalanceRequest.getAccount()) - .tenantKey(tenantSecretKey.getTenantKey()) - .systemCurrency(gameExchangeBalanceRequest.getCurrencyCode()) - .agentId(keyInfo.getCode()) - .agentKey(keyInfo.getKey()) - .build()); - } - // 获取用户信息 Member member = memberService.selectMemberByAccount(gameExchangeBalanceRequest.getAccount(), gameExchangeBalanceRequest.getCurrencyCode(), gameExchangeBalanceRequest.getPlatformCode()); ApiException.notNull(member, ErrorCode.ACCOUNT_NOT_EXIST.getCode()); + List gameExchangeMonies = gameExchangeMoneyService.selectGameExchangeMoneyList( + GameExchangeMoney.builder() + .tenantKey(tenantSecretKey.getTenantKey()) + .orderId(gameExchangeBalanceRequest.getOrderId()) + .build() + ); - //操作第三方额度接口 - ExchangeTransferMoneyRequestDTO exchangeTransferMoneyRequestDTO = ExchangeTransferMoneyRequestDTO.builder() - .agentId(keyInfo.getCode()) - .agentKey(keyInfo.getKey()) - .orderId(gameExchangeBalanceRequest.getOrderId()) - .account(member.getGameAccount()) - .currency(targetCurrency) + ApiException.isTrue(CollectionUtils.isEmpty(gameExchangeMonies), ErrorCode.DUPLICATE_ORDER_ID.getCode()); + + + Long gameExchangeMoneyId = IdUtil.getSnowflakeNextId(); + GameExchangeDTO exchangeMoney = GameExchangeDTO.builder() + .id(gameExchangeMoneyId) .tenantKey(tenantSecretKey.getTenantKey()) - .quota(quota) - .amount(gameExchangeBalanceRequest.getAmount()) - .transferType(gameExchangeBalanceRequest.getTransferType()) - .vendor(platform) - .keyInfo(keyInfo) - .systemCurrency(gameExchangeBalanceRequest.getCurrencyCode()) + .memberId(member.getId()) + .gameAccount(member.getGameAccount()) + .memberAccount(member.getMemberAccount()) + .exchangeType(gameExchangeBalanceRequest.getTransferType()) + .currencyCode(gameExchangeBalanceRequest.getCurrencyCode()) + .orderId(gameExchangeBalanceRequest.getOrderId()) + .balance(gameExchangeBalanceRequest.getAmount()) + .triggerType(TriggerType.MANUAL.getCode()) + .platformCode(gameExchangeBalanceRequest.getPlatformCode()).build(); - .build(); - Long exchangeTransferId = iGamesService.exchangeTransferByAgentId(exchangeTransferMoneyRequestDTO); - GameExchangeMoney gameExchangeMoney = gameExchangeMoneyService.selectGameExchangeMoneyById(exchangeTransferId); - GameExchangeBalanceResponse gameExchangeBalanceResponse = new GameExchangeBalanceResponse(); - BeanUtils.copyProperties(gameExchangeMoney, gameExchangeBalanceResponse); - return AjaxResult.success(gameExchangeBalanceResponse); + + //转出设置转出金额为0 + if (TransferType.ALL.getCode().equals(gameExchangeBalanceRequest.getTransferType())){ + exchangeMoney.setBalance(BigDecimal.ZERO); + } + + + ExtInfo extInfo = platform.getExtInfo(); + Long timeout = 5000L; + if (extInfo != null) { + timeout = extInfo.getTimeout(TimeOutType.GAME_EXCHANGE_MONEY.getCode()); + } + + + DeferredResult output = new DeferredResult<>(timeout); + AsyncManager.me().executeOrdered( + exchangeMoney.getOrderId(), + () -> { + try { + stepProcessorFactory.getStepProcessor(GameExchangeStep.CREATE_ORDER).process(exchangeMoney); + + GameExchangeMoney gameExchangeMoney = gameExchangeMoneyService.selectGameExchangeMoneyById(gameExchangeMoneyId); + GameExchangeBalanceResponse gameExchangeBalanceResponse = new GameExchangeBalanceResponse(); + BeanUtils.copyProperties(gameExchangeMoney, gameExchangeBalanceResponse); + output.setResult(AjaxResult.success(gameExchangeBalanceResponse)); + + } catch (Exception e) { + log.error("ApiGameController [exchangeBalance] 余额转移失败 gameExchangeMoneyId {}", gameExchangeMoneyId,e); + stepProcessorFactory.getStepProcessor(GameExchangeStep.getByCode(exchangeMoney.getStep())).rollBack(exchangeMoney); + output.setErrorResult(AjaxResult.error(ErrorCode.BALANCE_TRANSFER_FAILED.getCode(), ErrorCode.BALANCE_TRANSFER_FAILED.getMessage())); + } + + } + ); + // 超时时间处理逻辑 + output.onTimeout(() -> { + GameExchangeMoney gameExchangeMoney = gameExchangeMoneyService.selectGameExchangeMoneyById(gameExchangeMoneyId); + GameExchangeBalanceResponse gameExchangeBalanceResponse = new GameExchangeBalanceResponse(); + BeanUtils.copyProperties(gameExchangeMoney, gameExchangeBalanceResponse); + output.setErrorResult(AjaxResult.success(gameExchangeBalanceResponse)); + }); + return output; } @@ -294,11 +330,6 @@ public class ApiGameController extends BaseController { ApiException.notNull(iGamesService, ErrorCode.PLATFORM_NOT_EXIST.getCode()); -// TenantSecretKey tenantSecretKey = keyConfig.get(); -// GameSecretKeyCurrencyDTO gameSecretKey = gameSecretKeyCurrencyService.findByGameSecretKeyCurrencyDTO(GameSecretKeyCurrencyDTO.builder() -// .platformCode(gameCreateFreeSpinRequest.getPlatformCode()) -// .systemCurrency(gameCreateFreeSpinRequest.getCurrencyCode()).build()); -// ApiException.notNull(gameSecretKey, ErrorCode.CURRENCY_NOT_EXIST.getCode()); Platform platform = platformService.get(gameCreateFreeSpinRequest.getPlatformCode()); ApiException.notNull(platform, ErrorCode.PLATFORM_NOT_EXIST.getCode()); diff --git a/ff-game/src/main/java/com/ff/common/dto/GameBalanceExchange.java b/ff-game/src/main/java/com/ff/common/dto/GameBalanceExchange.java index 15c82ff..ae9260b 100644 --- a/ff-game/src/main/java/com/ff/common/dto/GameBalanceExchange.java +++ b/ff-game/src/main/java/com/ff/common/dto/GameBalanceExchange.java @@ -67,4 +67,9 @@ public class GameBalanceExchange extends GamesBaseRequestDTO implements Serializ */ private String sourceId; + /** + * 就是全部 + */ + private Boolean isAll; + } diff --git a/ff-game/src/main/java/com/ff/common/service/impl/TenantGameQuotaServiceImpl.java b/ff-game/src/main/java/com/ff/common/service/impl/TenantGameQuotaServiceImpl.java index 25f5253..cf85cf6 100644 --- a/ff-game/src/main/java/com/ff/common/service/impl/TenantGameQuotaServiceImpl.java +++ b/ff-game/src/main/java/com/ff/common/service/impl/TenantGameQuotaServiceImpl.java @@ -152,7 +152,7 @@ public class TenantGameQuotaServiceImpl implements ITenantGameQuotaService { BigDecimal balance = balanceChangesDTO.getBalance(); //如果有汇率 则需要计算真实扣除额度 if (!ObjectUtils.isEmpty(balanceChangesDTO.getActualBalance())) { - balance = NumberUtil.div(balance, balanceChangesDTO.getActualBalance(), 2, RoundingMode.FLOOR); + balance = NumberUtil.div(balance, balanceChangesDTO.getActualBalance(), 5, RoundingMode.FLOOR); } if (BigDecimal.ZERO.compareTo(balance) >= 0) { @@ -222,7 +222,7 @@ public class TenantGameQuotaServiceImpl implements ITenantGameQuotaService { BigDecimal balance = balanceRealChangesDTO.getBalance(); //如果有汇率 则需要计算真实扣除额度 if (!ObjectUtils.isEmpty(balanceRealChangesDTO.getActualBalance())) { - balance = NumberUtil.div(balance, balanceRealChangesDTO.getActualBalance(), 2, RoundingMode.FLOOR); + balance = NumberUtil.div(balance, balanceRealChangesDTO.getActualBalance(), 5, RoundingMode.FLOOR); } if (BigDecimal.ZERO.compareTo(balance) >= 0) { @@ -317,14 +317,18 @@ public class TenantGameQuotaServiceImpl implements ITenantGameQuotaService { // 如果是出账操作 if (isOut) { - // 获取第三方钱包余额 - MemberInfoRequestDTO gamesBaseRequestDTO = MemberInfoRequestDTO.builder() - .accounts(member.getGameAccount()) - .agentId(gameBalanceExchange.getAgentId()) - .currency(gameBalanceExchange.getCurrency()) - .agentKey(gameBalanceExchange.getAgentKey()) - .build(); - balanceRequestAmount = iGamesService.getMemberInfo(gamesBaseRequestDTO).getBalance(); + if (ObjectUtils.isEmpty(gameBalanceExchange.getIsAll())||gameBalanceExchange.getIsAll()){ + // 获取第三方钱包余额 + MemberInfoRequestDTO gamesBaseRequestDTO = MemberInfoRequestDTO.builder() + .accounts(member.getGameAccount()) + .agentId(gameBalanceExchange.getAgentId()) + .currency(gameBalanceExchange.getCurrency()) + .agentKey(gameBalanceExchange.getAgentKey()) + .build(); + balanceRequestAmount = iGamesService.getMemberInfo(gamesBaseRequestDTO).getBalance(); + } + + balanceRequestAmount = NumberUtil.add(balanceRequestAmount, NumberUtil.mul(balanceRequestAmount, NumberUtil.div(tenantPlatform.getUseCost(), Constants.HUNDRED))); // 计算累计转入和转出金额 diff --git a/ff-game/src/main/java/com/ff/game/api/ae/impl/GamesAEServiceImpl.java b/ff-game/src/main/java/com/ff/game/api/ae/impl/GamesAEServiceImpl.java index 612c597..67a09dd 100644 --- a/ff-game/src/main/java/com/ff/game/api/ae/impl/GamesAEServiceImpl.java +++ b/ff-game/src/main/java/com/ff/game/api/ae/impl/GamesAEServiceImpl.java @@ -228,34 +228,8 @@ public class GamesAEServiceImpl implements IGamesService { log.info("GamesAEServiceImpl [exchangeTransferByAgentId] 请求参数 {}", exchangeTransferMoneyRequestDTO); - Member member = memberService.selectMemberByGameAccount(exchangeTransferMoneyRequestDTO.getAccount()); - String transactionId = GamePlatforms.AE.getCode() + IdUtils.simpleUUID(); - List gameExchangeMonies = gameExchangeMoneyService.selectGameExchangeMoneyList( - GameExchangeMoney.builder() - .tenantKey(exchangeTransferMoneyRequestDTO.getTenantKey()) - .orderId(exchangeTransferMoneyRequestDTO.getOrderId()) - .build() - ); - Assert.isTrue(CollectionUtils.isEmpty(gameExchangeMonies), "订单号重复"); + GameExchangeMoney exchangeMoney = gameExchangeMoneyService.selectGameExchangeMoneyById(exchangeTransferMoneyRequestDTO.getGameExchangeId()); - //获取下一个自增id - GameExchangeMoney exchangeMoney = GameExchangeMoney - .builder() - .tenantKey(exchangeTransferMoneyRequestDTO.getTenantKey()) - .orderId(exchangeTransferMoneyRequestDTO.getOrderId()) - .quota(exchangeTransferMoneyRequestDTO.getQuota()) - .balance(exchangeTransferMoneyRequestDTO.getAmount()) - .exchangeType(exchangeTransferMoneyRequestDTO.getTransferType()) - .currencyCode(exchangeTransferMoneyRequestDTO.getSystemCurrency()) - .memberId(member.getId()) - .transactionId(transactionId) - .platformCode(GamePlatforms.AE.getInfo()) - .build(); - exchangeMoney.setCreateBy(Constants.SYSTEM); - exchangeMoney.setStatus(StatusType.IN_PROGRESS.getValue()); - exchangeMoney.setStep(GameExchangeStep.CREATE_ORDER.getCode()); - exchangeMoney.setStepStatus(GameExchangeStepStatus.SUCCESS.getCode()); - gameExchangeMoneyService.insertGameExchangeMoney(exchangeMoney); Map params = this.getKey(exchangeTransferMoneyRequestDTO); @@ -264,13 +238,13 @@ public class GamesAEServiceImpl implements IGamesService { if (TransferType.GAMES.getCode().equals(exchangeTransferMoneyRequestDTO.getTransferType())) { params.put("userId", exchangeTransferMoneyRequestDTO.getAccount()); - params.put("txCode", transactionId); + params.put("txCode", exchangeTransferMoneyRequestDTO.getTransactionId()); params.put("transferAmount", exchangeTransferMoneyRequestDTO.getAmount()); deposit = AEClient.deposit(params); } else { params.put("userId", exchangeTransferMoneyRequestDTO.getAccount()); - params.put("txCode", transactionId); + params.put("txCode", exchangeTransferMoneyRequestDTO.getTransactionId()); params.put("withdrawType", 1); deposit = AEClient.withdraw(params); } diff --git a/ff-game/src/main/java/com/ff/game/api/dg/service/impl/GamesDGServiceImpl.java b/ff-game/src/main/java/com/ff/game/api/dg/service/impl/GamesDGServiceImpl.java index b4315e9..ca49446 100644 --- a/ff-game/src/main/java/com/ff/game/api/dg/service/impl/GamesDGServiceImpl.java +++ b/ff-game/src/main/java/com/ff/game/api/dg/service/impl/GamesDGServiceImpl.java @@ -220,39 +220,14 @@ public class GamesDGServiceImpl implements IGamesService { log.info("GamesDGServiceImpl [exchangeTransferByAgentId] 请求参数 {}", exchangeTransferMoneyRequestDTO); - Member member = memberService.selectMemberByGameAccount(exchangeTransferMoneyRequestDTO.getAccount()); - String transactionId = GamePlatforms.DG.getInfo() + IdUtils.simpleUUID(); - List gameExchangeMonies = gameExchangeMoneyService.selectGameExchangeMoneyList( - GameExchangeMoney.builder() - .tenantKey(exchangeTransferMoneyRequestDTO.getTenantKey()) - .orderId(exchangeTransferMoneyRequestDTO.getOrderId()) - .build() - ); - Assert.isTrue(CollectionUtils.isEmpty(gameExchangeMonies), "订单号重复"); + GameExchangeMoney exchangeMoney = gameExchangeMoneyService.selectGameExchangeMoneyById(exchangeTransferMoneyRequestDTO.getGameExchangeId()); + - //获取下一个自增id - GameExchangeMoney exchangeMoney = GameExchangeMoney - .builder() - .tenantKey(exchangeTransferMoneyRequestDTO.getTenantKey()) - .orderId(exchangeTransferMoneyRequestDTO.getOrderId()) - .quota(exchangeTransferMoneyRequestDTO.getQuota()) - .balance(exchangeTransferMoneyRequestDTO.getAmount()) - .exchangeType(exchangeTransferMoneyRequestDTO.getTransferType()) - .currencyCode(exchangeTransferMoneyRequestDTO.getSystemCurrency()) - .memberId(member.getId()) - .transactionId(transactionId) - .platformCode(GamePlatforms.DG.getInfo()) - .build(); - exchangeMoney.setCreateBy(Constants.SYSTEM); - exchangeMoney.setStatus(StatusType.IN_PROGRESS.getValue()); - exchangeMoney.setStep(GameExchangeStep.CREATE_ORDER.getCode()); - exchangeMoney.setStepStatus(GameExchangeStepStatus.SUCCESS.getCode()); - gameExchangeMoneyService.insertGameExchangeMoney(exchangeMoney); BigDecimal amount = exchangeTransferMoneyRequestDTO.getAmount(); if (TransferType.ALL.getCode().equals(exchangeTransferMoneyRequestDTO.getTransferType())) { // 获取第三方钱包余额 MemberInfoRequestDTO gamesBaseRequestDTO = MemberInfoRequestDTO.builder() - .accounts(member.getGameAccount()) + .accounts(exchangeTransferMoneyRequestDTO.getAccount()) .agentId(exchangeTransferMoneyRequestDTO.getAgentId()) .currency(exchangeTransferMoneyRequestDTO.getCurrency()) .agentKey(exchangeTransferMoneyRequestDTO.getAgentKey()) @@ -265,7 +240,7 @@ public class GamesDGServiceImpl implements IGamesService { Map params = new LinkedHashMap<>(); params.put("username", exchangeTransferMoneyRequestDTO.getAccount()); params.put("amount", amount); - params.put("serial", transactionId); + params.put("serial", exchangeTransferMoneyRequestDTO.getTransactionId()); Map headerMap = this.getKey(exchangeTransferMoneyRequestDTO); DGTransactionResponseDTO dgTransactionResponseDTO = DGClient.exchangeTransferByAgentId(params, headerMap); diff --git a/ff-game/src/main/java/com/ff/game/api/exchange/AbstractStepProcessor.java b/ff-game/src/main/java/com/ff/game/api/exchange/AbstractStepProcessor.java new file mode 100644 index 0000000..6e0713f --- /dev/null +++ b/ff-game/src/main/java/com/ff/game/api/exchange/AbstractStepProcessor.java @@ -0,0 +1,118 @@ +package com.ff.game.api.exchange; + +import com.ff.base.enums.GameExchangeStep; +import com.ff.base.enums.GameExchangeStepStatus; +import com.ff.base.exception.base.BaseException; +import com.ff.game.api.exchange.dto.GameExchangeDTO; +import com.ff.game.domain.GameExchangeMoney; +import com.ff.game.service.IGameExchangeMoneyService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.transaction.TransactionDefinition; +import org.springframework.transaction.support.TransactionTemplate; + +import javax.annotation.Resource; + +/** + * 抽象步进处理机 + * + * @author shi + * @date 2025/04/09 + */ +@Slf4j +public abstract class AbstractStepProcessor implements StepProcessorService { + + + @Resource + private StepProcessorFactory stepProcessorFactory; + + + @Resource + private IGameExchangeMoneyService gameExchangeMoneyService; + + /** + * 过程 + * + * @param gameExchangeMoney 游戏兑换货币 + */ + @Override + public void process(GameExchangeDTO gameExchangeMoney) { + boolean processResult = false; + try { + processResult = doProcess(gameExchangeMoney); + } catch (Exception e) { + log.error("游戏余额转移{}-步骤任务{}-执行异常", gameExchangeMoney.getId(), stepKey().getDescription(), e); + throw new BaseException("游戏余额转移"+gameExchangeMoney.getId()+"-步骤任务"+stepKey().getDescription()+"-执行异常" ); + } + //更新状态 + if (processResult) { + log.info("游戏余额转移{}-步骤任务{}-执行成功", gameExchangeMoney.getId(), stepKey().getDescription()); + triggerNextStep(gameExchangeMoney); + } + } + + + + /** + * 降低 + * + * @param gameExchangeMoney 游戏兑换货币 + */ + @Override + public void rollBack(GameExchangeDTO gameExchangeMoney){ + boolean processResult = false; + try { + processResult = doRollBack(gameExchangeMoney); + } catch (Exception e) { + log.error("游戏余额转移{}-步骤任务{}-回滚异常", gameExchangeMoney.getId(), stepKey().getDescription(), e); + } + if (processResult) { + log.info("游戏余额转移{}-步骤任务{}-回滚成功", gameExchangeMoney.getId(), stepKey().getDescription()); + triggerBackStep(gameExchangeMoney); + } + } + + + /** + * 触发后退 + * + * @param exchangeMoney 兑换货币 + */ + private void triggerBackStep(GameExchangeDTO exchangeMoney) { + GameExchangeStep nextStep = backStepProcessor(); + if (nextStep != null) { + stepProcessorFactory.getStepProcessor(nextStep).rollBack(exchangeMoney); + } + } + + + + /** + * 触发下一步 + * + * @param exchangeMoney 兑换货币 + */ + private void triggerNextStep(GameExchangeDTO exchangeMoney) { + GameExchangeStep nextStep = nextStepProcessor(); + if (nextStep != null) { + stepProcessorFactory.getStepProcessor(nextStep).process(exchangeMoney); + } + } + + /** + * 一定要回滚 + * + * @param gameExchangeMoney 游戏兑换货币 + * @return boolean + * @throws Exception 例外 + */ + abstract public boolean doRollBack(GameExchangeDTO gameExchangeMoney) throws Exception; + + /** + * do过程 + * + * @param gameExchangeMoney 游戏兑换货币 + * @return boolean + * @throws Exception 例外 + */ + abstract public boolean doProcess(GameExchangeDTO gameExchangeMoney) throws Exception; +} diff --git a/ff-game/src/main/java/com/ff/game/api/exchange/StepProcessorFactory.java b/ff-game/src/main/java/com/ff/game/api/exchange/StepProcessorFactory.java new file mode 100644 index 0000000..7db1768 --- /dev/null +++ b/ff-game/src/main/java/com/ff/game/api/exchange/StepProcessorFactory.java @@ -0,0 +1,47 @@ +package com.ff.game.api.exchange; + +import com.ff.base.enums.GameExchangeStep; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import javax.annotation.PostConstruct; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * 步进处理机厂 + * + * @author shi + * @date 2025/04/09 + */ +@Component +public class StepProcessorFactory { + + @Autowired + List stepProcessors; + + private Map processorMap; + + @PostConstruct + public void init() { + Map map = new HashMap<>(); + for (StepProcessorService stepProcessor : stepProcessors) { + map.put(stepProcessor.stepKey(), stepProcessor); + } + + processorMap = Collections.unmodifiableMap(map); + } + + /** + * 获取步进处理器 + * + * @param stepKey 步进键 + * @return {@link StepProcessorService } + */ + public StepProcessorService getStepProcessor(GameExchangeStep stepKey) { + return processorMap.get(stepKey); + } + +} diff --git a/ff-game/src/main/java/com/ff/game/api/exchange/StepProcessorService.java b/ff-game/src/main/java/com/ff/game/api/exchange/StepProcessorService.java new file mode 100644 index 0000000..be5efb8 --- /dev/null +++ b/ff-game/src/main/java/com/ff/game/api/exchange/StepProcessorService.java @@ -0,0 +1,56 @@ +package com.ff.game.api.exchange; + +import com.ff.base.enums.GameExchangeStep; +import com.ff.game.api.exchange.dto.GameExchangeDTO; + +/** + * 步进处理机 + * + * @author shi + * @date 2025/04/09 + */ +public interface StepProcessorService { + + /** + * 返回处理器类型 + * + * @return {@link GameExchangeStep } + */ + GameExchangeStep stepKey(); + + + /** + * 过程 + * + * @param gameExchangeMoney 游戏兑换货币 + */ + void process(GameExchangeDTO gameExchangeMoney); + + + /** + * 回退 + * + * @param gameExchangeMoney 游戏兑换货币 + */ + void rollBack(GameExchangeDTO gameExchangeMoney); + + + /** + * 步骤之间有依赖 + * 找出下一个步骤处理器进行处理 + * + * @return + */ + GameExchangeStep nextStepProcessor(); + + + /** + * 步骤之间有依赖 + * 找出上一个步骤处理器进行处理 + * + * @return {@link GameExchangeStep } + */ + GameExchangeStep backStepProcessor(); + + +} diff --git a/ff-game/src/main/java/com/ff/game/api/exchange/dto/GameExchangeDTO.java b/ff-game/src/main/java/com/ff/game/api/exchange/dto/GameExchangeDTO.java new file mode 100644 index 0000000..584e9f6 --- /dev/null +++ b/ff-game/src/main/java/com/ff/game/api/exchange/dto/GameExchangeDTO.java @@ -0,0 +1,32 @@ +package com.ff.game.api.exchange.dto; + +import com.ff.base.annotation.Excel; +import com.ff.game.domain.GameExchangeMoney; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * 游戏兑换货币dto + * + * @author shi + * @date 2025/04/09 + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +@SuperBuilder +public class GameExchangeDTO extends GameExchangeMoney { + /** + * 触发类型 1 用户调用手动触发 2 定时器触发 + */ + private Integer triggerType; + + /** 会员账号 */ + private String memberAccount; + + /** 游戏账号 */ + private String gameAccount; + +} diff --git a/ff-game/src/main/java/com/ff/game/api/exchange/impl/AddBalanceServiceImpl.java b/ff-game/src/main/java/com/ff/game/api/exchange/impl/AddBalanceServiceImpl.java new file mode 100644 index 0000000..b45e7d3 --- /dev/null +++ b/ff-game/src/main/java/com/ff/game/api/exchange/impl/AddBalanceServiceImpl.java @@ -0,0 +1,170 @@ +package com.ff.game.api.exchange.impl; + +import com.ff.base.constant.Constants; +import com.ff.base.enums.*; +import com.ff.base.exception.base.ApiException; +import com.ff.base.utils.StringUtils; +import com.ff.common.domain.TenantGameQuotaFlow; +import com.ff.common.dto.BalanceChangesDTO; +import com.ff.common.dto.GameBalanceExchange; +import com.ff.common.service.ITenantGameQuotaFlowService; +import com.ff.common.service.ITenantGameQuotaService; +import com.ff.game.api.IGamesService; +import com.ff.game.api.exchange.AbstractStepProcessor; +import com.ff.game.api.exchange.dto.GameExchangeDTO; +import com.ff.game.api.request.ExchangeTransferMoneyRequestDTO; +import com.ff.game.api.request.ExchangeTransferStatusRequestDTO; +import com.ff.game.api.request.ExchangeTransferStatusResponseDTO; +import com.ff.game.domain.KeyInfo; +import com.ff.game.domain.Platform; +import com.ff.game.service.IGameExchangeMoneyService; +import com.ff.game.service.IPlatformService; +import com.ff.member.domain.Member; +import com.ff.member.service.IMemberService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Service; +import org.springframework.transaction.PlatformTransactionManager; +import org.springframework.transaction.TransactionDefinition; +import org.springframework.transaction.support.TransactionTemplate; + +import javax.annotation.Resource; +import java.math.BigDecimal; +import java.util.List; +import java.util.Map; + + +/** + * 增加余额 + * + * @author shi + * @date 2025/04/09 + */ +@Service +@Order(4) +public class AddBalanceServiceImpl extends AbstractStepProcessor { + + + @Resource + private IMemberService memberService; + + @Resource + private ITenantGameQuotaService tenantGameQuotaService; + @Resource + private IGameExchangeMoneyService gameExchangeMoneyService; + @Resource + private PlatformTransactionManager transactionManager; + @Resource + private IPlatformService platformService; + /** + * 步进键 + * + * @return {@link GameExchangeStep } + */ + @Override + public GameExchangeStep stepKey() { + return GameExchangeStep.TENANT_QUOTA_DEDUCTED; + } + + + /** + * do过程 + * + * @param gameExchangeMoney 游戏兑换货币 + * @return boolean + */ + @Override + public boolean doProcess(GameExchangeDTO gameExchangeMoney) { + //如果不是之前的步骤代码执行过了 或者是转入操作 + if (!gameExchangeMoney.getStep().equals(GameExchangeStep.PLATFORM_TRANSACTION.getCode()) ) { + return Boolean.TRUE; + } + if (!gameExchangeMoney.getStepStatus().equals(StatusType.SUCCESS.getValue())){ + return Boolean.TRUE; + } + + TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager); + transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW); + Boolean result = transactionTemplate.execute(transactionStatus -> { + //不是转入操作 + if (!TransferType.ALL.getCode().equals(gameExchangeMoney.getExchangeType())) { + gameExchangeMoney.setStep(GameExchangeStep.DEDUCT_BALANCE.getCode()); + gameExchangeMoney.setStepStatus(GameExchangeStepStatus.SUCCESS.getCode()); + gameExchangeMoney.setStatus(StatusType.SUCCESS.getValue()); + return gameExchangeMoneyService.updateGameExchangeMoney(gameExchangeMoney) > 0; + } + + Platform platform = platformService.get(gameExchangeMoney.getPlatformCode()); + KeyInfo keyInfo = null; + for (KeyInfo keyData : platform.getKeyInfo()) { + if (StringUtils.isNotEmpty(gameExchangeMoney.getCurrencyCode())) { + if (keyData.getCurrency().equalsIgnoreCase(gameExchangeMoney.getCurrencyCode())) { + keyInfo = keyData; + break; + } + } + } + + + BigDecimal decimal = tenantGameQuotaService.gameBalanceExchange(GameBalanceExchange.builder() + .platformCode(gameExchangeMoney.getPlatformCode()) + .sourceId(String.valueOf(gameExchangeMoney.getId())) + .currencyCode(gameExchangeMoney.getCurrencyCode()) + .currency(gameExchangeMoney.getCurrencyCode()) + .transferType(gameExchangeMoney.getExchangeType()) + .amount(gameExchangeMoney.getBalance()) + .isAll(Boolean.FALSE) + .account(memberService.selectMemberById(gameExchangeMoney.getMemberId()).getMemberAccount()) + .tenantKey(gameExchangeMoney.getTenantKey()) + .systemCurrency(gameExchangeMoney.getCurrencyCode()) + .agentId(keyInfo.getCode()) + .agentKey(keyInfo.getKey()) + .build()); + + gameExchangeMoney.setQuota(decimal); + gameExchangeMoney.setStep(GameExchangeStep.TENANT_QUOTA_DEDUCTED.getCode()); + gameExchangeMoney.setStepStatus(GameExchangeStepStatus.SUCCESS.getCode()); + gameExchangeMoney.setStatus(StatusType.SUCCESS.getValue()); + return gameExchangeMoneyService.updateGameExchangeMoney(gameExchangeMoney) > 0; + + }); + return Boolean.TRUE.equals(result); + + + } + + + /** + * 一定要回滚 最后一步成功了就结束了 + * + * @param gameExchangeMoney 游戏兑换货币 + * @return boolean + */ + @Override + public boolean doRollBack(GameExchangeDTO gameExchangeMoney) { + return Boolean.TRUE; + } + + /** + * 下一步处理器 + * + * @return {@link GameExchangeStep } + */ + @Override + public GameExchangeStep nextStepProcessor() { + return null; + } + + /** + * 后级处理器 最后一步无法回滚 + * + * @return {@link GameExchangeStep } + */ + @Override + public GameExchangeStep backStepProcessor() { + { + return null; + } + } + +} diff --git a/ff-game/src/main/java/com/ff/game/api/exchange/impl/CreateOrderServiceImpl.java b/ff-game/src/main/java/com/ff/game/api/exchange/impl/CreateOrderServiceImpl.java new file mode 100644 index 0000000..15701b0 --- /dev/null +++ b/ff-game/src/main/java/com/ff/game/api/exchange/impl/CreateOrderServiceImpl.java @@ -0,0 +1,146 @@ +package com.ff.game.api.exchange.impl; + +import com.ff.base.constant.Constants; +import com.ff.base.enums.*; +import com.ff.base.exception.base.ApiException; +import com.ff.base.manager.AsyncManager; +import com.ff.base.utils.DateUtils; +import com.ff.base.utils.uuid.IdUtils; +import com.ff.game.api.exchange.AbstractStepProcessor; +import com.ff.game.api.exchange.StepProcessorFactory; +import com.ff.game.api.exchange.StepProcessorService; +import com.ff.game.api.exchange.dto.GameExchangeDTO; +import com.ff.game.api.request.ExchangeTransferStatusRequestDTO; +import com.ff.game.domain.GameExchangeMoney; +import com.ff.game.service.IGameExchangeMoneyService; +import com.ff.member.domain.Member; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import javax.crypto.spec.SecretKeySpec; +import java.util.Base64; + +/** + * 创建订单impl + * + * @author shi + * @date 2025/04/09 + */ +@Service +@Order(1) +public class CreateOrderServiceImpl extends AbstractStepProcessor { + + @Resource + private IGameExchangeMoneyService gameExchangeMoneyService; + + + @Resource + private StepProcessorFactory stepProcessorFactory; + + /** + * 步进键 + * + * @return {@link GameExchangeStep } + */ + @Override + public GameExchangeStep stepKey() { + return GameExchangeStep.CREATE_ORDER; + } + + + /** + * do过程 + * + * @param gameExchangeMoney 游戏兑换货币 + * @return boolean + */ + @Override + public boolean doProcess(GameExchangeDTO gameExchangeMoney) { + + + gameExchangeMoney.setTransactionId(this.getTransactionId(GamePlatforms.getByCode(gameExchangeMoney.getPlatformCode()),gameExchangeMoney.getExchangeType(),gameExchangeMoney.getGameAccount())); + gameExchangeMoney.setCreateBy(Constants.SYSTEM); + gameExchangeMoney.setStatus(StatusType.IN_PROGRESS.getValue()); + gameExchangeMoney.setStep(GameExchangeStep.CREATE_ORDER.getCode()); + gameExchangeMoney.setStepStatus(GameExchangeStepStatus.SUCCESS.getCode()); + return gameExchangeMoneyService.insertGameExchangeMoney(gameExchangeMoney) > 0; + } + + /** + * 获取交易id + * + * @return {@link String } + */ + private String getTransactionId(GamePlatforms gamePlatforms,Integer exchangeType ,String account) { + switch (gamePlatforms) { + case AE: + return GamePlatforms.AE.getCode() + IdUtils.simpleUUID(); + case JILI: + return GamePlatforms.JILI.getInfo() + IdUtils.simpleUUID(); + case XK: + return GamePlatforms.XK.getCode() + IdUtils.simpleUUID(); + case PG: + return gameExchangeMoneyService.getTransactionId(GamePlatforms.PG.getCode(), 32); + case PGX: + return gameExchangeMoneyService.getTransactionId(GamePlatforms.PGX.getInfo(), 17); + case FC: + return gameExchangeMoneyService.getTransactionId(GamePlatforms.FC.getInfo(), 30); + case DG: + return GamePlatforms.DG.getInfo() + IdUtils.simpleUUID(); + + case MT: + return GamePlatforms.MT.getCode() + IdUtils.simpleUUID(); + case SA: + //判断是转入还是转出 + String transactionId = "OUT" + DateUtils.dateTimeNow() + account; + if (!TransferType.ALL.getCode().equals(exchangeType)) { + transactionId = "IN" + DateUtils.dateTimeNow() + account; + } + + return transactionId; + case KM: + return GamePlatforms.KM.getInfo() + IdUtils.simpleUUID(); + case PGT: + return gameExchangeMoneyService.getTransactionId(GamePlatforms.PGT.getInfo(), 17); + } + throw new ApiException(ErrorCode.PLATFORM_NOT_EXIST.getCode()); + } + + + /** + * 一定要回滚 + * + * @param gameExchangeMoney 游戏兑换货币 + * @return boolean + */ + @Override + public boolean doRollBack(GameExchangeDTO gameExchangeMoney) { + gameExchangeMoney.setStep(GameExchangeStep.CREATE_ORDER.getCode()); + gameExchangeMoney.setStepStatus(GameExchangeStepStatus.FAILURE.getCode()); + gameExchangeMoney.setStatus(StatusType.FAILURE.getValue()); + gameExchangeMoney.setUpdateBy(Constants.SYSTEM); + gameExchangeMoney.setUpdateTime(DateUtils.getNowDate()); + return gameExchangeMoneyService.updateGameExchangeMoney(gameExchangeMoney) > 0; + } + + /** + * 下一步处理器 + * + * @return {@link GameExchangeStep } + */ + @Override + public GameExchangeStep nextStepProcessor() { + return GameExchangeStep.DEDUCT_BALANCE; + } + + /** + * 后级处理器 + * + * @return {@link GameExchangeStep } + */ + @Override + public GameExchangeStep backStepProcessor() { + return null; + } +} diff --git a/ff-game/src/main/java/com/ff/game/api/exchange/impl/DeductBalanceServiceImpl.java b/ff-game/src/main/java/com/ff/game/api/exchange/impl/DeductBalanceServiceImpl.java new file mode 100644 index 0000000..5407d80 --- /dev/null +++ b/ff-game/src/main/java/com/ff/game/api/exchange/impl/DeductBalanceServiceImpl.java @@ -0,0 +1,189 @@ +package com.ff.game.api.exchange.impl; + +import com.ff.base.constant.Constants; +import com.ff.base.enums.*; +import com.ff.base.exception.base.ApiException; +import com.ff.base.utils.DateUtils; +import com.ff.base.utils.QuotaUtils; +import com.ff.base.utils.StringUtils; +import com.ff.base.utils.uuid.IdUtils; +import com.ff.common.domain.TenantGameQuota; +import com.ff.common.domain.TenantGameQuotaFlow; +import com.ff.common.dto.BalanceChangesDTO; +import com.ff.common.dto.GameBalanceExchange; +import com.ff.common.service.ITenantGameQuotaFlowService; +import com.ff.common.service.ITenantGameQuotaService; +import com.ff.game.api.exchange.AbstractStepProcessor; +import com.ff.game.api.exchange.StepProcessorFactory; +import com.ff.game.api.exchange.dto.GameExchangeDTO; +import com.ff.game.domain.GameExchangeMoney; +import com.ff.game.domain.KeyInfo; +import com.ff.game.domain.Platform; +import com.ff.game.service.IGameExchangeMoneyService; +import com.ff.game.service.IPlatformService; +import com.ff.member.service.IMemberService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Service; +import org.springframework.transaction.PlatformTransactionManager; +import org.springframework.transaction.TransactionDefinition; +import org.springframework.transaction.support.TransactionTemplate; + +import javax.annotation.Resource; +import java.math.BigDecimal; +import java.util.List; + + +/** + * 转入提前扣租户余额impl + * + * @author shi + * @date 2025/04/09 + */ +@Service +@Order(2) +public class DeductBalanceServiceImpl extends AbstractStepProcessor { + + @Resource + private IGameExchangeMoneyService gameExchangeMoneyService; + + @Resource + private ITenantGameQuotaService tenantGameQuotaService; + + @Resource + private IMemberService memberService; + + @Resource + private IPlatformService platformService; + @Resource + private ITenantGameQuotaFlowService tenantGameQuotaFlowService; + @Autowired + private PlatformTransactionManager transactionManager; + + /** + * 步进键 + * + * @return {@link GameExchangeStep } + */ + @Override + public GameExchangeStep stepKey() { + return GameExchangeStep.DEDUCT_BALANCE; + } + + + /** + * do过程 + * + * @param gameExchangeMoney 游戏兑换货币 + * @return boolean + */ + @Override + public boolean doProcess(GameExchangeDTO gameExchangeMoney) { + TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager); + transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW); + Boolean result = transactionTemplate.execute(transactionStatus -> { + + //如果不是之前的步骤代码执行过了 + if (!gameExchangeMoney.getStep().equals(this.backStepProcessor().getCode())) { + return Boolean.TRUE; + } + //不是转入操作 + if (!TransferType.GAMES.getCode().equals(gameExchangeMoney.getExchangeType())) { + gameExchangeMoney.setStep(GameExchangeStep.DEDUCT_BALANCE.getCode()); + gameExchangeMoney.setStepStatus(GameExchangeStepStatus.SUCCESS.getCode()); + return gameExchangeMoneyService.updateGameExchangeMoney(gameExchangeMoney) > 0; + } + + Platform platform = platformService.get(gameExchangeMoney.getPlatformCode()); + KeyInfo keyInfo = null; + for (KeyInfo keyData : platform.getKeyInfo()) { + if (StringUtils.isNotEmpty(gameExchangeMoney.getCurrencyCode())) { + if (keyData.getCurrency().equalsIgnoreCase(gameExchangeMoney.getCurrencyCode())) { + keyInfo = keyData; + break; + } + } + } + BigDecimal decimal = tenantGameQuotaService.gameBalanceExchange(GameBalanceExchange.builder() + .platformCode(gameExchangeMoney.getPlatformCode()) + .sourceId(String.valueOf(gameExchangeMoney.getId())) + .currencyCode(gameExchangeMoney.getCurrencyCode()) + .currency(gameExchangeMoney.getCurrencyCode()) + .transferType(gameExchangeMoney.getExchangeType()) + .amount(gameExchangeMoney.getBalance()) + .account(memberService.selectMemberById(gameExchangeMoney.getMemberId()).getMemberAccount()) + .tenantKey(gameExchangeMoney.getTenantKey()) + .systemCurrency(gameExchangeMoney.getCurrencyCode()) + .agentId(keyInfo.getCode()) + .isAll(Boolean.TRUE) + .agentKey(keyInfo.getKey()) + .build()); + + gameExchangeMoney.setQuota(decimal); + + + gameExchangeMoney.setStep(GameExchangeStep.DEDUCT_BALANCE.getCode()); + gameExchangeMoney.setStepStatus(GameExchangeStepStatus.SUCCESS.getCode()); + return gameExchangeMoneyService.updateGameExchangeMoney(gameExchangeMoney) > 0; + }); + return Boolean.TRUE.equals(result); + } + + + /** + * 一定要回滚 + * + * @param gameExchangeMoney 游戏兑换货币 + * @return boolean + */ + @Override + public boolean doRollBack(GameExchangeDTO gameExchangeMoney) { + //如果不是之前的步骤代码执行过了 或者是转入操作 + if (!gameExchangeMoney.getStep().equals(this.stepKey().getCode())) { + return Boolean.TRUE; + } + TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager); + transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW); + List tenantGameQuotaFlows = tenantGameQuotaFlowService.selectTenantGameQuotaFlowList( + TenantGameQuotaFlow.builder() + .sourceId(String.valueOf(gameExchangeMoney.getId())) + .isOut(Boolean.FALSE) + .build()); + //取出第一个 + TenantGameQuotaFlow tenantGameQuotaFlow = tenantGameQuotaFlows.get(0); + return tenantGameQuotaService.balanceChanges(BalanceChangesDTO.builder() + .isOut(Boolean.TRUE) + .platformCode(tenantGameQuotaFlow.getPlatformCode()) + .currencyCode(tenantGameQuotaFlow.getCurrencyCode()) + .tenantKey(tenantGameQuotaFlow.getTenantKey()) + .balance(tenantGameQuotaFlow.getBalance()) + .sourceId(tenantGameQuotaFlow.getSourceId()) + .memberId(gameExchangeMoney.getMemberId()) + .operationType(OperationType.API_BALANCE.getCode()) + .remark(OperationType.API_BALANCE.getDescription()) + .quotaType(tenantGameQuotaFlow.getQuotaType()).build()); + } + + /** + * 下一步处理器 + * + * @return {@link GameExchangeStep } + */ + @Override + public GameExchangeStep nextStepProcessor() { + return GameExchangeStep.PLATFORM_TRANSACTION; + } + + /** + * 后级处理器 + * + * @return {@link GameExchangeStep } + */ + @Override + public GameExchangeStep backStepProcessor() { + { + return GameExchangeStep.CREATE_ORDER; + } + } + +} diff --git a/ff-game/src/main/java/com/ff/game/api/exchange/impl/PlatformTransactionServiceImpl.java b/ff-game/src/main/java/com/ff/game/api/exchange/impl/PlatformTransactionServiceImpl.java new file mode 100644 index 0000000..104decc --- /dev/null +++ b/ff-game/src/main/java/com/ff/game/api/exchange/impl/PlatformTransactionServiceImpl.java @@ -0,0 +1,221 @@ +package com.ff.game.api.exchange.impl; + +import com.ff.base.constant.Constants; +import com.ff.base.enums.*; +import com.ff.base.exception.base.ApiException; +import com.ff.base.utils.StringUtils; +import com.ff.common.domain.TenantGameQuotaFlow; +import com.ff.common.dto.BalanceChangesDTO; +import com.ff.common.dto.GameBalanceExchange; +import com.ff.common.service.ITenantGameQuotaFlowService; +import com.ff.common.service.ITenantGameQuotaService; +import com.ff.game.api.IGamesService; +import com.ff.game.api.exchange.AbstractStepProcessor; +import com.ff.game.api.exchange.dto.GameExchangeDTO; +import com.ff.game.api.request.ExchangeTransferMoneyRequestDTO; +import com.ff.game.api.request.ExchangeTransferStatusRequestDTO; +import com.ff.game.api.request.ExchangeTransferStatusResponseDTO; +import com.ff.game.domain.GameExchangeMoney; +import com.ff.game.domain.KeyInfo; +import com.ff.game.domain.Platform; +import com.ff.game.service.IGameExchangeMoneyService; +import com.ff.game.service.IPlatformService; +import com.ff.member.domain.Member; +import com.ff.member.service.IMemberService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.math.BigDecimal; +import java.util.List; +import java.util.Map; + + +/** + * 操作第三方扣减 + * + * @author shi + * @date 2025/04/09 + */ +@Service +@Order(3) +public class PlatformTransactionServiceImpl extends AbstractStepProcessor { + + + @Resource + private IGameExchangeMoneyService gameExchangeMoneyService; + + @Resource + private IMemberService memberService; + + @Resource + private IPlatformService platformService; + + @Autowired + private Map gamesService; + + /** + * 步进键 + * + * @return {@link GameExchangeStep } + */ + @Override + public GameExchangeStep stepKey() { + return GameExchangeStep.PLATFORM_TRANSACTION; + } + + + /** + * do过程 + * + * @param gameExchangeMoney 游戏兑换货币 + * @return boolean + */ + @Override + public boolean doProcess(GameExchangeDTO gameExchangeMoney) { + //如果不是之前的步骤代码执行过了 + if (!gameExchangeMoney.getStep().equals(this.backStepProcessor().getCode())) { + return Boolean.TRUE; + } + + + Platform platform = platformService.get(gameExchangeMoney.getPlatformCode()); + + String targetCurrency = platform.getCurrencyInfo().get(gameExchangeMoney.getCurrencyCode()); + ApiException.notNull(targetCurrency, ErrorCode.CURRENCY_NOT_EXIST.getCode()); + + KeyInfo keyInfo = null; + for (KeyInfo keyData : platform.getKeyInfo()) { + if (StringUtils.isNotEmpty(gameExchangeMoney.getCurrencyCode())) { + if (keyData.getCurrency().equalsIgnoreCase(gameExchangeMoney.getCurrencyCode())) { + keyInfo = keyData; + break; + } + } + } + Member member = memberService.selectMemberById(gameExchangeMoney.getMemberId()); + IGamesService iGamesService = gamesService.get(gameExchangeMoney.getPlatformCode() + Constants.SERVICE); + + //查询订单详情 + if (TriggerType.TIMER.getCode() == gameExchangeMoney.getTriggerType()) { + ExchangeTransferStatusRequestDTO exchangeTransferStatusRequestDTO = new ExchangeTransferStatusRequestDTO(); + exchangeTransferStatusRequestDTO.setAccount(member.getGameAccount()); + exchangeTransferStatusRequestDTO.setCurrency(targetCurrency); + exchangeTransferStatusRequestDTO.setOrderId(gameExchangeMoney.getTransactionId()); + exchangeTransferStatusRequestDTO.setAgentId(keyInfo.getCode()); + exchangeTransferStatusRequestDTO.setAgentKey(keyInfo.getKey()); + exchangeTransferStatusRequestDTO.setGameExchangeMoneyId(gameExchangeMoney.getId()); + exchangeTransferStatusRequestDTO.setVendor(platform); + exchangeTransferStatusRequestDTO.setKeyInfo(keyInfo); + exchangeTransferStatusRequestDTO.setSystemCurrency(gameExchangeMoney.getCurrencyCode()); + ExchangeTransferStatusResponseDTO statusResponseDTO = iGamesService.exchangeTransferStatus(exchangeTransferStatusRequestDTO); + //订单已成功 + if (StatusType.SUCCESS.getValue().equals(statusResponseDTO.getStatusType())) { + return Boolean.TRUE; + } + } + + try { + //操作第三方额度接口 + ExchangeTransferMoneyRequestDTO exchangeTransferMoneyRequestDTO = ExchangeTransferMoneyRequestDTO.builder() + .agentId(keyInfo.getCode()) + .agentKey(keyInfo.getKey()) + .account(member.getGameAccount()) + .currency(targetCurrency) + .amount(gameExchangeMoney.getBalance()) + .transferType(gameExchangeMoney.getExchangeType()) + .transactionId(gameExchangeMoney.getTransactionId()) + .gameExchangeId(gameExchangeMoney.getId()) + .vendor(platform) + .keyInfo(keyInfo) + .build(); + Long id = iGamesService.exchangeTransferByAgentId(exchangeTransferMoneyRequestDTO); + }catch (Exception e){ + //做二次确认调订单详情接口 + this.doRollBack(gameExchangeMoney); + if (GameExchangeStepStatus.FAILURE.getCode() == gameExchangeMoney.getStepStatus()){ + throw new ApiException(ErrorCode.BALANCE_TRANSFER_FAILED.getCode()); + } + } + + + GameExchangeMoney exchangeMoney = gameExchangeMoneyService.selectGameExchangeMoneyById(gameExchangeMoney.getId()); + gameExchangeMoney.setBalance(exchangeMoney.getBalance()); + gameExchangeMoney.setStep(exchangeMoney.getStep()); + gameExchangeMoney.setStepStatus(exchangeMoney.getStepStatus()); + return gameExchangeMoneyService.updateGameExchangeMoney(gameExchangeMoney) > 0; + } + + + /** + * 一定要回滚 + * + * @param gameExchangeMoney 游戏兑换货币 + * @return boolean + */ + @Override + public boolean doRollBack(GameExchangeDTO gameExchangeMoney) { + + Platform platform = platformService.get(gameExchangeMoney.getPlatformCode()); + + String targetCurrency = platform.getCurrencyInfo().get(gameExchangeMoney.getCurrencyCode()); + ApiException.notNull(targetCurrency, ErrorCode.CURRENCY_NOT_EXIST.getCode()); + + KeyInfo keyInfo = null; + for (KeyInfo keyData : platform.getKeyInfo()) { + if (StringUtils.isNotEmpty(gameExchangeMoney.getCurrencyCode())) { + if (keyData.getCurrency().equalsIgnoreCase(gameExchangeMoney.getCurrencyCode())) { + keyInfo = keyData; + break; + } + } + } + Member member = memberService.selectMemberById(gameExchangeMoney.getMemberId()); + IGamesService iGamesService = gamesService.get(gameExchangeMoney.getPlatformCode() + Constants.SERVICE); + + ExchangeTransferStatusRequestDTO exchangeTransferStatusRequestDTO = new ExchangeTransferStatusRequestDTO(); + exchangeTransferStatusRequestDTO.setAccount(member.getGameAccount()); + exchangeTransferStatusRequestDTO.setCurrency(targetCurrency); + exchangeTransferStatusRequestDTO.setOrderId(gameExchangeMoney.getTransactionId()); + exchangeTransferStatusRequestDTO.setAgentId(keyInfo.getCode()); + exchangeTransferStatusRequestDTO.setAgentKey(keyInfo.getKey()); + exchangeTransferStatusRequestDTO.setGameExchangeMoneyId(gameExchangeMoney.getId()); + exchangeTransferStatusRequestDTO.setVendor(platform); + exchangeTransferStatusRequestDTO.setKeyInfo(keyInfo); + exchangeTransferStatusRequestDTO.setSystemCurrency(gameExchangeMoney.getCurrencyCode()); + ExchangeTransferStatusResponseDTO statusResponseDTO = iGamesService.exchangeTransferStatus(exchangeTransferStatusRequestDTO); + //订单已成功 + if (StatusType.SUCCESS.getValue().equals(statusResponseDTO.getStatusType())) { + gameExchangeMoney.setStep(GameExchangeStep.PLATFORM_TRANSACTION.getCode()); + gameExchangeMoney.setStepStatus(GameExchangeStepStatus.SUCCESS.getCode()); + return gameExchangeMoneyService.updateGameExchangeMoney(gameExchangeMoney) > 0; + } + gameExchangeMoney.setStep(GameExchangeStep.PLATFORM_TRANSACTION.getCode()); + gameExchangeMoney.setStepStatus(GameExchangeStepStatus.FAILURE.getCode()); + return gameExchangeMoneyService.updateGameExchangeMoney(gameExchangeMoney) > 0; + } + + /** + * 下一步处理器 + * + * @return {@link GameExchangeStep } + */ + @Override + public GameExchangeStep nextStepProcessor() { + return GameExchangeStep.TENANT_QUOTA_DEDUCTED; + } + + /** + * 后级处理器 + * + * @return {@link GameExchangeStep } + */ + @Override + public GameExchangeStep backStepProcessor() { + { + return GameExchangeStep.DEDUCT_BALANCE; + } + } + +} diff --git a/ff-game/src/main/java/com/ff/game/api/fc/impl/GamesFCServiceImpl.java b/ff-game/src/main/java/com/ff/game/api/fc/impl/GamesFCServiceImpl.java index 1c4a951..d5a4f85 100644 --- a/ff-game/src/main/java/com/ff/game/api/fc/impl/GamesFCServiceImpl.java +++ b/ff-game/src/main/java/com/ff/game/api/fc/impl/GamesFCServiceImpl.java @@ -313,34 +313,7 @@ public class GamesFCServiceImpl implements IGamesService { log.info("GamesFCServiceImpl [exchangeTransferByAgentId] 请求参数 {}", exchangeTransferMoneyRequestDTO); - Member member = memberService.selectMemberByGameAccount(exchangeTransferMoneyRequestDTO.getAccount()); - String transactionId = gameExchangeMoneyService.getTransactionId(GamePlatforms.FC.getInfo(), 30); - List gameExchangeMonies = gameExchangeMoneyService.selectGameExchangeMoneyList( - GameExchangeMoney.builder() - .tenantKey(exchangeTransferMoneyRequestDTO.getTenantKey()) - .orderId(exchangeTransferMoneyRequestDTO.getOrderId()) - .build() - ); - Assert.isTrue(CollectionUtils.isEmpty(gameExchangeMonies), "订单号重复"); - - //获取下一个自增id - GameExchangeMoney exchangeMoney = GameExchangeMoney - .builder() - .tenantKey(exchangeTransferMoneyRequestDTO.getTenantKey()) - .orderId(exchangeTransferMoneyRequestDTO.getOrderId()) - .quota(exchangeTransferMoneyRequestDTO.getQuota()) - .balance(exchangeTransferMoneyRequestDTO.getAmount()) - .exchangeType(exchangeTransferMoneyRequestDTO.getTransferType()) - .currencyCode(exchangeTransferMoneyRequestDTO.getSystemCurrency()) - .memberId(member.getId()) - .transactionId(transactionId) - .platformCode(GamePlatforms.FC.getInfo()) - .build(); - exchangeMoney.setCreateBy(Constants.SYSTEM); - exchangeMoney.setStatus(StatusType.IN_PROGRESS.getValue()); - exchangeMoney.setStep(GameExchangeStep.CREATE_ORDER.getCode()); - exchangeMoney.setStepStatus(GameExchangeStepStatus.SUCCESS.getCode()); - gameExchangeMoneyService.insertGameExchangeMoney(exchangeMoney); + GameExchangeMoney exchangeMoney = gameExchangeMoneyService.selectGameExchangeMoneyById(exchangeTransferMoneyRequestDTO.getGameExchangeId()); //获取余额 @@ -352,7 +325,7 @@ public class GamesFCServiceImpl implements IGamesService { //获取当前游戏币 MemberInfoRequestDTO gamesBaseRequestDTO = MemberInfoRequestDTO.builder() - .accounts(member.getGameAccount()) + .accounts(exchangeTransferMoneyRequestDTO.getAccount()) .agentId(exchangeTransferMoneyRequestDTO.getAgentId()) .agentKey(exchangeTransferMoneyRequestDTO.getAgentKey()) .currency(exchangeTransferMoneyRequestDTO.getCurrency()) @@ -366,7 +339,7 @@ public class GamesFCServiceImpl implements IGamesService { Map paramsMap = new HashMap<>(); paramsMap.put("MemberAccount", exchangeTransferMoneyRequestDTO.getAccount()); - paramsMap.put("TrsID", transactionId); + paramsMap.put("TrsID", exchangeTransferMoneyRequestDTO.getTransactionId()); paramsMap.put("AllOut", type); paramsMap.put("Points", amount); paramsMap.putAll(getKeyMap(paramsMap, gamesBaseRequestDTO.getAgentKey(), gamesBaseRequestDTO.getCurrency(), gamesBaseRequestDTO.getAgentId())); diff --git a/ff-game/src/main/java/com/ff/game/api/jili/service/impl/GamesJILIServiceImpl.java b/ff-game/src/main/java/com/ff/game/api/jili/service/impl/GamesJILIServiceImpl.java index f82a544..367f30e 100644 --- a/ff-game/src/main/java/com/ff/game/api/jili/service/impl/GamesJILIServiceImpl.java +++ b/ff-game/src/main/java/com/ff/game/api/jili/service/impl/GamesJILIServiceImpl.java @@ -280,35 +280,10 @@ public class GamesJILIServiceImpl implements IGamesService { public Long exchangeTransferByAgentId(ExchangeTransferMoneyRequestDTO exchangeTransferMoneyRequestDTO) { Member member = memberService.selectMemberByGameAccount(exchangeTransferMoneyRequestDTO.getAccount()); - String transactionId = GamePlatforms.JILI.getInfo() + IdUtils.simpleUUID(); - - List gameExchangeMonies = gameExchangeMoneyService.selectGameExchangeMoneyList( - GameExchangeMoney.builder() - .tenantKey(exchangeTransferMoneyRequestDTO.getTenantKey()) - .orderId(exchangeTransferMoneyRequestDTO.getOrderId()) - .build() - ); - Assert.isTrue(CollectionUtils.isEmpty(gameExchangeMonies), "订单号重复"); + GameExchangeMoney exchangeMoney = gameExchangeMoneyService.selectGameExchangeMoneyById(exchangeTransferMoneyRequestDTO.getGameExchangeId()); + - //获取下一个自增id - GameExchangeMoney exchangeMoney = GameExchangeMoney - .builder() - .orderId(exchangeTransferMoneyRequestDTO.getOrderId()) - .tenantKey(exchangeTransferMoneyRequestDTO.getTenantKey()) - .quota(exchangeTransferMoneyRequestDTO.getQuota()) - .balance(exchangeTransferMoneyRequestDTO.getAmount()) - .exchangeType(exchangeTransferMoneyRequestDTO.getTransferType()) - .currencyCode(exchangeTransferMoneyRequestDTO.getSystemCurrency()) - .memberId(member.getId()) - .transactionId(transactionId) - .platformCode(GamePlatforms.JILI.getInfo()) - .build(); - exchangeMoney.setCreateBy(Constants.SYSTEM); - exchangeMoney.setStatus(StatusType.IN_PROGRESS.getValue()); - exchangeMoney.setStep(GameExchangeStep.CREATE_ORDER.getCode()); - exchangeMoney.setStepStatus(GameExchangeStepStatus.SUCCESS.getCode()); - gameExchangeMoneyService.insertGameExchangeMoney(exchangeMoney); String query = "Account=" + exchangeTransferMoneyRequestDTO.getAccount() diff --git a/ff-game/src/main/java/com/ff/game/api/km/impl/GamesKMServiceImpl.java b/ff-game/src/main/java/com/ff/game/api/km/impl/GamesKMServiceImpl.java index 6029bbc..07fb272 100644 --- a/ff-game/src/main/java/com/ff/game/api/km/impl/GamesKMServiceImpl.java +++ b/ff-game/src/main/java/com/ff/game/api/km/impl/GamesKMServiceImpl.java @@ -319,41 +319,17 @@ public class GamesKMServiceImpl implements IGamesService { log.info("GamesKMServiceImpl [exchangeTransferByAgentId] 请求参数 {}", exchangeTransferMoneyRequestDTO); - Member member = memberService.selectMemberByGameAccount(exchangeTransferMoneyRequestDTO.getAccount()); - String transactionId = GamePlatforms.KM.getInfo() + IdUtils.simpleUUID(); - List gameExchangeMonies = gameExchangeMoneyService.selectGameExchangeMoneyList( - GameExchangeMoney.builder() - .tenantKey(exchangeTransferMoneyRequestDTO.getTenantKey()) - .orderId(exchangeTransferMoneyRequestDTO.getOrderId()) - .build() - ); - Assert.isTrue(CollectionUtils.isEmpty(gameExchangeMonies), "订单号重复"); + GameExchangeMoney exchangeMoney = gameExchangeMoneyService.selectGameExchangeMoneyById(exchangeTransferMoneyRequestDTO.getGameExchangeId()); + + - //获取下一个自增id - GameExchangeMoney exchangeMoney = GameExchangeMoney - .builder() - .tenantKey(exchangeTransferMoneyRequestDTO.getTenantKey()) - .orderId(exchangeTransferMoneyRequestDTO.getOrderId()) - .quota(exchangeTransferMoneyRequestDTO.getQuota()) - .balance(exchangeTransferMoneyRequestDTO.getAmount()) - .exchangeType(exchangeTransferMoneyRequestDTO.getTransferType()) - .currencyCode(exchangeTransferMoneyRequestDTO.getSystemCurrency()) - .memberId(member.getId()) - .transactionId(transactionId) - .platformCode(GamePlatforms.KM.getInfo()) - .build(); - exchangeMoney.setCreateBy(Constants.SYSTEM); - exchangeMoney.setStatus(StatusType.IN_PROGRESS.getValue()); - exchangeMoney.setStep(GameExchangeStep.CREATE_ORDER.getCode()); - exchangeMoney.setStepStatus(GameExchangeStepStatus.SUCCESS.getCode()); - gameExchangeMoneyService.insertGameExchangeMoney(exchangeMoney); BigDecimal amount = exchangeTransferMoneyRequestDTO.getAmount(); if (TransferType.ALL.getCode().equals(exchangeTransferMoneyRequestDTO.getTransferType())) { // 获取第三方钱包余额 MemberInfoRequestDTO gamesBaseRequestDTO = MemberInfoRequestDTO.builder() - .accounts(member.getGameAccount()) + .accounts(exchangeTransferMoneyRequestDTO.getAccount()) .agentId(exchangeTransferMoneyRequestDTO.getAgentId()) .currency(exchangeTransferMoneyRequestDTO.getCurrency()) .agentKey(exchangeTransferMoneyRequestDTO.getAgentKey()) @@ -366,7 +342,7 @@ public class GamesKMServiceImpl implements IGamesService { params.put("userid", exchangeTransferMoneyRequestDTO.getAccount()); params.put("amt", amount); params.put("cur", exchangeTransferMoneyRequestDTO.getCurrency()); - params.put("txid", transactionId); + params.put("txid", exchangeTransferMoneyRequestDTO.getTransactionId()); Map headerMap = this.getKey(exchangeTransferMoneyRequestDTO); KMTransactionResponse kmTransactionResponse; diff --git a/ff-game/src/main/java/com/ff/game/api/meitian/impl/MeiTianGameServiceImpl.java b/ff-game/src/main/java/com/ff/game/api/meitian/impl/MeiTianGameServiceImpl.java index c01c1aa..8ebe789 100644 --- a/ff-game/src/main/java/com/ff/game/api/meitian/impl/MeiTianGameServiceImpl.java +++ b/ff-game/src/main/java/com/ff/game/api/meitian/impl/MeiTianGameServiceImpl.java @@ -267,35 +267,10 @@ public class MeiTianGameServiceImpl implements IGamesService { public Long exchangeTransferByAgentId(ExchangeTransferMoneyRequestDTO exchangeTransferMoneyRequestDTO) { Member member = memberService.selectMemberByGameAccount(exchangeTransferMoneyRequestDTO.getAccount()); - String transactionId = GamePlatforms.MT.getCode() + IdUtils.simpleUUID(); - - List gameExchangeMonies = gameExchangeMoneyService.selectGameExchangeMoneyList( - GameExchangeMoney.builder() - .tenantKey(exchangeTransferMoneyRequestDTO.getTenantKey()) - .orderId(exchangeTransferMoneyRequestDTO.getOrderId()) - .build() - ); - Assert.isTrue(CollectionUtils.isEmpty(gameExchangeMonies), "订单号重复"); + GameExchangeMoney exchangeMoney = gameExchangeMoneyService.selectGameExchangeMoneyById(exchangeTransferMoneyRequestDTO.getGameExchangeId()); + - //获取下一个自增id - GameExchangeMoney exchangeMoney = GameExchangeMoney - .builder() - .orderId(exchangeTransferMoneyRequestDTO.getOrderId()) - .tenantKey(exchangeTransferMoneyRequestDTO.getTenantKey()) - .quota(exchangeTransferMoneyRequestDTO.getQuota()) - .balance(exchangeTransferMoneyRequestDTO.getAmount()) - .exchangeType(exchangeTransferMoneyRequestDTO.getTransferType()) - .currencyCode(exchangeTransferMoneyRequestDTO.getSystemCurrency()) - .memberId(member.getId()) - .transactionId(transactionId) - .platformCode(GamePlatforms.MT.getCode()) - .build(); - exchangeMoney.setCreateBy(Constants.SYSTEM); - exchangeMoney.setStatus(StatusType.IN_PROGRESS.getValue()); - exchangeMoney.setStep(GameExchangeStep.CREATE_ORDER.getCode()); - exchangeMoney.setStepStatus(GameExchangeStepStatus.SUCCESS.getCode()); - gameExchangeMoneyService.insertGameExchangeMoney(exchangeMoney); String key = exchangeTransferMoneyRequestDTO.getAgentKey(); String merchantId = exchangeTransferMoneyRequestDTO.getAgentId(); @@ -314,7 +289,7 @@ public class MeiTianGameServiceImpl implements IGamesService { Map rawMap = new LinkedHashMap<>(); rawMap.put("merchantId", merchantId); rawMap.put("playerName", playerName); - rawMap.put("extTransId", transactionId); + rawMap.put("extTransId", exchangeTransferMoneyRequestDTO.getTransactionId()); rawMap.put("coins", coins); String rawData = JSON.toJSONString(rawMap); String data = null; @@ -333,7 +308,7 @@ public class MeiTianGameServiceImpl implements IGamesService { merchantId, playerName, coins, - transactionId, + exchangeTransferMoneyRequestDTO.getTransactionId(), md5Code, data ); @@ -366,7 +341,7 @@ public class MeiTianGameServiceImpl implements IGamesService { merchantId, playerName, coins, - transactionId, + exchangeTransferMoneyRequestDTO.getTransactionId(), md5Code, data ); diff --git a/ff-game/src/main/java/com/ff/game/api/ng/service/impl/GamesPGServiceImpl.java b/ff-game/src/main/java/com/ff/game/api/ng/service/impl/GamesPGServiceImpl.java index c1b9208..9c950c5 100644 --- a/ff-game/src/main/java/com/ff/game/api/ng/service/impl/GamesPGServiceImpl.java +++ b/ff-game/src/main/java/com/ff/game/api/ng/service/impl/GamesPGServiceImpl.java @@ -285,41 +285,15 @@ public class GamesPGServiceImpl implements IGamesService { log.info("GamesNGServiceImpl [exchangeTransferByAgentId] 请求参数 {}", exchangeTransferMoneyRequestDTO); - Member member = memberService.selectMemberByGameAccount(exchangeTransferMoneyRequestDTO.getAccount()); - String transactionId = gameExchangeMoneyService.getTransactionId(GamePlatforms.PG.getCode(), 32); - List gameExchangeMonies = gameExchangeMoneyService.selectGameExchangeMoneyList( - GameExchangeMoney.builder() - .tenantKey(exchangeTransferMoneyRequestDTO.getTenantKey()) - .orderId(exchangeTransferMoneyRequestDTO.getOrderId()) - .build() - ); - Assert.isTrue(CollectionUtils.isEmpty(gameExchangeMonies), "订单号重复"); + GameExchangeMoney exchangeMoney = gameExchangeMoneyService.selectGameExchangeMoneyById(exchangeTransferMoneyRequestDTO.getGameExchangeId()); - //获取下一个自增id - GameExchangeMoney exchangeMoney = GameExchangeMoney - .builder() - .tenantKey(exchangeTransferMoneyRequestDTO.getTenantKey()) - .orderId(exchangeTransferMoneyRequestDTO.getOrderId()) - .quota(exchangeTransferMoneyRequestDTO.getQuota()) - .balance(exchangeTransferMoneyRequestDTO.getAmount()) - .exchangeType(exchangeTransferMoneyRequestDTO.getTransferType()) - .currencyCode(exchangeTransferMoneyRequestDTO.getSystemCurrency()) - .memberId(member.getId()) - .transactionId(transactionId) - .platformCode(GamePlatforms.PG.getCode()) - .build(); - exchangeMoney.setCreateBy(Constants.SYSTEM); - exchangeMoney.setStatus(StatusType.IN_PROGRESS.getValue()); - exchangeMoney.setStep(GameExchangeStep.CREATE_ORDER.getCode()); - exchangeMoney.setStepStatus(GameExchangeStepStatus.SUCCESS.getCode()); - gameExchangeMoneyService.insertGameExchangeMoney(exchangeMoney); //获取余额 String type = TransferType.ALL.getCode().equals(exchangeTransferMoneyRequestDTO.getTransferType()) ? NGTransferType.TRANSFER_OUT.getValue() : NGTransferType.TRANSFER_IN.getValue(); //获取当前游戏币 MemberInfoRequestDTO gamesBaseRequestDTO = MemberInfoRequestDTO.builder() - .accounts(member.getGameAccount()) + .accounts(exchangeTransferMoneyRequestDTO.getAccount()) .agentId(exchangeTransferMoneyRequestDTO.getAgentId()) .agentKey(exchangeTransferMoneyRequestDTO.getAgentKey()) .currency(exchangeTransferMoneyRequestDTO.getCurrency()) @@ -337,7 +311,7 @@ public class GamesPGServiceImpl implements IGamesService { paramsMap.put("currency", exchangeTransferMoneyRequestDTO.getCurrency()); paramsMap.put("type", type); paramsMap.put("amount", exchangeTransferMoneyRequestDTO.getAmount()); - paramsMap.put("orderId", transactionId); + paramsMap.put("orderId", exchangeTransferMoneyRequestDTO.getTransactionId()); Map key = this.getKey(exchangeTransferMoneyRequestDTO); diff --git a/ff-game/src/main/java/com/ff/game/api/pgt/impl/GamesPGTServiceImpl.java b/ff-game/src/main/java/com/ff/game/api/pgt/impl/GamesPGTServiceImpl.java index 02f89a9..f95ced5 100644 --- a/ff-game/src/main/java/com/ff/game/api/pgt/impl/GamesPGTServiceImpl.java +++ b/ff-game/src/main/java/com/ff/game/api/pgt/impl/GamesPGTServiceImpl.java @@ -268,39 +268,11 @@ public class GamesPGTServiceImpl implements IGamesService { public Long exchangeTransferByAgentId(ExchangeTransferMoneyRequestDTO exchangeTransferMoneyRequestDTO) { log.info("GamesPGTServiceImpl [exchangeTransferByAgentId] 请求参数 {}", exchangeTransferMoneyRequestDTO); - String currency = exchangeTransferMoneyRequestDTO.getCurrency(); - Member member = memberService.selectMemberByGameAccount(exchangeTransferMoneyRequestDTO.getAccount()); - String transactionId = gameExchangeMoneyService.getTransactionId(GamePlatforms.PGX.getInfo(), 17); - List gameExchangeMonies = gameExchangeMoneyService.selectGameExchangeMoneyList( - GameExchangeMoney.builder() - .tenantKey(exchangeTransferMoneyRequestDTO.getTenantKey()) - .orderId(exchangeTransferMoneyRequestDTO.getOrderId()) - .build() - ); - Assert.isTrue(CollectionUtils.isEmpty(gameExchangeMonies), "订单号重复"); + GameExchangeMoney exchangeMoney = gameExchangeMoneyService.selectGameExchangeMoneyById(exchangeTransferMoneyRequestDTO.getGameExchangeId()); - //获取下一个自增id - GameExchangeMoney exchangeMoney = GameExchangeMoney - .builder() - .tenantKey(exchangeTransferMoneyRequestDTO.getTenantKey()) - .orderId(exchangeTransferMoneyRequestDTO.getOrderId()) - .quota(exchangeTransferMoneyRequestDTO.getQuota()) - .balance(exchangeTransferMoneyRequestDTO.getAmount()) - .exchangeType(exchangeTransferMoneyRequestDTO.getTransferType()) - .currencyCode(currency) - .memberId(member.getId()) - .transactionId(transactionId) - .platformCode(GamePlatforms.PGT.getInfo()) - .build(); - exchangeMoney.setCreateBy(Constants.SYSTEM); - exchangeMoney.setStatus(StatusType.IN_PROGRESS.getValue()); - exchangeMoney.setStep(GameExchangeStep.CREATE_ORDER.getCode()); - exchangeMoney.setStepStatus(GameExchangeStepStatus.SUCCESS.getCode()); - gameExchangeMoneyService.insertGameExchangeMoney(exchangeMoney); - BigDecimal amount = exchangeTransferMoneyRequestDTO.getAmount(); BigDecimal amountBefore = BigDecimal.ZERO; @@ -322,7 +294,7 @@ public class GamesPGTServiceImpl implements IGamesService { Map paramsMap = new LinkedHashMap<>(); paramsMap.put("username", exchangeTransferMoneyRequestDTO.getAccount()); paramsMap.put("amount", amount.setScale(2, RoundingMode.DOWN).toString()); - paramsMap.put("transactionRef", transactionId); + paramsMap.put("transactionRef", exchangeTransferMoneyRequestDTO.getTransactionId()); paramsMap.put("productId", productId); Map key = this.getKey(exchangeTransferMoneyRequestDTO); PGTExchangeTransferResponse errorResponse; diff --git a/ff-game/src/main/java/com/ff/game/api/pgx/impl/GamesPGXServiceImpl.java b/ff-game/src/main/java/com/ff/game/api/pgx/impl/GamesPGXServiceImpl.java index 65c4e08..a125396 100644 --- a/ff-game/src/main/java/com/ff/game/api/pgx/impl/GamesPGXServiceImpl.java +++ b/ff-game/src/main/java/com/ff/game/api/pgx/impl/GamesPGXServiceImpl.java @@ -278,35 +278,9 @@ public class GamesPGXServiceImpl implements IGamesService { log.info("GamesPGXServiceImpl [exchangeTransferByAgentId] 请求参数 {}", exchangeTransferMoneyRequestDTO); - Member member = memberService.selectMemberByGameAccount(exchangeTransferMoneyRequestDTO.getAccount()); - String transactionId = gameExchangeMoneyService.getTransactionId(GamePlatforms.PGX.getInfo(), 17); - List gameExchangeMonies = gameExchangeMoneyService.selectGameExchangeMoneyList( - GameExchangeMoney.builder() - .tenantKey(exchangeTransferMoneyRequestDTO.getTenantKey()) - .orderId(exchangeTransferMoneyRequestDTO.getOrderId()) - .build() - ); - Assert.isTrue(CollectionUtils.isEmpty(gameExchangeMonies), "订单号重复"); + GameExchangeMoney exchangeMoney = gameExchangeMoneyService.selectGameExchangeMoneyById(exchangeTransferMoneyRequestDTO.getGameExchangeId()); - //获取下一个自增id - GameExchangeMoney exchangeMoney = GameExchangeMoney - .builder() - .tenantKey(exchangeTransferMoneyRequestDTO.getTenantKey()) - .orderId(exchangeTransferMoneyRequestDTO.getOrderId()) - .quota(exchangeTransferMoneyRequestDTO.getQuota()) - .balance(exchangeTransferMoneyRequestDTO.getAmount()) - .exchangeType(exchangeTransferMoneyRequestDTO.getTransferType()) - .currencyCode(exchangeTransferMoneyRequestDTO.getSystemCurrency()) - .memberId(member.getId()) - .transactionId(transactionId) - .platformCode(GamePlatforms.PGX.getInfo()) - .build(); - exchangeMoney.setCreateBy(Constants.SYSTEM); - exchangeMoney.setStatus(StatusType.IN_PROGRESS.getValue()); - exchangeMoney.setStep(GameExchangeStep.CREATE_ORDER.getCode()); - exchangeMoney.setStepStatus(GameExchangeStepStatus.SUCCESS.getCode()); - gameExchangeMoneyService.insertGameExchangeMoney(exchangeMoney); //获取余额 String type = TransferType.ALL.getCode().equals(exchangeTransferMoneyRequestDTO.getTransferType()) ? PGXTransferType.WITHDRAW.getCode() : PGXTransferType.DEPOSIT.getCode(); @@ -339,7 +313,7 @@ public class GamesPGXServiceImpl implements IGamesService { paramsMap.put("operatorcode", exchangeTransferMoneyRequestDTO.getAgentId()); paramsMap.put("password", keyInfo.getPassword()); paramsMap.put("providercode", keyInfo.getProviderCode()); - paramsMap.put("referenceid", transactionId); + paramsMap.put("referenceid", exchangeTransferMoneyRequestDTO.getTransactionId()); paramsMap.put("type", type); paramsMap.put("username", exchangeTransferMoneyRequestDTO.getAccount()); String key = this.getKey(paramsMap, exchangeTransferMoneyRequestDTO); diff --git a/ff-game/src/main/java/com/ff/game/api/request/ExchangeTransferMoneyRequestDTO.java b/ff-game/src/main/java/com/ff/game/api/request/ExchangeTransferMoneyRequestDTO.java index b9b1dfa..fcd104c 100644 --- a/ff-game/src/main/java/com/ff/game/api/request/ExchangeTransferMoneyRequestDTO.java +++ b/ff-game/src/main/java/com/ff/game/api/request/ExchangeTransferMoneyRequestDTO.java @@ -27,15 +27,7 @@ public class ExchangeTransferMoneyRequestDTO extends GamesBaseRequestDTO { */ private String account; - /** - * 租户密钥 - */ - private String tenantKey; - /** - * 订单id - */ - private String orderId; /** * 金额 */ @@ -43,9 +35,14 @@ public class ExchangeTransferMoneyRequestDTO extends GamesBaseRequestDTO { /** - * 租户额度 + * 游戏交换id */ - private BigDecimal quota; + private Long gameExchangeId; + + /** + * 交易编号 + */ + private String transactionId; /** diff --git a/ff-game/src/main/java/com/ff/game/api/sa/impl/GamesSAServiceImpl.java b/ff-game/src/main/java/com/ff/game/api/sa/impl/GamesSAServiceImpl.java index c697f95..8b44bdc 100644 --- a/ff-game/src/main/java/com/ff/game/api/sa/impl/GamesSAServiceImpl.java +++ b/ff-game/src/main/java/com/ff/game/api/sa/impl/GamesSAServiceImpl.java @@ -256,45 +256,15 @@ public class GamesSAServiceImpl implements IGamesService { public Long exchangeTransferByAgentId(ExchangeTransferMoneyRequestDTO exchangeTransferMoneyRequestDTO) { log.info("GamesSAServiceImpl [exchangeTransferByAgentId] 请求参数 {}", exchangeTransferMoneyRequestDTO); - Member member = memberService.selectMemberByGameAccount(exchangeTransferMoneyRequestDTO.getAccount()); - List gameExchangeMonies = gameExchangeMoneyService.selectGameExchangeMoneyList( - GameExchangeMoney.builder() - .tenantKey(exchangeTransferMoneyRequestDTO.getTenantKey()) - .orderId(exchangeTransferMoneyRequestDTO.getOrderId()) - .build() - ); - Assert.isTrue(CollectionUtils.isEmpty(gameExchangeMonies), "订单号重复"); - //判断是转入还是转出 - String transactionId = "OUT" + DateUtils.dateTimeNow() + exchangeTransferMoneyRequestDTO.getAccount(); - if (!TransferType.ALL.getCode().equals(exchangeTransferMoneyRequestDTO.getTransferType())) { - transactionId = "IN" + DateUtils.dateTimeNow() + exchangeTransferMoneyRequestDTO.getAccount(); - } + GameExchangeMoney exchangeMoney = gameExchangeMoneyService.selectGameExchangeMoneyById(exchangeTransferMoneyRequestDTO.getGameExchangeId()); - //获取下一个自增id - GameExchangeMoney exchangeMoney = GameExchangeMoney - .builder() - .tenantKey(exchangeTransferMoneyRequestDTO.getTenantKey()) - .orderId(exchangeTransferMoneyRequestDTO.getOrderId()) - .quota(exchangeTransferMoneyRequestDTO.getQuota()) - .balance(exchangeTransferMoneyRequestDTO.getAmount()) - .exchangeType(exchangeTransferMoneyRequestDTO.getTransferType()) - .currencyCode(exchangeTransferMoneyRequestDTO.getSystemCurrency()) - .memberId(member.getId()) - .transactionId(transactionId) - .platformCode(GamePlatforms.SA.getInfo()) - .build(); - exchangeMoney.setCreateBy(Constants.SYSTEM); - exchangeMoney.setStatus(StatusType.IN_PROGRESS.getValue()); - exchangeMoney.setStep(GameExchangeStep.CREATE_ORDER.getCode()); - exchangeMoney.setStepStatus(GameExchangeStepStatus.SUCCESS.getCode()); - gameExchangeMoneyService.insertGameExchangeMoney(exchangeMoney); if (TransferType.ALL.getCode().equals(exchangeTransferMoneyRequestDTO.getTransferType())) { Map params = new LinkedHashMap<>(); params.put("Username", exchangeTransferMoneyRequestDTO.getAccount()); - params.put("OrderId", exchangeMoney.getTransactionId()); + params.put("OrderId", exchangeTransferMoneyRequestDTO.getTransactionId()); String query = JsonUtil.mapToQueryString(params); exchangeTransferMoneyRequestDTO.setQuery(query); String key = this.getKey(exchangeTransferMoneyRequestDTO, "DebitAllBalanceDV"); @@ -324,7 +294,7 @@ public class GamesSAServiceImpl implements IGamesService { } else { Map params = new LinkedHashMap<>(); params.put("Username", exchangeTransferMoneyRequestDTO.getAccount()); - params.put("OrderId", exchangeMoney.getTransactionId()); + params.put("OrderId", exchangeTransferMoneyRequestDTO.getTransactionId()); params.put("CreditAmount", exchangeTransferMoneyRequestDTO.getAmount().stripTrailingZeros().toPlainString()); params.put("CurrencyType", exchangeTransferMoneyRequestDTO.getCurrency()); String query = JsonUtil.mapToQueryString(params); diff --git a/ff-game/src/main/java/com/ff/game/api/xk/client/XKClient.java b/ff-game/src/main/java/com/ff/game/api/xk/client/XKClient.java index af567fd..d84a42f 100644 --- a/ff-game/src/main/java/com/ff/game/api/xk/client/XKClient.java +++ b/ff-game/src/main/java/com/ff/game/api/xk/client/XKClient.java @@ -61,6 +61,16 @@ public interface XKClient { @Post(url = "/exchangeTransferByAgentId") XKExchangeMoneyResponseDTO exchangeTransferByAgentId( @JSONBody Map params); + + /** + * 按代理id进行交换转账 + * + * @param params 参数 + * @return {@link XKCheckTransferByTransactionIdDTO } + */ + @Post(url = "/getTransferRecordByTransactionId") + XKCheckTransferByTransactionIdDTO checkTransferByTransactionId( @JSONBody Map params); + /** * 按时间获取投注记录 * diff --git a/ff-game/src/main/java/com/ff/game/api/xk/dto/XKCheckTransferByTransactionIdDTO.java b/ff-game/src/main/java/com/ff/game/api/xk/dto/XKCheckTransferByTransactionIdDTO.java new file mode 100644 index 0000000..8c8cabd --- /dev/null +++ b/ff-game/src/main/java/com/ff/game/api/xk/dto/XKCheckTransferByTransactionIdDTO.java @@ -0,0 +1,76 @@ +package com.ff.game.api.xk.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; + +import java.math.BigDecimal; + +/** + * xkcheck按交易id dto转账 + * + * @author shi + * @date 2025/04/09 + */ +@Data +public class XKCheckTransferByTransactionIdDTO { + /** + * 响应码 + */ + @JsonProperty("code") + private Integer code; + + /** + * 响应消息 + */ + @JsonProperty("msg") + private String msg; + + /** + * 响应数据 + */ + @JsonProperty("data") + private TransactionData data; + + /** + * 交易数据 + */ + @Data + public static class TransactionData { + + /** + * 会员唯一识别值 + */ + @JsonProperty("account") + private String account; + + /** + * 交易序号,额度转移纪录唯一值 + */ + @JsonProperty("transactionId") + private String transactionId; + + /** + * 交易时间(时间戳,单位毫秒) + */ + @JsonProperty("transferTime") + private Long transferTime; + + /** + * 交易金额(Decimal(16,4)) + */ + @JsonProperty("amount") + private BigDecimal amount; + + /** + * 转账类型 + */ + @JsonProperty("transferType") + private Integer transferType; + + /** + * 状态 + */ + @JsonProperty("status") + private Integer status; + } +} diff --git a/ff-game/src/main/java/com/ff/game/api/xk/service/impl/GamesXKServiceImpl.java b/ff-game/src/main/java/com/ff/game/api/xk/service/impl/GamesXKServiceImpl.java index 3a39919..ce73a29 100644 --- a/ff-game/src/main/java/com/ff/game/api/xk/service/impl/GamesXKServiceImpl.java +++ b/ff-game/src/main/java/com/ff/game/api/xk/service/impl/GamesXKServiceImpl.java @@ -188,7 +188,7 @@ public class GamesXKServiceImpl implements IGamesService { params.put("key", key); params.put("disableFullScreen", gamesLogin.getDisableFullScreen()); params.put("homeUrl", gamesLogin.getHomeUrl()); - params.put("platform", gamesLogin.getVendor()); + params.put("platform", gamesLogin.getPlatform()); XKLoginWithoutRedirectResponseDTO xkLoginWithoutRedirectResponseDTO = xkClient.loginWithoutRedirect(params); //判断是否获取成功 if (this.getIsSuccess(xkLoginWithoutRedirectResponseDTO.getCode())) { @@ -243,7 +243,7 @@ public class GamesXKServiceImpl implements IGamesService { game.setPlatformType(platformType); game.setGameName(gamesDataDTO.getName()); game.setCreateBy(Constants.SYSTEM); - game.setGameId(StringUtils.addSuffix(GamePlatforms.SA.getCode(), 1)); + game.setGameId(StringUtils.addSuffix(GamePlatforms.XK.getCode(), gamesDataDTO.getGameId())); List nameInfos = new ArrayList<>(); nameInfos.add(new NameInfo(gamesDataDTO.getName(), "zh-CN")); game.setNameInfo(nameInfos); @@ -276,40 +276,16 @@ public class GamesXKServiceImpl implements IGamesService { @Transactional public Long exchangeTransferByAgentId(ExchangeTransferMoneyRequestDTO exchangeTransferMoneyRequestDTO) { log.info("GamesXKServiceImpl [exchangeTransferByAgentId] 请求参数 {}", exchangeTransferMoneyRequestDTO); -// GameSecretKeyCurrency currencyDTO = gameSecretKeyCurrencyService.findByGameSecretKeyCurrencyDTO(GameSecretKeyCurrencyDTO.builder() -// .platformCode(GamePlatforms.XK.getInfo()) -// .code(exchangeTransferMoneyRequestDTO.getAgentId()) -// .build()); - Member member = memberService.selectMemberByGameAccount(exchangeTransferMoneyRequestDTO.getAccount()); - String transactionId = GamePlatforms.XK.getCode() + IdUtils.simpleUUID(); - List gameExchangeMonies = gameExchangeMoneyService.selectGameExchangeMoneyList( - GameExchangeMoney.builder() - .tenantKey(exchangeTransferMoneyRequestDTO.getTenantKey()) - .orderId(exchangeTransferMoneyRequestDTO.getOrderId()) - .build() - ); - Assert.isTrue(CollectionUtils.isEmpty(gameExchangeMonies), "订单号重复"); - //获取下一个自增id - GameExchangeMoney exchangeMoney = GameExchangeMoney - .builder() - .tenantKey(exchangeTransferMoneyRequestDTO.getTenantKey()) - .orderId(exchangeTransferMoneyRequestDTO.getOrderId()) - .quota(exchangeTransferMoneyRequestDTO.getQuota()) - .balance(exchangeTransferMoneyRequestDTO.getAmount()) - .exchangeType(exchangeTransferMoneyRequestDTO.getTransferType()) - .currencyCode(exchangeTransferMoneyRequestDTO.getSystemCurrency()) - .memberId(member.getId()) - .transactionId(transactionId) - .platformCode(GamePlatforms.XK.getCode()) - .build(); - exchangeMoney.setCreateBy(Constants.SYSTEM); - //接口限制限制50字符 - exchangeMoney.setTransactionId(GamePlatforms.XK.getCode() + IdUtils.simpleUUID()); + GameExchangeMoney exchangeMoney = gameExchangeMoneyService.selectGameExchangeMoneyById(exchangeTransferMoneyRequestDTO.getGameExchangeId()); + + + + Map params = new LinkedHashMap<>(); params.put("account", exchangeTransferMoneyRequestDTO.getAccount()); - params.put("transactionId", exchangeMoney.getTransactionId()); + params.put("transactionId", exchangeTransferMoneyRequestDTO.getTransactionId()); params.put("amount", exchangeTransferMoneyRequestDTO.getAmount().stripTrailingZeros().toPlainString()); params.put("transferType", exchangeTransferMoneyRequestDTO.getTransferType()); params.put("agentId", exchangeTransferMoneyRequestDTO.getAgentId()); @@ -329,9 +305,16 @@ public class GamesXKServiceImpl implements IGamesService { exchangeMoney.setCoinAfter(exchangeMoneyResponseData.getCoinAfter()); exchangeMoney.setCurrencyBefore(exchangeMoneyResponseData.getCurrencyBefore()); exchangeMoney.setCurrencyAfter(exchangeMoneyResponseData.getCurrencyAfter()); - exchangeMoney.setStatus(exchangeMoneyResponseData.getStatus()); - gameExchangeMoneyService.insertGameExchangeMoney(exchangeMoney); + + exchangeMoney.setStep(GameExchangeStep.PLATFORM_TRANSACTION.getCode()); + exchangeMoney.setStepStatus(exchangeMoneyResponseData.getStatus()); + gameExchangeMoneyService.updateGameExchangeMoney(exchangeMoney); + } else { + exchangeMoney.setStep(GameExchangeStep.PLATFORM_TRANSACTION.getCode()); + exchangeMoney.setStepStatus(GameExchangeStepStatus.FAILURE.getCode()); + gameExchangeMoneyService.updateGameExchangeMoney(exchangeMoney); + log.error("GamesXKServiceImpl [exchangeTransferByAgentId] 金额转移失败,错误代码{},错误信息{}", exchangeMoneyResponse.getCode(), exchangeMoneyResponse.getMsg()); throw new BaseException(exchangeMoneyResponse.getMsg()); } @@ -347,7 +330,27 @@ public class GamesXKServiceImpl implements IGamesService { */ @Override public ExchangeTransferStatusResponseDTO exchangeTransferStatus(ExchangeTransferStatusRequestDTO exchangeTransferMoneyRequestDTO) { - return new ExchangeTransferStatusResponseDTO(); + Map params = new LinkedHashMap<>(); + params.put("transactionId", exchangeTransferMoneyRequestDTO.getOrderId()); + params.put("agentId", exchangeTransferMoneyRequestDTO.getAgentId()); + String query = JsonUtil.mapToQueryString(params); + exchangeTransferMoneyRequestDTO.setQuery(query); + String key = this.getKey(exchangeTransferMoneyRequestDTO); + params.put("key", key); + XKCheckTransferByTransactionIdDTO xkCheckTransferByTransactionIdDTO = xkClient.checkTransferByTransactionId(params); + //判断是否转移成功 + if (this.getIsSuccess(xkCheckTransferByTransactionIdDTO.getCode())) { + XKCheckTransferByTransactionIdDTO.TransactionData data = xkCheckTransferByTransactionIdDTO.getData(); + return ExchangeTransferStatusResponseDTO.builder() + .statusType(data.getStatus()) + .balance(data.getAmount()) + .build(); + } else { + return ExchangeTransferStatusResponseDTO.builder() + .statusType(StatusType.FAILURE.getValue()) + .build(); + } + } @@ -359,7 +362,6 @@ public class GamesXKServiceImpl implements IGamesService { */ @Override public Boolean getBetRecordByTime(BetRecordByTimeDTO betRecordByTimeDTO) { -// List gameBettingDetails = new ArrayList<>(); //请求参数 log.info("GamesXKServiceImpl [getBetRecordByTime] 请求参数 {}", betRecordByTimeDTO); Map params = new LinkedHashMap<>(); @@ -416,7 +418,51 @@ public class GamesXKServiceImpl implements IGamesService { */ @Override public Boolean getBetRecordByHistoryTime(BetRecordByTimeDTO betRecordByTimeDTO) { - return null; + //请求参数 + log.info("GamesXKServiceImpl [getBetRecordByHistoryTime] 请求参数 {}", betRecordByTimeDTO); + Map params = new LinkedHashMap<>(); + params.put("startTime", betRecordByTimeDTO.getStartTime()); + params.put("endTime", betRecordByTimeDTO.getEndTime()); + params.put("page", betRecordByTimeDTO.getPage()); + params.put("pageLimit", betRecordByTimeDTO.getPageLimit()); + params.put("agentId", betRecordByTimeDTO.getAgentId()); + String query = JsonUtil.mapToQueryString(params); + betRecordByTimeDTO.setQuery(query); + String key = this.getKey(betRecordByTimeDTO); + params.put("key", key); + XKBetRecordResponseDTO xkBetRecordResponseDTO = xkClient.getBetRecordByTime(params); + + //判断是否获取成功 + if (this.getIsSuccess(xkBetRecordResponseDTO.getCode())) { + //数据组装 + XKBetRecordResponseDTO.DataBean dataBean = xkBetRecordResponseDTO.getData(); + this.batchInsert(xkBetRecordResponseDTO, betRecordByTimeDTO); + + //获取下一页数据 + while (!Objects.equals(dataBean.getCurrentPage(), dataBean.getTotalPages()) && dataBean.getTotalPages() > 0) { + betRecordByTimeDTO.setPage(dataBean.getCurrentPage() + 1); + //请求参数 + params = new LinkedHashMap<>(); + params.put("startTime", betRecordByTimeDTO.getStartTime()); + params.put("endTime", betRecordByTimeDTO.getEndTime()); + params.put("page", betRecordByTimeDTO.getPage()); + params.put("pageLimit", betRecordByTimeDTO.getPageLimit()); + params.put("agentId", betRecordByTimeDTO.getAgentId()); + query = JsonUtil.mapToQueryString(params); + betRecordByTimeDTO.setQuery(query); + key = this.getKey(betRecordByTimeDTO); + params.put("key", key); + xkBetRecordResponseDTO = xkClient.getBetRecordByTime(params); + dataBean = xkBetRecordResponseDTO.getData(); + this.batchInsert(xkBetRecordResponseDTO, betRecordByTimeDTO); + } + + + return Boolean.TRUE; + } else { + log.error("GamesXKServiceImpl [getBetRecordByHistoryTime] 获取投注记录失败,错误代码{},错误信息{}", xkBetRecordResponseDTO.getCode(), xkBetRecordResponseDTO.getMsg()); + throw new BaseException(xkBetRecordResponseDTO.getMsg()); + } } /** @@ -516,7 +562,7 @@ public class GamesXKServiceImpl implements IGamesService { * * @param xkBetRecordResponseDTO xk下注记录响应dto */ - private void batchInsert(XKBetRecordResponseDTO xkBetRecordResponseDTO, BetRecordByTimeDTO betRecordByTimeDTO) { + private synchronized void batchInsert(XKBetRecordResponseDTO xkBetRecordResponseDTO, BetRecordByTimeDTO betRecordByTimeDTO) { List gameBettingDetails = new ArrayList<>(); List wagersIds = new ArrayList<>(); //数据组装 diff --git a/ff-game/src/main/java/com/ff/game/domain/ExtInfo.java b/ff-game/src/main/java/com/ff/game/domain/ExtInfo.java index c86d5f9..2736dba 100644 --- a/ff-game/src/main/java/com/ff/game/domain/ExtInfo.java +++ b/ff-game/src/main/java/com/ff/game/domain/ExtInfo.java @@ -1,6 +1,7 @@ package com.ff.game.domain; import lombok.Data; +import org.springframework.util.ObjectUtils; import java.io.Serializable; import java.util.Map; @@ -13,8 +14,26 @@ public class ExtInfo implements Serializable { // 币种信息,key为其它平台的币种id,value为我们自己的币种 private Map currency; + /** + * 超时时间 + */ + private Map timeout; public String getOurCurrency(String currencyId) { return currency == null ? null : currency.get(currencyId); } + + /** + * 获取超时 + * + * @param key 钥匙 + * @return {@link Long } + */ + public Long getTimeout(String key) { + Map timeout = this.timeout; + if (!ObjectUtils.isEmpty(timeout) && timeout.containsKey(key)) { + return timeout.get(key); + } + return 5000L; + } } diff --git a/ff-game/src/main/java/com/ff/game/service/impl/GameExchangeMoneyServiceImpl.java b/ff-game/src/main/java/com/ff/game/service/impl/GameExchangeMoneyServiceImpl.java index 9018a3f..059ede3 100644 --- a/ff-game/src/main/java/com/ff/game/service/impl/GameExchangeMoneyServiceImpl.java +++ b/ff-game/src/main/java/com/ff/game/service/impl/GameExchangeMoneyServiceImpl.java @@ -14,6 +14,7 @@ import com.ff.game.mapper.GameExchangeMoneyMapper; import com.ff.game.domain.GameExchangeMoney; import com.ff.game.service.IGameExchangeMoneyService; import org.springframework.util.CollectionUtils; +import org.springframework.util.ObjectUtils; /** * 会员金额转移记录Service业务层处理 @@ -65,7 +66,9 @@ public class GameExchangeMoneyServiceImpl implements IGameExchangeMoneyService @Override public int insertGameExchangeMoney(GameExchangeMoney gameExchangeMoney) { - gameExchangeMoney.setId(IdUtil.getSnowflakeNextId()); + if (ObjectUtils.isEmpty(gameExchangeMoney.getId())){ + gameExchangeMoney.setId(IdUtil.getSnowflakeNextId()); + } gameExchangeMoney.setCreateTime(DateUtils.getNowDate()); return gameExchangeMoneyMapper.insertGameExchangeMoney(gameExchangeMoney); } diff --git a/ff-game/src/main/resources/mapper/common/TenantGameQuotaFlowMapper.xml b/ff-game/src/main/resources/mapper/common/TenantGameQuotaFlowMapper.xml index 398b666..a20678d 100644 --- a/ff-game/src/main/resources/mapper/common/TenantGameQuotaFlowMapper.xml +++ b/ff-game/src/main/resources/mapper/common/TenantGameQuotaFlowMapper.xml @@ -57,6 +57,9 @@ and quota_type = #{quotaType} + + and source_id = #{sourceId} + and member_id = #{memberId}