public async Task Handle(ConfirmOrderLabelPurchaseCommand message) // 2.2 Seller : confirm the label purchase.
        {
            if (message == null)
            {
                throw new ArgumentNullException(nameof(message));
            }

            var order = await _orderRepository.Get(message.OrderId);

            if (order == null)
            {
                return;
            }

            order.IsLabelPurchased = true;
            order.TrackingNumber   = message.TrackingNumber;
            order.ShipmentDigest   = null;
            await _orderRepository.Update(order);

            _eventPublisher.Publish(new OrderLabelPurchasedEvent
            {
                CommonId       = message.CommonId,
                OrderId        = message.OrderId,
                TrackingNumber = order.TrackingNumber,
                Subject        = order.Subject,
                SellerId       = order.SellerId
            });
        }
        public async Task <ConfirmOrderLabelPurchaseValidationResult> Validate(string subject, ConfirmOrderLabelPurchaseCommand command)
        {
            if (string.IsNullOrWhiteSpace(subject))
            {
                throw new ArgumentException(nameof(subject));
            }

            if (command == null)
            {
                throw new ArgumentNullException(nameof(command));
            }

            var order = await _orderRepository.Get(command.OrderId);

            if (order == null) // Check order exists.
            {
                return(new ConfirmOrderLabelPurchaseValidationResult(ErrorDescriptions.TheOrderDoesntExist));
            }

            if (order.SellerId != subject) // Only the seller can purchase the label.
            {
                return(new ConfirmOrderLabelPurchaseValidationResult(ErrorDescriptions.TheOrderLabelCanBePurchasedOnlyBySeller));
            }

            if (order.Status != OrderAggregateStatus.Confirmed) // The order state should be confirmed.
            {
                return(new ConfirmOrderLabelPurchaseValidationResult(ErrorDescriptions.TheOrderIsNotConfirmed));
            }

            var payer = await _openidClient.GetPublicClaims(_settingsProvider.GetBaseOpenidUrl(), subject); // Retrieve the payer information.

            if (payer == null)
            {
                return(new ConfirmOrderLabelPurchaseValidationResult(ErrorDescriptions.ThePayerPaypalAccountNotExist));
            }

            var seller = await _openidClient.GetPublicClaims(_settingsProvider.GetBaseOpenidUrl(), order.SellerId); // Retrieve the seller information.

            if (seller == null)
            {
                return(new ConfirmOrderLabelPurchaseValidationResult(ErrorDescriptions.TheSellerPaypalAccountNotExist));
            }

            var paypalBuyer  = payer.Claims.FirstOrDefault(c => c.Type == "paypal_email");
            var paypalSeller = seller.Claims.FirstOrDefault(c => c.Type == "paypal_email");

            if (paypalBuyer == null || string.IsNullOrWhiteSpace(paypalBuyer.Value))
            {
                return(new ConfirmOrderLabelPurchaseValidationResult(ErrorDescriptions.ThePayerPaypalAccountNotExist));
            }

            if (paypalSeller == null || string.IsNullOrWhiteSpace(paypalSeller.Value))
            {
                return(new ConfirmOrderLabelPurchaseValidationResult(ErrorDescriptions.TheSellerPaypalAccountNotExist));
            }

            return(new ConfirmOrderLabelPurchaseValidationResult(order, payer, seller));
        }
        public async Task <IActionResult> Execute(string orderId, string subject, string commonId, JObject jObj)
        {
            if (jObj == null)
            {
                throw new ArgumentNullException(nameof(jObj));
            }


            ConfirmOrderLabelPurchaseCommand command = null;

            try
            {
                command = _requestBuilder.GetConfirmOrderLabelPurchase(jObj);
            }
            catch (ArgumentException ex)
            {
                var error = _responseBuilder.GetError(ErrorCodes.Request, ex.Message);
                return(_controllerHelper.BuildResponse(HttpStatusCode.BadRequest, error));
            }

            command.OrderId  = orderId;
            command.CommonId = commonId;
            var validationResult = await _validator.Validate(subject, command); // Validate the command.

            if (!validationResult.IsValid)
            {
                var error = _responseBuilder.GetError(ErrorCodes.Request, validationResult.Message);
                return(_controllerHelper.BuildResponse(HttpStatusCode.BadRequest, error));
            }

            if (validationResult.Order.OrderParcel.Transporter != Transporters.Ups) // Only UPS transport mode is supported.
            {
                var error = _responseBuilder.GetError(ErrorCodes.Request, ErrorDescriptions.TheUpsIsOnlySupported);
                return(_controllerHelper.BuildResponse(HttpStatusCode.BadRequest, error));
            }

            var acceptUpsShipment = await _upsClient.AcceptShip(new AcceptShipParameter // 1. Accept UPS shipment.
            {
                Credentials = new UpsCredentials
                {
                    LicenseNumber = _settingsProvider.GetUpsLicenseNumber(),
                    Password      = _settingsProvider.GetUpsPassword(),
                    UserName      = _settingsProvider.GetUpsUsername()
                },
                ShipmentDigest = validationResult.Order.ShipmentDigest
            });

            if (acceptUpsShipment.Response.ResponseStatusCode == "0")
            {
                var error = _responseBuilder.GetError(ErrorCodes.Request, acceptUpsShipment.Response.Error.ErrorDescription);
                return(_controllerHelper.BuildResponse(HttpStatusCode.BadRequest, error));
            }

            var order = validationResult.Order;
            var token = await _paypalOauthClient.GetAccessToken(_settingsProvider.GetPaypalClientId(), _settingsProvider.GetPaypalClientSecret(),
                                                                new PaypalOauthClientOptions
            {
                ApplicationMode = PaypalApplicationModes.sandbox
            });

            if (order.OrderPayment.PaymentMethod == OrderPayments.Paypal) // Update transaction.
            {
                var transactionId   = order.OrderPayment.TransactionId;
                var newPrice        = new JObject();
                var newPriceDetails = new JObject();
                newPriceDetails.Add("shipping", order.ShippingPrice);
                newPriceDetails.Add("subtotal", order.TotalPrice);
                newPrice.Add("total", order.TotalPrice + order.ShippingPrice);
                newPrice.Add("currency", "EUR");
                newPrice.Add("details", newPriceDetails);
                var updatePayment = await _paypalClient.UpdatePayment(transactionId, new UpdatePaymentParameter
                {
                    AccessToken = token.AccessToken,
                    JsonPatches = new[]
                    {
                        new JsonPatch
                        {
                            Operation = JsonPatchOperations.replace,
                            Path      = "/transactions/0/amount",
                            Value     = newPrice
                        }
                    }
                });

                if (!updatePayment.IsValid)
                {
                    var error = _responseBuilder.GetError(ErrorCodes.Request, updatePayment.ErrorResponse.Message);
                    return(_controllerHelper.BuildResponse(HttpStatusCode.BadRequest, error));
                }
            }

            var acceptedPayment = await _paypalClient.ExecutePayment(command.TransactionId, new ExecutePaymentParameter // Accept the payment.
            {
                AccessToken = token.AccessToken,
                PayerId     = command.PayerId
            });

            if (!acceptedPayment.IsValid)
            {
                await _upsClient.Cancel(acceptUpsShipment.ShipmentResults.ShipmentIdentificationNumber, new UpsCredentials
                {
                    LicenseNumber = _settingsProvider.GetUpsLicenseNumber(),
                    Password      = _settingsProvider.GetUpsPassword(),
                    UserName      = _settingsProvider.GetUpsUsername()
                });

                var error = _responseBuilder.GetError(ErrorCodes.Request, acceptedPayment.ErrorResponse.Message);
                return(_controllerHelper.BuildResponse(HttpStatusCode.BadRequest, error));
            }

            command.TrackingNumber = acceptUpsShipment.ShipmentResults.PackageResults.TrackingNumber;
            _commandSender.Send(command);
            return(new OkResult());
        }