Помоги отрефакторить этот C# код:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Security.Cryptography;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using CryptonatorAPI;
using CryptonatorAPI.enums;
using CryptonatorAPI.json;
using Leaf.xNet;
using Qiwi.BillPayments.Client;
using Qiwi.BillPayments.Model;
using Qiwi.BillPayments.Model.In;
using Telegram.Bot;
using Telegram.Bot.Types.Payments;
using Telegram.Bot.Types.ReplyMarkups;
using static TelegramBot.Program;

namespace TelegramBot
{
    public class Payments
    {
        private const string billPaymentsClientKey = "eyJ2ZXJzaW9uIjoiUDJQIiwiZGF0YSI6eyJwYXlpbl9tZXJjaGFudF9zaXRlX3VpZCI6Im9zdXMtMDAiLCJ1c2VyX2lkIjoiNzkyMDEzMDI0NzMiLCJzZWNyZXQiOiJmNGE3OGVjYzllNTAyMTUwMWM0YTRkYzRjOTI4ZjY2ODU0YjU4ZGVjODY3NWU4ZDVlNmU4MDRmYTEzODNmMTViIn19";

        private const string cryptoApiKey = "HRV3WQW-BQX4971-HAVVRSS-ZYVJ4XY";
        private const string cryptoEmail = "dra1n.crimson@gmail.com";
        private const string cryptoPassword = "25031977dD";

        public static async Task QiwiPaymentAsync(long chatId)
        {
            var client = BillPaymentsClientFactory.Create(billPaymentsClientKey);
            try
            {
                var result = await client.CreateBillAsync(info: new CreateBillInfo()
                {
                    BillId = Guid.NewGuid().ToString(),
                    Amount = new MoneyAmount
                    {
                        ValueDecimal = 650,
                        CurrencyEnum = CurrencyEnum.Rub
                    },
                    ExpirationDateTime = DateTime.Now.AddMinutes(35)
                });

                DataBase.UpdatePaymentInfo(chatId, "Qiwi", result.BillId);
                MessageType.OrderUrl(chatId, result.PayUrl.AbsoluteUri);
                Console.WriteLine("Qiwi invoice created");
            }
            catch (Exception)
            {
                await QiwiPaymentAsync(chatId); // retry
            }
        }

        public static async void CryptoPayment(long chatId, string callbackId)
        {
            try
            {
                string orderId = RandomString(9);
                string url = "https://api.nowpayments.io/v1/invoice";
                string key = "HRV3WQW-BQX4971-HAVVRSS-ZYVJ4XY";
                string data = $"{{\"price_amount\":15,\"price_currency\":\"USD\",\"order_id\":\"{orderId}\",\"ipn_callback_url\":\"https://t.me/sfeam_bot\",\"success_url\":\"https://t.me/sfeam_bot\",\"cancel_url\":\"https://t.me/sfeam_bot\"}}";
                var request = (HttpWebRequest)WebRequest.Create(url);
                request.Method = "POST";
                request.ContentType = "application/json";
                request.Headers.Add("x-api-key", key);
                request.ContentLength = data.Length;
                using (var streamWriter = new StreamWriter(request.GetRequestStream()))
                {
                    streamWriter.Write(data);
                }
                var response = (HttpWebResponse)request.GetResponse();
                string responseString = new StreamReader(response.GetResponseStream()).ReadToEnd();
                CryptoJsonClass crypto = JsonSerializer.Deserialize<CryptoJsonClass>(responseString);

                DataBase.UpdatePaymentInfo(chatId, "Crypto", orderId);

                MessageType.OrderUrl(chatId, crypto.invoice_url);
                
                Console.WriteLine("Crypto invoice created");
            }
            catch
            {
                await BotClient.AnswerCallbackQueryAsync(callbackId, "Оплата в криптовалюте временно недоступна. Попробуйте позже.", true);
                MessageType.OrderListServices(chatId);
            }
        }

        public static async void FowPayPayment(long chatId, string callbackId)
        {
            try
            {
                string orderId = RandomString(12);

                string url = FowPayGenerateInvoice("1480", "650", orderId);

                DataBase.UpdatePaymentInfo(chatId, "FowPay", orderId);

                MessageType.OrderUrl(chatId, url);

                Console.WriteLine("FowPay invoice created");
            }
            catch
            {
                await BotClient.AnswerCallbackQueryAsync(callbackId, "Оплата через FowPay временно недоступна. Попробуйте позже.", true);
                MessageType.OrderListServices(chatId);
            }
        }

        static string FowPayGenerateInvoice(string shop, string amount, string order)
        {
            using (var request = new HttpRequest())
            {
                request.AddHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8");
                request.AddHeader("Accept-Encoding", "gzip, deflate, br");
                request.AddHeader("Accept-Language", "ru-RU,ru;q=0.8,en-US;q=0.6,en;q=0.4");
                request.AddHeader("Cache-Control", "max-age=0");
                request.AddHeader("Connection", "keep-alive");
                request.AddHeader("Content-Type", "application/x-www-form-urlencoded");
                request.AddHeader("Host", "fowpay.com");
                request.AddHeader("Origin", "https://fowpay.com");
                request.AddHeader("Referer", "https://fowpay.com/pay");
                request.AddHeader("Upgrade-Insecure-Requests", "1");
                request.AddHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36");

                var sign = GetSignature(shop, order, amount, "2d8b86fdfe9071f93c31515a011e73ef");
                return "https://fowpay.com/pay" + $"?shop={shop}&amount={amount}&order={order}&sign={sign}";
            }
        }

