diff --git a/ff-admin/src/main/java/com/ff/annotation/HeaderCheckAspect.java b/ff-admin/src/main/java/com/ff/annotation/HeaderCheckAspect.java index 3500898..a1ce566 100644 --- a/ff-admin/src/main/java/com/ff/annotation/HeaderCheckAspect.java +++ b/ff-admin/src/main/java/com/ff/annotation/HeaderCheckAspect.java @@ -59,7 +59,6 @@ public class HeaderCheckAspect { TenantSecretKey tenantSecretKey = tenantSecretKeyService.selectTenantSecretKeyByTenantKey(key); - Assert.isTrue(!tenantSecretKey.getAgentType(), "当前用户不是租户"); Assert.notNull(tenantSecretKey, "key不存在"); Assert.isTrue(tenantSecretKey.getTenantStatus(), "当前租户已停用"); diff --git a/ff-admin/src/main/java/com/ff/api/controller/ApiAgentController.java b/ff-admin/src/main/java/com/ff/api/controller/ApiAgentController.java index 6cae887..04d5b7c 100644 --- a/ff-admin/src/main/java/com/ff/api/controller/ApiAgentController.java +++ b/ff-admin/src/main/java/com/ff/api/controller/ApiAgentController.java @@ -5,7 +5,7 @@ import com.ff.annotation.CheckHeader; import com.ff.api.response.TenantInfoResponse; import com.ff.base.core.controller.BaseController; import com.ff.base.core.domain.AjaxResult; -import com.ff.base.enums.TenantQuotaType; +import com.ff.base.enums.QuotaType; import com.ff.base.utils.bean.BeanUtils; import com.ff.common.domain.TenantGameQuota; import com.ff.common.domain.TenantSecretKey; @@ -44,7 +44,7 @@ public class ApiAgentController extends BaseController { @PostMapping("/create/tenant") public AjaxResult info() { TenantSecretKey tenantSecretKey = keyConfig.get(); - TenantGameQuota tenantGameQuota = tenantGameQuotaService.selectTenantGameQuotaByTenantKey(tenantSecretKey.getTenantKey(), TenantQuotaType.BALANCE.getCode()); + TenantGameQuota tenantGameQuota = tenantGameQuotaService.selectTenantGameQuotaByTenantKey(tenantSecretKey.getTenantKey(), QuotaType.BALANCE.getCode()); TenantInfoResponse tenantInfoResponse= new TenantInfoResponse(); BeanUtils.copyProperties(tenantGameQuota,tenantInfoResponse); return AjaxResult.success(tenantInfoResponse); diff --git a/ff-admin/src/main/java/com/ff/api/controller/ApiGameController.java b/ff-admin/src/main/java/com/ff/api/controller/ApiGameController.java index 98f3909..117df18 100644 --- a/ff-admin/src/main/java/com/ff/api/controller/ApiGameController.java +++ b/ff-admin/src/main/java/com/ff/api/controller/ApiGameController.java @@ -1,9 +1,7 @@ package com.ff.api.controller; -import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.util.NumberUtil; -import com.dtflys.forest.annotation.Post; import com.ff.annotation.CheckHeader; import com.ff.api.request.*; import com.ff.api.response.*; @@ -11,16 +9,16 @@ 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.OperationType; -import com.ff.base.enums.TransferType; +import com.ff.base.enums.*; import com.ff.base.exception.base.ApiException; import com.ff.base.exception.base.BaseException; +import com.ff.base.utils.QuotaUtils; import com.ff.base.utils.StringUtils; import com.ff.base.utils.bean.BeanUtils; import com.ff.common.domain.TenantGameQuotaFlow; import com.ff.common.domain.TenantSecretKey; 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.config.KeyConfig; @@ -47,9 +45,7 @@ import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; import java.math.BigDecimal; import java.util.*; -import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CountDownLatch; -import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.stream.Collectors; @@ -183,63 +179,33 @@ public class ApiGameController extends BaseController { IGamesService iGamesService = gamesService.get(gameExchangeBalanceRequest.getPlatformCode() + Constants.SERVICE); - + ApiException.notNull(iGamesService, ErrorCode.PLATFORM_NOT_EXIST.getCode()); TenantSecretKey tenantSecretKey = keyConfig.get(); + GameSecretKey gameSecretKey = gameSecretKeyService.findSecretKeyByPlatformAndSystemCode(gameExchangeBalanceRequest.getPlatformCode(), gameExchangeBalanceRequest.getCurrencyCode()); ApiException.notNull(gameSecretKey, ErrorCode.CURRENCY_NOT_EXIST.getCode()); - - Member member = memberService.selectMemberByGameAccount(StringUtils.addSuffix(gameExchangeBalanceRequest.getAccount(), gameExchangeBalanceRequest.getCurrencyCode() + tenantSecretKey.getTenantSn())); - ApiException.notNull(member, ErrorCode.ACCOUNT_NOT_EXIST.getCode()); - - //操作租户额度 - boolean isOut = gameExchangeBalanceRequest.getTransferType() == 1; - BigDecimal balanceRequestAmount = gameExchangeBalanceRequest.getAmount(); - //如果是增加不可以超过对应的额度 - if (isOut) { - - //获取第三方钱包余额 - MemberInfoRequestDTO gamesBaseRequestDTO = MemberInfoRequestDTO.builder() - .accounts(member.getGameAccount()) - .agentId(gameSecretKey.getCode()) - .agentKey(gameSecretKey.getKey()) - .build(); - balanceRequestAmount = iGamesService.getMemberInfo(gamesBaseRequestDTO).getBalance(); - //转入金额 - BigDecimal balanceInto = tenantGameQuotaFlowService.getBalanceByMemberId(TenantGameQuotaFlow.builder() - .isOut(Boolean.TRUE) - .tenantKey(tenantSecretKey.getTenantKey()) - .memberId(member.getId()) - .build()); - //转出金额 - BigDecimal balanceOut = tenantGameQuotaFlowService.getBalanceByMemberId(TenantGameQuotaFlow.builder() - .isOut(Boolean.FALSE) - .tenantKey(tenantSecretKey.getTenantKey()) - .memberId(member.getId()) - .build()); - //如果转入金额+本次转入金额 大于转出额度则取差值 - if (NumberUtil.add(balanceInto, balanceRequestAmount).compareTo(balanceOut) > 0) { - balanceRequestAmount = NumberUtil.sub(balanceOut, balanceInto); - } - } - //租户余额操作 - tenantGameQuotaService.balanceChanges(BalanceChangesDTO.builder() - .isOut(isOut) + BigDecimal quota = tenantGameQuotaService.gameBalanceExchange(GameBalanceExchange.builder() + .platformCode(gameExchangeBalanceRequest.getPlatformCode()) + .currencyCode(gameExchangeBalanceRequest.getCurrencyCode()) + .transferType(gameExchangeBalanceRequest.getTransferType()) + .amount(gameExchangeBalanceRequest.getAmount()) + .account(gameExchangeBalanceRequest.getAccount()) .tenantKey(tenantSecretKey.getTenantKey()) - .balance(balanceRequestAmount) - .memberId(member.getId()) - .operationType(OperationType.API_BALANCE.getCode()) - .remark(OperationType.API_BALANCE.getDescription()) .build()); + // 获取用户信息 + Member member = memberService.selectMemberByGameAccount(StringUtils.addSuffix(gameExchangeBalanceRequest.getAccount(), gameExchangeBalanceRequest.getCurrencyCode() + tenantSecretKey.getTenantSn())); + + //操作第三方额度接口 ExchangeTransferMoneyRequestDTO exchangeTransferMoneyRequestDTO = ExchangeTransferMoneyRequestDTO.builder() .agentId(gameSecretKey.getCode()) .agentKey(gameSecretKey.getKey()) .account(member.getGameAccount()) .tenantKey(tenantSecretKey.getTenantKey()) - .quota(balanceRequestAmount) + .quota(quota) .amount(gameExchangeBalanceRequest.getAmount()) .transferType(gameExchangeBalanceRequest.getTransferType()) .build(); @@ -311,9 +277,9 @@ public class ApiGameController extends BaseController { params.put("endTime", gameCreateFreeSpinRequest.getEndTime()); List bettingDetails = gameBettingDetailsService.selectGameBettingDetailsList(gameBettingDetails); TableDataInfo dataTable = getDataTable(bettingDetails); - List result=new ArrayList<>(); + List result = new ArrayList<>(); for (GameBettingDetails row : (List) dataTable.getRows()) { - GameBettingDetailsResponse gameBettingDetailsResponse=new GameBettingDetailsResponse(); + GameBettingDetailsResponse gameBettingDetailsResponse = new GameBettingDetailsResponse(); BeanUtils.copyProperties(row, gameBettingDetailsResponse); Member member = memberService.selectMemberById(row.getMemberId()); gameBettingDetailsResponse.setAccount(member.getMemberAccount()); @@ -335,7 +301,6 @@ public class ApiGameController extends BaseController { public AjaxResult getDetail(@Validated @RequestBody GameGetDetailRequest gameGetDetailRequest) { - GameSecretKey gameSecretKey = gameSecretKeyService.findSecretKeyByPlatformAndSystemCode(gameGetDetailRequest.getPlatformCode(), gameGetDetailRequest.getCurrencyCode()); ApiException.notNull(gameSecretKey, ErrorCode.CURRENCY_NOT_EXIST.getCode()); @@ -425,9 +390,9 @@ public class ApiGameController extends BaseController { params.put("endTime", gameGetFreeSpinDashflowRequest.getEndTime()); List gameFreeRecords = gameFreeRecordService.selectGameFreeRecordList(gameFreeRecord); TableDataInfo dataTable = getDataTable(gameFreeRecords); - List result=new ArrayList<>(); + List result = new ArrayList<>(); for (GameFreeRecord row : (List) dataTable.getRows()) { - GameFreeRecordResponse gameFreeRecordResponse=new GameFreeRecordResponse(); + GameFreeRecordResponse gameFreeRecordResponse = new GameFreeRecordResponse(); BeanUtils.copyProperties(row, gameFreeRecordResponse); Member member = memberService.selectMemberById(row.getMemberId()); gameFreeRecordResponse.setMemberAccount(member.getMemberAccount()); @@ -525,34 +490,15 @@ public class ApiGameController extends BaseController { balanceMap.put(gameExchangeMoney.getPlatformCode(), gameExchangeMoney.getBalance()); BigDecimal balance = gameExchangeMoney.getBalance(); balanceAll = NumberUtil.add(balanceAll, balance); - //转入金额 - BigDecimal balanceInto = tenantGameQuotaFlowService.getBalanceByMemberId(TenantGameQuotaFlow.builder() - .isOut(Boolean.TRUE) - .tenantKey(tenantSecretKey.getTenantKey()) - .memberId(member.getId()) - .build()); - //转出金额 - BigDecimal balanceOut = tenantGameQuotaFlowService.getBalanceByMemberId(TenantGameQuotaFlow.builder() - .isOut(Boolean.FALSE) - .tenantKey(tenantSecretKey.getTenantKey()) - .memberId(member.getId()) - .build()); - //如果转入金额+本次转入金额 大于转出额度则取差值 - if (NumberUtil.add(balanceInto, balance).compareTo(NumberUtil.add(balanceOut, BigDecimal.ZERO)) > 0) { - balance = NumberUtil.sub(balanceOut, balanceInto); - } - //更新租户额度 - gameExchangeMoney.setQuota(balance); - gameExchangeMoneyService.updateGameExchangeMoney(gameExchangeMoney); - //余额扣除 - tenantGameQuotaService.balanceChanges(BalanceChangesDTO.builder() - .isOut(Boolean.TRUE) + //操作租户额度 + tenantGameQuotaService.gameBalanceExchange(GameBalanceExchange.builder() + .platformCode(gameExchangeMoney.getPlatformCode()) + .currencyCode(gameExchangeMoney.getCurrencyCode()) + .transferType(TransferType.ALL.getCode()) + .amount(gameExchangeMoney.getBalance()) + .account(member.getMemberAccount()) .tenantKey(tenantSecretKey.getTenantKey()) - .balance(balance) - .memberId(member.getId()) - .operationType(OperationType.API_BALANCE.getCode()) - .remark(OperationType.API_BALANCE.getDescription()) .build()); } diff --git a/ff-admin/src/main/java/com/ff/api/controller/ApiTenantController.java b/ff-admin/src/main/java/com/ff/api/controller/ApiTenantController.java index 3014cd9..e7f4cae 100644 --- a/ff-admin/src/main/java/com/ff/api/controller/ApiTenantController.java +++ b/ff-admin/src/main/java/com/ff/api/controller/ApiTenantController.java @@ -1,56 +1,22 @@ package com.ff.api.controller; -import cn.hutool.core.util.NumberUtil; import com.ff.annotation.CheckHeader; -import com.ff.api.request.*; -import com.ff.api.response.GameExchangeBalanceResponse; import com.ff.api.response.TenantInfoResponse; -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.OperationType; -import com.ff.base.enums.TenantQuotaType; -import com.ff.base.enums.TransferType; -import com.ff.base.exception.base.BaseException; -import com.ff.base.utils.StringUtils; +import com.ff.base.enums.QuotaType; import com.ff.base.utils.bean.BeanUtils; import com.ff.common.domain.TenantGameQuota; -import com.ff.common.domain.TenantGameQuotaFlow; import com.ff.common.domain.TenantSecretKey; -import com.ff.common.dto.BalanceChangesDTO; -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.request.*; -import com.ff.game.domain.*; -import com.ff.game.service.*; -import com.ff.member.domain.Member; -import com.ff.member.service.IMemberService; -import com.github.pagehelper.PageHelper; import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; -import org.springframework.transaction.annotation.Transactional; -import org.springframework.util.Assert; -import org.springframework.util.ObjectUtils; -import org.springframework.validation.annotation.Validated; 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 javax.annotation.Resource; -import java.math.BigDecimal; -import java.util.ArrayList; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.Future; /** * api控制器 @@ -78,7 +44,7 @@ public class ApiTenantController extends BaseController { @PostMapping("/info") public AjaxResult info() { TenantSecretKey tenantSecretKey = keyConfig.get(); - TenantGameQuota tenantGameQuota = tenantGameQuotaService.selectTenantGameQuotaByTenantKey(tenantSecretKey.getTenantKey(), TenantQuotaType.BALANCE.getCode()); + TenantGameQuota tenantGameQuota = tenantGameQuotaService.selectTenantGameQuotaByTenantKey(tenantSecretKey.getTenantKey(), QuotaType.BALANCE.getCode()); TenantInfoResponse tenantInfoResponse= new TenantInfoResponse(); BeanUtils.copyProperties(tenantGameQuota,tenantInfoResponse); return AjaxResult.success(tenantInfoResponse); diff --git a/ff-admin/src/main/java/com/ff/common/domain/TenantAgent.java b/ff-admin/src/main/java/com/ff/common/domain/TenantAgent.java new file mode 100644 index 0000000..350e1c6 --- /dev/null +++ b/ff-admin/src/main/java/com/ff/common/domain/TenantAgent.java @@ -0,0 +1,40 @@ +package com.ff.common.domain; + +import com.ff.base.annotation.Excel; +import com.ff.base.core.domain.BaseEntity; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 代理对象 ff_tenant_agent + * + * @author shi + * @date 2025-02-20 + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class TenantAgent extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 主键id */ + private Long id; + + /** 账号 */ + @Excel(name = "账号") + private String account; + + /** 密码 */ + @Excel(name = "密码") + private String password; + + /** 代理状态 1正常 0停用 */ + @Excel(name = "代理状态 1正常 0停用") + private Boolean agentStatus; + + +} diff --git a/ff-admin/src/main/java/com/ff/common/domain/TenantGameQuota.java b/ff-admin/src/main/java/com/ff/common/domain/TenantGameQuota.java index 4ca8349..d1fcda1 100644 --- a/ff-admin/src/main/java/com/ff/common/domain/TenantGameQuota.java +++ b/ff-admin/src/main/java/com/ff/common/domain/TenantGameQuota.java @@ -12,7 +12,7 @@ import lombok.NoArgsConstructor; * 租户游戏配额对象 ff_tenant_game_quota * * @author shi - * @date 2025-02-14 + * @date 2025-02-20 */ @Data @AllArgsConstructor @@ -33,9 +33,9 @@ public class TenantGameQuota extends BaseEntity @Excel(name = "游戏额度") private BigDecimal balance; - /** 额度类型 TenantQuotaType 枚举 */ - @Excel(name = "额度类型 TenantQuotaType 枚举") - private Integer quotaType; + /** 额度类型 TenantQuotaType 枚举或者平台_币种或者平台_币种_FALSE 假额度 */ + @Excel(name = "额度类型 TenantQuotaType 枚举或者平台_币种或者平台_币种_FALSE 假额度") + private String quotaType; /** 版本号 */ @Excel(name = "版本号") diff --git a/ff-admin/src/main/java/com/ff/common/domain/TenantGameQuotaFlow.java b/ff-admin/src/main/java/com/ff/common/domain/TenantGameQuotaFlow.java index 58118b4..e50a5fd 100644 --- a/ff-admin/src/main/java/com/ff/common/domain/TenantGameQuotaFlow.java +++ b/ff-admin/src/main/java/com/ff/common/domain/TenantGameQuotaFlow.java @@ -12,7 +12,7 @@ import lombok.NoArgsConstructor; * 租户游戏额度流水对象 ff_tenant_game_quota_flow * * @author shi - * @date 2025-02-12 + * @date 2025-02-20 */ @Data @AllArgsConstructor @@ -29,6 +29,10 @@ public class TenantGameQuotaFlow extends BaseEntity @Excel(name = "租户key") private String tenantKey; + /** 额度类型 */ + @Excel(name = "额度类型") + private String quotaType; + /** 用户账号id */ @Excel(name = "用户账号id") private Long memberId; diff --git a/ff-admin/src/main/java/com/ff/common/domain/TenantSecretKey.java b/ff-admin/src/main/java/com/ff/common/domain/TenantSecretKey.java index 3cb00c3..ade46d5 100644 --- a/ff-admin/src/main/java/com/ff/common/domain/TenantSecretKey.java +++ b/ff-admin/src/main/java/com/ff/common/domain/TenantSecretKey.java @@ -1,5 +1,6 @@ package com.ff.common.domain; +import java.math.BigDecimal; import com.ff.base.annotation.Excel; import com.ff.base.core.domain.BaseEntity; import lombok.AllArgsConstructor; @@ -11,7 +12,7 @@ import lombok.NoArgsConstructor; * 用户租户密钥对象 ff_tenant_secret_key * * @author shi - * @date 2025-02-14 + * @date 2025-02-20 */ @Data @AllArgsConstructor @@ -24,20 +25,22 @@ public class TenantSecretKey extends BaseEntity /** 主键id */ private Long id; - /** - * 代理类型 false 不是 - */ - private Boolean agentType; + /** 账号 */ + @Excel(name = "账号") + private String account; - /** - * 代理id - */ - private Long agentId; + /** 密码 */ + @Excel(name = "密码") + private String password; /** 租户key */ @Excel(name = "租户key") private String tenantKey; + /** 代理id */ + @Excel(name = "代理id") + private Long agentId; + /** 商户后缀 */ @Excel(name = "商户后缀") private String tenantSn; @@ -47,11 +50,24 @@ public class TenantSecretKey extends BaseEntity private String tenantSecret; /** 租户状态 1正常 0停用 */ + @Excel(name = "租户状态 1正常 0停用") private Boolean tenantStatus; + /** 额度类型 TenantQuotaType 枚举 */ + @Excel(name = "额度类型 TenantQuotaType 枚举") + private Integer quotaType; + + /** 买分比例 */ + @Excel(name = "买分比例") + private BigDecimal scoreRatio; + /** 租户类型 TenantType 枚举 */ @Excel(name = "租户类型 TenantType 枚举") private Integer tenantType; + /** 透支比例 */ + @Excel(name = "透支比例") + private BigDecimal depositRatio; + } diff --git a/ff-admin/src/main/java/com/ff/common/dto/BalanceChangesDTO.java b/ff-admin/src/main/java/com/ff/common/dto/BalanceChangesDTO.java index aee24f6..0f79a07 100644 --- a/ff-admin/src/main/java/com/ff/common/dto/BalanceChangesDTO.java +++ b/ff-admin/src/main/java/com/ff/common/dto/BalanceChangesDTO.java @@ -26,6 +26,10 @@ public class BalanceChangesDTO implements Serializable { /** 充值类型 false 扣除 true 充值 */ private Boolean isOut; + /** + * 配额类型 + */ + private String quotaType; /** 租户key */ private String tenantKey; diff --git a/ff-admin/src/main/java/com/ff/common/dto/GameBalanceExchange.java b/ff-admin/src/main/java/com/ff/common/dto/GameBalanceExchange.java new file mode 100644 index 0000000..efdf972 --- /dev/null +++ b/ff-admin/src/main/java/com/ff/common/dto/GameBalanceExchange.java @@ -0,0 +1,57 @@ +package com.ff.common.dto; + +import io.swagger.models.auth.In; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotBlank; +import java.io.Serializable; +import java.math.BigDecimal; + +/** + * 游戏余额兑换 + * + * @author shi + * @date 2025/02/21 + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class GameBalanceExchange implements Serializable { + private final static long serialVersionUID = 3452954102791311247L; + + + + /** + * 平台代码 + */ + private String platformCode; + + /** + * 货币代码 + */ + private String currencyCode; + + /** + * 交易类型 TransferType + */ + private Integer transferType; + + /** + * 游戏币数量 + */ + private BigDecimal amount; + + /** + * 账户 + */ + private String account; + + + /** 租户key */ + private String tenantKey; + +} diff --git a/ff-admin/src/main/java/com/ff/common/mapper/TenantGameQuotaMapper.java b/ff-admin/src/main/java/com/ff/common/mapper/TenantGameQuotaMapper.java index 6b81a9e..aa1873c 100644 --- a/ff-admin/src/main/java/com/ff/common/mapper/TenantGameQuotaMapper.java +++ b/ff-admin/src/main/java/com/ff/common/mapper/TenantGameQuotaMapper.java @@ -27,7 +27,7 @@ public interface TenantGameQuotaMapper { * @param tenantKey 租户游戏配额主键 * @return 租户游戏配额 */ - TenantGameQuota selectTenantGameQuotaByTenantKey(@Param("tenantKey") String tenantKey,@Param("quotaType") Integer quotaType); + TenantGameQuota selectTenantGameQuotaByTenantKey(@Param("tenantKey") String tenantKey,@Param("quotaType") String quotaType); /** * 查询租户游戏配额列表 diff --git a/ff-admin/src/main/java/com/ff/common/service/ITenantGameQuotaService.java b/ff-admin/src/main/java/com/ff/common/service/ITenantGameQuotaService.java index debc673..de96339 100644 --- a/ff-admin/src/main/java/com/ff/common/service/ITenantGameQuotaService.java +++ b/ff-admin/src/main/java/com/ff/common/service/ITenantGameQuotaService.java @@ -1,8 +1,10 @@ package com.ff.common.service; +import java.math.BigDecimal; import java.util.List; import com.ff.common.domain.TenantGameQuota; import com.ff.common.dto.BalanceChangesDTO; +import com.ff.common.dto.GameBalanceExchange; import org.apache.ibatis.annotations.Param; /** @@ -69,6 +71,13 @@ public interface ITenantGameQuotaService */ Boolean balanceChanges(BalanceChangesDTO balanceChangesDTO); + /** + * 游戏余额兑换 + * + * @param gameBalanceExchange 游戏余额兑换 + * @return {@link BigDecimal } + */ + BigDecimal gameBalanceExchange(GameBalanceExchange gameBalanceExchange); /** * 查询租户游戏配额 @@ -76,5 +85,5 @@ public interface ITenantGameQuotaService * @param tenantKey 租户游戏配额主键 * @return 租户游戏配额 */ - TenantGameQuota selectTenantGameQuotaByTenantKey(String tenantKey, Integer quotaType); + TenantGameQuota selectTenantGameQuotaByTenantKey(String tenantKey, String quotaType); } diff --git a/ff-admin/src/main/java/com/ff/common/service/impl/TenantGameQuotaServiceImpl.java b/ff-admin/src/main/java/com/ff/common/service/impl/TenantGameQuotaServiceImpl.java index 551fcd2..3fa2e90 100644 --- a/ff-admin/src/main/java/com/ff/common/service/impl/TenantGameQuotaServiceImpl.java +++ b/ff-admin/src/main/java/com/ff/common/service/impl/TenantGameQuotaServiceImpl.java @@ -2,20 +2,27 @@ package com.ff.common.service.impl; import java.math.BigDecimal; import java.util.List; +import java.util.Map; import cn.hutool.core.util.NumberUtil; import com.ff.base.constant.Constants; -import com.ff.base.enums.TenantQuotaType; -import com.ff.base.enums.TenantType; +import com.ff.base.enums.*; +import com.ff.base.exception.base.ApiException; import com.ff.base.utils.DateUtils; -import com.ff.base.utils.MessageUtils; -import com.ff.base.utils.SecurityUtils; +import com.ff.base.utils.QuotaUtils; +import com.ff.base.utils.StringUtils; import com.ff.common.domain.TenantGameQuotaFlow; import com.ff.common.domain.TenantSecretKey; import com.ff.common.dto.BalanceChangesDTO; -import com.ff.common.mapper.TenantGameQuotaFlowMapper; +import com.ff.common.dto.GameBalanceExchange; import com.ff.common.service.ITenantGameQuotaFlowService; import com.ff.common.service.ITenantSecretKeyService; +import com.ff.game.api.IGamesService; +import com.ff.game.api.request.MemberInfoRequestDTO; +import com.ff.game.domain.GameSecretKey; +import com.ff.game.service.IGameSecretKeyService; +import com.ff.member.domain.Member; +import com.ff.member.service.IMemberService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.ff.common.mapper.TenantGameQuotaMapper; @@ -44,6 +51,18 @@ public class TenantGameQuotaServiceImpl implements ITenantGameQuotaService { @Resource private ITenantSecretKeyService tenantSecretKeyService; + + @Resource + private IMemberService memberService; + + + @Resource + private IGameSecretKeyService gameSecretKeyService; + + + @Autowired + private Map gamesService; + /** * 查询租户游戏配额 * @@ -120,10 +139,8 @@ public class TenantGameQuotaServiceImpl implements ITenantGameQuotaService { */ @Override public Boolean balanceChanges(BalanceChangesDTO balanceChangesDTO) { - TenantGameQuota tenantGameQuota = tenantGameQuotaMapper.selectTenantGameQuotaByTenantKey(balanceChangesDTO.getTenantKey(), TenantQuotaType.BALANCE.getCode()); - - Assert.isTrue(!ObjectUtils.isEmpty(tenantGameQuota), "租户余额额度不足"); + TenantGameQuota tenantGameQuota = this.selectTenantGameQuotaByTenantKey(balanceChangesDTO.getTenantKey(), balanceChangesDTO.getQuotaType()); BigDecimal balanceBefore = tenantGameQuota.getBalance(); BigDecimal balance = balanceChangesDTO.getBalance(); if (BigDecimal.ZERO.compareTo(balance) >= 0) { @@ -139,8 +156,7 @@ public class TenantGameQuotaServiceImpl implements ITenantGameQuotaService { //判断剩余额度是否大于0 TenantSecretKey tenantSecretKey = tenantSecretKeyService.selectTenantSecretKeyByTenantKey(balanceChangesDTO.getTenantKey()); if (TenantType.DEPOSIT.getCode().equals(tenantSecretKey.getTenantType())) { - TenantGameQuota depositQuota = tenantGameQuotaMapper.selectTenantGameQuotaByTenantKey(balanceChangesDTO.getTenantKey(), TenantQuotaType.DEPOSIT.getCode()); - + TenantGameQuota depositQuota = tenantGameQuotaMapper.selectTenantGameQuotaByTenantKey(balanceChangesDTO.getTenantKey(), QuotaUtils.getReputationQuota(balanceChangesDTO.getQuotaType())); //判断剩余额度是否大于0 Assert.isTrue(balanceAfter.compareTo(depositQuota.getBalance().negate()) >= 0, "余额额度不足"); } else { @@ -153,13 +169,14 @@ public class TenantGameQuotaServiceImpl implements ITenantGameQuotaService { Boolean changedBalanceResult = tenantGameQuotaMapper.changeBalance(TenantGameQuota.builder() .tenantKey(balanceChangesDTO.getTenantKey()) .balance(balanceAfter) - .quotaType(TenantQuotaType.BALANCE.getCode()) + .quotaType(balanceChangesDTO.getQuotaType()) .version(tenantGameQuota.getVersion()) .build()); Assert.isTrue(changedBalanceResult, "租户游戏额度操作失败"); //插入流水 TenantGameQuotaFlow tenantGameQuotaFlow = TenantGameQuotaFlow.builder() + .quotaType(balanceChangesDTO.getQuotaType()) .tenantKey(balanceChangesDTO.getTenantKey()) .isOut(balanceChangesDTO.getIsOut()) .balanceAfter(balanceAfter) @@ -175,6 +192,148 @@ public class TenantGameQuotaServiceImpl implements ITenantGameQuotaService { return changedBalanceResult; } + /** + * 游戏余额兑换 + * + * @param gameBalanceExchange 游戏余额兑换 + * @return {@link BigDecimal } + */ + @Override + public BigDecimal gameBalanceExchange(GameBalanceExchange gameBalanceExchange) { + // 获取平台接口密钥 + GameSecretKey gameSecretKey = gameSecretKeyService.findSecretKeyByPlatformAndSystemCode(gameBalanceExchange.getPlatformCode(), gameBalanceExchange.getCurrencyCode()); + // 检查平台密钥是否存在,否则抛出异常 + ApiException.notNull(gameSecretKey, ErrorCode.CURRENCY_NOT_EXIST.getCode()); + + // 获取租户信息 + TenantSecretKey tenantSecretKey = tenantSecretKeyService.selectTenantSecretKeyByTenantKey(gameBalanceExchange.getTenantKey()); + // 获取用户信息 + Member member = memberService.selectMemberByGameAccount(StringUtils.addSuffix(gameBalanceExchange.getAccount(), gameBalanceExchange.getCurrencyCode() + tenantSecretKey.getTenantSn())); + // 检查用户是否存在,否则抛出异常 + ApiException.notNull(member, ErrorCode.ACCOUNT_NOT_EXIST.getCode()); + + // 根据平台代码获取平台接口 + IGamesService iGamesService = gamesService.get(gameBalanceExchange.getPlatformCode() + Constants.SERVICE); + + // 初始化额度类型为余额 + String quotaType = QuotaType.BALANCE.getCode(); + // 根据租户额度类型调整额度类型 + if (TenantQuotaType.SINGLE.getCode().equals(tenantSecretKey.getQuotaType())) { + quotaType = QuotaUtils.getPlatformQuota(gameBalanceExchange.getPlatformCode(), gameBalanceExchange.getCurrencyCode()); + } + + // 判断操作类型(出账/入账) + boolean isOut = gameBalanceExchange.getTransferType().equals(TransferType.ALL.getCode()); + // 初始化操作金额 + BigDecimal balanceRequestAmount = gameBalanceExchange.getAmount(); + + // 如果是出账操作 + if (isOut) { + // 获取第三方钱包余额 + MemberInfoRequestDTO gamesBaseRequestDTO = MemberInfoRequestDTO.builder() + .accounts(member.getGameAccount()) + .agentId(gameSecretKey.getCode()) + .agentKey(gameSecretKey.getKey()) + .build(); + balanceRequestAmount = iGamesService.getMemberInfo(gamesBaseRequestDTO).getBalance(); + + // 计算累计转入和转出金额 + BigDecimal balanceInto = tenantGameQuotaFlowService.getBalanceByMemberId(TenantGameQuotaFlow.builder() + .isOut(Boolean.TRUE) + .quotaType(quotaType) + .tenantKey(gameBalanceExchange.getTenantKey()) + .memberId(member.getId()) + .build()); + BigDecimal balanceOut = tenantGameQuotaFlowService.getBalanceByMemberId(TenantGameQuotaFlow.builder() + .isOut(Boolean.FALSE) + .quotaType(quotaType) + .tenantKey(gameBalanceExchange.getTenantKey()) + .memberId(member.getId()) + .build()); + + // 初始化平台额度 + BigDecimal platformBalance = BigDecimal.ZERO; + // 确保转入金额不超过转出额度 + if (NumberUtil.add(balanceInto, balanceRequestAmount).compareTo(balanceOut) > 0) { + BigDecimal difference = NumberUtil.sub(balanceOut, balanceInto); + platformBalance = NumberUtil.sub(balanceRequestAmount, difference); + balanceRequestAmount = difference; + } + + // 如果有平台额度变化,进行余额调整 + if (platformBalance.compareTo(BigDecimal.ZERO) > 0) { + this.balanceChanges(BalanceChangesDTO.builder() + .isOut(Boolean.TRUE) + .tenantKey(gameBalanceExchange.getTenantKey()) + .balance(platformBalance) + .memberId(member.getId()) + .operationType(OperationType.API_BALANCE.getCode()) + .remark(OperationType.API_BALANCE.getDescription()) + .quotaType(QuotaUtils.getFalseTenantQuota(gameBalanceExchange.getPlatformCode(), gameBalanceExchange.getCurrencyCode())) + .build()); + } + + // 进行租户余额调整 + this.balanceChanges(BalanceChangesDTO.builder() + .isOut(isOut) + .tenantKey(gameBalanceExchange.getTenantKey()) + .balance(balanceRequestAmount) + .memberId(member.getId()) + .operationType(OperationType.API_BALANCE.getCode()) + .quotaType(quotaType) + .remark(OperationType.API_BALANCE.getDescription()) + .build()); + + } else { + // 如果是扣账操作,首先处理假额度 + String falseTenantQuotaType = QuotaUtils.getFalseTenantQuota(gameBalanceExchange.getPlatformCode(), gameBalanceExchange.getCurrencyCode()); + TenantGameQuota falseTenantQuota = selectTenantGameQuotaByTenantKey(tenantSecretKey.getTenantKey(), falseTenantQuotaType); + if (falseTenantQuota.getBalance().compareTo(BigDecimal.ZERO) > 0) { + BigDecimal amountToDeduct = gameBalanceExchange.getAmount(); + BigDecimal falseQuotaBalance = falseTenantQuota.getBalance(); + if (falseQuotaBalance.compareTo(amountToDeduct) >= 0) { + // 假额度足够扣除本次所需金额 + this.balanceChanges(BalanceChangesDTO.builder() + .isOut(Boolean.FALSE) + .tenantKey(tenantSecretKey.getTenantKey()) + .balance(amountToDeduct) + .memberId(member.getId()) + .operationType(OperationType.API_BALANCE.getCode()) + .quotaType(falseTenantQuotaType) + .remark(OperationType.API_BALANCE.getDescription()) + .build()); + balanceRequestAmount = BigDecimal.ZERO; + } else { + // 假额度不足以扣除本次所需金额,扣除全部假额度 + balanceRequestAmount = amountToDeduct.subtract(falseQuotaBalance); + this.balanceChanges(BalanceChangesDTO.builder() + .isOut(Boolean.FALSE) + .tenantKey(tenantSecretKey.getTenantKey()) + .balance(falseQuotaBalance) + .memberId(member.getId()) + .operationType(OperationType.API_BALANCE.getCode()) + .quotaType(falseTenantQuotaType) + .remark(OperationType.API_BALANCE.getDescription()) + .build()); + } + } + // 处理剩余的入账金额 + if (balanceRequestAmount.compareTo(BigDecimal.ZERO) > 0) { + this.balanceChanges(BalanceChangesDTO.builder() + .isOut(Boolean.FALSE) + .tenantKey(tenantSecretKey.getTenantKey()) + .balance(balanceRequestAmount) + .memberId(member.getId()) + .operationType(OperationType.API_BALANCE.getCode()) + .quotaType(quotaType) + .remark(OperationType.API_BALANCE.getDescription()) + .build()); + } + } + return balanceRequestAmount; + } + + /** * 按租户密钥选择租户游戏配额 * @@ -183,7 +342,19 @@ public class TenantGameQuotaServiceImpl implements ITenantGameQuotaService { * @return {@link TenantGameQuota } */ @Override - public TenantGameQuota selectTenantGameQuotaByTenantKey(String tenantKey, Integer quotaType) { - return tenantGameQuotaMapper.selectTenantGameQuotaByTenantKey(tenantKey, quotaType); + public TenantGameQuota selectTenantGameQuotaByTenantKey(String tenantKey, String quotaType) { + TenantGameQuota tenantGameQuota = tenantGameQuotaMapper.selectTenantGameQuotaByTenantKey(tenantKey, quotaType); + + //如果当前钱包不存在 + if (ObjectUtils.isEmpty(tenantGameQuota)) { + tenantGameQuota = TenantGameQuota.builder() + .tenantKey(tenantKey) + .balance(BigDecimal.ZERO) + .quotaType(quotaType) + .version(0) + .build(); + tenantGameQuotaMapper.insertTenantGameQuota(tenantGameQuota); + } + return tenantGameQuota; } } diff --git a/ff-admin/src/main/resources/mapper/common/TenantAgentMapper.xml b/ff-admin/src/main/resources/mapper/common/TenantAgentMapper.xml new file mode 100644 index 0000000..ee4f431 --- /dev/null +++ b/ff-admin/src/main/resources/mapper/common/TenantAgentMapper.xml @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + select id, account, password, agent_status, create_by, create_time, update_by, update_time from ff_tenant_agent + + + + + + + + insert into ff_tenant_agent + + account, + password, + agent_status, + create_by, + create_time, + update_by, + update_time, + + + #{account}, + #{password}, + #{agentStatus}, + #{createBy}, + #{createTime}, + #{updateBy}, + #{updateTime}, + + + + + update ff_tenant_agent + + account = #{account}, + password = #{password}, + agent_status = #{agentStatus}, + create_by = #{createBy}, + create_time = #{createTime}, + update_by = #{updateBy}, + update_time = #{updateTime}, + + where id = #{id} + + + + delete from ff_tenant_agent where id = #{id} + + + + delete from ff_tenant_agent where id in + + #{id} + + + \ No newline at end of file diff --git a/ff-admin/src/main/resources/mapper/common/TenantGameQuotaFlowMapper.xml b/ff-admin/src/main/resources/mapper/common/TenantGameQuotaFlowMapper.xml index db19465..20f306d 100644 --- a/ff-admin/src/main/resources/mapper/common/TenantGameQuotaFlowMapper.xml +++ b/ff-admin/src/main/resources/mapper/common/TenantGameQuotaFlowMapper.xml @@ -1,12 +1,13 @@ +PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" +"http://mybatis.org/dtd/mybatis-3-mapper.dtd"> - + + @@ -21,13 +22,14 @@ - select id, tenant_key, member_id, is_out, operation_type, balance_before, balance, balance_after, remark, create_by, create_time, update_by, update_time from ff_tenant_game_quota_flow + select id, tenant_key, quota_type, member_id, is_out, operation_type, balance_before, balance, balance_after, remark, create_by, create_time, update_by, update_time from ff_tenant_game_quota_flow - + - + and tenant_key = #{tenantKey} and balance = #{balance} - and quota_type = #{quotaType} + and quota_type = #{quotaType} and version = #{version} - + - + + and account = #{account} + and password = #{password} and tenant_key = #{tenantKey} - and agent_type = #{agentType} and agent_id = #{agentId} and tenant_sn = #{tenantSn} and tenant_secret = #{tenantSecret} and tenant_status = #{tenantStatus} + and quota_type = #{quotaType} + and score_ratio = #{scoreRatio} and tenant_type = #{tenantType} + and deposit_ratio = #{depositRatio} - +