private OrderVM Convert(Model.Order order, ClientOrderDetalization clientDetalization, IEnumerable <DriverOrderDetalization> driverDetalizations, IEnumerable <OrderStatusHistory> statusHistories)
        {
            var orderVM = new OrderVM
            {
                Id                 = order.Id,
                Number             = order.Number,
                ClientDetalization = new ClientDetalizationVM
                {
                    ClientId     = clientDetalization.ClientId,
                    ClientPhone  = clientDetalization.ClientPhone,
                    Address      = clientDetalization.Address,
                    Latitude     = clientDetalization.Latitude,
                    Longitude    = clientDetalization.Longitude,
                    Quantity     = clientDetalization.Quantity,
                    Price        = clientDetalization.FuelPrice,
                    Cost         = clientDetalization.Cost,
                    CreationDate = clientDetalization.CreationDate,
                    FuelType     = new FuelTypeVM
                    {
                        Id = clientDetalization.FuelTypeId
                    }
                }
            };

            if (driverDetalizations != null && driverDetalizations.Any())
            {
                var driverDetalizationsVM = new List <DriverDetalizationVM>();
                foreach (var driverDetalization in driverDetalizations)
                {
                    driverDetalizationsVM.Add(new DriverDetalizationVM
                    {
                        ReceiptDate = driverDetalization.ReceiptDate,
                        DriverId    = driverDetalization.DriverId
                    });
                }
                orderVM.DriverDetalizations = driverDetalizationsVM;
            }

            if (statusHistories != null && statusHistories.Any())
            {
                var statusHistoriesVM = new List <HistoryStatusItemVM>();
                foreach (var statusHistory in statusHistories)
                {
                    statusHistoriesVM.Add(new HistoryStatusItemVM
                    {
                        ChangeTime = statusHistory.ChangeTime,
                        Status     = (OrderStatusVM)statusHistory.Status
                    });
                }
                orderVM.HistoryStatuses = statusHistoriesVM;
            }

            return(orderVM);
        }
        private async Task <GetYandexPaymentLinkResponse> CreatePaymentAsync(string orderNumber, ClientOrderDetalization clientDetalization)
        {
            var createPaymentUrl = string.Concat(_configuration["PaymentCashOptions:APIEndpoint"], _configuration["PaymentCashOptions:CreatePaymentMethod"]);
            var supplierRequest  = new GetYandexPaymentLinkRequest
            {
                Amount = new PaymentAmount {
                    Value = clientDetalization.Cost
                },
                Confirmation = new PaymentReturn {
                    ReturnUrl = _configuration["PaymentCashOptions:ReturnUrl"]
                },
                Description = $"Оплата заказа №{orderNumber}"
            };
            var strSupplierRequest  = JsonConvert.SerializeObject(supplierRequest);
            var strSupplierResponse = string.Empty;

            try
            {
                var credentials = Encoding.ASCII.GetBytes($"{_configuration["PaymentCashOptions:ShopId"]}:{_configuration["PaymentCashOptions:SecretKey"]}");
                _httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", System.Convert.ToBase64String(credentials));
                _httpClient.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "application/json");
                _httpClient.DefaultRequestHeaders.TryAddWithoutValidation("Idempotence-Key", clientDetalization.PaymentIdempotenceKey);

                using (var response = await _httpClient.PostAsync(createPaymentUrl,
                                                                  new StringContent(strSupplierRequest, Encoding.UTF8, "application/json")))
                {
                    strSupplierResponse = await response.Content.ReadAsStringAsync();

                    if (response.StatusCode == System.Net.HttpStatusCode.OK)
                    {
                        return(JsonConvert.DeserializeObject <GetYandexPaymentLinkResponse>(strSupplierResponse));
                    }
                    else
                    {
                        // логгируем некорректный ответ
                        _logger.LogError(GetFatalPaymentMessage(response.StatusCode, strSupplierRequest, strSupplierResponse));
                    }
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, GetFatalPaymentMessage(System.Net.HttpStatusCode.InternalServerError, strSupplierRequest, strSupplierResponse));
            }

            // иначе была ошибка, и она была залоггирована
            return(null);
        }
        public async Task <OrderUpdateResponse> PostOne(ApplicationUser currentUser, IConfiguration configuration, OrderUpdateRequest request)
        {
            var response = new OrderUpdateResponse();

            Model.Order order = null;

            if ((currentUser == null && string.IsNullOrEmpty(request.ClientPhone)) ||
                (currentUser != null && !(currentUser is Client))) // только клиент может добавлять заказ (или по номеру телефону)
            {
                response.AddError(_stringLocalizer[CustomStringLocalizer.NO_RIGHTS_TO_CREATE_UPDATE_ORDER]);
                return(response);
            }

            if (request.Id.HasValue)
            {
                order = await _fuelContext.Orders.FirstOrDefaultAsync(x => x.Id == request.Id.Value);
            }
            else
            {
                order = new Model.Order();
            }

            if (order == null)
            {
                response.AddError(_stringLocalizer[CustomStringLocalizer.ORDER_NOT_FOUND]);
                return(response);
            }

            if (string.IsNullOrEmpty(order.Number))
            {
                order.Number = OrderNumberGenerator.GetNumber(_fuelContext);
            }

            ClientOrderDetalization clientDetalization = null;

            if (request.Id.HasValue)
            {
                clientDetalization = await _fuelContext.ClientDetalizations.FirstOrDefaultAsync(x => x.OrderId == order.Id);
            }
            else
            {
                clientDetalization = new ClientOrderDetalization();
            }
            if (clientDetalization.CreationDate == default)
            {
                clientDetalization.CreationDate = DateTime.Now;
            }
            clientDetalization.ClientId    = currentUser?.Id;
            clientDetalization.ClientPhone = request.ClientPhone;
            clientDetalization.Address     = request.Address;
            clientDetalization.FuelTypeId  = request.FuelTypeId;
            clientDetalization.Latitude    = request.Latitude;
            clientDetalization.Longitude   = request.Longitude;
            clientDetalization.Quantity    = request.Quantity;
            clientDetalization.FuelPrice   = request.Price;
            clientDetalization.Cost        = request.Price * request.Quantity;

            if (string.IsNullOrEmpty(clientDetalization.PaymentIdempotenceKey))
            {
                clientDetalization.PaymentIdempotenceKey = Guid.NewGuid().ToString();
            }

            if (request.Id.HasValue)
            {
                clientDetalization.OrderId = order.Id;

                _fuelContext.Orders.Update(order);
                _fuelContext.ClientDetalizations.Update(clientDetalization);
            }
            else
            {
                clientDetalization.Order = order;

                //await _fuelContext.Orders.AddAsync(order);
                await _fuelContext.ClientDetalizations.AddAsync(clientDetalization);
            }
            await _fuelContext.SaveChangesAsync();

            if (!request.Id.HasValue)
            {
                // записать в историю, что заказ создан
                await AddStatusToHistory(order.Id, OrderStatusVM.Created);
            }

            var currentOrderStatus = await GetLastStatusRecord(order.Id);

            if (currentOrderStatus != null && currentOrderStatus.Status == Model.Enums.OrderStatus.Created)
            {
                // отправить запрос на создание платежа в яндекс.кассе
                var yandexResponse = await CreatePaymentAsync(order.Number, clientDetalization);

                if (yandexResponse != null)
                {
                    response.PaymentLink = yandexResponse.Confirmation?.ConfirmationUrl;

                    // повторяющаяся таска до тех пор, пока не станет ясен статус заказа (оплачен/отменен)
                    BackgroundJob.Schedule(() => CheckPaymentProcessingAsync(order.Id, yandexResponse.Id), TimeSpan.FromSeconds(15.0));
                }
            }

            response.Id = order.Id;
            return(response);
        }