/// /// <summary>
        /// Cria uma venda com uma coleção de boletos
        /// </summary>
        /// <param name="boletoTransactionCollection">Coleção de boletos</param>
        /// <returns></returns>
        public HttpResponse<CreateSaleResponse> Create(Collection<BoletoTransaction> boletoTransactionCollection)
        {
            CreateSaleRequest createSaleRequest = new CreateSaleRequest();
            createSaleRequest.BoletoTransactionCollection = boletoTransactionCollection;
            // Se não for informado o comprador nem o carrinho de compras não será possível utilizar o serviço de anti fraude.
            createSaleRequest.Options = new SaleOptions() { IsAntiFraudEnabled = false };

            return this.Create(createSaleRequest);
        }
        /// <summary>
        /// Cria uma venda, contendo transações de boleto e/ou cartão de crédito
        /// </summary>
        /// <param name="createSaleRequest">Dados da venda</param>
        /// <returns></returns>
        public HttpResponse<CreateSaleResponse> Create(CreateSaleRequest createSaleRequest) {

            // Configura MerchantKey e o header
            NameValueCollection headers = this.GetHeaders();
            headers.Add("MerchantKey", this.MerchantKey.ToString());

            // Envia requisição
            return this.HttpUtility.SubmitRequest<CreateSaleRequest, CreateSaleResponse>(createSaleRequest,
                string.Concat(this.HostUri, this.ResourceName), HttpVerbEnum.Post, HttpContentTypeEnum.Json, headers);
        }
        /// <summary>
        /// Cria uma venda com uma coleção de transações de cartão de crédito
        /// </summary>
        /// <param name="creditCardTransactionCollection">Coleção de transações de cartão de crédito</param>
        /// <param name="orderReference">Identificação do pedido na loja</param>
        /// <returns></returns>
        public HttpResponse<CreateSaleResponse> Create(Collection<CreditCardTransaction> creditCardTransactionCollection, string orderReference) {

            CreateSaleRequest createSaleRequest = new CreateSaleRequest();
            createSaleRequest.CreditCardTransactionCollection = creditCardTransactionCollection;
            // Se não for informado o comprador nem o carrinho de compras não será possível utilizar o serviço de anti fraude.
            createSaleRequest.Options = new SaleOptions() { IsAntiFraudEnabled = false };
            if (string.IsNullOrWhiteSpace(orderReference) == false) {
                createSaleRequest.Order = new Order() {
                    OrderReference = orderReference
                };
            }

            return this.Create(createSaleRequest);
        }
        internal static bool ProcessPayment(CustomerTicket ticket, Guid instantBuy, string securityCode)
        {
            var amountTransaction = (long)(ticket.Quantity * ticket.Event.Price);

            try
            {
                Log.Info($"Create transaction for ticket {ticket.Id} and for customer {ticket.IdCustomer}");

                // Cria a transação.
                var transaction = new CreditCardTransaction()
                {
                    AmountInCents = amountTransaction,
                    CreditCard = new CreditCard()
                    {
                        InstantBuyKey = instantBuy,
                        SecurityCode = securityCode
                    },
                };

                // Cria requisição.
                var createSaleRequest = new CreateSaleRequest()
                {
                    // Adiciona a transação na requisição.
                    CreditCardTransactionCollection = new Collection<CreditCardTransaction>(new CreditCardTransaction[] { transaction }),
                };

                Log.Info($"Make request for transaction for ticket {ticket.Id} and for customer {ticket.IdCustomer}");

                var serviceClient = new GatewayServiceClient(merchantKey, hostUri);

                // Autoriza a transação e recebe a resposta do gateway.
                var httpResponse = serviceClient.Sale.Create(createSaleRequest);

                Log.Info($"Request Status for transaction for ticket {ticket.Id} and for customer {ticket.IdCustomer} with status {httpResponse.HttpStatusCode}");
                if (httpResponse.Response.CreditCardTransactionResultCollection != null)
                {
                    var transactionStatus = httpResponse.Response.CreditCardTransactionResultCollection.FirstOrDefault().CreditCardTransactionStatus;
                    Log.Info($"Transaction Status for ticket {ticket.Id} with status {transactionStatus.ToString()}");

                    if (transactionStatus == CreditCardTransactionStatusEnum.NotAuthorized)
                        ticket.Status = Enum.StatusEnum.NotAuthorized;

                    if (transactionStatus == CreditCardTransactionStatusEnum.Captured)
                        ticket.Status = Enum.StatusEnum.Authorized;
                    
                    return true;
                }

                return false;
            }
            catch (System.Exception ex)
            {
                Log.Error($"Request Error for transaction for ticket {ticket.Id} and for customer {ticket.IdCustomer}", ex);
                throw ex;
            }
            finally
            {
                Log.Info($"End Request for transaction for ticket {ticket.Id} and for customer {ticket.IdCustomer}");
            }

        }
        internal static bool ProcessPayment(CustomerTicket ticket, CustomerPayment payment, out Guid instantBuy)
        {
            var amountTransaction = (long)(ticket.Quantity * ticket.Event.Price);
            var expiration = payment.Expiration.Split('/');
            var expMonth = Convert.ToInt32(expiration.FirstOrDefault());
            var expYear = Convert.ToInt32(expiration.LastOrDefault());

            instantBuy = Guid.Empty;

            try
            {
                Log.Info($"Create transaction for ticket {ticket.Id} and for customer {ticket.IdCustomer}");

                // Cria a transação.
                var transaction = new CreditCardTransaction()
                {
                    AmountInCents = amountTransaction,
                    CreditCard = new CreditCard()
                    {
                        CreditCardBrand = ConvertCreditCardBrand(payment),
                        CreditCardNumber = payment.CreditCardNumber,
                        ExpMonth = expMonth,
                        ExpYear = expYear,
                        HolderName = payment.HolderName,
                        SecurityCode = payment.SecurityCode
                    },
                };

                // Cria requisição.
                var createSaleRequest = new CreateSaleRequest()
                {
                    // Adiciona a transação na requisição.
                    CreditCardTransactionCollection = new Collection<CreditCardTransaction>(new CreditCardTransaction[] { transaction }),
                };

                Log.Info($"Make request for transaction for ticket {ticket.Id} and for customer {ticket.IdCustomer}");

                var serviceClient = new GatewayServiceClient(merchantKey, hostUri);

                // Autoriza a transação e recebe a resposta do gateway.
                var httpResponse = serviceClient.Sale.Create(createSaleRequest);

                Log.Info($"Request Status for transaction for ticket {ticket.Id} and for customer {ticket.IdCustomer} with status {httpResponse.HttpStatusCode}");
                if (httpResponse.Response.CreditCardTransactionResultCollection != null)
                {
                    var transactionStatus = httpResponse.Response.CreditCardTransactionResultCollection.FirstOrDefault().CreditCardTransactionStatus;
                    Log.Info($"Transaction Status for ticket {ticket.Id} with status {transactionStatus.ToString()}");

                    if (transactionStatus == CreditCardTransactionStatusEnum.NotAuthorized)
                        ticket.Status = Enum.StatusEnum.NotAuthorized;

                    if (transactionStatus == CreditCardTransactionStatusEnum.Captured)
                        ticket.Status = Enum.StatusEnum.Authorized;

                    if (payment.KeepSave)
                        instantBuy = httpResponse.Response.CreditCardTransactionResultCollection.FirstOrDefault().CreditCard.InstantBuyKey;
                    
                    return true;

                }

                return false;
            }
            catch (System.Exception ex)
            {
                Log.Error($"Request Error for transaction for ticket {ticket.Id} and for customer {ticket.IdCustomer}", ex);
                throw ex;
            }
            finally
            {
                Log.Info($"End Request for transaction for ticket {ticket.Id} and for customer {ticket.IdCustomer}");
            }

        }
        public void ItShouldCreateATransactionWithInstantBuyKey() {
            // Cria o cliente para retentar a transação.
            IGatewayServiceClient serviceClient = this.GetGatewayServiceClient();

            // Cria transação de cartão de crédito para ser retentada
            HttpResponse<CreateSaleResponse> saleResponse = serviceClient.Sale.Create(this._createCreditCardSaleRequest);

            Assert.AreEqual(saleResponse.HttpStatusCode, HttpStatusCode.Created);

            var instantBuyKey = saleResponse.Response.CreditCardTransactionResultCollection.Select(x => x.CreditCard.InstantBuyKey);

            // Cria requisição com instant buy key
            CreateSaleRequest createSale = new CreateSaleRequest {
                CreditCardTransactionCollection = new Collection<CreditCardTransaction>
                {
                    new CreditCardTransaction
                    {
                        AmountInCents = 10000,
                        CreditCard = new CreditCard
                        {
                            InstantBuyKey = instantBuyKey.FirstOrDefault()
                        }
                    }
                }
            };

            // Faz a requisição
            HttpResponse<CreateSaleResponse> httpResponse = serviceClient.Sale.Create(createSale);

            Assert.AreEqual(HttpStatusCode.Created, httpResponse.HttpStatusCode);
        }
        public void ItShouldCreateSaleWithAllFields() {
            CreateSaleRequest saleRequest = new CreateSaleRequest();

            // Dados da transação de cartão de crédito.
            saleRequest.CreditCardTransactionCollection = new Collection<CreditCardTransaction>() {
                new CreditCardTransaction() {
                    AmountInCents = 100,
                    CreditCardOperation = CreditCardOperationEnum.AuthAndCapture,
                    CreditCard = new CreditCard() {
                        CreditCardBrand = CreditCardBrandEnum.Visa,
                        CreditCardNumber = "4111111111111111",
                        ExpMonth = 10,
                        ExpYear = 2018,
                        HolderName = "Somebody",
                        SecurityCode = "123"
                    },
                    // Opcional.  
                    Options = new CreditCardTransactionOptions() {
                        // Indica que a transação é de simulação.
                        PaymentMethodCode = 1
                    }
                }
            };

            // Dados do comprador.
            saleRequest.Buyer = new Buyer() {
                DocumentNumber = "11111111111",
                DocumentType = DocumentTypeEnum.CPF,
                Email = "*****@*****.**",
                EmailType = EmailTypeEnum.Personal,
                Gender = GenderEnum.M,
                HomePhone = "(21) 12345678",
                Name = "Somebody",
                PersonType = PersonTypeEnum.Person,
                AddressCollection = new Collection<BuyerAddress>() {
                    new BuyerAddress() {
                        AddressType = AddressTypeEnum.Residential,
                        City = "Rio de Janeiro",
                        Complement = "10º floor",
                        Country = CountryEnum.Brazil.ToString(),
                        District = "Centro",
                        Number = "199",
                        State = "RJ",
                        Street = "Rua da Quitanda",
                        ZipCode = "20091005"
                    }
                }
            };

            // Dados do carrinho de compras.
            saleRequest.ShoppingCartCollection = new Collection<ShoppingCart>() {
                new ShoppingCart() {
                    FreightCostInCents = 0,
                    ShoppingCartItemCollection = new Collection<ShoppingCartItem>() {
                        new ShoppingCartItem() {
                            Description = "Teclado Padrão",
                            ItemReference = "#1234",
                            Name = "Teclado",
                            Quantity = 3,
                            TotalCostInCents = 60,
                            UnitCostInCents = 20
                        }
                    }
                }
            };

            // Indica que o pedido usará anti fraude.
            saleRequest.Options.IsAntiFraudEnabled = true;

            // Cria o cliente que enviará a transação para o gateway.
            IGatewayServiceClient serviceClient = this.GetGatewayServiceClient();

            // Autoriza a transação de cartão de crédito e recebe a resposta do gateway.
            HttpResponse<CreateSaleResponse> httpResponse = serviceClient.Sale.Create(saleRequest);

            Assert.AreEqual(HttpStatusCode.Created, httpResponse.HttpStatusCode);
        }
        /// <summary>Cria requisição.</summary>
        private CreateSaleRequest GenerateSaleRequest(IOrder order, Collection<CreditCardTransaction> cardTransictions, Collection<BoletoTransaction> boletoTransaction)
        {
            if (cardTransictions.IsNullOrEmpty() && boletoTransaction.IsNullOrEmpty())
                throw new InvalidOperationException("É necessario enviar uma transação");

            var createSaleRequest = new CreateSaleRequest()
            {
                Order = new GatewayApiClient.DataContracts.Order()
                {
                    OrderReference = order.TransactionReference
                }
            };

            if (!cardTransictions.IsNullOrEmpty())
                createSaleRequest.CreditCardTransactionCollection = cardTransictions;

            if (!boletoTransaction.IsNullOrEmpty())
                createSaleRequest.BoletoTransactionCollection = boletoTransaction;

            return createSaleRequest;
        }
        private CreateSaleRequest CreateSaleRequest(Collection<CreditCardTransaction> CreditCardTransactionCollection)
        {
            var createSaleRequest = new CreateSaleRequest()
            {
                // Add the transaction in the request.
                CreditCardTransactionCollection = CreditCardTransactionCollection,
                Order = new Order()
                {
                    OrderReference = Guid.NewGuid().ToString()
                }
            };

            return createSaleRequest;
        }