        static string GetSignature(string shopId, string orderId, string orderAmount, string secret)
        {
            var md5 = new MD5CryptoServiceProvider();
            var bytes = md5.ComputeHash(Encoding.UTF8.GetBytes($"{shopId}:{orderAmount}:{secret}:{orderId}"));
            return BitConverter.ToString(bytes).Replace("-", "").ToLower();
        }

        public static bool CheckPayment(long chatId)
        {
            UserInfo userInfo = DataBase.GetUserFullInfo(chatId);
            
        retry:
            try
            {
                switch (userInfo.ServiceForPay)
                {
                    case "Qiwi":
                        var client = BillPaymentsClientFactory.Create("eyJ2ZXJzaW9uIjoiUDJQIiwiZGF0YSI6eyJwYXlpbl9tZXJjaGFudF9zaXRlX3VpZCI6Im9zdXMtMDAiLCJ1c2VyX2lkIjoiNzkyMDEzMDI0NzMiLCJzZWNyZXQiOiJmNGE3OGVjYzllNTAyMTUwMWM0YTRkYzRjOTI4ZjY2ODU0YjU4ZGVjODY3NWU4ZDVlNmU4MDRmYTEzODNmMTViIn19");
                        var result = client.GetBillInfoAsync(userInfo.BillId).Result;
                        if (result.Status.ValueString != "PAID")
                        {
                            return false;
                        }

                        if (result.Status.ValueString == "PAID")
                        {
                            if (userInfo.SubTime <= DateTime.Now)
                            {
                                DataBase.UpdatePaymentSuccessful(chatId, userInfo, DateTime.Now.AddDays(30));
                                return true;
                            }
                            else
                            {
                                DataBase.UpdatePaymentSuccessful(chatId, userInfo, userInfo.SubTime.AddDays(30));
                                return true;
                            }
                        }
                        break;
                    case "Crypto":
                        OrderList? orderList = JsonSerializer.Deserialize<OrderList>(GetPayments(GetJWTToken()));
                        var order = orderList?.data.Find(x => x.order_id == userInfo.BillId && x.payment_status == "finished");
                        if (order is not {payment_status: "finished"})
                        {
                            return false;
                        }

                        if (order.payment_status == "finished")
                        {
                            if (userInfo.SubTime <= DateTime.Now)
                            {
                                DataBase.UpdatePaymentSuccessful(chatId, userInfo, DateTime.Now.AddDays(30));
                                return true;
                            }
                            else
                            {
                                DataBase.UpdatePaymentSuccessful(chatId, userInfo, userInfo.SubTime.AddDays(30));
                                return true;
                            }
                        }
                        break;

                        return false;
                }
            }
            catch (Exception)
            {
                goto retry;
            }

            return false;
        }

        private static string RandomString(int length)
        {
            const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
            return new string(Enumerable.Repeat(chars, length).Select(s => s[new Random().Next(s.Length)]).ToArray());
        }

        private static string GetJWTToken()
        {
            string url = "https://api.nowpayments.io/v1/auth";
            string data = "{\"email\":\"dra1n.crimson@gmail.com\",\"password\":\"25031977dD\"}";
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
            request.Method = "POST";
            request.ContentType = "application/json";
            request.ContentLength = data.Length;
            using (StreamWriter writer = new StreamWriter(request.GetRequestStream()))
            {
                writer.Write(data);
            }

            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            string responseString = new StreamReader(response.GetResponseStream()).ReadToEnd();
            string token = responseString.Split("\"token\":\"")[1];
            token = token.Split("\"")[0];
            return token;
        }

        private static string GetPayments(string token)
        {
            string url = "https://api.nowpayments.io/v1/payment/";
            string xApiKey = "HRV3WQW-BQX4971-HAVVRSS-ZYVJ4XY";
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
            request.Method = "GET";
            request.Headers.Add("Authorization", "Bearer " + token);
            request.Headers.Add("x-api-key", xApiKey);
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            Stream dataStream = response.GetResponseStream();
            StreamReader reader = new StreamReader(dataStream);
            string responseFromServer = reader.ReadToEnd();
            reader.Close();
            dataStream.Close();
            response.Close();
            return responseFromServer;
        }
    }

    public class CryptoJsonClass
    {
        public string id { get; set; }
        public string token_id { get; set; }
        public string order_id { get; set; }
        public object order_description { get; set; }
        public string price_amount { get; set; }
        public string price_currency { get; set; }
        public object pay_currency { get; set; }
        public string ipn_callback_url { get; set; }
        public string invoice_url { get; set; }
        public string success_url { get; set; }
        public string cancel_url { get; set; }
        public object partially_paid_url { get; set; }
        public DateTime created_at { get; set; }
        public DateTime updated_at { get; set; }
    }

    public class Datum
    {
        public object payment_id { get; set; }
        public object invoice_id { get; set; }
        public string payment_status { get; set; }
        public string pay_address { get; set; }
        public int price_amount { get; set; }
        public string price_currency { get; set; }
        public double pay_amount { get; set; }
        public double actually_paid { get; set; }
        public string pay_currency { get; set; }
        public string order_id { get; set; }
        public string order_description { get; set; }
        public string purchase_id { get; set; }
        public double outcome_amount { get; set; }
        public string outcome_currency { get; set; }
        public string payout_hash { get; set; }
        public string payin_hash { get; set; }
        public DateTime created_at { get; set; }
        public DateTime updated_at { get; set; }
        public string payin_extra_id { get; set; }
    }

    public class OrderList
    {
        public List<Datum> data { get; set; }
        public int limit { get; set; }
        public int page { get; set; }
        public int pagesCount { get; set; }
        public int total { get; set; }
    }
}