public async Task <ActionResult> Index(string firstName, string lastName, string id)
        {
            Braintree.Customer customer = await paaPaymentService.UpdateCustomerAsync(firstName, lastName, id);

            ViewBag.Message = "Updated Successfully";
            return(View(customer));
        }
        public ActionResult Index()
        {
            string merchantID  = System.Configuration.ConfigurationManager.AppSettings["Braintree.MerchantID"];
            string environment = System.Configuration.ConfigurationManager.AppSettings["Braintree.Environment"];
            string publickey   = System.Configuration.ConfigurationManager.AppSettings["Braintree.PublicKey"];
            string privatekey  = System.Configuration.ConfigurationManager.AppSettings["Braintree.PriavteKey"];

            Braintree.BraintreeGateway gateway = new Braintree.BraintreeGateway(environment, merchantID, publickey, privatekey);

            var customerGateway = gateway.Customer;

            Braintree.CustomerSearchRequest query = new Braintree.CustomerSearchRequest();
            query.Email.Is(User.Identity.Name);
            var matchedCustomers = customerGateway.Search(query);

            Braintree.Customer customer = null;
            if (matchedCustomers.Ids.Count == 0)
            {
                Braintree.CustomerRequest newCustomer = new Braintree.CustomerRequest();
                newCustomer.Email = User.Identity.Name;

                var result = customerGateway.Create(newCustomer);
                customer = result.Target;
            }
            else
            {
                customer = matchedCustomers.FirstItem;
            }
            return(View(customer));
        }
        // GET: Checkout
        public ActionResult Index()
        {
            Models.CheckoutDetails details = new Models.CheckoutDetails();
            Guid cartID = Guid.Parse(Request.Cookies["cartID"].Value);

            details.CurrentCart = db.Carts.Find(cartID);
            details.Addresses   = new Braintree.Address[0];
            if (User.Identity.IsAuthenticated)
            {
                string merchantId  = System.Configuration.ConfigurationManager.AppSettings["Braintree.MerchantId"];
                string environment = System.Configuration.ConfigurationManager.AppSettings["Braintree.Environment"];
                string publicKey   = System.Configuration.ConfigurationManager.AppSettings["Braintree.PublicKey"];
                string privateKey  = System.Configuration.ConfigurationManager.AppSettings["Braintree.PrivateKey"];
                Braintree.BraintreeGateway gateway = new Braintree.BraintreeGateway(environment, merchantId, publicKey, privateKey);

                var customerGateway = gateway.Customer;
                Braintree.CustomerSearchRequest query = new Braintree.CustomerSearchRequest();
                query.Email.Is(User.Identity.Name);
                var matchedCustomers        = customerGateway.Search(query);
                Braintree.Customer customer = null;
                if (matchedCustomers.Ids.Count == 0)
                {
                    Braintree.CustomerRequest newCustomer = new Braintree.CustomerRequest();
                    newCustomer.Email = User.Identity.Name;

                    var result = customerGateway.Create(newCustomer);
                    customer = result.Target;
                }
                else
                {
                    customer = matchedCustomers.FirstItem;
                }

                details.Addresses = customer.Addresses;
            }
            return(View(details));
        }
