Exemple #1
0
        public async Task <IHttpActionResult> BuyFinish(string id, string state)
        {
            var hostedPage = (await _chargeBee.HostedPage.Retrieve(id).Request()).HostedPage;

            if (hostedPage.State != cbm.HostedPage.StateEnum.Succeeded)
            {
                // We should only get here if the signup was completed.
                throw new InvalidOperationException("Asked to complete signup for subscription when checkout did not complete.");
            }

            var passThruContent = JsonConvert.DeserializeObject <BuyPassThruContent>(hostedPage.PassThruContent);

            ChargeBeeUtilities.ParseCustomerId(hostedPage.Content.Subscription.CustomerId, out var accountType, out var accountId);

            ChangeSummary changes;

            using (var context = new ShipHubContext()) {
                changes = await context.BulkUpdateSubscriptions(new[] {
                    new SubscriptionTableType()
                    {
                        AccountId    = accountId,
                        State        = SubscriptionState.Subscribed.ToString(),
                        TrialEndDate = null,
                        Version      = hostedPage.Content.Subscription.ResourceVersion.Value,
                    },
                });
            }

            if (!changes.IsEmpty)
            {
                await _queueClient.NotifyChanges(changes);
            }

            if (passThruContent.AnalyticsId != null)
            {
                await _mixpanelClient.TrackAsync(
                    "Purchased",
                    passThruContent.AnalyticsId,
                    new {
                    plan        = hostedPage.Content.Subscription.PlanId,
                    customer_id = hostedPage.Content.Subscription.CustomerId,
                    // These refer to the account performing the action, which in the case of
                    // an org subscription, is different than the account being purchased.
                    _github_id    = passThruContent.ActorId,
                    _github_login = passThruContent.ActorLogin,
                });
            }

            var hashParams = new ThankYouPageHashParameters()
            {
                Value  = hostedPage.Content.Subscription.PlanUnitPrice.Value / 100,
                PlanId = hostedPage.Content.Subscription.PlanId,
            };
            var hashParamBase64 = Convert.ToBase64String(Encoding.UTF8.GetBytes(
                                                             JsonConvert.SerializeObject(hashParams, GitHubSerialization.JsonSerializerSettings)));

            return(Redirect($"https://{_configuration.WebsiteHostName}/signup-thankyou.html#{WebUtility.UrlEncode(hashParamBase64)}"));
        }
        public async Task HandleSubscriptionStateChange(ChargeBeeWebhookPayload payload)
        {
            var           accountId = ChargeBeeUtilities.AccountIdFromCustomerId(payload.Content.Customer.Id);
            ChangeSummary changes;
            var           tasks = new List <Task>();

            using (var context = new ShipHubContext()) {
                var sub = await context.Subscriptions
                          .AsNoTracking()
                          .SingleOrDefaultAsync(x => x.AccountId == accountId);

                if (sub == null)
                {
                    // We only care to update subscriptions we've already sync'ed.  This case often happens
                    // in development - e.g., you might be testing subscriptions on your local machine, and
                    // chargebee delivers webhook calls to shiphub-dev about subscriptions it doesn't know
                    // about yet.
                    return;
                }

                long incomingVersion;

                if (payload.EventType == "customer_deleted")
                {
                    incomingVersion = payload.Content.Customer.ResourceVersion;
                }
                else
                {
                    incomingVersion = payload.Content.Subscription.ResourceVersion;
                }

                if (incomingVersion <= sub.Version)
                {
                    // We're receiving webhook events out-of-order (which can happen due to re-delivery),
                    // so ignore.
                    return;
                }

                sub.Version = incomingVersion;
                var beforeState = sub.State;

                if (payload.EventType.Equals("subscription_deleted") ||
                    payload.EventType.Equals("customer_deleted"))
                {
                    sub.State        = SubscriptionState.NotSubscribed;
                    sub.TrialEndDate = null;
                }
                else
                {
                    switch (payload.Content.Subscription.Status)
                    {
                    case "in_trial":
                        sub.State        = SubscriptionState.InTrial;
                        sub.TrialEndDate = DateTimeOffset.FromUnixTimeSeconds((long)payload.Content.Subscription.TrialEnd);
                        break;

                    case "active":
                    case "non_renewing":
                    case "future":
                        sub.State        = SubscriptionState.Subscribed;
                        sub.TrialEndDate = null;
                        break;

                    case "cancelled":
                        sub.State        = SubscriptionState.NotSubscribed;
                        sub.TrialEndDate = null;
                        break;
                    }
                }

                changes = await context.BulkUpdateSubscriptions(new[] {
                    new SubscriptionTableType()
                    {
                        AccountId    = sub.AccountId,
                        State        = sub.StateName,
                        TrialEndDate = sub.TrialEndDate,
                        Version      = sub.Version,
                    }
                });
            }

            if (!changes.IsEmpty)
            {
                await _queueClient.NotifyChanges(changes);
            }

            await Task.WhenAll(tasks);
        }