public ActionResult Subscribe(StripeTokenResponse data) { var myCustomer = new StripeCustomerCreateOptions(); myCustomer.Email = User.Identity.Name; myCustomer.SourceToken = data.StripeToken; myCustomer.PlanId = ConfigurationManager.AppSettings["stripe:plan"]; // only if you have a plan myCustomer.TaxPercent = 0; // only if you are passing a plan, this tax percent will be added to the price. Metrics.Info($"Creating subscription for {myCustomer.Email} {myCustomer.SourceToken} {myCustomer.PlanId}"); var customerService = new StripeCustomerService(ConfigurationManager.AppSettings["stripe:token_secret"]); StripeCustomer stripeCustomer = customerService.Create(myCustomer); using (var db = new Email2SmsContext()) { var userId = GetUserId(); var row = db.Subscriptions.FirstOrDefault(f => f.User == userId); if (row == null) { row = new Subscription { User = userId }; db.Subscriptions.Add(row); } row.StripeCustomer = stripeCustomer.Id; row.LastInvoiceUtc = DateTime.UtcNow; db.SaveChanges(); } return(Redirect("~/home/setup")); }
public object MessageCallback(TwilioCallback data) { if (data.MessageStatus == "delivered" && TwilioProvider.HasTwilio()) { Metrics.Info($"Callback: delivered message {data.MessageSid}"); using (var db = new Email2SmsContext()) { var twilio = TwilioProvider.GetTwilio(); Message msg = null; for (int i = 0; i < 10; i++) { msg = twilio.GetMessage(data.MessageSid); Metrics.Info($"Message {data.MessageSid} price: {msg.Price}"); if (msg.Price < 0) { break; } Thread.Sleep(1000); } if (msg.Price == 0) { Metrics.Error($"Couldn't get price for message {data.MessageSid}"); throw new ApplicationException("Couldn't get price"); } using (var scope = db.Database.BeginTransaction()) { try { var dbMsg = db.InvoiceItems .Where(f => f.Sid == data.MessageSid) .Select(f => new { Msg = f, Sub = f.SendTo.Subscription }).FirstOrDefault(); if (dbMsg != null && !dbMsg.Msg.Price.HasValue) { dbMsg.Msg.Price = -msg.Price; db.SaveChanges(); scope.Commit(); } } catch (Exception) { scope.Rollback(); throw; } } } } return("OK"); }
public ActionResult History() { using (var db = new Email2SmsContext()) { var userId = GetUserId(); return(View(db.InvoiceItems.Where(f => f.SendTo.Subscription.User == userId).Select(f => new HistoryRow { Phone = f.SendTo.Address, Message = f.Message.Text, When = f.SendTime, Cost = f.Price }) .OrderByDescending(f => f.When) .Take(50) .ToArray())); } }
public ActionResult Setup() { Metrics.Info("Tracing information"); using (var db = new Email2SmsContext()) { var userId = GetUserId(); var data = db.Subscriptions.Where(f => f.User == userId) .Select(f => new { f, Phones = f.Phones }) .AsNoTracking() .FirstOrDefault(); return(View(new SetupInfoViewModel { Email = User.Identity.Name, Customer = data?.f, Phones = data?.Phones?.Where(f => f.Active)?.Select(f => f.Address)?.ToArray() ?? new string[0], Inactive = data?.Phones?.Where(f => !f.Active)?.Select(f => f.Address)?.ToArray() ?? new string[0] })); } }
private object InvoiceCreated(StripeCreateInvoice invoiceData) { using (var db = new Email2SmsContext()) { var sub = db.Subscriptions.Where(f => f.StripeCustomer == invoiceData.Customer).FirstOrDefault(); if (sub == null) { Metrics.Error($"Tried to create invoice for {invoiceData.Customer}, who doesn't seem to be a subscriber"); return("Not Known"); } var end = DateTimeOffset.FromUnixTimeSeconds(invoiceData.Period_End).UtcDateTime; var charges = db.InvoiceItems.Where( f => f.SendTime < end && f.SendTime >= f.SendTo.Subscription.LastInvoiceUtc && f.SendTo.Subscription.StripeCustomer == invoiceData.Customer ).Select(f => f.Price).ToArray(); var sum = (int)((charges.Sum() ?? 0.0M) * 100); if (sum > 0) { var stripe = new StripeInvoiceItemService(ConfigurationManager.AppSettings["stripe:token_secret"]); Metrics.Info($"Charging {sub.StripeCustomer} ${charges.Sum().Value} for {charges.Length} messages"); var response = stripe.Create(new StripeInvoiceItemCreateOptions { Amount = sum, Currency = "usd", CustomerId = invoiceData.Customer, Description = $"Messages x {charges.Length}" }); } sub.LastInvoiceUtc = end; db.SaveChanges(); } return("OK"); }
public object Post(EmailMessage message) { try { using (var db = new Email2SmsContext()) { var msgLog = GetMessageLog(message); db.MessageLog.Add(msgLog); db.SaveChanges(); string plainMessage = message.plain; var locationMatch = Regex.Match(plainMessage, "(4\\d\\.\\d+)[N ,]+[W\\- ]?(12\\d+\\.\\d+)", RegexOptions.IgnoreCase); if (locationMatch.Success) { plainMessage += string.Format(" http://maps.google.com/?q={0},-{1}", locationMatch.Groups[1].Value, locationMatch.Groups[2].Value); } // A quick in-memory duplicate check backed up by a database dupe check in case we've been recycled. DateTime duplicateTime = DateTime.UtcNow.AddMinutes(-5); lock (cacheLock) { if (messageCache.Contains(plainMessage)) { return("Duplicate"); } else { messageCache.Add(plainMessage, DateTime.UtcNow, DateTimeOffset.UtcNow.AddMinutes(5)); } } if (db.InvoiceItems.Any(f => f.Message.Text == plainMessage && f.SendTime > duplicateTime)) { return("Duplicate"); } var list = db.Phones.Where(f => f.Active).ToList(); if (TwilioProvider.HasTwilio()) { var twilioClient = TwilioProvider.GetTwilio(); var twilioFroms = TwilioProvider.GetNumbers(); var fromIndex = 0; var twilioCallback = ConfigurationManager.AppSettings["twilio:callback"]; foreach (var item in list) { var twilioMsg = twilioClient.SendMessage(twilioFroms[fromIndex], item.Address, plainMessage, twilioCallback); fromIndex = (fromIndex + 1) % twilioFroms.Length; db.InvoiceItems.Add(new InvoiceLog { SendTo = item, Sid = twilioMsg.Sid, SendTime = DateTime.UtcNow, Message = msgLog }); db.SaveChanges(); } } } } catch (Exception ex) { Metrics.Exception(ex); } return("OK"); }
public ActionResult Setup(string phones) { string[] list = phones.Split('\n').Select(f => f.Trim()).Distinct().Where(f => !string.IsNullOrWhiteSpace(f)).ToArray(); string message = null; for (int i = 0; i < list.Length; i++) { if (list[i].Length != 10 || !Regex.IsMatch(list[i], "\\d{10}")) { message = (message ?? "Error: ") + " Don't understand " + list[i]; } } if (message != null) { Metrics.Info(ViewBag.Message); ViewBag.Message = message; return(Setup()); } using (var db = new Email2SmsContext()) { var userId = GetUserId(); var dupes = db.Phones .Where(f => f.Subscription.User != userId) .Select(f => f.Address) .ToArray() .Intersect(list) .ToArray(); if (dupes.Length > 0) { ViewBag.Message = "Error: Phone numbers already used by someone else: " + string.Join(", ", dupes); Metrics.Info(ViewBag.Message); return(Setup()); } var sub = db.Subscriptions.Include(f => f.Phones).SingleOrDefault(f => f.User == userId); foreach (var p in list) { var match = sub.Phones.FirstOrDefault(f => f.Address == p); if (match == null) { if (TwilioProvider.HasTwilio()) { var client = TwilioProvider.GetTwilio(); Metrics.Info($"Sending welcome text to {p}"); client.SendMessage(TwilioProvider.GetNumbers().First(), p, "This number will now receive SAR pages. [email protected]"); } sub.Phones.Add(new Phone { Active = true, Address = p, Subscription = sub }); } else if (match.Active == false) { Metrics.Info($"Marking {p} as active"); match.Active = true; } } foreach (var p in sub.Phones.ToArray()) { var match = list.FirstOrDefault(f => f == p.Address); if (match == null) { if (db.InvoiceItems.Any(f => f.PhoneId == p.Id)) { Metrics.Info($"Marking phone {p.Address} inactive"); p.Active = false; } else { Metrics.Info($"Removing unused phone {match}"); sub.Phones.Remove(p); db.Phones.Remove(p); } } else { // Already marked active in above loop } } db.SaveChanges(); } ViewBag.Message = $"Saved {list.Count()} numbers"; return(Setup()); }