Example #4
0
        public async Task <IActionResult> Register(RegisterViewModel model)
        {
            if (ModelState.IsValid)
            {
                BoatChartesUser newUser = new BoatChartesUser
                {
                    UserName    = model.UserName,
                    Email       = model.Email,
                    FirstName   = model.FirstName,
                    LastName    = model.LastName,
                    PhoneNumber = model.PhoneNumber
                };
                IdentityResult creationResult = await this._signInManager.UserManager.CreateAsync(newUser);

                if (creationResult.Succeeded)
                {
                    IdentityResult passwordResult = await this._signInManager.UserManager.AddPasswordAsync(newUser, model.Password);

                    if (passwordResult.Succeeded)
                    {
                        Braintree.CustomerSearchRequest search = new Braintree.CustomerSearchRequest();
                        search.Email.Is(model.Email);
                        var searchResult = await _braintreeGateway.Customer.SearchAsync(search);

                        if (searchResult.Ids.Count == 0)
                        {
                            //create a new Braintree customer
                            await _braintreeGateway.Customer.CreateAsync(new Braintree.CustomerRequest
                            {
                                Email     = model.Email,
                                FirstName = model.FirstName,
                                LastName  = model.LastName,
                                Phone     = model.PhoneNumber
                            });
                        }
                        else
                        {
                            //update the existing Braintree customer
                            Braintree.Customer existingCustomer = searchResult.FirstItem;
                            await _braintreeGateway.Customer.UpdateAsync(existingCustomer.Id, new Braintree.CustomerRequest
                            {
                                FirstName = model.FirstName,
                                LastName  = model.LastName,
                                Phone     = model.PhoneNumber
                            });
                        }


                        var confirmationToken = await _signInManager.UserManager.GenerateEmailConfirmationTokenAsync(newUser);

                        confirmationToken = System.Net.WebUtility.UrlEncode(confirmationToken);

                        string     currentUrl      = Request.GetDisplayUrl();               //This will get me the URL for the current request
                        System.Uri uri             = new Uri(currentUrl);                   //This will wrap it in a "URI" object so I can split it into parts
                        string     confirmationUrl = uri.GetLeftPart(UriPartial.Authority); //This gives me just the scheme + authority of the URI
                        confirmationUrl += "/account/confirm?id=" + confirmationToken + "&userId=" + System.Net.WebUtility.UrlEncode(newUser.Id);


                        await this._signInManager.SignInAsync(newUser, false);

                        var emailResult = await this._emailService.SendEmailAsync(
                            model.Email,
                            "Welcome to My Boat!",
                            "<p>Thanks for signing up, " + model.UserName + "!</p><p><a href=\"" + confirmationUrl + "\">Confirm your account<a></p>",
                            "Thanks for signing up, " + model.UserName + "!"
                            );

                        if (!emailResult.Success)
                        {
                            throw new Exception(string.Join(',', emailResult.Errors.Select(x => x.Message)));
                        }
                        return(RedirectToAction("Index", "Home"));
                    }
                    else
                    {
                        foreach (var error in passwordResult.Errors)
                        {
                            ModelState.AddModelError(error.Code, error.Description);
                        }
                    }
                }
                else
                {
                    foreach (var error in creationResult.Errors)
                    {
                        ModelState.AddModelError(error.Code, error.Description);
                    }
                }
            }
            return(View());
        }
