Example #1
0
        public async ValueTask <CanPlayResponse> CanPlayAsync(CanPlayRequest value, CallContext context = default)
        {
            Guid guid = Guid.NewGuid();

            _logger.InfoLog($"[CardService.CanPlayAsync][-IN-] [{guid}] TransactionId {value.TransactionId} | ConcentratorId {value.ConcentratorId} | ControllerId {value.ControllerId} | CardType {value.CardType} | CardId {value.CardId} | ShouldPay {value.ShouldPay} | EndpointRssi: {value.EndpointRssi} | ConcentratorRssi {value.ConcentratorRssi}", GetIpAddress());
            // генерира ключ
            var key = $"{value.ControllerId}-{value.CardId}-{value.TransactionId}-{(value.ShouldPay ? 1 : 0)}";
            // извлича тюпъл от кеша за този ключ
            var cachedItem = CanPlayCacheService.Instance.Get(key, true);

            // ако има ключ в тюпъла
            if (!string.IsNullOrWhiteSpace(cachedItem.key))
            {
                // ако има резултат за този ключ в тюпъла
                if (cachedItem.successResponse != null)
                {
                    _logger.InfoLog($"[CardService.CanPlayAsync][-OUT-] [{guid}] TransactionId {value.TransactionId} | ConcentratorId {value.ConcentratorId} | ControllerId {value.ControllerId} | CardType {value.CardType} | CardId {value.CardId} | ShouldPay {value.ShouldPay} | EndpointRssi: {value.EndpointRssi} | ConcentratorRssi {value.ConcentratorRssi} | CACHED Result", GetIpAddress());
                    // връща резултата от тюпъла
                    return(cachedItem.successResponse);
                }
            }
            // резервира семафора за текущия тред и продължава, други тредове стигнали до тук чакат ...
            await semaphoreSlim.WaitAsync();

            // проверява за евнтуален тюпъл и резултат за този ключ от други тредове
            cachedItem = CanPlayCacheService.Instance.Get(key);
            if (cachedItem.successResponse != null)
            {
                _logger.InfoLog($"[CardService.CanPlayAsync][-OUT-] [{guid}] TransactionId {value.TransactionId} | ConcentratorId {value.ConcentratorId} | ControllerId {value.ControllerId} | CardType {value.CardType} | CardId {value.CardId} | ShouldPay {value.ShouldPay} | EndpointRssi: {value.EndpointRssi} | ConcentratorRssi {value.ConcentratorRssi} | CACHED Result", GetIpAddress());
                // освобождава семафора за следващи тредове, които чакат
                semaphoreSlim.Release();
                // връща резултата от тюпъла
                return(cachedItem.successResponse);
            }
            // резервира ключа в кеша, като създава тюпъл с този ключ, но без резултат
            CanPlayCacheService.Instance.Add(key, (key, null));
            CanPlayResponse response = null;

            try
            {
                // извлича резултата от апи-то (отнема много време)
                var tupleResult = await CanPlayAsyncInternal(guid, value.ConcentratorId, value.ControllerId, value.CardType, value.CardId, value.ShouldPay, value.TransactionId, value.EndpointRssi, value.ConcentratorRssi);

                if (tupleResult.success)
                {
                    // обновява резултата в тюпъла в кеша за резервирания ключ
                    CanPlayCacheService.Instance.Add(key, (key, tupleResult.response));
                }
                // връща резултата от апи-то
                response = tupleResult.response;
            }
            finally
            {
                // освобождава семафора за следващи тредове, които чакат
                semaphoreSlim.Release();
            }

            return(response ?? new CanPlayResponse
            {
                TransactionId = value.TransactionId,
                Time = DateTime.UtcNow,
                ResponseCode = 109,
                ConcentratorId = value.ConcentratorId,
                ControllerId = value.ControllerId,
                CardType = value.CardType,
                CardId = value.CardId,
                CardNumber = string.Empty,
                ServiceId = string.Empty,
                ServiceName = string.Empty,
                Permission = false,
                RelayType = string.Empty,
                RelayPulse = 0,
                RelayOnTime = 0,
                RelayOffTime = 0,
                RelayDisplayTime = 0,
                DisplayLine1 = "",
                DisplayLine2 = ""
            });
        }
