예제 #1
0
        public async Task <CustomerOrderAggregate> GetOrderByIdAsync(string orderId)
        {
            var order = await _customerOrderService.GetByIdAsync(orderId);

            if (order != null)
            {
                var result = await InnerGetCustomerOrderAggregatesFromCustomerOrdersAsync(new[] { order });

                return(result.FirstOrDefault());
            }
            return(null);
        }
        public async Task <ActionResult <CustomerOrder> > CreatePayment([FromBody] PaymentIn payment)
        {
            if (payment == null)
            {
                return(BadRequest($"{nameof(payment)} is required"));
            }
            if (string.IsNullOrEmpty(payment.OrderId))
            {
                return(BadRequest($"{nameof(payment.OrderId)} is required"));
            }
            var customerOrder = await _customerOrderService.GetByIdAsync(payment.OrderId);

            if (customerOrder == null)
            {
                return(BadRequest($"order with id: {nameof(payment.OrderId)} is not found"));
            }
            var authorizationResult = await _authorizationService.AuthorizeAsync(User, customerOrder, new OrderAuthorizationRequirement(ModuleConstants.Security.Permissions.Update));

            if (!authorizationResult.Succeeded)
            {
                return(Unauthorized());
            }
            await _paymentService.SaveChangesAsync(new[] { payment });

            return(Ok(payment));
        }
예제 #3
0
        private async Task CheckAuthAsync(IResolveFieldContext context, string orderId)
        {
            var order = await _customerOrderService.GetByIdAsync(orderId);

            var authorizationResult = await _authorizationService.AuthorizeAsync(context.GetCurrentPrincipal(), order, new CanAccessOrderAuthorizationRequirement());

            if (!authorizationResult.Succeeded)
            {
                throw new AuthorizationError($"Access denied");
            }
        }
        public async Task SaveChangesAsync_CreateNewOrder()
        {
            //Arrange
            var order = GetTestOrder($"order{DateTime.Now:O}");

            //Act
            await _customerOrderService.SaveChangesAsync(new[] { order });

            order = await _customerOrderService.GetByIdAsync(order.Id);

            //Assert
            Assert.Equal(PaymentStatus.Pending, order.InPayments.First().PaymentStatus);
            Assert.NotNull(order);
            Assert.Equal(PaymentStatus.Pending, order.InPayments.First().PaymentStatus);
            Assert.NotNull(order.InPayments.First().Status);
        }
예제 #5
0
        public async Task SaveChangesAsync_CreateNewOrder()
        {
            //Arrange
            var order    = GetTestOrder($"order{DateTime.Now:O}");
            var cacheKey = CacheKey.With(_customerOrderService.GetType(), "GetByIdsAsync", string.Join("-", order.Id), null);

            _platformMemoryCacheMock.Setup(pmc => pmc.CreateEntry(cacheKey)).Returns(_cacheEntryMock.Object);

            //Act
            await _customerOrderService.SaveChangesAsync(new[] { order });

            order = await _customerOrderService.GetByIdAsync(order.Id);

            //Assert
            Assert.Equal(PaymentStatus.Pending, order.InPayments.First().PaymentStatus);
            Assert.NotNull(order);
            Assert.Equal(PaymentStatus.Pending, order.InPayments.First().PaymentStatus);
            Assert.NotNull(order.InPayments.First().Status);
        }
        public async Task <ActionResult <CustomerOrder> > GetById(string id, [FromRoute] string respGroup = null)
        {
            var retVal = await _customerOrderService.GetByIdAsync(id, respGroup);

            if (retVal == null)
            {
                return(NotFound());
            }

            //TODO
            ////Scope bound security check
            //var scopes = _permissionScopeService.GetObjectPermissionScopeStrings(retVal).ToArray();
            //if (!_securityService.UserHasAnyPermission(User.Identity.Name, scopes, OrderPredefinedPermissions.Read))
            //{
            //    throw new HttpResponseException(HttpStatusCode.Unauthorized);
            //}

            ////Set scopes for UI scope bounded ACL checking
            //retVal.Scopes = scopes;

            return(Ok(retVal));
        }