Example #5
0
 public ActionResult UpdateAddress(string firstName, string lastName, string id)
 {
     Braintree.Customer customer = guitarStorePaymentService.UpdateCustomer(firstName, lastName, id);
     ViewBag.Message = "Updated Succesfully!";
     return(View(customer));
 }
        public async Task <IActionResult> Index(ShippingViewModel model)
        {
            await SetupViewAsync(model);

            System.Text.RegularExpressions.Regex regex = new System.Text.RegularExpressions.Regex(@"^\d{5}(?:[-\s]\d{4})?$");
            if (string.IsNullOrEmpty(model.ShippingZipCode) || !regex.IsMatch(model.ShippingZipCode))
            {
                ModelState.AddModelError("ZipCode", "Invalid ZipCode");
            }

            if (ModelState.IsValid)
            {
                Braintree.CustomerSearchRequest customerSearch = new Braintree.CustomerSearchRequest();
                customerSearch.Email.Is(model.Email);
                Braintree.Customer customer = null;
                var customers = await _braintreeGateway.Customer.SearchAsync(customerSearch);

                if (customers.Ids.Any())
                {
                    customer = customers.FirstItem;
                }
                else
                {
                    Braintree.CustomerRequest newCustomer = new Braintree.CustomerRequest
                    {
                        Email = model.Email
                    };
                    var creationResult = await _braintreeGateway.Customer.CreateAsync(newCustomer);

                    customer = creationResult.Target;
                }
                if (string.IsNullOrEmpty(model.CardToken))
                {
                    Braintree.CreditCard card = null;
                    if (customer.CreditCards.Any())
                    {
                        string lastFour = new string(model.CreditCardNumber.Skip(model.CreditCardNumber.Length - 4).ToArray());

                        card = customer.CreditCards.FirstOrDefault(
                            x => x.ExpirationMonth == model.ExpirationMonth &&
                            x.ExpirationYear == model.ExpirationYear &&
                            x.LastFour == lastFour);
                    }
                    if (card == null)
                    {
                        Braintree.CreditCardRequest newCard = new Braintree.CreditCardRequest
                        {
                            CustomerId      = customer.Id,
                            CardholderName  = model.CreditCardName,
                            CVV             = model.CreditCardVerificationValue,
                            ExpirationMonth = model.ExpirationMonth,
                            ExpirationYear  = model.ExpirationYear,
                            Number          = model.CreditCardNumber
                        };
                        var creationResult = await _braintreeGateway.CreditCard.CreateAsync(newCard);

                        card            = creationResult.Target;
                        model.CardToken = card.Token;
                    }
                }

                Braintree.TransactionRequest saleRequest = new Braintree.TransactionRequest();
                saleRequest.Amount = model.CartLineItem.Sum(x => (x.ProductConfiguration.Product.UnitPrice * x.Quantity ?? .99m));

                saleRequest.CustomerId         = customer.Id;
                saleRequest.PaymentMethodToken = model.CardToken;
                saleRequest.BillingAddress     = new Braintree.AddressRequest
                {
                    StreetAddress      = model.BillingAddress,
                    PostalCode         = model.BillingZipCode,
                    Region             = model.BillingState,
                    Locality           = model.BillingCity,
                    CountryName        = "United States of America",
                    CountryCodeAlpha2  = "US",
                    CountryCodeAlpha3  = "USA",
                    CountryCodeNumeric = "840"
                };

                var result = await _braintreeGateway.Transaction.SaleAsync(saleRequest);

                if (result.IsSuccess())
                {
                    //If model state is valid convert to order and show reciept
                    return(this.RedirectToAction("Index", "Receipt"));
                }

                foreach (var error in result.Errors.All())
                {
                    ModelState.AddModelError(error.Code.ToString(), error.Message);
                }
            }
            return(View(model));
        }
