Update subscription_creator to use the new strategy.
When creating subscriptions through the client, detect when the returned error
is saying the account already has a subscription, or the subscription already
exists in stripe.
Add an UpdateSubscription function that will update a subscription through the
API.
Update our subscription_creator listener to listen for profile creation and
login verification messages. This mainly involved fixing the constants (the
system, model, and topic) that the listener for profile creation was listening
for. It also meant adding a new updateMessageHandler that listens for login
verification, tries to create a subscription that has the user ID and email of
the login that was verified, and if a subscription already exists, updates it
instead to use the email address that was just verified. This will ensure that
users get their receipts automatically emailed to them by Stripe.
4 "code.secondbit.org/uuid.hg"
7 func stripeSubscriptionInMemstore(stripeSubscription string, m *Memstore) bool {
8 for _, sub := range m.subscriptions {
9 if sub.StripeSubscription == stripeSubscription {
16 func (m *Memstore) CreateSubscription(sub Subscription) error {
17 m.subscriptionLock.Lock()
18 defer m.subscriptionLock.Unlock()
20 if _, ok := m.subscriptions[sub.UserID.String()]; ok {
21 return ErrSubscriptionAlreadyExists
23 if stripeSubscriptionInMemstore(sub.StripeSubscription, m) {
24 return ErrStripeSubscriptionAlreadyExists
26 m.subscriptions[sub.UserID.String()] = sub
30 func (m *Memstore) UpdateSubscription(id uuid.ID, change SubscriptionChange) error {
32 return ErrSubscriptionChangeEmpty
35 m.subscriptionLock.Lock()
36 defer m.subscriptionLock.Unlock()
38 s, ok := m.subscriptions[id.String()]
40 return ErrSubscriptionNotFound
42 if change.StripeSubscription != nil {
43 if stripeSubscriptionInMemstore(*change.StripeSubscription, m) {
44 return ErrStripeSubscriptionAlreadyExists
48 m.subscriptions[id.String()] = s
52 func (m *Memstore) DeleteSubscription(id uuid.ID) error {
53 m.subscriptionLock.Lock()
54 defer m.subscriptionLock.Unlock()
56 _, ok := m.subscriptions[id.String()]
58 return ErrSubscriptionNotFound
60 delete(m.subscriptions, id.String())
64 func (m *Memstore) GetSubscriptions(ids []uuid.ID) (map[string]Subscription, error) {
66 return map[string]Subscription{}, ErrNoSubscriptionID
68 m.subscriptionLock.RLock()
69 defer m.subscriptionLock.RUnlock()
71 result := map[string]Subscription{}
73 for _, id := range ids {
74 s, ok := m.subscriptions[id.String()]
78 result[s.UserID.String()] = s
83 func (m *Memstore) GetSubscriptionStats() (SubscriptionStats, error) {
84 m.subscriptionLock.RLock()
85 defer m.subscriptionLock.RUnlock()
87 stats := SubscriptionStats{
88 Plans: map[string]int64{},
91 for _, subscription := range m.subscriptions {
93 stats.Plans[subscription.Plan]++
95 if subscription.Canceling {
98 if subscription.Status == "past_due" || subscription.Status == "unpaid" {