예제 #7
0
        public void Build(ISchema schema)
        {
            _ = schema.Query.AddField(new FieldType
            {
                Name      = "order",
                Arguments = new QueryArguments(
                    new QueryArgument <StringGraphType> {
                    Name = "id"
                },
                    new QueryArgument <StringGraphType> {
                    Name = "number"
                },
                    new QueryArgument <StringGraphType> {
                    Name = "cultureName", Description = "Culture name (\"en-US\")"
                }),
                Type     = GraphTypeExtenstionHelper.GetActualType <CustomerOrderType>(),
                Resolver = new AsyncFieldResolver <object>(async context =>
                {
                    var request = new GetOrderQuery
                    {
                        Number      = context.GetArgument <string>("number"),
                        OrderId     = context.GetArgument <string>("id"),
                        CultureName = context.GetArgument <string>(nameof(Currency.CultureName))
                    };

                    var orderAggregate = await _mediator.Send(request);

                    var authorizationResult = await _authorizationService.AuthorizeAsync(context.GetCurrentPrincipal(), orderAggregate.Order, new CanAccessOrderAuthorizationRequirement());

                    if (!authorizationResult.Succeeded)
                    {
                        throw new ExecutionError($"Access denied");
                    }

                    var allCurrencies = await _currencyService.GetAllCurrenciesAsync();
                    //Store all currencies in the user context for future resolve in the schema types
                    context.SetCurrencies(allCurrencies, request.CultureName);

                    //store order aggregate in the user context for future usage in the graph types resolvers
                    context.SetExpandedObjectGraph(orderAggregate);

                    return(orderAggregate);
                })
            });

            var orderConnectionBuilder = GraphTypeExtenstionHelper.CreateConnection <CustomerOrderType, object>()
                                         .Name("orders")
                                         .Argument <StringGraphType>("filter", "This parameter applies a filter to the query results")
                                         .Argument <StringGraphType>("sort", "The sort expression")
                                         .Argument <StringGraphType>("cultureName", "Culture name (\"en-US\")")
                                         .Argument <StringGraphType>("userId", "")
                                         .Unidirectional()
                                         .PageSize(20);

            orderConnectionBuilder.ResolveAsync(async context => await ResolveOrdersConnectionAsync(_mediator, context));

            schema.Query.AddField(orderConnectionBuilder.FieldType);


            var paymentsConnectionBuilder = GraphTypeExtenstionHelper.CreateConnection <PaymentInType, object>()
                                            .Name("payments")
                                            .Argument <StringGraphType>("filter", "This parameter applies a filter to the query results")
                                            .Argument <StringGraphType>("sort", "The sort expression")
                                            .Argument <StringGraphType>("cultureName", "Culture name (\"en-US\")")
                                            .Argument <NonNullGraphType <StringGraphType> >("userId", "")
                                            .Unidirectional()
                                            .PageSize(20);

            paymentsConnectionBuilder.ResolveAsync(async context => await ResolvePaymentsConnectionAsync(_mediator, context));
            schema.Query.AddField(paymentsConnectionBuilder.FieldType);


            _ = schema.Mutation.AddField(FieldBuilder.Create <object, CustomerOrderAggregate>(typeof(CustomerOrderType))
                                         .Name("createOrderFromCart")
                                         .Argument <NonNullGraphType <InputCreateOrderFromCartType> >(_commandName)
                                         .ResolveAsync(async context =>
            {
                var response = await _mediator.Send(context.GetArgument <CreateOrderFromCartCommand>(_commandName));
                context.SetExpandedObjectGraph(response);
                return(response);
            })
                                         .FieldType);

            _ = schema.Mutation.AddField(FieldBuilder.Create <object, bool>(typeof(BooleanGraphType))
                                         .Name("changeOrderStatus")
                                         .Argument <NonNullGraphType <InputChangeOrderStatusType> >(_commandName)
                                         .ResolveAsync(async context =>
            {
                var command = context.GetArgument <ChangeOrderStatusCommand>(_commandName);

                var order = await _customerOrderService.GetByIdAsync(command.OrderId);

                var authorizationResult = await _authorizationService.AuthorizeAsync(context.GetCurrentPrincipal(), order, new CanAccessOrderAuthorizationRequirement());

                if (!authorizationResult.Succeeded)
                {
                    throw new ExecutionError($"Access denied");
                }

                return(await _mediator.Send(command));
            })
                                         .FieldType);

            _ = schema.Mutation.AddField(FieldBuilder.Create <object, bool>(typeof(BooleanGraphType))
                                         .Name("confirmOrderPayment")
                                         .Argument <NonNullGraphType <InputConfirmOrderPaymentType> >(_commandName)
                                         .ResolveAsync(async context =>
            {
                var command = context.GetArgument <ConfirmOrderPaymentCommand>(_commandName);
                var order   = await _customerOrderService.GetByIdAsync(command.Payment.OrderId);

                var authorizationResult = await _authorizationService.AuthorizeAsync(context.GetCurrentPrincipal(), order, new CanAccessOrderAuthorizationRequirement());

                if (!authorizationResult.Succeeded)
                {
                    throw new ExecutionError($"Access denied");
                }

                return(await _mediator.Send(command));
            })
                                         .FieldType);

            _ = schema.Mutation.AddField(FieldBuilder.Create <object, bool>(typeof(BooleanGraphType))
                                         .Name("cancelOrderPayment")
                                         .Argument <NonNullGraphType <InputCancelOrderPaymentType> >(_commandName)
                                         .ResolveAsync(async context =>
            {
                var command = context.GetArgument <CancelOrderPaymentCommand>(_commandName);
                var order   = await _customerOrderService.GetByIdAsync(command.Payment.OrderId);

                var authorizationResult = await _authorizationService.AuthorizeAsync(context.GetCurrentPrincipal(), order, new CanAccessOrderAuthorizationRequirement());

                if (!authorizationResult.Succeeded)
                {
                    throw new ExecutionError($"Access denied");
                }

                return(await _mediator.Send(command));
            })
                                         .FieldType);
        }
        [Consumes("application/json", new[] { "application/json-patch+json" })] // It's a trick that allows ASP.NET infrastructure to select this action with body and ProcessOrderPaymentsWithoutBankCardInfo if no body
        public async Task <ActionResult <ProcessPaymentRequestResult> > ProcessOrderPayments([FromRoute] string orderId, [FromRoute] string paymentId, [FromBody] BankCardInfo bankCardInfo)
        {
            var order = await _customerOrderService.GetByIdAsync(orderId, CustomerOrderResponseGroup.Full.ToString());

            if (order == null)
            {
                var searchCriteria = AbstractTypeFactory <CustomerOrderSearchCriteria> .TryCreateInstance();

                searchCriteria.Number        = orderId;
                searchCriteria.ResponseGroup = CustomerOrderResponseGroup.Full.ToString();

                var orders = await _searchService.SearchCustomerOrdersAsync(searchCriteria);

                order = orders.Results.FirstOrDefault();
            }

            if (order == null)
            {
                throw new InvalidOperationException($"Cannot find order with ID {orderId}");
            }

            var authorizationResult = await _authorizationService.AuthorizeAsync(User, order, new OrderAuthorizationRequirement(ModuleConstants.Security.Permissions.Update));

            if (!authorizationResult.Succeeded)
            {
                return(Unauthorized());
            }

            var inPayment = order.InPayments.FirstOrDefault(x => x.Id == paymentId);

            if (inPayment == null)
            {
                throw new InvalidOperationException($"Cannot find payment with ID {paymentId}");
            }
            if (inPayment.PaymentMethod == null)
            {
                throw new InvalidOperationException($"Cannot find payment method with code {inPayment.GatewayCode}");
            }

            var store = await _storeService.GetByIdAsync(order.StoreId, StoreResponseGroup.StoreInfo.ToString());

            if (store == null)
            {
                throw new InvalidOperationException($"Cannot find store with ID {order.StoreId}");
            }

            var request = new ProcessPaymentRequest
            {
                OrderId      = order.Id,
                Order        = order,
                PaymentId    = inPayment.Id,
                Payment      = inPayment,
                StoreId      = order.StoreId,
                Store        = store,
                BankCardInfo = bankCardInfo
            };
            var result = inPayment.PaymentMethod.ProcessPayment(request);

            if (result.OuterId != null)
            {
                inPayment.OuterId = result.OuterId;
            }

            await _customerOrderService.SaveChangesAsync(new[] { order });

            return(Ok(result));
        }
        [Consumes("application/json", new[] { "application/json-patch+json" })] // It's a trick that allows ASP.NET infrastructure to select this action with body and ProcessOrderPaymentsWithoutBankCardInfo if no body
        public async Task <ActionResult <ProcessPaymentRequestResult> > ProcessOrderPayments([FromRoute] string orderId, [FromRoute] string paymentId, [FromBody] BankCardInfo bankCardInfo)
        {
            var order = await _customerOrderService.GetByIdAsync(orderId, CustomerOrderResponseGroup.Full.ToString());

            if (order == null)
            {
                var searchCriteria = AbstractTypeFactory <CustomerOrderSearchCriteria> .TryCreateInstance();

                searchCriteria.Number        = orderId;
                searchCriteria.ResponseGroup = CustomerOrderResponseGroup.Full.ToString();

                var orders = await _searchService.SearchCustomerOrdersAsync(searchCriteria);

                order = orders.Results.FirstOrDefault();
            }

            if (order == null)
            {
                throw new InvalidOperationException($"Cannot find order with ID {orderId}");
            }

            var authorizationResult = await _authorizationService.AuthorizeAsync(User, order, new OrderAuthorizationRequirement(ModuleConstants.Security.Permissions.Update));

            if (!authorizationResult.Succeeded)
            {
                return(Unauthorized());
            }

            var inPayment = order.InPayments.FirstOrDefault(x => x.Id == paymentId);

            if (inPayment == null)
            {
                throw new InvalidOperationException($"Cannot find payment with ID {paymentId}");
            }
            if (inPayment.PaymentMethod == null)
            {
                throw new InvalidOperationException($"Cannot find payment method with code {inPayment.GatewayCode}");
            }

            var store = await _storeService.GetByIdAsync(order.StoreId, StoreResponseGroup.StoreInfo.ToString());

            if (store == null)
            {
                throw new InvalidOperationException($"Cannot find store with ID {order.StoreId}");
            }

            var request = new ProcessPaymentRequest
            {
                OrderId      = order.Id,
                Order        = order,
                PaymentId    = inPayment.Id,
                Payment      = inPayment,
                StoreId      = order.StoreId,
                Store        = store,
                BankCardInfo = bankCardInfo
            };
            var result = inPayment.PaymentMethod.ProcessPayment(request);

            if (result.OuterId != null)
            {
                inPayment.OuterId = result.OuterId;
            }

            // Exclusive status set for DefaultManualPaymentMethod, otherwise the order be stuck in the "New" state.
            // Current payment flow suggests payment processing by payment method code,
            // but, unfortunately, there is no way to do set status directly in DefaultManualPaymentMethod, because it will produce cyclical references between order and payment modules.
            // One day, we should change the flow to commonly divide payment and order processing, but now it isn't.
            if (inPayment.PaymentMethod is DefaultManualPaymentMethod)
            {
                order.Status = result.NewPaymentStatus.ToString();
            }

            await _customerOrderService.SaveChangesAsync(new[] { order });

            return(Ok(result));
        }