Example #7
0
        public async Task <bool> UpdatePaymentMethodAsync(ISubscriber subscriber, PaymentMethodType paymentMethodType,
                                                          string paymentToken)
        {
            if (subscriber == null)
            {
                throw new ArgumentNullException(nameof(subscriber));
            }

            if (subscriber.Gateway.HasValue && subscriber.Gateway.Value != GatewayType.Stripe)
            {
                throw new GatewayException("Switching from one payment type to another is not supported. " +
                                           "Contact us for assistance.");
            }

            var createdCustomer = false;

            Braintree.Customer braintreeCustomer        = null;
            string             stipeCustomerSourceToken = null;
            var stripeCustomerMetadata = new Dictionary <string, string>();
            var stripePaymentMethod    = paymentMethodType == PaymentMethodType.Card ||
                                         paymentMethodType == PaymentMethodType.BankAccount;

            var      cardService     = new CardService();
            var      bankSerice      = new BankAccountService();
            var      customerService = new CustomerService();
            Customer customer        = null;

            if (!string.IsNullOrWhiteSpace(subscriber.GatewayCustomerId))
            {
                customer = await customerService.GetAsync(subscriber.GatewayCustomerId);

                if (customer.Metadata?.Any() ?? false)
                {
                    stripeCustomerMetadata = customer.Metadata;
                }
            }

            var hadBtCustomer = stripeCustomerMetadata.ContainsKey("btCustomerId");

            if (stripePaymentMethod)
            {
                stipeCustomerSourceToken = paymentToken;
            }
            else if (paymentMethodType == PaymentMethodType.PayPal)
            {
                if (hadBtCustomer)
                {
                    var pmResult = await _btGateway.PaymentMethod.CreateAsync(new Braintree.PaymentMethodRequest
                    {
                        CustomerId         = stripeCustomerMetadata["btCustomerId"],
                        PaymentMethodNonce = paymentToken
                    });

                    if (pmResult.IsSuccess())
                    {
                        var customerResult = await _btGateway.Customer.UpdateAsync(
                            stripeCustomerMetadata["btCustomerId"], new Braintree.CustomerRequest
                        {
                            DefaultPaymentMethodToken = pmResult.Target.Token
                        });

                        if (customerResult.IsSuccess() && customerResult.Target.PaymentMethods.Length > 0)
                        {
                            braintreeCustomer = customerResult.Target;
                        }
                        else
                        {
                            await _btGateway.PaymentMethod.DeleteAsync(pmResult.Target.Token);

                            hadBtCustomer = false;
                        }
                    }
                    else
                    {
                        hadBtCustomer = false;
                    }
                }

                if (!hadBtCustomer)
                {
                    var customerResult = await _btGateway.Customer.CreateAsync(new Braintree.CustomerRequest
                    {
                        PaymentMethodNonce = paymentToken,
                        Email = subscriber.BillingEmailAddress(),
                        Id    = subscriber.BraintreeCustomerIdPrefix() + subscriber.Id.ToString("N").ToLower() +
                                Utilities.CoreHelpers.RandomString(3, upper: false, numeric: false),
                        CustomFields = new Dictionary <string, string>
                        {
                            [subscriber.BraintreeIdField()] = subscriber.Id.ToString()
                        }
                    });

                    if (!customerResult.IsSuccess() || customerResult.Target.PaymentMethods.Length == 0)
                    {
                        throw new GatewayException("Failed to create PayPal customer record.");
                    }

                    braintreeCustomer = customerResult.Target;
                }
            }
            else
            {
                throw new GatewayException("Payment method is not supported at this time.");
            }

            if (stripeCustomerMetadata.ContainsKey("btCustomerId"))
            {
                if (braintreeCustomer?.Id != stripeCustomerMetadata["btCustomerId"])
                {
                    var nowSec = Utilities.CoreHelpers.ToEpocSeconds(DateTime.UtcNow);
                    stripeCustomerMetadata.Add($"btCustomerId_{nowSec}", stripeCustomerMetadata["btCustomerId"]);
                }
                stripeCustomerMetadata["btCustomerId"] = braintreeCustomer?.Id;
            }
            else if (!string.IsNullOrWhiteSpace(braintreeCustomer?.Id))
            {
                stripeCustomerMetadata.Add("btCustomerId", braintreeCustomer.Id);
            }

            try
            {
                if (customer == null)
                {
                    customer = await customerService.CreateAsync(new CustomerCreateOptions
                    {
                        Description = subscriber.BillingName(),
                        Email       = subscriber.BillingEmailAddress(),
                        SourceToken = stipeCustomerSourceToken,
                        Metadata    = stripeCustomerMetadata
                    });

                    subscriber.Gateway           = GatewayType.Stripe;
                    subscriber.GatewayCustomerId = customer.Id;
                    createdCustomer = true;
                }

                if (!createdCustomer)
                {
                    string defaultSourceId = null;
                    if (stripePaymentMethod)
                    {
                        if (paymentToken.StartsWith("btok_"))
                        {
                            var bankAccount = await bankSerice.CreateAsync(customer.Id, new BankAccountCreateOptions
                            {
                                SourceToken = paymentToken
                            });

                            defaultSourceId = bankAccount.Id;
                        }
                        else
                        {
                            var card = await cardService.CreateAsync(customer.Id, new CardCreateOptions
                            {
                                SourceToken = paymentToken,
                            });

                            defaultSourceId = card.Id;
                        }
                    }

                    foreach (var source in customer.Sources.Where(s => s.Id != defaultSourceId))
                    {
                        if (source is BankAccount)
                        {
                            await bankSerice.DeleteAsync(customer.Id, source.Id);
                        }
                        else if (source is Card)
                        {
                            await cardService.DeleteAsync(customer.Id, source.Id);
                        }
                    }

                    customer = await customerService.UpdateAsync(customer.Id, new CustomerUpdateOptions
                    {
                        Metadata      = stripeCustomerMetadata,
                        DefaultSource = defaultSourceId
                    });
                }
            }
            catch (Exception e)
            {
                if (braintreeCustomer != null && !hadBtCustomer)
                {
                    await _btGateway.Customer.DeleteAsync(braintreeCustomer.Id);
                }
                throw e;
            }

            return(createdCustomer);
        }
