public Result MakeDropOffDonation(int userID, DateTime date, string currencyCode)
        {
            var cartItems = _donateAccessor.GetCartItems(userID, currencyCode).Payload;

            var total = cartItems.Sum(x => x.TotalAmount);

            var donationResult = _donateAccessor.MakeDonation(userID, total, "dropoff", currencyCode);

            if (!donationResult.IsSuccess)
            {
                return(new Result(false, donationResult.Message));
            }

            var donation = donationResult.Payload;

            var dropOffDonation = new DropOffDonation
            {
                DonationID   = donation.DonationID,
                DeliveryDate = date
            };

            _donateAccessor.MakeDropOffDonation(dropOffDonation);

            var items = cartItems.Select(x => new DonationItem
            {
                DonationID    = donation.DonationID,
                ItemID        = x.ItemID,
                TotalAmount   = x.TotalAmount,
                NumberOfItems = x.NumItems,
                CurrencyID    = x.CurrencyID
            }).ToList();

            var itemsResult = _donateAccessor.AddDonationItems(items);

            if (itemsResult.IsSuccess)
            {
                _donateAccessor.ClearUserCart(userID);
            }

            SendDropOffDonationConfirmationEmail(userID, items, date.ToLongDateString());
            return(itemsResult);
        }
        public Result <MPESAPayment> MakeMPESAPayment(int userID, decimal total, string phoneNumber, bool isKES)
        {
            var timestamp = DateTime.Now.ToString("yyyyMMddhhmmss");

            phoneNumber = phoneNumber.Replace("+", "").Replace(" ", "");

            var mpesa = _configuration.GetSection("MPESA");
            int amount;

            if (isKES)
            {
                amount = (int)total;
            }
            else
            {
                var currency = _currencyAccessor.GetCurrencyByCode("KES").Payload;
                amount = (int)Round(total * currency.ConversionRateFromUSD, currency.RoundDigits);
            }
            var payment = new MPESAPaymentRequest
            {
                BusinessShortCode = mpesa["SandboxShortCode"],
                Password          = _encryptionService.GenerateMPESAPassword(mpesa["SandboxShortCode"], mpesa["SandboxPassKey"], timestamp),
                Timestamp         = timestamp,
                //For testing
                Amount           = 1,
                PartyA           = phoneNumber,
                PartyB           = mpesa["SandboxShortCode"],
                PhoneNumber      = phoneNumber,
                CallBackURL      = mpesa["SandboxCallBackURL"],
                AccountReference = CalcAccountReference(),
                TransactionDesc  = "CYEC Donation"
            };

            try
            {
                //GetAuthCode
                var authRequest = (HttpWebRequest)WebRequest.Create(mpesa["SandboxOAuthURL"]);
                authRequest.ContentType = "application/json";

                var authKey = "Basic " + Convert.ToBase64String((mpesa["SandboxConsumerKey"] + ":" + mpesa["SandboxConsumerSecret"]).Select(x => (byte)x).ToArray());
                authRequest.Headers.Add("Authorization", authKey);
                authRequest.Headers.Add("cache-control", "no-cache");
                authRequest.Method = "GET";

                var authResponse = (HttpWebResponse)authRequest.GetResponse();
                var result       = "";
                using (var streamReader = new StreamReader(authResponse.GetResponseStream()))
                {
                    result = streamReader.ReadToEnd();
                }

                var responseJSON = JsonConvert.DeserializeObject <JObject>(result);
                var authToken    = responseJSON["access_token"].ToString();

                //Send payment request
                var paymentRequest = (HttpWebRequest)WebRequest.Create(mpesa["SandboxURL"]);

                paymentRequest.ContentType = "application/json";
                paymentRequest.Accept      = "*/*";
                paymentRequest.KeepAlive   = true;
                paymentRequest.Headers.Add("Authorization", "Bearer " + authToken);
                paymentRequest.Method = "POST";

                using (var streamWriter = new StreamWriter(paymentRequest.GetRequestStream()))
                {
                    string json = string.Format(_paymentTemplate, payment.BusinessShortCode, payment.Password, payment.Timestamp, payment.Amount, payment.PartyA,
                                                payment.PartyB, payment.PhoneNumber, payment.CallBackURL, payment.AccountReference, payment.TransactionDesc);
                    json = "{" + json + "}";

                    streamWriter.Write(json);
                }

                var paymentResponse = (HttpWebResponse)paymentRequest.GetResponse();
                result = "";
                using (var streamReader = new StreamReader(paymentResponse.GetResponseStream()))
                {
                    result = streamReader.ReadToEnd();
                }

                responseJSON = JsonConvert.DeserializeObject <JObject>(result);
                var response = new MPESAPaymentResponse
                {
                    MerchantRequestID   = responseJSON["MerchantRequestID"].ToString(),
                    CheckoutRequestID   = responseJSON["CheckoutRequestID"].ToString(),
                    ResponseCode        = responseJSON["ResponseCode"].ToString(),
                    ResponseDescription = responseJSON["ResponseDescription"].ToString(),
                    CustomerMessage     = responseJSON["CustomerMessage"].ToString(),
                };

                if (response.ResponseCode != "0")
                {
                    return(new Result <MPESAPayment>(false, "Error initiating transaction."));
                }

                var donation = _donateAccessor.MakeDonation(userID, amount, "mpesa", "KES").Payload;

                var mpesaPayment = new MPESAPayment
                {
                    DonationID        = donation.DonationID,
                    MerchantRequestID = response.MerchantRequestID,
                    CheckoutRequestID = response.CheckoutRequestID,
                    AccountReference  = payment.AccountReference,
                    PaymentStatus     = "Pending",
                    PhoneNumber       = phoneNumber
                };
                _paymentAccessor.AddMPESAPayment(mpesaPayment);

                var cartItems = _donateAccessor.GetCartItems(userID, "KES").Payload;
                var items     = cartItems.Select(x => new DonationItem
                {
                    DonationID    = donation.DonationID,
                    ItemID        = x.ItemID,
                    TotalAmount   = x.TotalAmount,
                    NumberOfItems = x.NumItems,
                    CurrencyID    = x.CurrencyID
                }).ToList();

                _donateAccessor.AddDonationItems(items);

                return(new Result <MPESAPayment>(mpesaPayment));
            }
            catch (Exception ex)
            {
                return(new Result <MPESAPayment>(false, "An error occurred while sending the payment: " + ex.Message));
            }
        }