1
0
mirror of https://github.com/bitwarden/server.git synced 2025-05-20 19:14:32 -05:00

fix paypal edge case

This commit is contained in:
Kyle Spearrin 2019-02-23 17:40:46 -05:00
parent 2f5410de28
commit b5782f7b72

View File

@ -183,7 +183,8 @@ namespace Bit.Core.Services
var customerService = new CustomerService(); var customerService = new CustomerService();
var createdStripeCustomer = false; var createdStripeCustomer = false;
string stripeCustomerId = null; var addedCreditToStripeCustomer = false;
Customer customer = null;
Braintree.Transaction braintreeTransaction = null; Braintree.Transaction braintreeTransaction = null;
Braintree.Customer braintreeCustomer = null; Braintree.Customer braintreeCustomer = null;
var stripePaymentMethod = paymentMethodType == PaymentMethodType.Card || var stripePaymentMethod = paymentMethodType == PaymentMethodType.Card ||
@ -197,16 +198,16 @@ namespace Bit.Core.Services
{ {
await UpdatePaymentMethodAsync(user, paymentMethodType, paymentToken); await UpdatePaymentMethodAsync(user, paymentMethodType, paymentToken);
} }
catch catch { }
}
try
{ {
stripeCustomerId = null; customer = await customerService.GetAsync(user.GatewayCustomerId);
} }
} catch { }
stripeCustomerId = user.GatewayCustomerId;
createdStripeCustomer = false;
} }
if(string.IsNullOrWhiteSpace(stripeCustomerId) && !string.IsNullOrWhiteSpace(paymentToken)) if(customer == null && !string.IsNullOrWhiteSpace(paymentToken))
{ {
string stipeCustomerSourceToken = null; string stipeCustomerSourceToken = null;
var stripeCustomerMetadata = new Dictionary<string, string>(); var stripeCustomerMetadata = new Dictionary<string, string>();
@ -242,20 +243,24 @@ namespace Bit.Core.Services
throw new GatewayException("Payment method is not supported at this time."); throw new GatewayException("Payment method is not supported at this time.");
} }
var customer = await customerService.CreateAsync(new CustomerCreateOptions customer = await customerService.CreateAsync(new CustomerCreateOptions
{ {
Description = user.Name, Description = user.Name,
Email = user.Email, Email = user.Email,
SourceToken = stipeCustomerSourceToken, SourceToken = stipeCustomerSourceToken,
Metadata = stripeCustomerMetadata Metadata = stripeCustomerMetadata
}); });
stripeCustomerId = customer.Id;
createdStripeCustomer = true; createdStripeCustomer = true;
} }
if(customer == null)
{
throw new GatewayException("Could not set up customer payment profile.");
}
var subCreateOptions = new SubscriptionCreateOptions var subCreateOptions = new SubscriptionCreateOptions
{ {
CustomerId = stripeCustomerId, CustomerId = customer.Id,
Items = new List<SubscriptionItemOption>(), Items = new List<SubscriptionItemOption>(),
Metadata = new Dictionary<string, string> Metadata = new Dictionary<string, string>
{ {
@ -286,23 +291,22 @@ namespace Bit.Core.Services
{ {
var previewInvoice = await invoiceService.UpcomingAsync(new UpcomingInvoiceOptions var previewInvoice = await invoiceService.UpcomingAsync(new UpcomingInvoiceOptions
{ {
CustomerId = stripeCustomerId, CustomerId = customer.Id,
SubscriptionItems = ToInvoiceSubscriptionItemOptions(subCreateOptions.Items) SubscriptionItems = ToInvoiceSubscriptionItemOptions(subCreateOptions.Items)
}); });
await customerService.UpdateAsync(stripeCustomerId, new CustomerUpdateOptions if(previewInvoice.AmountDue > 0)
{ {
AccountBalance = -1 * previewInvoice.AmountDue var braintreeCustomerId = customer.Metadata != null &&
}); customer.Metadata.ContainsKey("btCustomerId") ? customer.Metadata["btCustomerId"] : null;
if(!string.IsNullOrWhiteSpace(braintreeCustomerId))
if(braintreeCustomer != null)
{ {
var btInvoiceAmount = (previewInvoice.AmountDue / 100M); var btInvoiceAmount = (previewInvoice.AmountDue / 100M);
var transactionResult = await _btGateway.Transaction.SaleAsync( var transactionResult = await _btGateway.Transaction.SaleAsync(
new Braintree.TransactionRequest new Braintree.TransactionRequest
{ {
Amount = btInvoiceAmount, Amount = btInvoiceAmount,
CustomerId = braintreeCustomer.Id, CustomerId = braintreeCustomerId,
Options = new Braintree.TransactionOptionsRequest Options = new Braintree.TransactionOptionsRequest
{ {
SubmitForSettlement = true, SubmitForSettlement = true,
@ -326,17 +330,24 @@ namespace Bit.Core.Services
subInvoiceMetadata.Add("btTransactionId", braintreeTransaction.Id); subInvoiceMetadata.Add("btTransactionId", braintreeTransaction.Id);
subInvoiceMetadata.Add("btPayPalTransactionId", subInvoiceMetadata.Add("btPayPalTransactionId",
braintreeTransaction.PayPalDetails.AuthorizationId); braintreeTransaction.PayPalDetails.AuthorizationId);
await customerService.UpdateAsync(customer.Id, new CustomerUpdateOptions
{
AccountBalance = -1 * previewInvoice.AmountDue
});
addedCreditToStripeCustomer = true;
} }
else else
{ {
throw new GatewayException("No payment was able to be collected."); throw new GatewayException("No payment was able to be collected.");
} }
} }
}
else if(paymentMethodType == PaymentMethodType.Credit) else if(paymentMethodType == PaymentMethodType.Credit)
{ {
var previewInvoice = await invoiceService.UpcomingAsync(new UpcomingInvoiceOptions var previewInvoice = await invoiceService.UpcomingAsync(new UpcomingInvoiceOptions
{ {
CustomerId = stripeCustomerId, CustomerId = customer.Id,
SubscriptionItems = ToInvoiceSubscriptionItemOptions(subCreateOptions.Items) SubscriptionItems = ToInvoiceSubscriptionItemOptions(subCreateOptions.Items)
}); });
if(previewInvoice.AmountDue > 0) if(previewInvoice.AmountDue > 0)
@ -369,9 +380,19 @@ namespace Bit.Core.Services
} }
catch(Exception e) catch(Exception e)
{ {
if(createdStripeCustomer && !string.IsNullOrWhiteSpace(stripeCustomerId)) if(customer != null)
{ {
await customerService.DeleteAsync(stripeCustomerId); if(createdStripeCustomer)
{
await customerService.DeleteAsync(customer.Id);
}
else if(addedCreditToStripeCustomer)
{
await customerService.UpdateAsync(customer.Id, new CustomerUpdateOptions
{
AccountBalance = customer.AccountBalance
});
}
} }
if(braintreeTransaction != null) if(braintreeTransaction != null)
{ {
@ -385,7 +406,7 @@ namespace Bit.Core.Services
} }
user.Gateway = GatewayType.Stripe; user.Gateway = GatewayType.Stripe;
user.GatewayCustomerId = stripeCustomerId; user.GatewayCustomerId = customer.Id;
user.GatewaySubscriptionId = subscription.Id; user.GatewaySubscriptionId = subscription.Id;
user.Premium = true; user.Premium = true;
user.PremiumExpirationDate = subscription.CurrentPeriodEnd; user.PremiumExpirationDate = subscription.CurrentPeriodEnd;