초기커밋
This commit is contained in:
155
BrokerApiCore/Services/EchoSystemService.cs
Normal file
155
BrokerApiCore/Services/EchoSystemService.cs
Normal file
@@ -0,0 +1,155 @@
|
||||
|
||||
using ServerCore;
|
||||
using ServerBase;
|
||||
using ServerCommon;
|
||||
using ServerCommon.BusinessLogDomain;
|
||||
|
||||
|
||||
|
||||
namespace BrokerCore.Services;
|
||||
|
||||
using Common;
|
||||
|
||||
public class EchoSystemService
|
||||
{
|
||||
private readonly IServerLogic m_server_logic;
|
||||
private string m_user_guid = string.Empty;
|
||||
CaliumEventRequest? m_calium_event_payload;
|
||||
const int m_retry_count_max = 5;
|
||||
const int m_retry_interval_ms = 1000;
|
||||
|
||||
public EchoSystemService(IServerLogic serverLogic)
|
||||
{
|
||||
m_server_logic = serverLogic;
|
||||
}
|
||||
|
||||
private class CaliumEchoSystemFailBusinessLog : ILogInvokerEx
|
||||
{
|
||||
private readonly CaliumEchoSystemFailLogData m_data_to_log;
|
||||
|
||||
public CaliumEchoSystemFailBusinessLog(CaliumEchoSystemFailLogData log) : base(LogDomainType.CaliumEchoSystem)
|
||||
{
|
||||
m_data_to_log = log;
|
||||
}
|
||||
|
||||
public override bool hasLog() => true;
|
||||
|
||||
protected override void fillup(ref BusinessLog.LogBody body)
|
||||
{
|
||||
body.append(new CaliumEchoSystemFailLogData(this, m_data_to_log));
|
||||
}
|
||||
}
|
||||
|
||||
public async Task createAndSetEventPayload(string accountId, string nickname, string userGuid,
|
||||
long sapphireDelta, string serverType, string eventType, string subType = "BrokerApiServer")
|
||||
{
|
||||
m_user_guid = userGuid;
|
||||
var calium_storage_attrib = await findCaliumStorage();
|
||||
var calium_event_payload = new CaliumEventRequest
|
||||
{
|
||||
m_event_id = Guid.NewGuid().ToString("N"),
|
||||
m_server_type = serverType,
|
||||
m_event_type = eventType, // CaliumEventType.extra_get.ToString(),
|
||||
// 확인용 문자열
|
||||
m_sub_type = subType,
|
||||
m_div_type = nickname,
|
||||
m_div_id = accountId,
|
||||
m_calium_delta = 0,
|
||||
m_sapphire_delta = Convert.ToDouble(sapphireDelta),
|
||||
m_current_epoch = calium_storage_attrib?.DailyEpoch ?? 0,
|
||||
m_current_inflation_rate = calium_storage_attrib?.ExchangerStorage.DailyInflationRate ?? Convert.ToDouble(0)
|
||||
};
|
||||
m_calium_event_payload = calium_event_payload;
|
||||
}
|
||||
|
||||
private async Task<CaliumStorageAttrib?> findCaliumStorage()
|
||||
{
|
||||
var dynamo_db_client = m_server_logic.getDynamoDbClient();
|
||||
var (result_pk, primary_key_object) = await DynamoDBDocBaseHelper.makePrimaryKey<CaliumStorageDoc>(m_user_guid);
|
||||
if (result_pk.isFail() || primary_key_object == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var config = dynamo_db_client.makeQueryConfigForReadByPKOnly(primary_key_object.PK);
|
||||
var (result, doc) =
|
||||
await dynamo_db_client.simpleQueryDocTypeWithQueryOperationConfig<CaliumStorageDoc>(config);
|
||||
var attrib = doc?.getAttrib<CaliumStorageAttrib>();
|
||||
return attrib;
|
||||
}
|
||||
|
||||
public async Task<Result> processCaliumEvent(IWithLogActor logActor)
|
||||
{
|
||||
Guard.Against.isNull(m_calium_event_payload, ServerErrorCode.InternalServerError,
|
||||
() => "m_calium_event_payload is null");
|
||||
var server_config = m_server_logic.getServerConfig();
|
||||
var url = server_config.EchoSystemConfig.BaseAddress;
|
||||
var echo_system_requester = new EchoSystemRequester(url);
|
||||
var result = new Result();
|
||||
CaliumEventResponse? echo_system_response = null;
|
||||
foreach (var _ in Enumerable.Range(0, m_retry_count_max))
|
||||
{
|
||||
(result, echo_system_response) = await echo_system_requester.postCaliumEvent(m_calium_event_payload);
|
||||
|
||||
if (result.isSuccess())
|
||||
{
|
||||
Log.getLogger().info("EchoSystemRequest Success");
|
||||
break;
|
||||
}
|
||||
|
||||
Log.getLogger().info("EchoSystemRequest Failed");
|
||||
if (result.ErrorCode == ServerErrorCode.FailToGetEchoSystemHttpError)
|
||||
{
|
||||
await Task.Delay(m_retry_interval_ms);
|
||||
}
|
||||
}
|
||||
|
||||
if (result.isSuccess())
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
//========================================
|
||||
// 여기서 부터 실패시 처리
|
||||
//========================================
|
||||
|
||||
await insertEventFailDoc(m_user_guid);
|
||||
|
||||
Log.getLogger().info($"EchoSystemRequest Failed => Code: {echo_system_response?.m_code}");
|
||||
|
||||
BusinessLogger.collectLog(logActor, new CaliumEchoSystemFailBusinessLog(
|
||||
new CaliumEchoSystemFailLogData
|
||||
{
|
||||
FailCode = echo_system_response?.m_code ?? string.Empty,
|
||||
FailMessages = echo_system_response?.m_messages ?? [],
|
||||
ReTry = false,
|
||||
EventData = m_calium_event_payload
|
||||
}));
|
||||
return result;
|
||||
}
|
||||
|
||||
// 칼리움 이벤트가 실패하면 CaliumEventDoc을 생성해서 채널 서버에 이 후에 처리하도록 유도한다.
|
||||
private async Task insertEventFailDoc(string userGuid)
|
||||
{
|
||||
var dynamo_db_client = m_server_logic.getDynamoDbClient();
|
||||
var request = m_calium_event_payload;
|
||||
Guard.Against.isNull(request, ServerErrorCode.InternalServerError, () => "m_calium_event_payload is null");
|
||||
var doc = new CaliumEventDoc(request.m_event_id);
|
||||
var attrib = doc.getAttrib<CaliumEventAttrib>();
|
||||
NullReferenceCheckHelper.throwIfNull(attrib, () => $"calium event attrib is null !!! - userGuid[{userGuid}]");
|
||||
|
||||
attrib.UserGuid = userGuid;
|
||||
attrib.EventData.m_server_type = request.m_server_type;
|
||||
attrib.EventData.m_event_type = request.m_event_type;
|
||||
attrib.EventData.m_sub_type = request.m_sub_type;
|
||||
attrib.EventData.m_div_type = request.m_div_type;
|
||||
attrib.EventData.m_div_id = request.m_div_id;
|
||||
attrib.EventData.m_calium_delta = request.m_calium_delta;
|
||||
attrib.EventData.m_sapphire_delta = request.m_sapphire_delta;
|
||||
attrib.EventData.m_current_epoch = request.m_current_epoch;
|
||||
attrib.EventData.m_current_inflation_rate = request.m_current_inflation_rate;
|
||||
attrib.Status = CaliumEventStatus.Regist;
|
||||
|
||||
await dynamo_db_client.simpleInsertDocumentWithDocType(doc);
|
||||
}
|
||||
}
|
||||
92
BrokerApiCore/Services/JwtGenerator.cs
Normal file
92
BrokerApiCore/Services/JwtGenerator.cs
Normal file
@@ -0,0 +1,92 @@
|
||||
|
||||
using System.IdentityModel.Tokens.Jwt;
|
||||
using System.Security.Claims;
|
||||
using System.Text;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
|
||||
using ServerCore; using ServerBase;
|
||||
|
||||
namespace BrokerCore.Services;
|
||||
using Common;
|
||||
|
||||
public class JwtGenerator
|
||||
{
|
||||
private readonly JwtOption m_jwt_option;
|
||||
|
||||
public JwtGenerator(JwtOption jwtOption)
|
||||
{
|
||||
m_jwt_option = jwtOption;
|
||||
}
|
||||
|
||||
public JwtOption JwtOption => m_jwt_option;
|
||||
|
||||
// Access Token 생성
|
||||
public string generateAccessToken(string planetId, string planetServerType, string? refreshToken = null)
|
||||
{
|
||||
// todo: 토큰 유효기간 설정
|
||||
var issued_at = new DateTime(2025, 3, 1, 0, 0, 0, DateTimeKind.Utc);
|
||||
var expires = issued_at.AddYears(1);
|
||||
var security_key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(m_jwt_option.Secret));
|
||||
var credentials = new SigningCredentials(security_key, SecurityAlgorithms.HmacSha256);
|
||||
|
||||
var claims = new[]
|
||||
{
|
||||
new Claim(JwtRegisteredClaimNames.Sid, planetId), // 사용자 ID
|
||||
new Claim(JwtRegisteredClaimNames.Typ, planetServerType),
|
||||
};
|
||||
var header = new JwtHeader(credentials);
|
||||
var payload = new JwtPayload(
|
||||
issuer:null,
|
||||
audience:null,
|
||||
claims: claims,
|
||||
notBefore: null, // 토큰이 유효 일시
|
||||
expires: expires, // 토큰 만료 일시
|
||||
issuedAt: issued_at // iat 발행일시
|
||||
);
|
||||
|
||||
var token = new JwtSecurityToken(header, payload);
|
||||
return new JwtSecurityTokenHandler().WriteToken(token);
|
||||
}
|
||||
}
|
||||
|
||||
public class JwtParser
|
||||
{
|
||||
private readonly JwtOption m_jwt_option;
|
||||
|
||||
public JwtParser(JwtOption jwtOption)
|
||||
{
|
||||
m_jwt_option = jwtOption;
|
||||
}
|
||||
|
||||
public ClaimsPrincipal? parseToken(string token)
|
||||
{
|
||||
var token_handler = new JwtSecurityTokenHandler();
|
||||
|
||||
// 시크릿 키를 바이트 배열로 변환
|
||||
var key = Encoding.UTF8.GetBytes(m_jwt_option.Secret);
|
||||
|
||||
// 토큰 검증 매개변수 설정
|
||||
var validation_parameters = new TokenValidationParameters
|
||||
{
|
||||
ValidateIssuer = false,
|
||||
ValidateAudience = false,
|
||||
ValidIssuer = "",
|
||||
ValidAudience = "",
|
||||
ValidateLifetime = true,
|
||||
ValidateIssuerSigningKey = true,
|
||||
IssuerSigningKey = new SymmetricSecurityKey(key)
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
// 토큰 검증 및 클레임 추출
|
||||
var principal = token_handler.ValidateToken(token, validation_parameters, out var validated_token);
|
||||
return principal;
|
||||
}
|
||||
catch (SecurityTokenException ex)
|
||||
{
|
||||
Log.getLogger().error($"JWT 파싱 에러 => {ex.Message}");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
185
BrokerApiCore/Services/JwtService.cs
Normal file
185
BrokerApiCore/Services/JwtService.cs
Normal file
@@ -0,0 +1,185 @@
|
||||
// namespace BrokerCore.Services;
|
||||
//
|
||||
// using System.IdentityModel.Tokens.Jwt;
|
||||
// using System.Security.Claims;
|
||||
// using System.Security.Cryptography;
|
||||
// using System.Text;
|
||||
//
|
||||
// using Microsoft.IdentityModel.Tokens;
|
||||
//
|
||||
// public interface IJwtUser
|
||||
// {
|
||||
// public string Id { get; }
|
||||
// }
|
||||
//
|
||||
// public interface IJwtAuth
|
||||
// {
|
||||
//
|
||||
// }
|
||||
//
|
||||
// public class RefreshToken
|
||||
// {
|
||||
// public int Id { get; set; }
|
||||
// public string Token { get; set; } = string.Empty;
|
||||
// public DateTime Created { get; set; } = DateTime.UtcNow;
|
||||
// public DateTime Expires { get; set; }
|
||||
// public bool IsExpired => DateTime.UtcNow >= Expires;
|
||||
// public DateTime? Revoked { get; set; }
|
||||
// public bool IsActive => Revoked == null && !IsExpired;
|
||||
// public string? ReplacedByToken { get; set; }
|
||||
// public string? ReasonRevoked { get; set; }
|
||||
// public int UserId { get; set; }
|
||||
// public IJwtUser User { get; set; } = null!;
|
||||
// }
|
||||
//
|
||||
// public interface IJwtService<in TUser, TAuth> where TUser : class
|
||||
// {
|
||||
// string generateJwtToken(TUser user, string secretKey, int expirationMinutes = 15);
|
||||
// string generateRefreshToken();
|
||||
// int? validateJwtToken(string token);
|
||||
// Task<TAuth> refreshTokenAsync(string token, string ipAddress);
|
||||
// Task revokeTokenAsync(string token, string ipAddress, string? reason = null);
|
||||
// }
|
||||
// public class JwtService: IJwtService<IJwtUser, IJwtAuth>
|
||||
// {
|
||||
// private string m_secret_key = string.Empty;
|
||||
// private int m_expiration_minutes = 15;
|
||||
// private string m_issuer = string.Empty;
|
||||
// private string m_audience = string.Empty;
|
||||
//
|
||||
// public string generateJwtToken(IJwtUser user)
|
||||
// {
|
||||
// if (user == null)
|
||||
// throw new ArgumentNullException(nameof(user));
|
||||
//
|
||||
// if (string.IsNullOrEmpty(m_secret_key))
|
||||
// throw new ArgumentNullException(nameof(m_secret_key));
|
||||
//
|
||||
// if (m_expiration_minutes <= 0)
|
||||
// throw new ArgumentOutOfRangeException(nameof(m_expiration_minutes), "Expiration minutes must be greater than zero.");
|
||||
//
|
||||
// var token_handler = new JwtSecurityTokenHandler();
|
||||
// var key = Encoding.ASCII.GetBytes(m_secret_key);
|
||||
//
|
||||
// var claims = new List<Claim>
|
||||
// {
|
||||
// new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()),
|
||||
// // new Claim(ClaimTypes.Name, user.Username),
|
||||
// // new Claim(ClaimTypes.Email, user.Email)
|
||||
// // 필요한 경우 추가 클레임 정의 (역할 등)
|
||||
// };
|
||||
//
|
||||
// var token_descriptor = new SecurityTokenDescriptor
|
||||
// {
|
||||
// Subject = new ClaimsIdentity(claims),
|
||||
// Expires = DateTime.UtcNow.AddMinutes(15), // 액세스 토큰 만료 시간 (짧게 설정)
|
||||
// Issuer = string.Empty,
|
||||
// Audience = string.Empty,
|
||||
// SigningCredentials = new SigningCredentials(
|
||||
// new SymmetricSecurityKey(key),
|
||||
// SecurityAlgorithms.HmacSha256Signature)
|
||||
// };
|
||||
//
|
||||
// var token = token_handler.CreateToken(token_descriptor);
|
||||
// return token_handler.WriteToken(token);
|
||||
// }
|
||||
//
|
||||
// public string generateRefreshToken()
|
||||
// {
|
||||
// var random_number = new byte[16];
|
||||
// using var rng = RandomNumberGenerator.Create();
|
||||
// rng.GetBytes(random_number);
|
||||
// return Convert.ToBase64String(random_number);
|
||||
// }
|
||||
//
|
||||
// public int? validateJwtToken(string token)
|
||||
// {
|
||||
// if (string.IsNullOrEmpty(token))
|
||||
// return null;
|
||||
//
|
||||
// var token_handler = new JwtSecurityTokenHandler();
|
||||
// var key = Encoding.ASCII.GetBytes(m_secret_key);
|
||||
//
|
||||
// try
|
||||
// {
|
||||
// token_handler.ValidateToken(token, new TokenValidationParameters
|
||||
// {
|
||||
// ValidateIssuerSigningKey = true,
|
||||
// IssuerSigningKey = new SymmetricSecurityKey(key),
|
||||
// ValidateIssuer = true,
|
||||
// ValidIssuer = this.m_issuer,
|
||||
// ValidateAudience = true,
|
||||
// ValidAudience = this.m_audience,
|
||||
// // 시간 검증 설정
|
||||
// ValidateLifetime = true,
|
||||
// ClockSkew = TimeSpan.Zero
|
||||
// }, out SecurityToken validated_token);
|
||||
//
|
||||
// var jwt_token = (JwtSecurityToken)validated_token;
|
||||
// var user_id = int.Parse(jwt_token.Claims.First(x => x.Type == ClaimTypes.NameIdentifier).Value);
|
||||
//
|
||||
// return user_id;
|
||||
// }
|
||||
// catch
|
||||
// {
|
||||
// // 토큰 검증 실패
|
||||
// return null;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// public Task<IJwtAuth> refreshTokenAsync(string token)
|
||||
// {
|
||||
// // 리프레시 토큰으로 유저 정보를 가져온다.
|
||||
// var user;
|
||||
//
|
||||
// // 사용자가 없거나 토큰이 존재하지 않음
|
||||
// if (user == null)
|
||||
// throw new SecurityTokenException("Invalid token");
|
||||
//
|
||||
// var refreshToken = user.RefreshTokens.Single(x => x.Token == token);
|
||||
//
|
||||
// // 토큰이 더 이상 활성 상태가 아니면 오류
|
||||
// if (!refreshToken.IsActive)
|
||||
// throw new SecurityTokenException("Invalid token");
|
||||
//
|
||||
// // 새 리프레시 토큰 생성
|
||||
// var newRefreshToken = generateRefreshTokenEntity();
|
||||
//
|
||||
// // 이전 토큰 폐기
|
||||
// refreshToken.Revoked = DateTime.UtcNow;
|
||||
// refreshToken.ReplacedByToken = newRefreshToken.Token;
|
||||
// refreshToken.ReasonRevoked = "Replaced by new token";
|
||||
//
|
||||
// // 새 리프레시 토큰 추가
|
||||
// user.RefreshTokens.Add(newRefreshToken);
|
||||
// _context.Update(user);
|
||||
// await _context.SaveChangesAsync();
|
||||
//
|
||||
// // 새 JWT 생성
|
||||
// var jwtToken = generateJwtToken(user);
|
||||
//
|
||||
// return new
|
||||
// {
|
||||
// Id = user.Id,
|
||||
// Username = user.Username,
|
||||
// Email = user.Email,
|
||||
// AccessToken = jwtToken,
|
||||
// RefreshToken = newRefreshToken.Token
|
||||
// };
|
||||
// }
|
||||
//
|
||||
// public Task revokeTokenAsync(string token, string ipAddress, string? reason = null)
|
||||
// {
|
||||
// throw new NotImplementedException();
|
||||
// }
|
||||
//
|
||||
// private RefreshToken generateRefreshTokenEntity()
|
||||
// {
|
||||
// return new RefreshToken
|
||||
// {
|
||||
// Token = generateRefreshToken(),
|
||||
// Expires = DateTime.UtcNow.AddDays(32), // 리프레시 토큰 만료 시간 (길게 설정)
|
||||
// Created = DateTime.UtcNow
|
||||
// };
|
||||
// }
|
||||
// }
|
||||
76
BrokerApiCore/Services/PlanetService.cs
Normal file
76
BrokerApiCore/Services/PlanetService.cs
Normal file
@@ -0,0 +1,76 @@
|
||||
namespace BrokerCore.Services;
|
||||
|
||||
using System.Security.Claims;
|
||||
|
||||
using BrokerBusinessLog;
|
||||
|
||||
using Microsoft.IdentityModel.JsonWebTokens;
|
||||
|
||||
using Repository;
|
||||
|
||||
using Common;
|
||||
|
||||
using ServerBase;
|
||||
using ServerCommon;
|
||||
|
||||
public class PlanetService
|
||||
{
|
||||
private readonly PlanetInfoRepo m_planet_info_repo;
|
||||
private readonly JwtGenerator m_jwt_generator;
|
||||
private readonly JwtParser m_jwt_parser;
|
||||
private PlanetProviderLogActor m_log_actor;
|
||||
|
||||
public PlanetService(PlanetInfoRepo planetInfoRepo, JwtGenerator jwtGenerator, JwtParser jwtParser)
|
||||
{
|
||||
m_planet_info_repo = planetInfoRepo;
|
||||
m_jwt_generator = jwtGenerator;
|
||||
m_jwt_parser = jwtParser;
|
||||
}
|
||||
|
||||
public async Task<string?> auth(string planetId, string planetSecretKey)
|
||||
{
|
||||
var (result, planet_info) = await m_planet_info_repo.findOne(planetId);
|
||||
Guard.Against.resultFail(result, ServerErrorCode.PlanetIdNotFound, () => "플래닛의 id가 존재하지 않음");
|
||||
Guard.Against.isNull(planet_info, ServerErrorCode.PlanetIdNotFound, () => "플래닛의 id가 존재하지 않음");
|
||||
Guard.Against.isFalse(planet_info.SecretKey == planetSecretKey,
|
||||
ServerErrorCode.PlanetSecretKeyDoesNotMatched, () => "플래닛에 제공한 엑세스키와 맞지 않음");
|
||||
|
||||
var access_token = m_jwt_generator.generateAccessToken(planetId, planet_info.ServerType);
|
||||
|
||||
// 비즈니스 로그
|
||||
m_log_actor = new PlanetProviderLogActor(planetId);
|
||||
BusinessLogger.collectLog(m_log_actor,
|
||||
new PlanetProviderAuthBusinessLog(
|
||||
new LogActionEx(LogActionType.BrokerApiPlanetAuth),
|
||||
new PlanetProviderAuthLogData { PlanetId = planetId, ExpireDateTime = DateTime.UtcNow }));
|
||||
return access_token;
|
||||
}
|
||||
|
||||
public (string, string) validate(string jwt)
|
||||
{
|
||||
if (jwt == m_jwt_generator.JwtOption.JwtTestPassToken)
|
||||
{
|
||||
return ("new_earth", "caliverse");
|
||||
}
|
||||
|
||||
var principal = m_jwt_parser.parseToken(jwt);
|
||||
Guard.Against.isNull(principal, ServerErrorCode.InvalidPlanetJwt, () => "jwt parsing error");
|
||||
|
||||
var exp_claim = principal.FindFirst(JwtRegisteredClaimNames.Exp)?.Value;
|
||||
Guard.Against.isNull(principal, ServerErrorCode.InvalidPlanetJwt, () => "no JwtRegisteredClaimNames.Exp value");
|
||||
|
||||
var exp_time = DateTimeOffset.FromUnixTimeSeconds(long.Parse(exp_claim ?? string.Empty));
|
||||
Guard.Against.isFalse(exp_time > DateTimeOffset.UtcNow, ServerErrorCode.ExpiredPlanetJwt,
|
||||
() => "Jwt has expired");
|
||||
|
||||
var planet_id = principal.FindFirstValue(JwtRegisteredClaimNames.Sid);
|
||||
Guard.Against.isNullOrEmptyOrWhiteSpace(planet_id, ServerErrorCode.InvalidPlanetJwt,
|
||||
() => "jwt parsing error no sub");
|
||||
|
||||
var planet_server_type = principal.FindFirstValue(JwtRegisteredClaimNames.Typ);
|
||||
Guard.Against.isNullOrEmptyOrWhiteSpace(planet_server_type, ServerErrorCode.InvalidPlanetJwt,
|
||||
() => "jwt parsing error no typ");
|
||||
|
||||
return (planet_id, planet_server_type);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
namespace BrokerCore.Services;
|
||||
|
||||
using Common;
|
||||
|
||||
using DbEntity;
|
||||
|
||||
using ServerBase;
|
||||
using ServerCommon;
|
||||
using MetaAssets;
|
||||
|
||||
using Repository;
|
||||
|
||||
|
||||
public class DailyAmountLimitChecker
|
||||
{
|
||||
private readonly PlanetItemExchangeOrderAmountTotalLimitRepo m_planet_item_exchange_order_amount_total_limit;
|
||||
private readonly PlanetItemExchangeOrderAmountUserLimitRepo m_planet_item_exchange_order_amount_user_limit;
|
||||
|
||||
public DailyAmountLimitChecker(
|
||||
PlanetItemExchangeOrderAmountTotalLimitRepo planetItemExchangeOrderAmountTotalLimit,
|
||||
PlanetItemExchangeOrderAmountUserLimitRepo planetItemExchangeOrderAmountUserLimit)
|
||||
{
|
||||
m_planet_item_exchange_order_amount_total_limit = planetItemExchangeOrderAmountTotalLimit;
|
||||
m_planet_item_exchange_order_amount_user_limit = planetItemExchangeOrderAmountUserLimit;
|
||||
}
|
||||
|
||||
public async Task<(Result result,
|
||||
PlanetItemExchangeOrderAmountTotalLimit? totalLimit,
|
||||
PlanetItemExchangeOrderAmountUserLimit? userLimit)>
|
||||
dailyLimitCheck(PlanetItemExchangeOrder order,
|
||||
PlanetItemExchangePolicyMetaData exchangePolicy, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var result = new Result();
|
||||
PlanetItemExchangeOrderAmountTotalLimit? total_limit = null;
|
||||
PlanetItemExchangeOrderAmountUserLimit? user_limit = null;
|
||||
try
|
||||
{
|
||||
var exchange_date = DateOnly.FromDateTime(order.CreatedAt.ToUniversalTime());
|
||||
|
||||
var total_daily_limit = exchangePolicy.DailyTotalAmountLimit;
|
||||
(result, total_limit) =
|
||||
await m_planet_item_exchange_order_amount_total_limit.findByExchangeMetaAndDateOrCreate(
|
||||
order.ExchangeMetaId,
|
||||
exchange_date,
|
||||
order.SeasonId,
|
||||
cancellationToken);
|
||||
Guard.Against.resultFail(result);
|
||||
Guard.Against.isNull(total_limit, ServerErrorCode.RdbError,
|
||||
()=>"PlanetItemExchangeOrderAmountTotalLimit not found");
|
||||
Guard.Against.isTrue(total_limit.DailyAmount + order.ExchangeMetaAmount > total_daily_limit,
|
||||
ServerErrorCode.ExchangeTotalOrderDailyLimitExceeded,
|
||||
()=>$"Daily total amount limit exceeded [{exchangePolicy.ID}] => current_total_daily_limit:{total_limit.DailyAmount} + order.ExchangeMetaAmount:{order.ExchangeMetaAmount} > total_daily_limit:{total_daily_limit}"
|
||||
);
|
||||
|
||||
var user_daily_limit = exchangePolicy.DailyUserAmountLimit;
|
||||
(result, user_limit) =
|
||||
await m_planet_item_exchange_order_amount_user_limit.findByExchangeMetaAndDateOrCreate(order.ExchangeMetaId,
|
||||
order.UserGuid, exchange_date, order.SeasonId, cancellationToken);
|
||||
Guard.Against.resultFail(result);
|
||||
Guard.Against.isNull(user_limit, ServerErrorCode.RdbError,
|
||||
()=>"PlanetItemExchangeOrderAmountUserLimit not found");
|
||||
Guard.Against.isTrue(user_limit.DailyAmount + order.ExchangeMetaAmount > user_daily_limit,
|
||||
ServerErrorCode.ExchangeUserOrderDailyLimitExceeded,
|
||||
()=>$"Daily user amount limit exceeded [{exchangePolicy.ID}] => current_user_daily_limit:{user_limit.DailyAmount} + order.ExchangeMetaAmount:{order.ExchangeMetaAmount} > user_daily_limit:{user_daily_limit}"
|
||||
);
|
||||
}
|
||||
catch (ApiException ex)
|
||||
{
|
||||
result.setFail((ServerErrorCode)ex.ErrorCode, ex.Message);
|
||||
return (result, total_limit, user_limit);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
result.setFail(ServerErrorCode.InternalServerError, ex.Message);
|
||||
return (result, total_limit, user_limit);
|
||||
}
|
||||
|
||||
return (result, total_limit, user_limit);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
|
||||
namespace BrokerCore.Services;
|
||||
|
||||
|
||||
using DbEntity;
|
||||
using Entity;
|
||||
|
||||
|
||||
|
||||
public interface IOrderCompletionStrategy
|
||||
{
|
||||
Task<PlanetItemExchangeOrder> completeOrder(
|
||||
PlanetUserEntity planetUserEntity,
|
||||
PlanetItemExchangeOrder order_created,
|
||||
CancellationToken cancellationToken = default);
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
using BrokerCore.DbEntity;
|
||||
|
||||
using MetaAssets;
|
||||
|
||||
namespace BrokerCore.Services;
|
||||
|
||||
public interface IOrderCreationStrategy
|
||||
{
|
||||
Task<(Result, PlanetItemExchangeOrder)> createOrder(
|
||||
PlanetItemExchangeOrder order,
|
||||
string planetServerType,
|
||||
PlanetItemExchangePolicyMetaData exchangePolicy,
|
||||
CancellationToken cancellationToken);
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
using ServerCommon;
|
||||
|
||||
namespace BrokerCore.Services;
|
||||
|
||||
public interface IOrderStrategyProvider
|
||||
{
|
||||
IOrderCreationStrategy? getCreationStrategy(CaliverseItemType itemType);
|
||||
IOrderCompletionStrategy? getCompletionStrategy(CaliverseItemType itemType);
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
using ServerCommon;
|
||||
|
||||
using System.Collections.Concurrent;
|
||||
|
||||
namespace BrokerCore.Services;
|
||||
|
||||
public class OrderStrategyProvider : IOrderStrategyProvider
|
||||
{
|
||||
private readonly IServiceProvider m_service_provider;
|
||||
private readonly ConcurrentDictionary<CaliverseItemType, Type> m_creation_strategy_map;
|
||||
private readonly ConcurrentDictionary<CaliverseItemType, Type> m_completion_strategy_map;
|
||||
|
||||
public OrderStrategyProvider(IServiceProvider serviceProvider)
|
||||
{
|
||||
m_service_provider = serviceProvider;
|
||||
|
||||
// 전략 맵핑 초기화
|
||||
m_creation_strategy_map = new ConcurrentDictionary<CaliverseItemType, Type>
|
||||
{
|
||||
[CaliverseItemType.Currency] = typeof(CurrencyExchangeCreationStrategy),
|
||||
[CaliverseItemType.CaliverseProduct] = typeof(ProductExchangeCreationStrategy)
|
||||
};
|
||||
|
||||
m_completion_strategy_map = new ConcurrentDictionary<CaliverseItemType, Type>
|
||||
{
|
||||
[CaliverseItemType.Currency] = typeof(CurrencyOrderCompletionStrategy),
|
||||
[CaliverseItemType.CaliverseProduct] = typeof(ProductOrderCompletionStrategy)
|
||||
};
|
||||
}
|
||||
|
||||
public IOrderCreationStrategy? getCreationStrategy(CaliverseItemType itemType)
|
||||
{
|
||||
if (m_creation_strategy_map.TryGetValue(itemType, out var strategy_type))
|
||||
{
|
||||
return m_service_provider.GetService(strategy_type) as IOrderCreationStrategy;
|
||||
}
|
||||
|
||||
// 기본 전략 반환
|
||||
return m_service_provider.GetService<CurrencyExchangeCreationStrategy>();
|
||||
}
|
||||
|
||||
public IOrderCompletionStrategy? getCompletionStrategy(CaliverseItemType itemType)
|
||||
{
|
||||
if (m_completion_strategy_map.TryGetValue(itemType, out var strategy_type))
|
||||
{
|
||||
return m_service_provider.GetService(strategy_type) as IOrderCompletionStrategy;
|
||||
}
|
||||
|
||||
// 기본 전략 반환
|
||||
return m_service_provider.GetService<CurrencyOrderCompletionStrategy>();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,218 @@
|
||||
namespace BrokerCore.Services;
|
||||
|
||||
using ServerCommon;
|
||||
|
||||
using Common;
|
||||
|
||||
using DbEntity;
|
||||
|
||||
using Repository;
|
||||
|
||||
using Entity;
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
using BrokerBusinessLog;
|
||||
|
||||
using MetaAssets;
|
||||
|
||||
using ServerCore; using ServerBase;
|
||||
|
||||
public class PlanetItemExchangeService
|
||||
{
|
||||
readonly PlanetUserEntity m_planet_user;
|
||||
private readonly IOrderStrategyProvider m_strategies;
|
||||
private readonly BrokerMetaTableRef m_meta_table_ref;
|
||||
private readonly PlanetItemExchangeOrderRepo m_planet_item_exchange_repo;
|
||||
private readonly DynamoDbClient m_dynamo_db_client;
|
||||
|
||||
public PlanetItemExchangeService(
|
||||
IServerLogic serverLogic,
|
||||
PlanetUserEntity planetUser,
|
||||
IOrderStrategyProvider strategies,
|
||||
BrokerMetaTableRef metaTableRef,
|
||||
PlanetItemExchangeOrderRepo planetItemExchangeOrderRepo)
|
||||
{
|
||||
m_planet_user = planetUser;
|
||||
m_strategies = strategies;
|
||||
m_meta_table_ref = metaTableRef;
|
||||
m_planet_user.onInit().Wait();
|
||||
m_planet_item_exchange_repo = planetItemExchangeOrderRepo;
|
||||
m_dynamo_db_client = serverLogic.getDynamoDbClient();
|
||||
}
|
||||
|
||||
public PlanetUserEntity PlanetUser => m_planet_user;
|
||||
|
||||
//===================================================================================================
|
||||
// 로그아웃 여부만 체크
|
||||
//===================================================================================================
|
||||
public bool isUserLoggedIn()
|
||||
{
|
||||
var user_attribute = m_planet_user.getEntityAttributeNotNull<UserAttribute>();
|
||||
return user_attribute.GameLoginDateTime > user_attribute.GameLogoutDateTime;
|
||||
}
|
||||
|
||||
//===================================================================================================
|
||||
// 유저 인증 및 account, user, nickname 정보 읽음
|
||||
//===================================================================================================
|
||||
public async Task validateAndGetUser(
|
||||
string accountId, string userGuid, string planetId
|
||||
)
|
||||
{
|
||||
m_planet_user.setPlanetId(planetId);
|
||||
var action = m_planet_user.getEntityActionNotNull<UserAuthAction>();
|
||||
|
||||
if (!string.IsNullOrEmpty(accountId))
|
||||
{
|
||||
var result = await action.findAndSetAllAttributeByAccountId(accountId);
|
||||
Guard.Against.resultFail(result);
|
||||
}
|
||||
else
|
||||
{
|
||||
var result = await action.findAndSetAllAttributeByUserGuid(userGuid);
|
||||
Guard.Against.resultFail(result);
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================================
|
||||
// 현재 재화 요청
|
||||
//=============================================================================================
|
||||
public async Task<double> getCurrencyAmount(string currencyTypeString)
|
||||
{
|
||||
var currency_type = currencyTypeString.convertEnumTypeAndValueStringToEnum(CurrencyType.None);
|
||||
Guard.Against.isFalse(currency_type != CurrencyType.None, ServerErrorCode.InvalidRequest,
|
||||
() => "Invalid currency type");
|
||||
CurrencyControlHelper.setDbConnector(m_dynamo_db_client);
|
||||
var user_guid = m_planet_user.getEntityAttributeNotNull<AccountAttribute>().UserGuid;
|
||||
var (result, current_sapphire_amount_double) =
|
||||
await CurrencyControlHelper.getMoneyByUserGuid(user_guid, currency_type);
|
||||
Guard.Against.resultFail(result);
|
||||
return current_sapphire_amount_double;
|
||||
}
|
||||
|
||||
//=============================================================================================
|
||||
// 교환 주문 조회
|
||||
//=============================================================================================
|
||||
public async Task<(IEnumerable<PlanetItemExchangeOrder>, int)> findOrderList(
|
||||
string planetId,
|
||||
string metaId,
|
||||
string seasonId,
|
||||
string userGuid,
|
||||
ExchangeOrderStatus? orderStatus = null,
|
||||
int pageIndex = 1,
|
||||
int pageSize = 20,
|
||||
string sortOrder = "asc",
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
var (result, orders, total_count) =
|
||||
await m_planet_item_exchange_repo.findList(
|
||||
planetId,
|
||||
metaId,
|
||||
seasonId,
|
||||
userGuid,
|
||||
orderStatus,
|
||||
pageIndex,
|
||||
pageSize,
|
||||
sortOrder,
|
||||
cancellationToken);
|
||||
Guard.Against.resultFail(result, ServerErrorCode.RdbError, () => result.ResultString);
|
||||
Guard.Against.isNull(orders, ServerErrorCode.RdbError, () => result.ResultString);
|
||||
return (orders, total_count);
|
||||
}
|
||||
|
||||
//=============================================================================================
|
||||
// 교환 주문 생성
|
||||
//=============================================================================================
|
||||
public async Task<(Result, PlanetItemExchangeOrder)> createOrder(
|
||||
string planetId,
|
||||
string seasonId,
|
||||
string planetServerType,
|
||||
string exchangeMetaId,
|
||||
int exchangeMetaAmount,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
// 메타 테이블에서 교환 정보 가져오기
|
||||
m_meta_table_ref.MetaTable.PlanetItemExchangePolicyMetaTable.PlanetItemExchangePolicyDataListbyID
|
||||
.TryGetValue(exchangeMetaId, out var exchange_policy);
|
||||
Guard.Against.isNull(exchange_policy, ServerErrorCode.MetaIdInvalid,
|
||||
() => $"Invalid ExchangeMetaId:{exchangeMetaId}");
|
||||
|
||||
// 주문 내역 생성
|
||||
var order = makeExchangeOrderInfo(planetId, seasonId, exchange_policy, exchangeMetaAmount);
|
||||
|
||||
// 아이템 유형에 따라 전략 선택
|
||||
var caliverse_item_type =
|
||||
exchange_policy.CaliverseItemType.convertEnumTypeAndValueStringToEnum(CaliverseItemType.None);
|
||||
|
||||
var strategy = m_strategies.getCreationStrategy(caliverse_item_type);
|
||||
Guard.Against.isNull(strategy, ServerErrorCode.InternalServerError,
|
||||
() => "createOrder Invalid Item Type Strategy");
|
||||
|
||||
var (result, order_info) =
|
||||
await strategy.createOrder(order, planetServerType, exchange_policy, cancellationToken);
|
||||
Guard.Against.resultFail(result, ServerErrorCode.InternalServerError, () => result.ResultString);
|
||||
|
||||
// 비즈니스 로그 작성
|
||||
BusinessLogger.collectLog(m_planet_user,
|
||||
new PlanetItemExchangeBusinessLog(new LogActionEx(LogActionType.BrokerApiUserExchangeOrderCreated),
|
||||
Helpers.createFromExchangeOrderLog(order)));
|
||||
|
||||
return (result, order_info);
|
||||
}
|
||||
|
||||
//=============================================================================================
|
||||
// 교환 주문 완료
|
||||
// 주문 상태가 Pending 이어야 한다.
|
||||
//=============================================================================================
|
||||
public async Task<PlanetItemExchangeOrder> completeOrder(
|
||||
string orderId, CancellationToken cancellationToken = default)
|
||||
{
|
||||
// 생성 주문 조회
|
||||
var (result, order_created) =
|
||||
await m_planet_item_exchange_repo.findOne(orderId, ExchangeOrderStatus.Pending, cancellationToken);
|
||||
Guard.Against.resultFail(result);
|
||||
Guard.Against.isNull(order_created, ServerErrorCode.ExchangeOrderIdNotFound, () => "Invalid Order Id");
|
||||
|
||||
// 주문 타입에 맞는 전략 선택 후 완료 처리
|
||||
var strategy = m_strategies.getCompletionStrategy(order_created.CaliverseItemType);
|
||||
Guard.Against.isNull(strategy, ServerErrorCode.InternalServerError, () => "completeOrder Invalid Order Type");
|
||||
var order_completed = await strategy.completeOrder(m_planet_user, order_created, cancellationToken);
|
||||
|
||||
// 비즈니스 로그 작성
|
||||
BusinessLogger.collectLog(m_planet_user,
|
||||
new PlanetItemExchangeBusinessLog(new LogActionEx(LogActionType.BrokerApiUserExchangeOrderCompleted),
|
||||
Helpers.createFromExchangeOrderLog(order_completed)));
|
||||
|
||||
return order_completed;
|
||||
}
|
||||
|
||||
private PlanetItemExchangeOrder makeExchangeOrderInfo(
|
||||
string planetId,
|
||||
string seasonId,
|
||||
PlanetItemExchangePolicyMetaData exchangePolicy,
|
||||
int exchangeMetaAmount)
|
||||
{
|
||||
var now = DateTime.UtcNow;
|
||||
return new PlanetItemExchangeOrder
|
||||
{
|
||||
OrderId = $"{now:yyMMdd}{Guid.NewGuid():N}",
|
||||
OrderStatus = ExchangeOrderStatus.Pending,
|
||||
SeasonId = seasonId,
|
||||
PlanetId = planetId,
|
||||
AccountId = m_planet_user.AccountId,
|
||||
UserGuid = m_planet_user.UserGuid,
|
||||
Nickname = m_planet_user.Nickname,
|
||||
CaliverseItemType =
|
||||
exchangePolicy.CaliverseItemType.convertEnumTypeAndValueStringToEnum(CaliverseItemType.None),
|
||||
CaliverseItemId = exchangePolicy.CaliverseItemId,
|
||||
CaliverseItemDeltaAmount = exchangeMetaAmount * exchangePolicy.CaliverseItemAmount,
|
||||
PlanetItemType = exchangePolicy.PlanetItemType.convertEnumTypeAndValueStringToEnum(PlanetItemType.None),
|
||||
PlanetItemId = exchangePolicy.PlanetItemId,
|
||||
PlanetItemDeltaAmount = exchangeMetaAmount * exchangePolicy.PlanetItemAmount,
|
||||
CreatedAt = now,
|
||||
CompletedAt = null,
|
||||
ExchangeMetaId = exchangePolicy.ID,
|
||||
ExchangeMetaAmount = exchangeMetaAmount,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace BrokerCore.Services;
|
||||
|
||||
using Entity;
|
||||
|
||||
public static class ServiceCollectionExtensions
|
||||
{
|
||||
public static IServiceCollection addExchangeServices(this IServiceCollection services)
|
||||
{
|
||||
services.AddScoped<PlanetUserEntity>();
|
||||
// 전략 등록
|
||||
services.AddScoped<CurrencyExchangeCreationStrategy>();
|
||||
services.AddScoped<ProductExchangeCreationStrategy>();
|
||||
services.AddScoped<CurrencyOrderCompletionStrategy>();
|
||||
services.AddScoped<ProductOrderCompletionStrategy>();
|
||||
|
||||
// 전략 제공자 등록
|
||||
services.AddScoped<IOrderStrategyProvider, OrderStrategyProvider>();
|
||||
|
||||
// 서비스 등록
|
||||
services.AddScoped<EchoSystemService>();
|
||||
// services.AddScoped<SapphireExchangeService>();
|
||||
services.AddScoped<PlanetItemExchangeService>();
|
||||
return services;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,163 @@
|
||||
using BrokerCore.DbEntity;
|
||||
using BrokerCore.Entity;
|
||||
using BrokerCore.Repository;
|
||||
|
||||
using Microsoft.Extensions.Logging;
|
||||
// using Polly;
|
||||
// using Polly.Retry;
|
||||
using MetaAssets;
|
||||
|
||||
using ServerCommon;
|
||||
|
||||
namespace BrokerCore.Services;
|
||||
using Common;
|
||||
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Storage;
|
||||
using Repository.Context;
|
||||
using ServerCore; using ServerBase;
|
||||
|
||||
//=========================================================================================
|
||||
// 플래닛의 아이템을 칼리버스 재화로 교환하는 주문 생성
|
||||
// Broker의 rdb(순수 교환 정보)와 DynamoDB(유저의 게임정보)를 사용하여 교환 주문을 생성한다.
|
||||
// 유저의 게임 정보에서 재화가 차감되면
|
||||
//=========================================================================================
|
||||
public class CurrencyExchangeCreationStrategy : IOrderCreationStrategy
|
||||
{
|
||||
private readonly PlanetUserEntity m_planet_user_entity;
|
||||
private readonly MetaverseBrokerDbContext m_broker_db_context;
|
||||
private readonly PlanetItemExchangeOrderRepo m_planet_item_exchange_repo;
|
||||
private readonly PlanetItemExchangeOrderAmountTotalLimitRepo m_planet_item_exchange_order_amount_total_limit;
|
||||
private readonly PlanetItemExchangeOrderAmountUserLimitRepo m_planet_item_exchange_order_amount_user_limit;
|
||||
private readonly DynamoDbClient m_dynamo_db_client;
|
||||
private readonly EchoSystemService m_echo_system_service;
|
||||
private readonly ILogger<CurrencyExchangeCreationStrategy>? m_logger;
|
||||
|
||||
public CurrencyExchangeCreationStrategy(
|
||||
IServerLogic serverLogic,
|
||||
PlanetUserEntity planetUserEntity,
|
||||
MetaverseBrokerDbContext brokerDbContext,
|
||||
PlanetItemExchangeOrderRepo planetItemExchangeRepo,
|
||||
PlanetItemExchangeOrderAmountTotalLimitRepo planetItemExchangeOrderAmountTotalLimit,
|
||||
PlanetItemExchangeOrderAmountUserLimitRepo planetItemExchangeOrderAmountUserLimit,
|
||||
EchoSystemService echoSystemService,
|
||||
ILogger<CurrencyExchangeCreationStrategy>? logger = null!)
|
||||
{
|
||||
m_planet_user_entity = planetUserEntity;
|
||||
m_broker_db_context = brokerDbContext;
|
||||
m_planet_item_exchange_repo = planetItemExchangeRepo;
|
||||
m_planet_item_exchange_order_amount_total_limit = planetItemExchangeOrderAmountTotalLimit;
|
||||
m_planet_item_exchange_order_amount_user_limit = planetItemExchangeOrderAmountUserLimit;
|
||||
m_dynamo_db_client = serverLogic.getDynamoDbClient();
|
||||
m_echo_system_service = echoSystemService;
|
||||
m_logger = logger;
|
||||
}
|
||||
|
||||
public async Task<(Result, PlanetItemExchangeOrder)> createOrder(
|
||||
PlanetItemExchangeOrder order,
|
||||
string planetServerType,
|
||||
PlanetItemExchangePolicyMetaData exchangePolicy, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var exchange_date = DateOnly.FromDateTime(order.CreatedAt.ToUniversalTime());
|
||||
var exchange_amount = order.ExchangeMetaAmount;
|
||||
var strategy = m_broker_db_context.Database.CreateExecutionStrategy();
|
||||
var execute_result = await strategy.ExecuteAsync<Result>(async () =>
|
||||
{
|
||||
var transaction_result = new Result();
|
||||
await using var transaction = await m_broker_db_context.Database.BeginTransactionAsync(cancellationToken);
|
||||
try
|
||||
{
|
||||
var daily_limit_checker = new DailyAmountLimitChecker(
|
||||
m_planet_item_exchange_order_amount_total_limit,
|
||||
m_planet_item_exchange_order_amount_user_limit);
|
||||
var (result, total_limit, user_limit) = await daily_limit_checker.dailyLimitCheck(order, exchangePolicy, cancellationToken);
|
||||
|
||||
// 신규 주문 정보 삽입
|
||||
await m_planet_item_exchange_repo.add(order, cancellationToken);
|
||||
Guard.Against.resultFail(result);
|
||||
Guard.Against.isNull(total_limit, ServerErrorCode.RdbError,
|
||||
()=>"PlanetItemExchangeOrderAmountTotalLimit not found");
|
||||
Guard.Against.isNull(user_limit, ServerErrorCode.RdbError,
|
||||
()=>"PlanetItemExchangeOrderAmountUserLimit not found");
|
||||
|
||||
var (currency_result, _) = await updateCurrency(exchange_amount, exchangePolicy);
|
||||
Guard.Against.resultFail(currency_result);
|
||||
|
||||
await m_planet_item_exchange_order_amount_total_limit.increaseDailyAmount(total_limit,
|
||||
exchange_amount, cancellationToken);
|
||||
|
||||
await m_planet_item_exchange_order_amount_user_limit.increaseDailyAmount(user_limit,
|
||||
exchange_amount, cancellationToken);
|
||||
|
||||
await transaction.CommitAsync(cancellationToken);
|
||||
|
||||
// 사파이어 처리인 경우 에코시스템에 통보
|
||||
if (string.Equals(exchangePolicy.CaliverseItemId, CurrencyType.Sapphire.ToString(),
|
||||
StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
var sapphire_delta = exchange_amount * exchangePolicy.CaliverseItemAmount;
|
||||
_ = notifyToEchoSystemEvent(planetServerType, sapphire_delta).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
if (transaction.GetDbTransaction().Connection is not null)
|
||||
{
|
||||
await transaction.RollbackAsync(cancellationToken);
|
||||
}
|
||||
|
||||
throw;
|
||||
}
|
||||
return transaction_result;
|
||||
});
|
||||
return (execute_result, order);
|
||||
}
|
||||
|
||||
private async Task<(Result, long)> updateCurrency(
|
||||
int exchangeMetaAmount,
|
||||
PlanetItemExchangePolicyMetaData exchangePolicy)
|
||||
{
|
||||
var currency_delta = exchangeMetaAmount * exchangePolicy.CaliverseItemAmount;
|
||||
CurrencyControlHelper.setDbConnector(m_dynamo_db_client);
|
||||
var (result, current_sapphire_amount_double) =
|
||||
await CurrencyControlHelper.spendMoneyByUserGuid(getUserGuid(), CurrencyType.Sapphire, currency_delta);
|
||||
var current_sapphire_amount = Convert.ToInt64(current_sapphire_amount_double);
|
||||
return (result, current_sapphire_amount);
|
||||
}
|
||||
|
||||
//===========================================================================================
|
||||
// 사파이어 처리인 경우 외부에 있는 에코시스템에 이벤트를 통보하여야 한다.
|
||||
//===========================================================================================
|
||||
private async Task notifyToEchoSystemEvent(
|
||||
string planetServerType,
|
||||
long sapphireDelta)
|
||||
{
|
||||
try
|
||||
{
|
||||
await m_echo_system_service.createAndSetEventPayload(
|
||||
accountId: getUserAccountId(),
|
||||
nickname: getUserNickname(),
|
||||
userGuid: getUserGuid(),
|
||||
sapphireDelta,
|
||||
planetServerType,
|
||||
CaliumEventType.extra_get.ToString()
|
||||
);
|
||||
|
||||
_ = await m_echo_system_service.processCaliumEvent(m_planet_user_entity);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
m_logger?.LogError(ex, "Failed to process calium event");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
private string getUserAccountId() =>
|
||||
m_planet_user_entity.getEntityAttributeNotNull<AccountAttribute>().AccountId;
|
||||
|
||||
private string getUserGuid() =>
|
||||
m_planet_user_entity.getEntityAttributeNotNull<AccountAttribute>().UserGuid;
|
||||
|
||||
private string getUserNickname() =>
|
||||
m_planet_user_entity.getEntityAttributeNotNull<NicknameAttribute>().Nickname;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
namespace BrokerCore.Services;
|
||||
using Common;
|
||||
using DbEntity;
|
||||
using Entity;
|
||||
using Repository;
|
||||
|
||||
// 화폐(Currency) 주문 완료 전략
|
||||
public class CurrencyOrderCompletionStrategy : IOrderCompletionStrategy
|
||||
{
|
||||
private readonly PlanetItemExchangeOrderRepo m_planet_item_exchange_repo;
|
||||
|
||||
public CurrencyOrderCompletionStrategy(PlanetItemExchangeOrderRepo planetItemExchangeOrderRepo)
|
||||
{
|
||||
m_planet_item_exchange_repo = planetItemExchangeOrderRepo;
|
||||
}
|
||||
|
||||
public async Task<PlanetItemExchangeOrder> completeOrder(PlanetUserEntity planetUserEntity,
|
||||
PlanetItemExchangeOrder orderCreated,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
var (result, order_completed) =
|
||||
await m_planet_item_exchange_repo.findAndUpdateStatus(orderCreated.OrderId, ExchangeOrderStatus.Completed, cancellationToken);
|
||||
Guard.Against.resultFail(result);
|
||||
Guard.Against.isNull(order_completed, ServerErrorCode.InvalidRequest,
|
||||
()=>"CurrencyOrderCompletionStrategy => Order not found");
|
||||
return order_completed;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
namespace BrokerCore.Services;
|
||||
|
||||
using Common;
|
||||
|
||||
using DbEntity;
|
||||
|
||||
using Repository;
|
||||
|
||||
using MetaAssets;
|
||||
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Storage;
|
||||
|
||||
using Repository.Context;
|
||||
|
||||
public class ProductExchangeCreationStrategy : IOrderCreationStrategy
|
||||
{
|
||||
private readonly MetaverseBrokerDbContext m_broker_db_context;
|
||||
private readonly PlanetItemExchangeOrderAmountTotalLimitRepo m_planet_item_exchange_order_amount_total_limit;
|
||||
private readonly PlanetItemExchangeOrderAmountUserLimitRepo m_planet_item_exchange_order_amount_user_limit;
|
||||
private readonly PlanetItemExchangeOrderRepo m_planet_item_exchange_repo;
|
||||
|
||||
public ProductExchangeCreationStrategy(
|
||||
MetaverseBrokerDbContext brokerDbContext,
|
||||
PlanetItemExchangeOrderAmountTotalLimitRepo planetItemExchangeOrderAmountTotalLimit,
|
||||
PlanetItemExchangeOrderAmountUserLimitRepo planetItemExchangeOrderAmountUserLimit,
|
||||
PlanetItemExchangeOrderRepo planetItemExchangeRepo)
|
||||
{
|
||||
m_broker_db_context = brokerDbContext;
|
||||
m_planet_item_exchange_order_amount_total_limit = planetItemExchangeOrderAmountTotalLimit;
|
||||
m_planet_item_exchange_order_amount_user_limit = planetItemExchangeOrderAmountUserLimit;
|
||||
m_planet_item_exchange_repo = planetItemExchangeRepo;
|
||||
}
|
||||
|
||||
public async Task<(Result, PlanetItemExchangeOrder)> createOrder(
|
||||
PlanetItemExchangeOrder order,
|
||||
string planetServerType,
|
||||
PlanetItemExchangePolicyMetaData exchangePolicy,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
var exchange_date = DateOnly.FromDateTime(order.CreatedAt.ToUniversalTime());
|
||||
var strategy = m_broker_db_context.Database.CreateExecutionStrategy();
|
||||
var execute_result = await strategy.ExecuteAsync<Result>(async () =>
|
||||
{
|
||||
Result result = null!;
|
||||
await using var transaction = await m_broker_db_context.Database.BeginTransactionAsync(cancellationToken);
|
||||
try
|
||||
{
|
||||
var daily_limit_checker = new DailyAmountLimitChecker(
|
||||
m_planet_item_exchange_order_amount_total_limit,
|
||||
m_planet_item_exchange_order_amount_user_limit);
|
||||
(result, var total_limit, var user_limit) = await daily_limit_checker.dailyLimitCheck(order, exchangePolicy, cancellationToken);
|
||||
|
||||
// 신규 주문 정보 삽입
|
||||
await m_planet_item_exchange_repo.add(order, cancellationToken);
|
||||
Guard.Against.resultFail(result);
|
||||
Guard.Against.isNull(total_limit, ServerErrorCode.RdbError,
|
||||
()=>"PlanetItemExchangeOrderAmountTotalLimit not found");
|
||||
Guard.Against.isNull(user_limit, ServerErrorCode.RdbError,
|
||||
()=>"PlanetItemExchangeOrderAmountUserLimit not found");
|
||||
|
||||
// 신규 주문 정보 삽입
|
||||
await m_planet_item_exchange_repo.add(order, cancellationToken);
|
||||
|
||||
await m_planet_item_exchange_order_amount_total_limit.increaseDailyAmount(total_limit,
|
||||
order.ExchangeMetaAmount, cancellationToken);
|
||||
|
||||
await m_planet_item_exchange_order_amount_user_limit.increaseDailyAmount(user_limit,
|
||||
order.ExchangeMetaAmount, cancellationToken);
|
||||
|
||||
await transaction.CommitAsync(cancellationToken);
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
if (transaction.GetDbTransaction().Connection is not null)
|
||||
{
|
||||
await transaction.RollbackAsync(cancellationToken);
|
||||
}
|
||||
return new Result
|
||||
{
|
||||
ErrorCode = ServerErrorCode.InternalServerError,
|
||||
ResultString = $"ProductExchangeCreationStrategy Transaction Error => {ex.Message}"
|
||||
};
|
||||
}
|
||||
return result;
|
||||
});
|
||||
return (execute_result, order);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
using ServerCore;
|
||||
using ServerBase;
|
||||
using ServerCommon;
|
||||
|
||||
|
||||
namespace BrokerCore.Services;
|
||||
|
||||
using BrokerBusinessLog;
|
||||
|
||||
using Common;
|
||||
|
||||
using DbEntity;
|
||||
|
||||
using Entity;
|
||||
using Entity.Actions;
|
||||
|
||||
using MetaAssets;
|
||||
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Storage;
|
||||
|
||||
using Repository;
|
||||
using Repository.Context;
|
||||
|
||||
// 아이템 주문 완료 전략
|
||||
public class ProductOrderCompletionStrategy : IOrderCompletionStrategy
|
||||
{
|
||||
private PlanetUserEntity m_planet_user_entity;
|
||||
private readonly BrokerMetaTableRef m_meta_table_ref;
|
||||
private readonly IServerLogic m_server_logic;
|
||||
private readonly MetaverseBrokerDbContext m_broker_db_context;
|
||||
private readonly PlanetItemExchangeOrderRepo m_planet_item_exchange_repo;
|
||||
|
||||
public ProductOrderCompletionStrategy(
|
||||
BrokerMetaTableRef metaTableRef,
|
||||
IServerLogic serverLogic,
|
||||
MetaverseBrokerDbContext brokerDbContext,
|
||||
PlanetItemExchangeOrderRepo planetItemExchangeRepo
|
||||
)
|
||||
{
|
||||
m_meta_table_ref = metaTableRef;
|
||||
m_server_logic = serverLogic;
|
||||
m_broker_db_context = brokerDbContext;
|
||||
m_planet_item_exchange_repo = planetItemExchangeRepo;
|
||||
}
|
||||
|
||||
public async Task<PlanetItemExchangeOrder> completeOrder(
|
||||
PlanetUserEntity planetUserEntity,
|
||||
PlanetItemExchangeOrder orderCreated,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
m_planet_user_entity = planetUserEntity;
|
||||
// 메타데이터 조회
|
||||
var exchange_policy = getExchangePolicyMeta(orderCreated.ExchangeMetaId);
|
||||
var product_meta = getProductMeta(exchange_policy.CaliverseItemId);
|
||||
var mail_meta = getSystemMailMeta(product_meta.SystemMail_First);
|
||||
|
||||
// 메일 발송 처리
|
||||
var broker_mail = new BrokerMailEntity(m_planet_user_entity, m_server_logic);
|
||||
var init_result = await broker_mail.onInit();
|
||||
Guard.Against.resultFail(init_result, init_result.ErrorCode, ()=>"BrokerMail onInit error");
|
||||
|
||||
var mail_send_action = broker_mail.getEntityActionNotNull<BrokerMailSendAction>();
|
||||
var mail_option = mail_send_action.createSystemSendMailOptionByMeta(product_meta, mail_meta,
|
||||
m_planet_user_entity.UserGuid,
|
||||
m_planet_user_entity.Nickname, orderCreated.ExchangeMetaAmount);
|
||||
|
||||
//==============================================================================================
|
||||
// rdb 트랜잭션 시작
|
||||
// 주문 완료 처리 임시
|
||||
// 메일 발송
|
||||
// 메일 발송 완료 시 주문 완료 처리 커밋
|
||||
// TODO: 재시도 전략 연구?
|
||||
//==============================================================================================
|
||||
PlanetItemExchangeOrder order_completed_result_object = null!;
|
||||
var strategy = m_broker_db_context.Database.CreateExecutionStrategy();
|
||||
var transaction_result = await strategy.ExecuteAsync(async () =>
|
||||
{
|
||||
await using var transaction =
|
||||
await m_broker_db_context.Database.BeginTransactionAsync(System.Data.IsolationLevel.RepeatableRead,
|
||||
cancellationToken);
|
||||
var (order_update_result, order_completed) = await m_planet_item_exchange_repo.findAndUpdateStatus(
|
||||
orderCreated.OrderId, ExchangeOrderStatus.Completed,
|
||||
cancellationToken);
|
||||
if (order_update_result.isFail())
|
||||
{
|
||||
await transaction.RollbackAsync(cancellationToken);
|
||||
return order_update_result;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var mail_send_result = await mail_send_action.sendMail(mail_option,
|
||||
async () => await transaction.CommitAsync(cancellationToken),
|
||||
async () => await transaction.RollbackAsync(cancellationToken)
|
||||
);
|
||||
if (mail_send_result.isFail())
|
||||
{
|
||||
await transaction.RollbackAsync(cancellationToken);
|
||||
return mail_send_result;
|
||||
}
|
||||
else if (order_completed is not null)
|
||||
{
|
||||
order_completed_result_object = order_completed;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (transaction.GetDbTransaction().Connection is not null)
|
||||
{
|
||||
await transaction.RollbackAsync(cancellationToken);
|
||||
}
|
||||
|
||||
return new Result
|
||||
{
|
||||
ErrorCode = ServerErrorCode.InternalServerError,
|
||||
ResultString = $"ProductOrderCompletionStrategy Transaction Error => {ex.Message}"
|
||||
};
|
||||
}
|
||||
|
||||
return new Result();
|
||||
});
|
||||
Guard.Against.resultFail(transaction_result);
|
||||
return order_completed_result_object;
|
||||
}
|
||||
|
||||
private PlanetItemExchangePolicyMetaData getExchangePolicyMeta(string exchangeMetaId)
|
||||
{
|
||||
m_meta_table_ref.MetaTable.PlanetItemExchangePolicyMetaTable.PlanetItemExchangePolicyDataListbyID.TryGetValue(
|
||||
exchangeMetaId, out var policy_meta);
|
||||
Guard.Against.isNull(policy_meta, ServerErrorCode.MetaIdInvalid,
|
||||
()=>"planet_item_exchange_policy_meta not found");
|
||||
return policy_meta;
|
||||
}
|
||||
|
||||
private ProductMetaData getProductMeta(string productMetaIdString)
|
||||
{
|
||||
var product_meta_id = Convert.ToInt32(productMetaIdString);
|
||||
m_meta_table_ref.MetaTable.ProductMetaTable.ProductMetaDataListbyId.TryGetValue(product_meta_id,
|
||||
out var product_meta);
|
||||
Guard.Against.isNull(product_meta, ServerErrorCode.MetaIdInvalid, ()=>"product meta not found");
|
||||
return product_meta;
|
||||
}
|
||||
|
||||
private SystemMailMetaData getSystemMailMeta(string systemMailDataId)
|
||||
{
|
||||
m_meta_table_ref.MetaTable.SystemMailMetaTable.SystemMailMetaDataListbyKey.TryGetValue(systemMailDataId,
|
||||
out var mail_data);
|
||||
Guard.Against.isNull(mail_data, ServerErrorCode.MetaIdInvalid, ()=>"system_mail_meta not found");
|
||||
return mail_data;
|
||||
}
|
||||
}
|
||||
212
BrokerApiCore/Services/UserAuthService.cs
Normal file
212
BrokerApiCore/Services/UserAuthService.cs
Normal file
@@ -0,0 +1,212 @@
|
||||
using System.IdentityModel.Tokens.Jwt;
|
||||
using System.Text;
|
||||
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
|
||||
using ServerCore; using ServerBase;
|
||||
|
||||
using ServerCommon;
|
||||
|
||||
namespace BrokerCore.Services;
|
||||
|
||||
using BrokerBusinessLog;
|
||||
|
||||
using Repository;
|
||||
|
||||
using Common;
|
||||
|
||||
using Entity;
|
||||
|
||||
public class UserAuthService
|
||||
{
|
||||
private readonly PlanetUserEntity m_planet_user_entity;
|
||||
private readonly SsoAccountRepo m_sso_account_repo;
|
||||
private readonly IServerLogic m_server_logic;
|
||||
|
||||
public string AccountId
|
||||
=> m_planet_user_entity.getEntityAttributeNotNull<AccountAttribute>().AccountId;
|
||||
|
||||
// public string Email { get; set; } = string.Empty;
|
||||
public string UserGuid
|
||||
=> m_planet_user_entity.getEntityAttributeNotNull<AccountAttribute>().UserGuid;
|
||||
|
||||
public string Nickname
|
||||
=> m_planet_user_entity.getEntityAttributeNotNull<NicknameAttribute>().Nickname;
|
||||
|
||||
public IServerLogic ServerLogic => m_server_logic;
|
||||
|
||||
public PlanetUserEntity PlanetUserEntity => m_planet_user_entity;
|
||||
|
||||
private ServerConfigMetaverseBroker? getServerConfig()
|
||||
{
|
||||
return m_server_logic.getServerConfig() as ServerConfigMetaverseBroker;
|
||||
}
|
||||
|
||||
public UserAuthService(SsoAccountRepo ssoAccountRepo, IServerLogic serverLogic)
|
||||
{
|
||||
m_sso_account_repo = ssoAccountRepo;
|
||||
m_server_logic = serverLogic;
|
||||
m_planet_user_entity = new PlanetUserEntity(serverLogic);
|
||||
m_planet_user_entity.onInit().Wait();
|
||||
}
|
||||
|
||||
public async Task<Result> authByWebPortalToken(string webPortalToken, string? planetId = null)
|
||||
{
|
||||
if (planetId is not null)
|
||||
{
|
||||
m_planet_user_entity.setPlanetId(planetId);
|
||||
}
|
||||
|
||||
var m_sso_jwt_secret_key = getServerConfig()?.SsoAccountAuthJwtSecretKey ?? string.Empty;
|
||||
Guard.Against.isNullOrEmptyOrWhiteSpace(m_sso_jwt_secret_key, ServerErrorCode.InternalServerError,
|
||||
()=>"SSO JWT secret key is required in server config");
|
||||
|
||||
var jwt_result = verifySsoAccountAuthJwt(webPortalToken,
|
||||
m_sso_jwt_secret_key,
|
||||
out var account_id, out var account_type, out var access_token);
|
||||
if (jwt_result.isFail())
|
||||
{
|
||||
var error_msg = $"Broker Api Failed to Auth From Jwt !!! : {jwt_result.toBasicString()}, {webPortalToken}";
|
||||
Log.getLogger().error(error_msg);
|
||||
return jwt_result;
|
||||
}
|
||||
|
||||
var result = await authByAccount(account_id);
|
||||
if (result.isSuccess())
|
||||
{
|
||||
if (planetId is not null)
|
||||
{
|
||||
// BrokerBusinessLogger.collectLog(m_planet_user_entity, LogActionType.BrokerApiUserLogin, new UserAuthLogInfo
|
||||
// {
|
||||
// AccountId = account_id,
|
||||
// UserGuid = UserGuid,
|
||||
// Nickname = Nickname,
|
||||
// });
|
||||
|
||||
BusinessLogger.collectLog(m_planet_user_entity,
|
||||
new PlanetUserAuthBusinessLog(
|
||||
new PlanetUserAuthLogData { AccountId = account_id, UserGuid = UserGuid, Nickname = Nickname, },
|
||||
LogActionType.BrokerApiUserLogin));
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task<Result> authFromEmail(string email)
|
||||
{
|
||||
var (result, sso_account) = await m_sso_account_repo.findOneByEmail(email);
|
||||
Guard.Against.resultFail(result);
|
||||
Guard.Against.isNull(sso_account, ServerErrorCode.AccountNotFound, ()=>"sso account not found");
|
||||
|
||||
result = await authByAccount(sso_account.Id.ToString());
|
||||
Guard.Against.resultFail(result);
|
||||
Guard.Against.isNull(sso_account, ServerErrorCode.UserNotFound, ()=>"user not found");
|
||||
return result;
|
||||
}
|
||||
|
||||
// todo: JwtParser를 사용해서 수정할 것
|
||||
private Result verifySsoAccountAuthJwt(string ssoJwt
|
||||
, string ssoJwtSecret
|
||||
, out string id, out AccountType accountType, out UInt64 accessToken)
|
||||
{
|
||||
id = string.Empty;
|
||||
accountType = AccountType.None;
|
||||
accessToken = 0;
|
||||
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
try
|
||||
{
|
||||
var token_handler = new JwtSecurityTokenHandler();
|
||||
var validation_parameters = getValidationUserTokenParameters(ssoJwtSecret);
|
||||
|
||||
var claim = token_handler.ValidateToken(ssoJwt, validation_parameters, out var validated_token);
|
||||
// account id
|
||||
id = claim.Claims.FirstOrDefault(x => x.Type == "id")?.Value ?? string.Empty;
|
||||
// account type
|
||||
accountType = claim.Claims.FirstOrDefault(x => x.Type == "accountType")?.Value
|
||||
?.convertEnumTypeAndValueStringToEnum(AccountType.None) ?? AccountType.None;
|
||||
// access token
|
||||
var access_token_string = claim.Claims.FirstOrDefault(x => x.Type == "accessToken")?.Value;
|
||||
accessToken = Convert.ToUInt64(access_token_string);
|
||||
}
|
||||
catch (SecurityTokenExpiredException e)
|
||||
{
|
||||
err_msg = $"Expired WebAuthJWT !!! : SecurityTokenExpiredException:{e}";
|
||||
result.setFail(ServerErrorCode.ExpiredUserJwt, err_msg);
|
||||
}
|
||||
catch (SecurityTokenException e)
|
||||
{
|
||||
err_msg = $"Failed to verify WebAuthJWT !!! : SecurityTokenException:{e}";
|
||||
result.setFail(ServerErrorCode.InvalidUserJwt, err_msg);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
err_msg = $"Exception !!!, WebAuthJWT !!! : Exception:{e}";
|
||||
result.setFail(ServerErrorCode.InvalidUserJwt, err_msg);
|
||||
}
|
||||
|
||||
if (result.isFail())
|
||||
{
|
||||
result = verifyForTestUserToken(ssoJwt, ssoJwtSecret, out id, out accountType, out accessToken);
|
||||
}
|
||||
|
||||
Guard.Against.resultFail(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
// 치트를 허용하도록 처리함
|
||||
private Result verifyForTestUserToken(string ssoJwt
|
||||
, string ssoJwtSecret
|
||||
, out string id, out AccountType accountType, out UInt64 accessToken)
|
||||
{
|
||||
var splits = ssoJwt.Split('|');
|
||||
if (splits.Length < 1 || splits[1] != ssoJwtSecret)
|
||||
{
|
||||
id = string.Empty;
|
||||
accountType = AccountType.None;
|
||||
accessToken = 0;
|
||||
return new Result
|
||||
{
|
||||
ErrorCode = ServerErrorCode.InvalidUserJwt, ResultString = "Failed to verify WebAuthJWT"
|
||||
};
|
||||
}
|
||||
|
||||
id = splits[0];
|
||||
accountType = AccountType.None;
|
||||
try
|
||||
{
|
||||
accessToken = Convert.ToUInt64(id);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
accessToken = 0;
|
||||
}
|
||||
|
||||
return new Result();
|
||||
}
|
||||
|
||||
private static TokenValidationParameters getValidationUserTokenParameters(string sdsoAccountAuthJwtSecretKey)
|
||||
{
|
||||
return new TokenValidationParameters()
|
||||
{
|
||||
ValidateLifetime = true,
|
||||
ValidateAudience = false,
|
||||
ValidateIssuer = false,
|
||||
ValidIssuer = "",
|
||||
ValidAudience = "",
|
||||
IssuerSigningKey =
|
||||
new SymmetricSecurityKey(
|
||||
Encoding.UTF8.GetBytes(
|
||||
sdsoAccountAuthJwtSecretKey))
|
||||
};
|
||||
}
|
||||
|
||||
public async Task<Result> authByAccount(string accountId)
|
||||
{
|
||||
var action = m_planet_user_entity.getEntityActionNotNull<UserAuthAction>();
|
||||
return await action.findAndSetAllAttributeByAccountId(accountId);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user