Example #2
0
        // метода се извиква при всяко запитване на конектнатия клиент
        public byte[] ProccessRequest(byte[] message)
        {
            //извличане на входните данни
            var splittedMessage = SplitByteArray(message, 0x1F).ToArray();

            if (splittedMessage.Count() == 0)
            {
                return new byte[] { 0x45, 0x52, 0x52, 0x4F, 0x52 }
            }
            ;                                                       //ERROR

            // how many tokens
            int tokensCount = splittedMessage.GetLength(0);
            // command
            string cmd = tokensCount >= 1 ? new string(
                splittedMessage[0]
                .Where(b => b != 0x1F && b != 0x1E)     // except:  0x1F - unit separator char(31), 0x1E - record separator char(30)
                .Select(b => (char)b)
                .ToArray()) : string.Empty;

            if (cmd.Equals("RG", StringComparison.InvariantCultureIgnoreCase))
            {
                CanPlayRequest request = CanPlayRequest.DeserializeASCII(splittedMessage);

                _logger.LogInformation(System.Text.Json.JsonSerializer.Serialize(request));
                Proto.CanPlayRequest proto_request = request.ToProtoCanPlayRequest();
                CanPlayResponse      response;
                try
                {
                    Proto.CanPlayResponse proto_response = _cardService.CanPlayAsync(proto_request).Result;
                    if (proto_response != null)
                    {
                        response = CanPlayResponse.FromProtoCanPlayResponse(proto_response);
                    }
                    else
                    {
                        response = new CanPlayResponse {
                            Success = false, MessageLine1 = "Err 109", MessageLine2 = "Internal server"
                        };
                        _logger.LogError("TextMessageService.ProccessRequest => Proto.CanPlayResponse is null");
                    }
                }
                catch (Exception ex)
                {
                    response = new CanPlayResponse {
                        Success = false, MessageLine1 = "Err 109", MessageLine2 = "Internal server"
                    };
                    _logger.LogError($"TextMessageService.ProccessRequest throws: {ex}");
                }
                _logger.LogInformation(System.Text.Json.JsonSerializer.Serialize(response));
                return(response.SerializeASCII());
            }
            else if (cmd.Equals("RP", StringComparison.InvariantCultureIgnoreCase))
            {
                ServicePriceRequest request = ServicePriceRequest.DeserializeASCII(splittedMessage);
                _logger.LogInformation(System.Text.Json.JsonSerializer.Serialize(request));
                Proto.ServicePriceRequest proto_request = request.ToProtoServicePriceRequest();
                ServicePriceResponse      response;
                try
                {
                    Proto.ServicePriceResponse proto_response = _cardService.ServicePriceAsync(proto_request).Result;
                    if (proto_response != null)
                    {
                        response = ServicePriceResponse.FromProtoServicePriceResponse(proto_response);
                    }
                    else
                    {
                        response = new ServicePriceResponse {
                            Success = false, MessageLine1 = "Err 109", MessageLine2 = "Internal server"
                        };
                        _logger.LogError("TextMessageService.ProccessRequest => Proto.ServicePriceRequest is null");
                    }
                }
                catch (Exception ex)
                {
                    response = new ServicePriceResponse {
                        Success = false, MessageLine1 = "Err 109", MessageLine2 = "Internal server"
                    };
                    _logger.LogError($"TextMessageService.ProccessRequest throws: {ex}");
                }
                _logger.LogInformation(System.Text.Json.JsonSerializer.Serialize(response));
                return(response.SerializeASCII());
            }
            else if (cmd.Equals("T", StringComparison.InvariantCultureIgnoreCase))
            {
                return(Encoding.ASCII.GetBytes($"{DateTime.Now:dd.MM.yyyy HH:mm}\x1E"));
            }
            else
            {
                return(Encoding.ASCII.GetBytes($"{DateTime.Now:dd.MM.yyyy HH:mm}\x1E"));
            }
        }
