mirror of
https://github.com/bitwarden/server.git
synced 2025-05-20 11:04:31 -05:00
fix paypal edge case
This commit is contained in:
parent
2f5410de28
commit
b5782f7b72
@ -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 { }
|
||||||
{
|
|
||||||
stripeCustomerId = null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
stripeCustomerId = user.GatewayCustomerId;
|
try
|
||||||
createdStripeCustomer = false;
|
{
|
||||||
|
customer = await customerService.GetAsync(user.GatewayCustomerId);
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
}
|
}
|
||||||
|
|
||||||
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,57 +291,63 @@ 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 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.");
|
var btInvoiceAmount = (previewInvoice.AmountDue / 100M);
|
||||||
}
|
var transactionResult = await _btGateway.Transaction.SaleAsync(
|
||||||
|
new Braintree.TransactionRequest
|
||||||
|
{
|
||||||
|
Amount = btInvoiceAmount,
|
||||||
|
CustomerId = braintreeCustomerId,
|
||||||
|
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()
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
braintreeTransaction = transactionResult.Target;
|
if(!transactionResult.IsSuccess())
|
||||||
subInvoiceMetadata.Add("btTransactionId", braintreeTransaction.Id);
|
{
|
||||||
subInvoiceMetadata.Add("btPayPalTransactionId",
|
throw new GatewayException("Failed to charge PayPal customer.");
|
||||||
braintreeTransaction.PayPalDetails.AuthorizationId);
|
}
|
||||||
}
|
|
||||||
else
|
braintreeTransaction = transactionResult.Target;
|
||||||
{
|
subInvoiceMetadata.Add("btTransactionId", braintreeTransaction.Id);
|
||||||
throw new GatewayException("No payment was able to be collected.");
|
subInvoiceMetadata.Add("btPayPalTransactionId",
|
||||||
|
braintreeTransaction.PayPalDetails.AuthorizationId);
|
||||||
|
|
||||||
|
await customerService.UpdateAsync(customer.Id, new CustomerUpdateOptions
|
||||||
|
{
|
||||||
|
AccountBalance = -1 * previewInvoice.AmountDue
|
||||||
|
});
|
||||||
|
addedCreditToStripeCustomer = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user