1
0
mirror of https://github.com/bitwarden/server.git synced 2025-01-23 22:01:28 +01:00

process credit from ipn

This commit is contained in:
Kyle Spearrin 2019-02-20 16:03:38 -05:00
parent 312ced0e3b
commit 494b3f18b6
3 changed files with 71 additions and 5 deletions

View File

@ -1,6 +1,8 @@
using Bit.Billing.Utilities;
using Bit.Core.Enums;
using Bit.Core.Models.Table;
using Bit.Core.Repositories;
using Bit.Core.Services;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
@ -18,17 +20,29 @@ namespace Bit.Billing.Controllers
private readonly PayPalClient _paypalClient;
private readonly PayPalIpnClient _paypalIpnClient;
private readonly ITransactionRepository _transactionRepository;
private readonly IOrganizationRepository _organizationRepository;
private readonly IUserRepository _userRepository;
private readonly IMailService _mailService;
private readonly IPaymentService _paymentService;
public PayPalController(
IOptions<BillingSettings> billingSettings,
PayPalClient paypalClient,
PayPalIpnClient paypalIpnClient,
ITransactionRepository transactionRepository)
ITransactionRepository transactionRepository,
IOrganizationRepository organizationRepository,
IUserRepository userRepository,
IMailService mailService,
IPaymentService paymentService)
{
_billingSettings = billingSettings?.Value;
_paypalClient = paypalClient;
_paypalIpnClient = paypalIpnClient;
_transactionRepository = transactionRepository;
_organizationRepository = organizationRepository;
_userRepository = userRepository;
_mailService = mailService;
_paymentService = paymentService;
}
[HttpPost("webhook")]
@ -197,7 +211,7 @@ namespace Bit.Billing.Controllers
{
try
{
await _transactionRepository.CreateAsync(new Core.Models.Table.Transaction
var tx = new Transaction
{
Amount = ipnTransaction.McGross,
CreationDate = ipnTransaction.PaymentDate,
@ -208,11 +222,35 @@ namespace Bit.Billing.Controllers
GatewayId = ipnTransaction.TxnId,
PaymentMethodType = PaymentMethodType.PayPal,
Details = ipnTransaction.TxnId
});
};
await _transactionRepository.CreateAsync(tx);
if(ipnTransaction.IsAccountCredit())
{
// TODO: Issue Stripe credit to user/org account
if(tx.OrganizationId.HasValue)
{
var org = await _organizationRepository.GetByIdAsync(tx.OrganizationId.Value);
if(org != null)
{
if(await _paymentService.CreditAccountAsync(org, tx.Amount))
{
await _organizationRepository.ReplaceAsync(org);
}
}
}
else
{
var user = await _userRepository.GetByIdAsync(tx.UserId.Value);
if(user != null)
{
if(await _paymentService.CreditAccountAsync(user, tx.Amount))
{
await _userRepository.ReplaceAsync(user);
}
}
}
// TODO: Send email about credit added?
}
}
// Catch foreign key violations because user/org could have been deleted.
@ -246,7 +284,7 @@ namespace Bit.Billing.Controllers
}
await _transactionRepository.ReplaceAsync(parentTransaction);
await _transactionRepository.CreateAsync(new Core.Models.Table.Transaction
await _transactionRepository.CreateAsync(new Transaction
{
Amount = ipnTransaction.McGross,
CreationDate = ipnTransaction.PaymentDate,

View File

@ -17,6 +17,7 @@ namespace Bit.Core.Services
Task ReinstateSubscriptionAsync(ISubscriber subscriber);
Task<bool> UpdatePaymentMethodAsync(ISubscriber subscriber, PaymentMethodType paymentMethodType,
string paymentToken);
Task<bool> CreditAccountAsync(ISubscriber subscriber, decimal creditAmount);
Task<BillingInfo> GetBillingAsync(ISubscriber subscriber);
Task<SubscriptionInfo> GetSubscriptionAsync(ISubscriber subscriber);
}

View File

@ -915,6 +915,33 @@ namespace Bit.Core.Services
return createdCustomer;
}
public async Task<bool> CreditAccountAsync(ISubscriber subscriber, decimal creditAmount)
{
var customerService = new CustomerService();
Customer customer = null;
var customerExists = subscriber.Gateway == GatewayType.Stripe &&
!string.IsNullOrWhiteSpace(subscriber.GatewaySubscriptionId);
if(customerExists)
{
customer = await customerService.GetAsync(subscriber.GatewaySubscriptionId);
}
else
{
customer = await customerService.CreateAsync(new CustomerCreateOptions
{
Email = subscriber.BillingEmailAddress(),
Description = subscriber.BillingName(),
});
subscriber.Gateway = GatewayType.Stripe;
subscriber.GatewayCustomerId = customer.Id;
}
await customerService.UpdateAsync(customer.Id, new CustomerUpdateOptions
{
AccountBalance = customer.AccountBalance - (long)(creditAmount * 100)
});
return !customerExists;
}
public async Task<BillingInfo> GetBillingAsync(ISubscriber subscriber)
{
var billingInfo = new BillingInfo();