Example #3
0
        private async ValueTask <(bool success, CanPlayResponse response)> CanPlayAsyncInternal(
            Guid guid,
            string concentratorId,
            string controllerId,
            int cardType,
            string cardId,
            bool shouldPay,
            int transactionId,
            int endpointRssi,
            int concentratorRssi)
        {
            Concentrator getConcentrator()
            {
                var repo = _serviceProvider.GetService <ICardSystemRepository <Concentrator> >();

                return(repo.AsNoTracking().FirstOrDefault(x => x.DeviceId == concentratorId));
            };
            ControllerConfigRelay getController()
            {
                var repo = _serviceProvider.GetService <ICardSystemRepository <ControllerConfigRelay> >();

                return(repo.AsNoTracking()
                       .Include(x => x.EGM)
                       .ThenInclude(x => x.AllowedCurrencies)
                       .FirstOrDefault(x => x.SerialNumber == controllerId && x.OwnerId == _ownerId));
            };
            Card getCard()
            {
                Card entity = null;
                ICardSystemRepository <Card> repo = null;
                string cardDBId = CardCacheServiceV2.Instance.GetIdByExternalId(cardId);

                if (!string.IsNullOrWhiteSpace(cardDBId))
                {
                    entity = CardCacheServiceV2.Instance.GetCard(_serviceProvider, cardDBId);
                    if (entity != null)
                    {
                        return(entity);
                    }
                    repo   = _serviceProvider.GetService <ICardSystemRepository <Card> >();
                    entity = repo.AsNoTracking()
                             .Include(x => x.CardMode)
                             .Include(x => x.User)
                             .FirstOrDefault(x => x.Id == cardDBId);
                    if (entity != null)
                    {
                        CardCacheServiceV2.Instance.AddCard(_serviceProvider, entity);
                        CardCacheServiceV2.Instance.AddNewMap(entity);
                    }
                    return(entity);
                }

                repo   = _serviceProvider.GetService <ICardSystemRepository <Card> >();
                entity = repo.AsNoTracking()
                         .Include(x => x.CardMode)
                         .Include(x => x.User)
                         .FirstOrDefault(x => x.ExternalId == cardId);
                if (entity != null)
                {
                    CardCacheServiceV2.Instance.AddCard(_serviceProvider, entity);
                    CardCacheServiceV2.Instance.AddNewMap(entity);
                }
                return(entity);
            };
            IEnumerable <CurrencyTemplate> getCurrencyTemplates()
            {
                var repo = _serviceProvider.GetService <ICardSystemRepository <CurrencyTemplate> >();

                return(repo.AsNoTracking()
                       .Where(x => x.OwnerId == _ownerId)
                       .ToList());
            }

            var concentrator = getConcentrator();

            if (concentrator == null)
            {
                var response = new CanPlayResponse
                {
                    TransactionId    = transactionId,
                    Time             = DateTime.UtcNow,
                    ResponseCode     = 101,
                    ConcentratorId   = concentratorId,
                    ControllerId     = controllerId,
                    CardType         = cardType,
                    CardId           = cardId,
                    CardNumber       = string.Empty,
                    ServiceId        = string.Empty,
                    ServiceName      = string.Empty,
                    Permission       = false,
                    RelayType        = string.Empty,
                    RelayPulse       = 0,
                    RelayOnTime      = 0,
                    RelayOffTime     = 0,
                    RelayDisplayTime = 0,
                    DisplayLine1     = "Err 101",
                    DisplayLine2     = "Concentrator N/A"
                };
                _logger.ErrorLog($"[CardService.CanPlayAsyncInternal][-OUT-] [{guid}] TransactionId {transactionId} | ConcentratorId {concentratorId} | ControllerId {controllerId} | CardType {cardType} | CardId {cardId} | ShouldPay {shouldPay} | EndpointRssi: {endpointRssi} | ConcentratorRssi {concentratorRssi} | {JsonSerializer.Serialize(response, new JsonSerializerOptions { WriteIndented = false })}", GetIpAddress());
                return(false, response);
            }
            var controller = getController();

            if (controller == null)
            {
                var response = new CanPlayResponse
                {
                    TransactionId    = transactionId,
                    Time             = DateTime.UtcNow,
                    ResponseCode     = 102,
                    ConcentratorId   = concentratorId,
                    ControllerId     = controllerId,
                    CardType         = cardType,
                    CardId           = cardId,
                    CardNumber       = string.Empty,
                    ServiceId        = string.Empty,
                    ServiceName      = string.Empty,
                    Permission       = false,
                    RelayType        = string.Empty,
                    RelayPulse       = 0,
                    RelayOnTime      = 0,
                    RelayOffTime     = 0,
                    RelayDisplayTime = 0,
                    DisplayLine1     = "Err 102",
                    DisplayLine2     = "Controller N/A"
                };
                _logger.ErrorLog($"[CardService.CanPlayAsyncInternal][-OUT-] [{guid}] TransactionId {transactionId} | ConcentratorId {concentratorId} | ControllerId {controllerId} | CardType {cardType} | CardId {cardId} | ShouldPay {shouldPay} | EndpointRssi: {endpointRssi} | ConcentratorRssi {concentratorRssi} | {JsonSerializer.Serialize(response, new JsonSerializerOptions { WriteIndented = false })}", GetIpAddress());
                return(false, response);
            }
            var card = getCard();

            if (card == null)
            {
                var response = new CanPlayResponse
                {
                    TransactionId    = transactionId,
                    Time             = DateTime.UtcNow,
                    ResponseCode     = 103,
                    ConcentratorId   = concentratorId,
                    ControllerId     = controllerId,
                    CardType         = cardType,
                    CardId           = cardId,
                    CardNumber       = string.Empty,
                    ServiceId        = string.Empty,
                    ServiceName      = string.Empty,
                    Permission       = false,
                    RelayType        = string.Empty,
                    RelayPulse       = 0,
                    RelayOnTime      = 0,
                    RelayOffTime     = 0,
                    RelayDisplayTime = 0,
                    DisplayLine1     = "Err 103",
                    DisplayLine2     = "Card N/A"
                };
                _logger.ErrorLog($"[CardService.CanPlayAsyncInternal][-OUT-] [{guid}] TransactionId {transactionId} | ConcentratorId {concentratorId} | ControllerId {controllerId} | CardType {cardType} | CardId {cardId} | ShouldPay {shouldPay} | EndpointRssi: {endpointRssi} | ConcentratorRssi {concentratorRssi} | {JsonSerializer.Serialize(response, new JsonSerializerOptions { WriteIndented = false })}", GetIpAddress());
                return(false, response);
            }
            var currencyTemplates = getCurrencyTemplates();

            IEnumerable <ScheduleDay> getScheduleDays()
            {
                IEnumerable <ScheduleDay> egmPriceModifiers = null;
                var repo = _serviceProvider.GetService <ICardSystemRepository <ScheduleDay> >();

                if (!string.IsNullOrWhiteSpace(controller.EGM.Id))
                {
                    egmPriceModifiers = repo.AsNoTracking()
                                        .Include(x => x.Hours)
                                        .Where(x => x.EGMId == controller.EGM.Id)
                                        .AsEnumerable();
                }
                if (egmPriceModifiers != null && !egmPriceModifiers.Any())
                {
                    egmPriceModifiers = repo
                                        .AsNoTracking()
                                        .Include(x => x.Hours)
                                        .Where(x => x.GameCenterId == controller.EGM.GameCenterId)
                                        .AsEnumerable();
                }
                return(egmPriceModifiers ?? new List <ScheduleDay>());
            }

            var scheduleDays = getScheduleDays();

            // ако се изиква плащане този метод променя баланса на картата
            var canPlayDto = _serviceProvider.GetService <ICanPlayService>().CanPlayV2(
                _serviceProvider,
                concentrator,
                controller,
                card,
                scheduleDays.ToList(),
                shouldPay,
                currencyTemplates);

            if (canPlayDto.HasError)
            {
                var errors   = canPlayDto.Message.Split('|');
                var response = new CanPlayResponse
                {
                    TransactionId    = transactionId,
                    Time             = DateTime.UtcNow,
                    ResponseCode     = int.Parse(errors[0]),
                    ConcentratorId   = concentratorId,
                    ControllerId     = controllerId,
                    CardType         = cardType,
                    CardId           = cardId,
                    CardNumber       = string.Empty,
                    ServiceId        = string.Empty,
                    ServiceName      = string.Empty,
                    Permission       = false,
                    RelayType        = string.Empty,
                    RelayPulse       = 0,
                    RelayOnTime      = 0,
                    RelayOffTime     = 0,
                    RelayDisplayTime = 0,
                    DisplayLine1     = $"Err {errors[0]}",
                    DisplayLine2     = errors[1]
                };
                _logger.ErrorLog($"[CardService.CanPlayAsyncInternal][-OUT-] [{guid}] TransactionId {transactionId} | ConcentratorId {concentratorId} | ControllerId {controllerId} | CardType {cardType} | CardId {cardId} | ShouldPay {shouldPay} | EndpointRssi: {endpointRssi} | ConcentratorRssi {concentratorRssi} | {JsonSerializer.Serialize(response, new JsonSerializerOptions { WriteIndented = false })}", GetIpAddress());
                return(false, response);
            }

            EGM gameDto = null;

            if (canPlayDto.CanPlay)
            {
                gameDto = controller.EGM;
            }

            var canPlayResponse = new CanPlayResponse
            {
                TransactionId    = transactionId,
                Time             = DateTime.UtcNow,
                ResponseCode     = 0,
                ConcentratorId   = concentrator.DeviceId,
                ControllerId     = controller.SerialNumber,
                CardType         = card.Type,
                CardId           = card.ExternalId,
                CardNumber       = card.Number,
                ServiceId        = canPlayDto.GameId,
                ServiceName      = canPlayDto.GameName,
                Permission       = canPlayDto.CanPlay,
                RelayType        = gameDto?.RelayMode,
                RelayPulse       = gameDto?.RelayPulse ?? 0,
                RelayOnTime      = gameDto?.RelayOnTime ?? 0,
                RelayOffTime     = gameDto?.RelayOffTime ?? 0,
                RelayDisplayTime = gameDto?.RelayDisplayTime ?? 0,
                DisplayLine1     = $"{canPlayDto.PricePerGame:F2}".Trim().Trim(',').Trim(),
                DisplayLine2     = $"{canPlayDto.RemainingBalance:F2}"
            };

            // само ако се изисква плащане логира плащането в транзакшън лога и обновява кеша на картата в api.icardmanager.eu
            if (shouldPay)
            {
                canPlayDto.GameId = gameDto?.Id;
                string relayInfo = $" | Relay ontime: {gameDto?.RelayOnTime}, Relay offtime: {gameDto?.RelayOffTime}, Relay pulse: {gameDto?.RelayPulse}, Relay display time: {gameDto?.RelayDisplayTime}, Relay mode: {gameDto?.RelayMode}, Game Serial Number: '{gameDto?.SerialNumber}'";
                CreateCanPlayLog(
                    concentrator.DeviceId,
                    controller.SerialNumber,
                    $"{canPlayDto.GameCenterName}{relayInfo}",
                    canPlayDto.GameId,
                    canPlayDto.GameName,
                    canPlayDto.CurrencyInfo,
                    card.ExternalId,
                    card.Type,
                    canPlayDto.PricePerGame,
                    canPlayDto.PaidFromBonusBalance,
                    canPlayDto.CanPlay,
                    gameDto?.GameCenterId,
                    gameDto != null ? gameDto.OwnerId : "system"
                    );
                try
                {
                    var apiResponse = await _restApiClient.GetAsync <string>(_configuration.GetSection("AppSettings:ApiServiceURL").Get <string>(), $"api/{_ownerId}/card/{card.Id}/reloadcache");

                    if (apiResponse.hasError)
                    {
                        _logger.ErrorLog($"[CardService.CanPlayAsyncInternal][-API-] [{guid}] TransactionId {transactionId} | ConcentratorId {concentratorId} | ControllerId {controllerId} | CardType {cardType} | CardId {cardId} | ShouldPay {shouldPay} | EndpointRssi: {endpointRssi} | ConcentratorRssi {concentratorRssi} | {apiResponse.errorMessage}", GetIpAddress());
                    }
                }
                catch (Exception ex)
                {
                    _logger.LogException($"CardService.CanPlayAsyncInternal throws: {ex}");
                }
            }

            _logger.InfoLog($"[CardService.CanPlayAsyncInternal][-OUT-] [{guid}] TransactionId {transactionId} | ConcentratorId {concentratorId} | ControllerId {controllerId} | CardType {cardType} | CardId {cardId} | ShouldPay {shouldPay} | EndpointRssi: {endpointRssi} | ConcentratorRssi {concentratorRssi} | DB Result {JsonSerializer.Serialize(canPlayResponse, new JsonSerializerOptions { WriteIndented = false })}", GetIpAddress());
            return(true, canPlayResponse);
        }