Пример #1
0
        public async Task <bool> UpdatePaymentMethodAsync(ISubscriber subscriber, string paymentToken)
        {
            if (subscriber == null)
            {
                throw new ArgumentNullException(nameof(subscriber));
            }

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

            var updatedSubscriber = false;

            var            cardService     = new StripeCardService();
            var            bankSerice      = new BankAccountService();
            var            customerService = new StripeCustomerService();
            StripeCustomer customer        = null;

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

            if (customer == null)
            {
                customer = await customerService.CreateAsync(new StripeCustomerCreateOptions
                {
                    Description = subscriber.BillingName(),
                    Email       = subscriber.BillingEmailAddress(),
                    SourceToken = paymentToken
                });

                subscriber.Gateway           = Enums.GatewayType.Stripe;
                subscriber.GatewayCustomerId = customer.Id;
                updatedSubscriber            = true;
            }
            else
            {
                if (paymentToken.StartsWith("btok_"))
                {
                    await bankSerice.CreateAsync(customer.Id, new BankAccountCreateOptions
                    {
                        SourceToken = paymentToken
                    });
                }
                else
                {
                    await cardService.CreateAsync(customer.Id, new StripeCardCreateOptions
                    {
                        SourceToken = paymentToken
                    });
                }

                if (!string.IsNullOrWhiteSpace(customer.DefaultSourceId))
                {
                    var source = customer.Sources.FirstOrDefault(s => s.Id == customer.DefaultSourceId);
                    if (source.BankAccount != null)
                    {
                        await bankSerice.DeleteAsync(customer.Id, customer.DefaultSourceId);
                    }
                    else if (source.Card != null)
                    {
                        await cardService.DeleteAsync(customer.Id, customer.DefaultSourceId);
                    }
                }
            }

            return(updatedSubscriber);
        }
Пример #2
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);
        }