Example #8
0
        public async Task PurchaseOrganizationAsync(Organization org, PaymentMethodType paymentMethodType,
                                                    string paymentToken, Models.StaticStore.Plan plan, short additionalStorageGb,
                                                    short additionalSeats, bool premiumAccessAddon)
        {
            var invoiceService  = new InvoiceService();
            var customerService = new CustomerService();

            Braintree.Customer braintreeCustomer        = null;
            string             stipeCustomerSourceToken = null;
            var stripeCustomerMetadata = new Dictionary <string, string>();
            var stripePaymentMethod    = paymentMethodType == PaymentMethodType.Card ||
                                         paymentMethodType == PaymentMethodType.BankAccount;

            if (stripePaymentMethod)
            {
                stipeCustomerSourceToken = paymentToken;
            }
            else if (paymentMethodType == PaymentMethodType.PayPal)
            {
                var randomSuffix   = Utilities.CoreHelpers.RandomString(3, upper: false, numeric: false);
                var customerResult = await _btGateway.Customer.CreateAsync(new Braintree.CustomerRequest
                {
                    PaymentMethodNonce = paymentToken,
                    Email        = org.BillingEmail,
                    Id           = org.BraintreeCustomerIdPrefix() + org.Id.ToString("N").ToLower() + randomSuffix,
                    CustomFields = new Dictionary <string, string>
                    {
                        [org.BraintreeIdField()] = org.Id.ToString()
                    }
                });

                if (!customerResult.IsSuccess() || customerResult.Target.PaymentMethods.Length == 0)
                {
                    throw new GatewayException("Failed to create PayPal customer record.");
                }

                braintreeCustomer = customerResult.Target;
                stripeCustomerMetadata.Add("btCustomerId", braintreeCustomer.Id);
            }
            else
            {
                throw new GatewayException("Payment method is not supported at this time.");
            }

            var subCreateOptions = new SubscriptionCreateOptions
            {
                TrialPeriodDays = plan.TrialPeriodDays,
                Items           = new List <SubscriptionItemOption>(),
                Metadata        = new Dictionary <string, string>
                {
                    [org.GatewayIdField()] = org.Id.ToString()
                }
            };

            if (plan.StripePlanId != null)
            {
                subCreateOptions.Items.Add(new SubscriptionItemOption
                {
                    PlanId   = plan.StripePlanId,
                    Quantity = 1
                });
            }

            if (additionalSeats > 0 && plan.StripeSeatPlanId != null)
            {
                subCreateOptions.Items.Add(new SubscriptionItemOption
                {
                    PlanId   = plan.StripeSeatPlanId,
                    Quantity = additionalSeats
                });
            }

            if (additionalStorageGb > 0)
            {
                subCreateOptions.Items.Add(new SubscriptionItemOption
                {
                    PlanId   = plan.StripeStoragePlanId,
                    Quantity = additionalStorageGb
                });
            }

            if (premiumAccessAddon && plan.StripePremiumAccessPlanId != null)
            {
                subCreateOptions.Items.Add(new SubscriptionItemOption
                {
                    PlanId   = plan.StripePremiumAccessPlanId,
                    Quantity = 1
                });
            }

            Customer     customer     = null;
            Subscription subscription = null;

            try
            {
                customer = await customerService.CreateAsync(new CustomerCreateOptions
                {
                    Description = org.BusinessName,
                    Email       = org.BillingEmail,
                    SourceToken = stipeCustomerSourceToken,
                    Metadata    = stripeCustomerMetadata
                });

                subCreateOptions.CustomerId = customer.Id;
                var subscriptionService = new SubscriptionService();
                subscription = await subscriptionService.CreateAsync(subCreateOptions);
            }
            catch (Exception e)
            {
                if (customer != null)
                {
                    await customerService.DeleteAsync(customer.Id);
                }
                if (braintreeCustomer != null)
                {
                    await _btGateway.Customer.DeleteAsync(braintreeCustomer.Id);
                }
                throw e;
            }

            org.Gateway               = GatewayType.Stripe;
            org.GatewayCustomerId     = customer.Id;
            org.GatewaySubscriptionId = subscription.Id;
            org.ExpirationDate        = subscription.CurrentPeriodEnd;
        }
