Exemple #1
0
        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"));
        }
Exemple #2
0
        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");
        }
Exemple #3
0
        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()));
            }
        }
Exemple #4
0
        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]
                }));
            }
        }
Exemple #5
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");
        }
Exemple #6
0
        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");
        }
Exemple #7
0
        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());
        }