protected void Page_Load(object sender, EventArgs e)
 {
     using (VendingModelContainer dc = new VendingModelContainer())
     {
         using (var dbContextTransaction = dc.Database.BeginTransaction())
         {
             try
             {
                 long   wvdid = Convert.ToInt64(Request.QueryString["wvdid"]);
                 string prg   = Request["prg"];
                 if (prg != null && wvdid != 0)
                 {
                     DateTime dt = DateTime.Now;
                     //убиваем неподтвержденные заявки на регистрацию, которым больше 3 часов. кто не успел - тот опоздал, блять)
                     long regrequestoldestdatetime = Convert.ToInt64(dt.AddHours(-3).ToString("yyyyMMddHHmmss"));
                     dc.WaterDevices.RemoveRange(dc.WaterDevices.Where(x => x.RegistrationRequestDateTime < regrequestoldestdatetime));
                     long         cdt    = Convert.ToInt64(dt.ToString("yyyyMMddHHmmss"));
                     string       cdtstr = dt.ToString("dd.MM.yyyy HH:mm:ss");
                     WaterDevices tmpwd  = dc.WaterDevices.Where(x => x.PendingRegistration && x.PendingRegistrationGUID == prg && x.ID == wvdid && !x.PendingRegConfirmed).First();
                     CryptoHelper ch     = new CryptoHelper();
                     SHA512       sha512 = new SHA512Managed();
                     //вычисляем хеш открытого ключа устройства
                     byte[] hash = sha512.ComputeHash(tmpwd.PublicKey);
                     //подписываем хеш открытого ключа устройства и формируем ответ. В ответе указываем текущее распределение лицензий с учетом текущей
                     Uri    url    = new Uri(Request.Url.Authority);
                     string output = url.GetLeftPart(UriPartial.Authority);
                     WaterDeviceRegistrationResponse authresp = new WaterDeviceRegistrationResponse
                     {
                         RegID          = tmpwd.ID,
                         ServerEndPoint = output
                     };
                     authresp.Signature = Convert.ToBase64String(ch.SignHashedData(hash));
                     int      activedevicescount  = dc.WaterDevices.Where(x => x.AccountID == tmpwd.AccountID && x.Valid && !x.Suspended && !x.PendingRegistration).Count();
                     int      pendingdevicescount = dc.WaterDevices.Where(x => x.AccountID == tmpwd.AccountID && x.Valid && !x.Suspended && x.PendingRegistration).Count();
                     Accounts tmpacc = dc.Accounts.Where(x => x.ID == tmpwd.AccountID && x.Valid && !x.Suspended).First();
                     authresp.AuthResponse = "SUCCESS " + (activedevicescount + 1).ToString() + "/" +
                                             (pendingdevicescount - 1).ToString() + "/" + tmpacc.DeviceCountLimit.ToString();
                     //Сериализуем объект авторизации в XML документ
                     var xs  = new XmlSerializer(authresp.GetType());
                     var xml = new Utf8StringWriter();
                     xs.Serialize(xml, authresp);
                     tmpwd.RegistrationResponse              = xml.ToString();
                     tmpwd.PendingRegistration               = false;
                     tmpwd.PendingRegConfirmationIP          = Request.UserHostAddress;
                     tmpwd.PendingRegConfirmed               = true;
                     tmpwd.PendingRegConfirmationDateTime    = cdt;
                     tmpwd.PendingRegConfirmationDateTimeStr = cdtstr;
                     tmpwd.RegistrationDateTime              = cdt;
                     tmpwd.RegistrationDateTimeStr           = cdtstr;
                     dc.SaveChanges();
                     dbContextTransaction.Commit();
                     Logger.AccountLog(Request.UserHostAddress, "Подтверждение регистрации устройства №" + tmpwd.ID + " получено", tmpwd.HardwareID, tmpacc.ID);
                     Logger.SystemLog(Request.UserHostAddress, "Пользователь подтвердил регистрацию устройства №" + tmpwd.ID, tmpacc.UserID, "Server");
                     confirmresult.ForeColor = System.Drawing.Color.Lime;
                     confirmresult.Text      = "Подтверждение получено";
                     MailMessage mail = new MailMessage();
                     mail.To.Add(tmpacc.UserID);
                     mail.From            = new MailAddress(WWWVars.MailFromAddress, WWWVars.EMailDisplayName, Encoding.UTF8);
                     mail.Subject         = "Регистрация устройства завершена";
                     mail.SubjectEncoding = Encoding.UTF8;
                     mail.Body            = "Добрый день, уважаемый\\ая сэр\\мадам.<br>" +
                                            "<p>В системе успешно зарегистрировано новое устройство: <br>" +
                                            "Номер: " + tmpwd.ID.ToString() + "<br>" +
                                            "Идентификатор: " + tmpwd.PendingRegistrationGUID + "<br>" +
                                            "Для завершения регистрации устройство должно быть включено и подключено в Интернету.<br><p>" +
                                            "=======================================<br>" +
                                            "письмо сгенерировано автоматически, отвечать на него не нужно. Контакты для обратной связи см. на сайте: <br>" + output;
                     mail.BodyEncoding = Encoding.UTF8;
                     mail.IsBodyHtml   = true;
                     mail.Priority     = MailPriority.High;
                     SmtpClient client = new SmtpClient
                     {
                         UseDefaultCredentials = !WWWVars.MailUseSMTPAuth,
                         Port      = WWWVars.SMTPPort,
                         Host      = WWWVars.SMTPHost,
                         EnableSsl = WWWVars.SMTPUseSSL,
                     };
                     if (!client.UseDefaultCredentials)
                     {
                         client.Credentials = new System.Net.NetworkCredential(WWWVars.MailLogin, WWWVars.MailPassword);
                     }
                     client.Send(mail);
                     Logger.AccountLog("Server", "Отправлено письмо с подтверждением регистрации устройства", tmpacc.UserID, tmpacc.ID);
                     Logger.SystemLog("Server", "Отправлено письмо с подтверждением регистрации устройства", tmpacc.UserID, "Server");
                 }
             }
             catch (Exception ex)
             {
                 confirmresult.ForeColor = System.Drawing.Color.Red;
                 confirmresult.Text      = "Ошибка: " + ex.HResult.ToString();
                 Logger.SystemLog(Request.UserHostAddress, "Ошибка при отправке письма с подтверждением регистрации устройства", ex.Message, "Server");
             }
         }
     }
 }
 protected void Page_Load(object sender, EventArgs e)
 {
     using (VendingModelContainer dc = new VendingModelContainer())
     {
         using (var dbContextTransaction = dc.Database.BeginTransaction())
         {
             Uri    url    = new Uri(Request.Url.Authority);
             string output = url.GetLeftPart(UriPartial.Authority);
             WaterDeviceRegistrationResponse authresp = new WaterDeviceRegistrationResponse
             {
                 RegID          = -1,
                 ServerEndPoint = output
             };
             try
             {
                 DateTime dt           = DateTime.Now;
                 long     cdt          = Convert.ToInt64(dt.ToString("yyyyMMddHHmmss"));
                 string   cdtstr       = dt.ToString("dd.MM.yyyy HH:mm:ss");
                 var      waterdevices = dc.WaterDevices;
                 //считываем запрос
                 string rawrequest = Request.Form["RegistrationRequest"];
                 byte[] bytes      = Convert.FromBase64String(rawrequest);
                 string requestxml = Encoding.UTF8.GetString(bytes);
                 //создаем объект запроса регистрации
                 WaterDeviceRegistrationRequest tmpreq      = Deserialize <WaterDeviceRegistrationRequest>(requestxml);
                 RSACryptoServiceProvider       rsaProvider = null;
                 CryptoHelper ch = new CryptoHelper();
                 //расшифровываем запрос
                 byte[] plaintextbytes = ch.DecryptData(tmpreq.AuthorizationString);
                 byte[] tmphwidbytes   = new byte[] { };
                 byte[] tmpuidbytes    = new byte[] { };
                 //делим массив данных на две части, разделитель byte[3] { 254, 11, 254 }
                 for (int i = 0; i < plaintextbytes.Length; i++)
                 {
                     if (plaintextbytes[i] == 254 && plaintextbytes[i + 1] == 11 && plaintextbytes[i + 2] == 254)
                     {
                         Array.Resize(ref tmphwidbytes, i);
                         Array.Copy(plaintextbytes, 0, tmphwidbytes, 0, tmphwidbytes.Length);
                         Array.Resize(ref tmpuidbytes, plaintextbytes.Length - i - 3);
                         Array.Copy(plaintextbytes, i + 3, tmpuidbytes, 0, tmpuidbytes.Length);
                         break;
                     }
                 }
                 //поля запроса: учетная запись и аппаратный идентификатор устройства
                 string userid = Encoding.UTF8.GetString(tmpuidbytes);
                 string hwid   = Encoding.UTF8.GetString(tmphwidbytes);
                 //инициализируем криптодвижок для проверки подписи присланных данных
                 rsaProvider = new RSACryptoServiceProvider();
                 rsaProvider.ImportCspBlob(tmpreq.PublicKey);
                 SHA512 sha512 = new SHA512Managed();
                 //вычисляем хеш присланных данных
                 byte[]   hash = sha512.ComputeHash(plaintextbytes);
                 int      activedevicescount;
                 int      pendingdevicescount;
                 Accounts tmpacc;
                 //проверяем подпись
                 bool signcorrect = rsaProvider.VerifyData(plaintextbytes, CryptoConfig.MapNameToOID("SHA512"), tmpreq.AuthSignature);
                 if (signcorrect)
                 {
                     //подпись корректна, ищем акаунт
                     tmpacc              = dc.Accounts.First(x => x.UserID == userid && x.Valid && !x.Suspended);
                     activedevicescount  = waterdevices.Where(x => x.AccountID == tmpacc.ID && x.Valid && !x.Suspended && !x.PendingRegistration).Count();
                     pendingdevicescount = waterdevices.Where(x => x.AccountID == tmpacc.ID && x.Valid && !x.Suspended && x.PendingRegistration).Count();
                     WaterDevices tmpdev = null;
                     //пробуем найти акаунт с таким же аппаратным идентификатором, чтобы исключить дубликаты
                     try
                     {
                         tmpdev = waterdevices.Where(x => x.HardwareID == hwid /* && x.AccountID == tmpacc.ID && x.Valid && !x.Suspended*/).First();
                         //если устройство нашлось и зарегистрировано, отсылаем содержимое лицензии
                         if (!tmpdev.PendingRegistration)
                         {
                             authresp = Deserialize <WaterDeviceRegistrationResponse>(tmpdev.RegistrationResponse);
                         }
                         else
                         //если устройство нашлось и ожидает регистрации
                         {
                             authresp.Signature    = "";
                             authresp.AuthResponse = "OK_PENDING";
                         }
                     }
                     catch
                     {
                     }
                     //если в базе нет устройства
                     if (tmpdev == null)
                     {
                         //есть неиспользованные лицензии, формируем запись нового устройства
                         if (activedevicescount < tmpacc.DeviceCountLimit)
                         {
                             WaterDevices newwaterdevice = new WaterDevices()
                             {
                                 CustomerServiceContactPhone = tmpacc.DefaultContactPhone,
                                 HardwareID          = hwid,
                                 AccountID           = tmpacc.ID,
                                 LocationAddress     = "",
                                 LocationLatitude    = 0,
                                 LocationLongtitude  = 0,
                                 ProductName         = "Вода питьевая",
                                 PendingRegistration = true,
                                 PRICE_PER_ITEM_MDE  = 500,
                                 PublicKey           = tmpreq.PublicKey,
                                 RegistrationRequest = requestxml,
                                 Suspended           = false,
                                 Valid = true,
                                 RegistrationDateTime              = 0,
                                 RegistrationRequestDateTime       = cdt,
                                 RegistrationDateTimeStr           = "",
                                 RegistrationRequestDateTimeStr    = cdtstr,
                                 RegistrationResponse              = "",
                                 PendingRegistrationGUID           = Guid.NewGuid().ToString(),
                                 PendingRegConfirmed               = false,
                                 PendingRegConfirmationIP          = "",
                                 PendingRegConfirmationDateTime    = 0,
                                 PendingRegConfirmationDateTimeStr = ""
                             };
                             //добавляем запись в БД
                             waterdevices.Add(newwaterdevice);
                             dc.SaveChanges();
                             Logger.AccountLog(Request.UserHostAddress, "Принята заявка на регистрацию нового устройства", newwaterdevice.HardwareID, tmpacc.ID);
                             Logger.SystemLog(Request.UserHostAddress, "Регистрация нового устройства", tmpacc.UserID, "Server");
                             MailMessage mail = new MailMessage();
                             mail.To.Add(tmpacc.UserID);
                             mail.From            = new MailAddress(WWWVars.MailFromAddress, WWWVars.EMailDisplayName, Encoding.UTF8);
                             mail.Subject         = WWWVars.RegDeviceMailSubject;
                             mail.SubjectEncoding = Encoding.UTF8;
                             string confirmurl = output + "/User/ConfirmRegistration.aspx?wvdid=" + newwaterdevice.ID.ToString() + "&prg=" +
                                                 newwaterdevice.PendingRegistrationGUID;
                             mail.Body = "Добрый день, уважаемый\\ая сэр\\мадам.<br>" +
                                         "<p>В систему добавлена заявка на регистрацию нового устройства. Для подтверждения пройдите по ссылке ниже:<br>" +
                                         "<a href=\"" + confirmurl + "\">" + confirmurl + "</a><br>" +
                                         "<b><font color=\"red\">Внимание: Ссылка будет активной в течение 3 часов!<br> Если вы не завершите регистрацию до " + DateTime.Now.AddHours(3).ToString("dd.MM.yyyy HH:mm:ss") +
                                         ", процедуру регистрации необходимо будет повторить на устройстве с использованием файла лицензии.</font></b><br></p>" +
                                         "=======================================<br>" +
                                         "письмо сгенерировано автоматически, отвечать на него не нужно. Контакты для обратной связи см. на сайте: <br>" + output;
                             mail.BodyEncoding = Encoding.UTF8;
                             mail.IsBodyHtml   = true;
                             mail.Priority     = MailPriority.High;
                             SmtpClient client = new SmtpClient
                             {
                                 UseDefaultCredentials = !WWWVars.MailUseSMTPAuth,
                                 Port      = WWWVars.SMTPPort,
                                 Host      = WWWVars.SMTPHost,
                                 EnableSsl = WWWVars.SMTPUseSSL,
                             };
                             if (!client.UseDefaultCredentials)
                             {
                                 client.Credentials = new System.Net.NetworkCredential(WWWVars.MailLogin, WWWVars.MailPassword);
                             }
                             client.Send(mail);
                             authresp.AuthResponse = "OK_PENDING";
                             Logger.AccountLog("Server", "Отправлено электронное письмо о регистрации нового устройства", tmpacc.UserID, tmpacc.ID);
                             Logger.SystemLog("Server", "Отправлено письмо о регистрации нового устройства", tmpacc.UserID, "Server");
                         }
                         //превышен лимит лицензий, отказ регистрации
                         else
                         {
                             authresp.Signature    = "";
                             authresp.AuthResponse = "DENY_OVERQUOTA";
                         }
                     }
                     else
                     //устройство уже есть в БД, ничего не делаем
                     {
                     }
                 }
                 else
                 //подпись некорректна, отказ регистрации
                 {
                     authresp.Signature    = "";
                     authresp.AuthResponse = "DENY_SIGNATURE_MISMATCH";
                 }
                 //сохраняем изменения в БД
                 dbContextTransaction.Commit();
             }
             catch (Exception ex)
             {
                 //что-то пошло не так, ошибка на любом этапе, прерываем регистрацию, откатываем изменения в БД
                 if (ex.HResult != -2146233040)
                 {
                     dbContextTransaction.Rollback();
                     authresp.Signature    = "";
                     authresp.AuthResponse = "ABORT CODE: " + ex.HResult.ToString();
                     Logger.SystemLog(Request.UserHostAddress, "Ошибка при регистрации устройства: " + ex.Message, "", "Server");
                 }
             }
             finally
             {
                 //Сериализуем объект авторизации в XML документ
                 var xs  = new XmlSerializer(authresp.GetType());
                 var xml = new Utf8StringWriter();
                 xs.Serialize(xml, authresp);
                 //переводим в массив байт, кодируем в Base64 для передачи по http
                 byte[] xmlbytes       = Encoding.UTF8.GetBytes(xml.ToString());
                 string xmlbytesbase64 = Convert.ToBase64String(xmlbytes);
                 //отсылаем ответ устройству
                 Response.Clear();
                 Response.Write(xmlbytesbase64);
             }
         }
     }
 }