Example #9
0
        public async Task PurchasePremiumAsync(User user, PaymentMethodType paymentMethodType, string paymentToken,
                                               short additionalStorageGb)
        {
            var invoiceService  = new InvoiceService();
            var customerService = new CustomerService();

            var    createdStripeCustomer = false;
            string stripeCustomerId      = null;

            Braintree.Transaction braintreeTransaction = null;
            Braintree.Customer    braintreeCustomer    = null;
            var stripePaymentMethod = paymentMethodType == PaymentMethodType.Card ||
                                      paymentMethodType == PaymentMethodType.BankAccount;

            if (paymentMethodType == PaymentMethodType.BankAccount)
            {
                throw new GatewayException("Bank account payment method is not supported at this time.");
            }

            if (user.Gateway == GatewayType.Stripe && !string.IsNullOrWhiteSpace(user.GatewayCustomerId))
            {
                try
                {
                    await UpdatePaymentMethodAsync(user, paymentMethodType, paymentToken);

                    stripeCustomerId      = user.GatewayCustomerId;
                    createdStripeCustomer = false;
                }
                catch (Exception)
                {
                    stripeCustomerId = null;
                }
            }

            if (string.IsNullOrWhiteSpace(stripeCustomerId))
            {
                string stipeCustomerSourceToken = null;
                var    stripeCustomerMetadata   = new Dictionary <string, string>();

                if (stripePaymentMethod)
                {
                    stipeCustomerSourceToken = paymentToken;
                }
                else if (paymentMethodType == PaymentMethodType.PayPal)
                {
                    var randomSuffix   = Utilities.CoreHelpers.RandomString(3, upper: false, numeric: false);
                    var customerResult = await _btGateway.Customer.CreateAsync(new Braintree.CustomerRequest
                    {
                        PaymentMethodNonce = paymentToken,
                        Email        = user.Email,
                        Id           = user.BraintreeCustomerIdPrefix() + user.Id.ToString("N").ToLower() + randomSuffix,
                        CustomFields = new Dictionary <string, string>
                        {
                            [user.BraintreeIdField()] = user.Id.ToString()
                        }
                    });

                    if (!customerResult.IsSuccess() || customerResult.Target.PaymentMethods.Length == 0)
                    {
                        throw new GatewayException("Failed to create PayPal customer record.");
                    }

                    braintreeCustomer = customerResult.Target;
                    stripeCustomerMetadata.Add("btCustomerId", braintreeCustomer.Id);
                }
                else
                {
                    throw new GatewayException("Payment method is not supported at this time.");
                }

                var customer = await customerService.CreateAsync(new CustomerCreateOptions
                {
                    Description = user.Name,
                    Email       = user.Email,
                    SourceToken = stipeCustomerSourceToken,
                    Metadata    = stripeCustomerMetadata
                });

                stripeCustomerId      = customer.Id;
                createdStripeCustomer = true;
            }

            var subCreateOptions = new SubscriptionCreateOptions
            {
                CustomerId = stripeCustomerId,
                Items      = new List <SubscriptionItemOption>(),
                Metadata   = new Dictionary <string, string>
                {
                    [user.GatewayIdField()] = user.Id.ToString()
                }
            };

            subCreateOptions.Items.Add(new SubscriptionItemOption
            {
                PlanId   = PremiumPlanId,
                Quantity = 1,
            });

            if (additionalStorageGb > 0)
            {
                subCreateOptions.Items.Add(new SubscriptionItemOption
                {
                    PlanId   = StoragePlanId,
                    Quantity = additionalStorageGb
                });
            }

            var          subInvoiceMetadata = new Dictionary <string, string>();
            Subscription subscription       = null;

            try
            {
                if (!stripePaymentMethod)
                {
                    var previewInvoice = await invoiceService.UpcomingAsync(new UpcomingInvoiceOptions
                    {
                        CustomerId        = stripeCustomerId,
                        SubscriptionItems = ToInvoiceSubscriptionItemOptions(subCreateOptions.Items)
                    });

                    await customerService.UpdateAsync(stripeCustomerId, new CustomerUpdateOptions
                    {
                        AccountBalance = -1 * previewInvoice.AmountDue
                    });

                    if (braintreeCustomer != null)
                    {
                        var btInvoiceAmount   = (previewInvoice.AmountDue / 100M);
                        var transactionResult = await _btGateway.Transaction.SaleAsync(
                            new Braintree.TransactionRequest
                        {
                            Amount     = btInvoiceAmount,
                            CustomerId = braintreeCustomer.Id,
                            Options    = new Braintree.TransactionOptionsRequest
                            {
                                SubmitForSettlement = true,
                                PayPal = new Braintree.TransactionOptionsPayPalRequest
                                {
                                    CustomField = $"{user.BraintreeIdField()}:{user.Id}"
                                }
                            },
                            CustomFields = new Dictionary <string, string>
                            {
                                [user.BraintreeIdField()] = user.Id.ToString()
                            }
                        });

                        if (!transactionResult.IsSuccess())
                        {
                            throw new GatewayException("Failed to charge PayPal customer.");
                        }

                        braintreeTransaction = transactionResult.Target;
                        subInvoiceMetadata.Add("btTransactionId", braintreeTransaction.Id);
                        subInvoiceMetadata.Add("btPayPalTransactionId",
                                               braintreeTransaction.PayPalDetails.AuthorizationId);
                    }
                    else
                    {
                        throw new GatewayException("No payment was able to be collected.");
                    }
                }

                var subscriptionService = new SubscriptionService();
                subscription = await subscriptionService.CreateAsync(subCreateOptions);

                if (!stripePaymentMethod && subInvoiceMetadata.Any())
                {
                    var invoices = await invoiceService.ListAsync(new InvoiceListOptions
                    {
                        SubscriptionId = subscription.Id
                    });

                    var invoice = invoices?.FirstOrDefault();
                    if (invoice == null)
                    {
                        throw new GatewayException("Invoice not found.");
                    }

                    await invoiceService.UpdateAsync(invoice.Id, new InvoiceUpdateOptions
                    {
                        Metadata = subInvoiceMetadata
                    });
                }
            }
            catch (Exception e)
            {
                if (createdStripeCustomer && !string.IsNullOrWhiteSpace(stripeCustomerId))
                {
                    await customerService.DeleteAsync(stripeCustomerId);
                }
                if (braintreeTransaction != null)
                {
                    await _btGateway.Transaction.RefundAsync(braintreeTransaction.Id);
                }
                if (braintreeCustomer != null)
                {
                    await _btGateway.Customer.DeleteAsync(braintreeCustomer.Id);
                }
                throw e;
            }

            user.Gateway               = GatewayType.Stripe;
            user.GatewayCustomerId     = stripeCustomerId;
            user.GatewaySubscriptionId = subscription.Id;
            user.Premium               = true;
            user.PremiumExpirationDate = subscription.CurrentPeriodEnd;
        }