860 lines
49 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Web;
using gehGassi.Core.Interfaces;
using gehGassi.Core.Services;
using gehGassi.Domain.Common;
using gehGassi.Domain.Payment;
using gehGassi.Domain.Walks;
using gehGassi.Dto.Messages;
using gehGassi.External.Services;
using gehGassi.Persistence.Migrations;
using gehGassi.Web.Hubs;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
namespace gehGassi.Web.Controllers
{
/// <summary>
/// Controller für die Kommunikation mit MangoPay
/// </summary>
[Authorize]
public class MangoPayController : BaseController
{
private readonly IMangoPayService _mangoPayService;
private readonly IPaymentTransactionService _paymentTransactionService;
private readonly IWalkService _walkService;
private readonly ISystemMessageService _systemMessageService;
private readonly IAppHubSender _appHubSender;
private readonly IServiceScopeFactory _resolver;
private readonly IPushNotificationService _pushNotificationService;
private readonly ILogger<MangoPayController> _logger;
/// <summary>
/// Erstellt eine Instanz
/// </summary>
/// <param name="mangoPayService">Instanz eines IMangoPayService</param>
/// <param name="paymentTransactionService">Instanz eines IPaymentTransactionService</param>
/// <param name="walkService">Instanz eines IWalkService</param>
/// <param name="systemMessageService">Instanz eines ISystemMessageService</param>
/// <param name="appHubSender">Instanz eines IAppHubSender</param>
/// <param name="resolver">Instanz einer IServiceScopeFactory</param>
/// <param name="logger">Instanz eines ILogger</param>
/// <param name="pushNotificationService">Instanz eines IPushNotificationService</param>
public MangoPayController(IMangoPayService mangoPayService, IPaymentTransactionService paymentTransactionService, IWalkService walkService, ISystemMessageService systemMessageService, IAppHubSender appHubSender,
IServiceScopeFactory resolver, ILogger<MangoPayController> logger, IPushNotificationService pushNotificationService)
{
_mangoPayService = mangoPayService;
_paymentTransactionService = paymentTransactionService;
_walkService = walkService;
_systemMessageService = systemMessageService;
_appHubSender = appHubSender;
_resolver = resolver;
_pushNotificationService = pushNotificationService;
//_logger = logger;
}
/// <summary>
/// Nimmt das Ergebnis einer Einzahlungsatkion bei MangoPay entgegen
/// </summary>
/// <param name="transactionId">TransaktionsId bei Mangopay</param>
/// <returns>200 ok</returns>
[AllowAnonymous]
public async Task<IActionResult> PayInReturn(string transactionId)
{
//Zuerst prüfen ob die Tranksation bei MangoPay erfolgreich war...
var transactionResponse = await _mangoPayService.GetTransactionAsync(transactionId);
//_logger.LogWarning($"PayInReturn: TransactionId {transactionId}");
if (transactionResponse.Success)
{
var mangoPayTransaction = transactionResponse.Value;
if (mangoPayTransaction.Status == PaymentTransactionStatus.SUCCEEDED)
{
//_logger.LogWarning($"PayInReturn: Transaction SUCCEDED");
//nun die Transaktion lokal holen und sehen ob eine mit dem Status CREATED existiert...
var paymentTransaction = await _paymentTransactionService.GetAsync(mangoPayTransaction.TransactionId, PaymentTransactionType.PayIn, PaymentTransactionStatus.CREATED);
if (paymentTransaction != null)
{
//_logger.LogWarning($"PayInReturn: PaymentTansaction with status CREATED exists");
var paymentTransactionSuccess = await _paymentTransactionService.GetAsync(mangoPayTransaction.TransactionId, PaymentTransactionType.PayIn, PaymentTransactionStatus.SUCCEEDED);
if (paymentTransactionSuccess != null) return BadRequest();
//_logger.LogWarning($"PayInReturn: PaymentTansaction with status SUCCEEDED does not exist --> OK");
paymentTransactionSuccess = _paymentTransactionService.Create(mangoPayTransaction.TransactionId, PaymentTransactionType.PayIn, PaymentTransactionStatus.SUCCEEDED, paymentTransaction.WalkId,
paymentTransaction.TargetAppUserId, paymentTransaction.TargetWalletId, string.Empty, string.Empty, paymentTransaction.Ammount, paymentTransaction.FromCredit, "EUR", paymentTransaction.PayInType);
_paymentTransactionService.Add(paymentTransactionSuccess);
await _paymentTransactionService.CommitAsync("System");
//_logger.LogWarning($"PayInReturn: PaymentTansaction with status SUCCEEDED created");
//Die Zahlung war erfolgreich. Also dies nun beim Walk ablegen und die Benutzer benachrichtigen
var walk = await _walkService.GetAsync(paymentTransactionSuccess.WalkId);
if (walk != null)
{
//_logger.LogWarning($"PayInReturn: Walk exists");
//Wenn noch ein Teil vom Guthabenkonto genommen werden muss
if (paymentTransactionSuccess.FromCredit > 0)
{
var tag = $"Walk_Authorize_{walk.Id}";
await _mangoPayService.TransferMoneyFromCreditToFeeAccountAsync(walk.DogOwnerId, paymentTransactionSuccess.FromCredit, tag);
//_logger.LogWarning($"PayInReturn: TransferMoneyFromCreditToFeeAccountAsync done");
}
walk.PaymentStatus = PaymentStatus.Authorized;
walk.UpdatedAt = DateTimeOffset.UtcNow;
await _walkService.CommitAsync("System");
//_logger.LogWarning($"PayInReturn: Paymentstatus set to Authorized");
//Wallets aktualisieren
await _mangoPayService.GetWalletBalanceAsync(walk.DogOwnerId, WalletType.Credits);
await _mangoPayService.GetWalletBalanceAsync(walk.DogOwnerId, WalletType.Fees);
//_logger.LogWarning($"PayInReturn: Wallets updated");
//Überlappende Walks die im Status "Request" sind, stornieren
await _walkService.CancelWalkRequestsAsync(walk.DogWalkerId, walk.Start, walk.End);
await _walkService.CommitAsync("System");
//_logger.LogWarning($"PayInReturn: CancelWalkRequestsAsync done");
//Walker informieren. TODO: pushnotification?
_systemMessageService.Add(walk.DogWalkerId, AppUserType.DogWalker, walk.Id, SystemMessageTables.Walk, SystemMessageType.WalkAdded, DateTimeOffset.UtcNow.AddDays(14));
await _systemMessageService.CommitAsync("System");
await _appHubSender.SystemMessageAddedAsync(walk.DogWalkerId);
await _pushNotificationService.SendNewWalkAsync(walk.DogWalkerId, walk.Id);
//_logger.LogWarning($"PayInReturn: Systemmessage sent");
var returnUrl = Url.Action("PayInSuccess", "MangoPay", new{walkId = walk.Id}, protocol: HttpContext.Request.Scheme);
//_logger.LogWarning($"PayInReturn: redirecting to: {returnUrl}");
#if DEBUG
returnUrl = $"http://10.0.0.31:54763/de/mangopay/payinsuccess?walkId={HttpUtility.UrlEncode(walk.Id)}";// Url.Action("PayInReturn", "MangoPay", , protocol: "http");
#endif
return Redirect(returnUrl);
}
else
{
//_logger.LogWarning($"PayInReturn: Walk does not exist");
}
}
}
else
{
//Gescheitert. Kann diverse Gründe haben. z.B. nicht genügend Geld auf dem Wallet
//nun die Transaktion lokal holen und sehen ob eine mit dem Status CREATED existiert...
var paymentTransaction = await _paymentTransactionService.GetAsync(mangoPayTransaction.TransactionId, PaymentTransactionType.PayIn, PaymentTransactionStatus.CREATED);
if (paymentTransaction != null)
{
//_logger.LogWarning($"PayInReturn: Transaction FAILED");
var paymentTransactionFailed = _paymentTransactionService.Create(mangoPayTransaction.TransactionId, PaymentTransactionType.PayIn, PaymentTransactionStatus.FAILED, paymentTransaction.WalkId, paymentTransaction.TargetAppUserId, paymentTransaction.TargetWalletId, string.Empty, string.Empty, paymentTransaction.Ammount, paymentTransaction.FromCredit, "EUR", transactionResponse.Value.ResultMessage, transactionResponse.Value.ResultCode, new Dictionary<string, string>(), paymentTransaction.PayInType);
_paymentTransactionService.Add(paymentTransactionFailed);
await _paymentTransactionService.CommitAsync("System");
var returnUrl = Url.Action("PayInFailed", "MangoPay", new { walkId = paymentTransaction.WalkId }, protocol: HttpContext.Request.Scheme);
//_logger.LogWarning($"PayInReturn: redirecting to: {returnUrl}");
#if DEBUG
returnUrl = $"http://10.0.0.31:54763/de/mangopay/payinfailed?walkId={HttpUtility.UrlEncode(paymentTransaction.WalkId)}";// Url.Action("PayInReturn", "MangoPay", , protocol: "http");
#endif
return Redirect(returnUrl);
}
}
}
else
{
var paymentTransaction = await _paymentTransactionService.GetAsync(transactionId, PaymentTransactionType.PayIn, PaymentTransactionStatus.CREATED);
if (paymentTransaction != null)
{
var paymentTransactionFailed = _paymentTransactionService.Create(transactionId, PaymentTransactionType.PayIn, PaymentTransactionStatus.FAILED, paymentTransaction.WalkId, paymentTransaction.TargetAppUserId, paymentTransaction.TargetWalletId, string.Empty, string.Empty, paymentTransaction.Ammount, paymentTransaction.FromCredit, "EUR", transactionResponse.ErrorMessage, transactionResponse.ErrorType, transactionResponse.ErrorMessages, paymentTransaction.PayInType);
_paymentTransactionService.Add(paymentTransactionFailed);
await _paymentTransactionService.CommitAsync("System");
var returnUrl = Url.Action("PayInFailed", "MangoPay", new { walkId = paymentTransaction.WalkId }, protocol: HttpContext.Request.Scheme);
#if DEBUG
returnUrl = $"http://10.0.0.31:54763/de/mangopay/payinfailed?walkId={HttpUtility.UrlEncode(paymentTransaction.WalkId)}";// Url.Action("PayInReturn", "MangoPay", , protocol: "http");
#endif
return Redirect(returnUrl);
}
}
return BadRequest();
}
/// <summary>
/// Signal, dass eine Zahlung erfolgreich war für einen Walk
/// </summary>
/// <param name="walkId">ID des Walks</param>
/// <returns>200 OK</returns>
[AllowAnonymous]
public async Task<IActionResult> PayInSuccess(string walkId)
{
//_logger.LogWarning($"PayInSuccess: called for walkid {walkId}");
await Task.Delay(1);
ViewBag.DarkMode = false;
return View();
}
/// <summary>
/// Signal, dass eine Zahlung nicht erfolgreich war für einen Walk
/// </summary>
/// <param name="walkId">ID des Walks</param>
/// <returns>200 OK</returns>
[AllowAnonymous]
public async Task<IActionResult> PayInFailed(string walkId)
{
//_logger.LogWarning($"PayInFailed: called for walkid {walkId}");
await Task.Delay(1);
ViewBag.DarkMode = false;
return View();
}
/// <summary>
/// Webhook für MangoPay
/// </summary>
/// <param name="eventType">Event-Typ</param>
/// <param name="ressourceId">Id der Ressource</param>
/// <returns>200 OK</returns>
[AllowAnonymous]
public async Task<IActionResult> WebHook(string eventType, string ressourceId)
{
if (!string.IsNullOrWhiteSpace(eventType) && !string.IsNullOrWhiteSpace(ressourceId))
{
var serviceProvider = HttpContext.RequestServices;
if (eventType == "KYC_SUCCEEDED")
{
var documentId = ressourceId;
_ = Task.Run(() => HandleKycSucceded(documentId, _resolver));
}
else if (eventType == "KYC_FAILED")
{
var documentId = ressourceId;
_ = Task.Run(() => HandleKycFailed(documentId, _resolver));
}
else if (eventType == "KYC_OUTDATED")
{
var documentId = ressourceId;
_ = Task.Run(() => HandleKycOutdated(documentId, _resolver));
}
else if (eventType == "PAYOUT_NORMAL_SUCCEEDED")
{
var payoutId = ressourceId;
_ = Task.Run(() => HandlePayOutSucceeded(payoutId, _resolver));
}
else if (eventType == "PAYOUT_NORMAL_FAILED")
{
var payoutId = ressourceId;
_ = Task.Run(() => HandlePayOutFailed(payoutId, _resolver));
}
else if (eventType == "PAYOUT_REFUND_SUCCEEDED")
{
var payoutId = ressourceId;
_ = Task.Run(() => HandlePayOutRefunded(payoutId, _resolver));
}
else if (eventType == "PAYIN_NORMAL_SUCCEEDED")
{
var payinId = ressourceId;
_ = Task.Run(() => HandlePayInSucceeded(payinId, _resolver));
}
else if (eventType == "PAYIN_NORMAL_FAILED")
{
var payinId = ressourceId;
_ = Task.Run(() => HandlePayInFailed(payinId, _resolver));
}
}
return Ok();
}
#region Private
/// <summary>
/// Eine KYC-Überprüfung war erfolgreich
/// </summary>
/// <param name="documentId">Id des Kyc-Dokumentes bei MangoPay</param>
/// <param name="resolver">IServiceScopeFactory</param>
/// <returns>Task</returns>
private async Task HandleKycSucceded(string documentId, IServiceScopeFactory resolver)
{
try
{
using var scope = resolver.CreateScope();
var svcProvider = scope.ServiceProvider;
var identityDocumentService = (IIdentityDocumentService)svcProvider.GetService(typeof(IIdentityDocumentService));
var appUserService = (IAppUserService)svcProvider.GetService(typeof(IAppUserService));
var systemMessageService = (ISystemMessageService)svcProvider.GetService(typeof(ISystemMessageService));
var appHubSender = (IAppHubSender)svcProvider.GetService(typeof(IAppHubSender));
if (identityDocumentService != null && appUserService != null && systemMessageService != null && appHubSender != null)
{
var identityDocument = await identityDocumentService.GetByMangoPayIdAsync(documentId);
if (identityDocument != null)
{
var documentResult = await _mangoPayService.GetKycDocumentAsync(documentId);
if (documentResult != null && documentResult.Success)
{
identityDocument.Status = documentResult.Value.Status;
identityDocument.Processed = documentResult.Value.ProcessedDate;
identityDocument.UpdatedAt = DateTimeOffset.UtcNow;
await identityDocumentService.CommitAsync("System");
var appUser = await appUserService.GetAsync(identityDocument.AppUserId);
if (appUser != null)
{
appUser.KycPassed = true;
appUser.KycPassedDate = DateTimeOffset.UtcNow;
appUser.UpdatedAt = DateTimeOffset.UtcNow;
if (!appUser.Verified)
{
appUser.Verified = true;
appUser.VerifiedDate = DateTimeOffset.UtcNow;
}
await appUserService.CommitAsync("System");
}
//Benachrichtigung
if (appUser != null)
{
if (appUser.Type == AppUserType.DogOwner || appUser.Type == AppUserType.Both)
{
systemMessageService.Add(appUser.Id, AppUserType.DogOwner, identityDocument.Id, SystemMessageTables.IdentityDocument, SystemMessageType.IdentityDocumentUpdate, DateTimeOffset.UtcNow.AddDays(14));
await _systemMessageService.CommitAsync(User.Identity.Name);
await _appHubSender.SystemMessageAddedAsync(appUser.Id);
await _pushNotificationService.SendIdentityDocumentUpdateAsync(appUser.Id, identityDocument.Id);
}
else if (appUser.Type == AppUserType.DogWalker || appUser.Type == AppUserType.Both)
{
systemMessageService.Add(appUser.Id, AppUserType.DogWalker, identityDocument.Id, SystemMessageTables.IdentityDocument, SystemMessageType.IdentityDocumentUpdate, DateTimeOffset.UtcNow.AddDays(14));
await _systemMessageService.CommitAsync(User.Identity.Name);
await _appHubSender.SystemMessageAddedAsync(appUser.Id);
await _pushNotificationService.SendIdentityDocumentUpdateAsync(appUser.Id, identityDocument.Id);
}
}
}
}
}
await Task.Delay(1);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
}
}
/// <summary>
/// Eine KYC-Überprüfung ist gescheitert
/// </summary>
/// <param name="documentId">Id des Kyc-Dokumentes bei MangoPay</param>
/// <param name="resolver">IServiceScopeFactory</param>
/// <returns>Task</returns>
private async Task HandleKycFailed(string documentId, IServiceScopeFactory resolver)
{
try
{
using var scope = resolver.CreateScope();
var svcProvider = scope.ServiceProvider;
var identityDocumentService = (IIdentityDocumentService)svcProvider.GetService(typeof(IIdentityDocumentService));
var appUserService = (IAppUserService)svcProvider.GetService(typeof(IAppUserService));
var systemMessageService = (ISystemMessageService)svcProvider.GetService(typeof(ISystemMessageService));
var appHubSender = (IAppHubSender)svcProvider.GetService(typeof(IAppHubSender));
if (identityDocumentService != null && appUserService != null && systemMessageService != null && appHubSender != null)
{
var identityDocument = await identityDocumentService.GetByMangoPayIdAsync(documentId);
if (identityDocument != null)
{
var documentResult = await _mangoPayService.GetKycDocumentAsync(documentId);
if (documentResult != null && documentResult.Success)
{
identityDocument.Status = documentResult.Value.Status;
identityDocument.Processed = documentResult.Value.ProcessedDate;
identityDocument.RefusedReasonType = documentResult.Value.RefusedReasonType;
identityDocument.RefusedReasonMessage = documentResult.Value.RefusedReasonMessage;
if (documentResult.Value.Flags != null && documentResult.Value.Flags.Any())
identityDocument.FlagsValue = string.Join(";", documentResult.Value.Flags);
else
identityDocument.FlagsValue = string.Empty;
identityDocument.UpdatedAt = DateTimeOffset.UtcNow;
await identityDocumentService.CommitAsync("System");
var appUser = await appUserService.GetAsync(identityDocument.AppUserId);
if (appUser != null)
{
appUser.KycPassed = false;
appUser.KycPassedDate = null;
appUser.UpdatedAt = DateTimeOffset.UtcNow;
await appUserService.CommitAsync("System");
}
//Benachrichtigung
if (appUser != null)
{
if (appUser.Type == AppUserType.DogOwner || appUser.Type == AppUserType.Both)
{
systemMessageService.Add(appUser.Id, AppUserType.DogOwner, identityDocument.Id, SystemMessageTables.IdentityDocument, SystemMessageType.IdentityDocumentUpdate, DateTimeOffset.UtcNow.AddDays(14));
await _systemMessageService.CommitAsync(User.Identity.Name);
await _appHubSender.SystemMessageAddedAsync(appUser.Id);
await _pushNotificationService.SendIdentityDocumentUpdateAsync(appUser.Id, identityDocument.Id);
}
else if (appUser.Type == AppUserType.DogWalker || appUser.Type == AppUserType.Both)
{
systemMessageService.Add(appUser.Id, AppUserType.DogWalker, identityDocument.Id, SystemMessageTables.IdentityDocument, SystemMessageType.IdentityDocumentUpdate, DateTimeOffset.UtcNow.AddDays(14));
await _systemMessageService.CommitAsync(User.Identity.Name);
await _appHubSender.SystemMessageAddedAsync(appUser.Id);
await _pushNotificationService.SendIdentityDocumentUpdateAsync(appUser.Id, identityDocument.Id);
}
}
}
}
}
await Task.Delay(1);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
}
}
/// <summary>
/// Eine KYC-Überprüfung ist gescheitert
/// </summary>
/// <param name="documentId">Id des Kyc-Dokumentes bei MangoPay</param>
/// <param name="resolver">IServiceScopeFactory</param>
/// <returns>Task</returns>
private async Task HandleKycOutdated(string documentId, IServiceScopeFactory resolver)
{
try
{
using var scope = resolver.CreateScope();
var svcProvider = scope.ServiceProvider;
var identityDocumentService = (IIdentityDocumentService)svcProvider.GetService(typeof(IIdentityDocumentService));
var appUserService = (IAppUserService)svcProvider.GetService(typeof(IAppUserService));
var systemMessageService = (ISystemMessageService)svcProvider.GetService(typeof(ISystemMessageService));
var appHubSender = (IAppHubSender)svcProvider.GetService(typeof(IAppHubSender));
if (identityDocumentService != null && appUserService != null && systemMessageService != null && appHubSender != null)
{
var identityDocument = await identityDocumentService.GetByMangoPayIdAsync(documentId);
if (identityDocument != null)
{
var documentResult = await _mangoPayService.GetKycDocumentAsync(documentId);
if (documentResult != null && documentResult.Success)
{
identityDocument.Status = documentResult.Value.Status;
identityDocument.Processed = documentResult.Value.ProcessedDate;
identityDocument.RefusedReasonType = documentResult.Value.RefusedReasonType;
identityDocument.RefusedReasonMessage = documentResult.Value.RefusedReasonMessage;
if (documentResult.Value.Flags != null && documentResult.Value.Flags.Any())
identityDocument.FlagsValue = string.Join(";", documentResult.Value.Flags);
else
identityDocument.FlagsValue = string.Empty;
identityDocument.UpdatedAt = DateTimeOffset.UtcNow;
await identityDocumentService.CommitAsync("System");
var appUser = await appUserService.GetAsync(identityDocument.AppUserId);
var latestIdentityDocument = await identityDocumentService.GetLatestAsync(identityDocument.AppUserId);
if (latestIdentityDocument != null && latestIdentityDocument.Id == identityDocument.Id)
{
//Wenn das das aktuell gültige KYC-Dokument ist, dann KYC vom App-User wieder entfernen
if (appUser != null)
{
appUser.KycPassed = false;
appUser.KycPassedDate = null;
appUser.UpdatedAt = DateTimeOffset.UtcNow;
await appUserService.CommitAsync("System");
}
}
//Benachrichtigung
if (appUser != null)
{
if (appUser.Type == AppUserType.DogOwner || appUser.Type == AppUserType.Both)
{
systemMessageService.Add(appUser.Id, AppUserType.DogOwner, identityDocument.Id, SystemMessageTables.IdentityDocument, SystemMessageType.IdentityDocumentUpdate, DateTimeOffset.UtcNow.AddDays(14));
await _systemMessageService.CommitAsync(User.Identity.Name);
await _appHubSender.SystemMessageAddedAsync(appUser.Id);
await _pushNotificationService.SendIdentityDocumentUpdateAsync(appUser.Id, identityDocument.Id);
}
else if (appUser.Type == AppUserType.DogWalker || appUser.Type == AppUserType.Both)
{
systemMessageService.Add(appUser.Id, AppUserType.DogWalker, identityDocument.Id, SystemMessageTables.IdentityDocument, SystemMessageType.IdentityDocumentUpdate, DateTimeOffset.UtcNow.AddDays(14));
await _systemMessageService.CommitAsync(User.Identity.Name);
await _appHubSender.SystemMessageAddedAsync(appUser.Id);
await _pushNotificationService.SendIdentityDocumentUpdateAsync(appUser.Id, identityDocument.Id);
}
}
}
}
}
await Task.Delay(1);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
}
}
/// <summary>
/// Eine Auszahlung war erfolgreich
/// </summary>
/// <param name="payoutId">Id der Auszahlung</param>
/// <param name="resolver">IServiceScopeFactory</param>
/// <returns>Task</returns>
private async Task HandlePayOutSucceeded(string payoutId, IServiceScopeFactory resolver)
{
try
{
using var scope = resolver.CreateScope();
var svcProvider = scope.ServiceProvider;
var payoutService = (IPayoutService)svcProvider.GetService(typeof(IPayoutService));
var appUserService = (IAppUserService)svcProvider.GetService(typeof(IAppUserService));
var systemMessageService = (ISystemMessageService)svcProvider.GetService(typeof(ISystemMessageService));
var appHubSender = (IAppHubSender)svcProvider.GetService(typeof(IAppHubSender));
if (payoutService != null && appUserService != null && systemMessageService != null && appHubSender != null)
{
var payout = await payoutService.GetByMangoPayIdAsync(payoutId);
if (payout != null)
{
var payoutResult = await _mangoPayService.GetPayoutAsync(payoutId);
if (payoutResult != null && payoutResult.Success)
{
payout.Status = payoutResult.Value.Status;
payout.ExecutionDate = payoutResult.Value.ExecutionDate;
payout.ResultCode = payoutResult.Value.ResultCode;
payout.ResultMessage = payoutResult.Value.ResultMessage;
payout.UpdatedAt = DateTimeOffset.UtcNow;
await payoutService.CommitAsync("System");
var appUser = await appUserService.GetAsync(payout.AppUserId);
//Benachrichtigung
if (appUser != null)
{
if (appUser.Type == AppUserType.DogOwner || appUser.Type == AppUserType.Both)
{
systemMessageService.Add(appUser.Id, AppUserType.DogOwner, payout.Id, SystemMessageTables.Payout, SystemMessageType.PayoutUpdate, DateTimeOffset.UtcNow.AddDays(14));
await _systemMessageService.CommitAsync(User.Identity.Name);
await _appHubSender.SystemMessageAddedAsync(appUser.Id);
await _pushNotificationService.SendPayoutUpdateAsync(appUser.Id, payout.Id);
}
else if (appUser.Type == AppUserType.DogWalker || appUser.Type == AppUserType.Both)
{
systemMessageService.Add(appUser.Id, AppUserType.DogWalker, payout.Id, SystemMessageTables.Payout, SystemMessageType.PayoutUpdate, DateTimeOffset.UtcNow.AddDays(14));
await _systemMessageService.CommitAsync(User.Identity.Name);
await _appHubSender.SystemMessageAddedAsync(appUser.Id);
await _pushNotificationService.SendPayoutUpdateAsync(appUser.Id, payout.Id);
}
}
}
}
}
await Task.Delay(1);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
}
}
/// <summary>
/// Eine Auszahlung ist gescheitert
/// </summary>
/// <param name="payoutId">Id der Auszahlung</param>
/// <param name="resolver">IServiceScopeFactory</param>
/// <returns>Task</returns>
private async Task HandlePayOutFailed(string payoutId, IServiceScopeFactory resolver)
{
try
{
using var scope = resolver.CreateScope();
var svcProvider = scope.ServiceProvider;
var payoutService = (IPayoutService)svcProvider.GetService(typeof(IPayoutService));
var appUserService = (IAppUserService)svcProvider.GetService(typeof(IAppUserService));
var systemMessageService = (ISystemMessageService)svcProvider.GetService(typeof(ISystemMessageService));
var appHubSender = (IAppHubSender)svcProvider.GetService(typeof(IAppHubSender));
if (payoutService != null && appUserService != null && systemMessageService != null && appHubSender != null)
{
var payout = await payoutService.GetByMangoPayIdAsync(payoutId);
if (payout != null)
{
var payoutResult = await _mangoPayService.GetPayoutAsync(payoutId);
if (payoutResult != null && payoutResult.Success)
{
payout.Status = payoutResult.Value.Status;
payout.ExecutionDate = payoutResult.Value.ExecutionDate;
payout.ResultCode = payoutResult.Value.ResultCode;
payout.ResultMessage = payoutResult.Value.ResultMessage;
payout.UpdatedAt = DateTimeOffset.UtcNow;
await payoutService.CommitAsync("System");
var appUser = await appUserService.GetAsync(payout.AppUserId);
//Benachrichtigung
if (appUser != null)
{
if (appUser.Type == AppUserType.DogOwner || appUser.Type == AppUserType.Both)
{
systemMessageService.Add(appUser.Id, AppUserType.DogOwner, payout.Id, SystemMessageTables.Payout, SystemMessageType.PayoutUpdate, DateTimeOffset.UtcNow.AddDays(14));
await _systemMessageService.CommitAsync(User.Identity.Name);
await _appHubSender.SystemMessageAddedAsync(appUser.Id);
await _pushNotificationService.SendPayoutUpdateAsync(appUser.Id, payout.Id);
}
else if (appUser.Type == AppUserType.DogWalker || appUser.Type == AppUserType.Both)
{
systemMessageService.Add(appUser.Id, AppUserType.DogWalker, payout.Id, SystemMessageTables.Payout, SystemMessageType.PayoutUpdate, DateTimeOffset.UtcNow.AddDays(14));
await _systemMessageService.CommitAsync(User.Identity.Name);
await _appHubSender.SystemMessageAddedAsync(appUser.Id);
await _pushNotificationService.SendPayoutUpdateAsync(appUser.Id, payout.Id);
}
}
}
}
}
await Task.Delay(1);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
}
}
/// <summary>
/// Eine Auszahlung ist gescheitert und wurde zurücküberwiesen
/// </summary>
/// <param name="refundId">Id der Rückzahlung</param>
/// <param name="resolver">IServiceScopeFactory</param>
/// <returns>Task</returns>
private async Task HandlePayOutRefunded(string refundId, IServiceScopeFactory resolver)
{
try
{
using var scope = resolver.CreateScope();
var svcProvider = scope.ServiceProvider;
var payoutService = (IPayoutService)svcProvider.GetService(typeof(IPayoutService));
var appUserService = (IAppUserService)svcProvider.GetService(typeof(IAppUserService));
var systemMessageService = (ISystemMessageService)svcProvider.GetService(typeof(ISystemMessageService));
var appHubSender = (IAppHubSender)svcProvider.GetService(typeof(IAppHubSender));
if (payoutService != null && appUserService != null && systemMessageService != null && appHubSender != null)
{
var refundResult = await _mangoPayService.GetRefundAsync(refundId);
if (refundResult.Success && refundResult.Value.Status == PaymentTransactionStatus.SUCCEEDED)
{
var payout = await payoutService.GetByMangoPayIdAsync(refundResult.Value.OriginalTransactionId);
if (payout != null)
{
payout.Status = PaymentTransactionStatus.FAILED;
payout.Refunded = true;
payout.RefundReasonType = refundResult.Value.RefundReasonType;
payout.RefundReasonMessage = refundResult.Value.RefundReasonMessage;
payout.UpdatedAt = DateTimeOffset.UtcNow;
await payoutService.CommitAsync("System");
var appUser = await appUserService.GetAsync(payout.AppUserId);
//Benachrichtigung
if (appUser != null)
{
if (appUser.Type == AppUserType.DogOwner || appUser.Type == AppUserType.Both)
{
systemMessageService.Add(appUser.Id, AppUserType.DogOwner, payout.Id, SystemMessageTables.Payout, SystemMessageType.PayoutUpdate, DateTimeOffset.UtcNow.AddDays(14));
await _systemMessageService.CommitAsync(User.Identity.Name);
await _appHubSender.SystemMessageAddedAsync(appUser.Id);
await _pushNotificationService.SendPayoutUpdateAsync(appUser.Id, payout.Id);
}
else if (appUser.Type == AppUserType.DogWalker || appUser.Type == AppUserType.Both)
{
systemMessageService.Add(appUser.Id, AppUserType.DogWalker, payout.Id, SystemMessageTables.Payout, SystemMessageType.PayoutUpdate, DateTimeOffset.UtcNow.AddDays(14));
await _systemMessageService.CommitAsync(User.Identity.Name);
await _appHubSender.SystemMessageAddedAsync(appUser.Id);
await _pushNotificationService.SendPayoutUpdateAsync(appUser.Id, payout.Id);
}
}
}
}
}
await Task.Delay(1);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
}
}
/// <summary>
/// Eine Einzahlung war erfolgreich
/// </summary>
/// <param name="payinId">Id der Einzahlung</param>
/// <param name="resolver">IServiceScopeFactory</param>
/// <returns>Task</returns>
private async Task HandlePayInSucceeded(string payinId, IServiceScopeFactory resolver)
{
//30 Sekunden warten, falls der Event schneller kommen sollte als in der App
await Task.Delay(30000);
try
{
using var scope = resolver.CreateScope();
var svcProvider = scope.ServiceProvider;
var paymentTransactionService = (IPaymentTransactionService)svcProvider.GetService(typeof(IPaymentTransactionService));
var appUserService = (IAppUserService)svcProvider.GetService(typeof(IAppUserService));
var systemMessageService = (ISystemMessageService)svcProvider.GetService(typeof(ISystemMessageService));
var appHubSender = (IAppHubSender)svcProvider.GetService(typeof(IAppHubSender));
if (paymentTransactionService != null && appUserService != null && systemMessageService != null && appHubSender != null)
{
var paymentTransaction = await paymentTransactionService.GetAsync(payinId, PaymentTransactionType.PayIn);
if (paymentTransaction != null)
{
//Es muss zumindest eine Transaktion geben die den Status CREATED hat
if (paymentTransaction.Status == PaymentTransactionStatus.CREATED)
{
var paymentTransactionSuccess = _paymentTransactionService.Create(payinId, PaymentTransactionType.PayIn, PaymentTransactionStatus.SUCCEEDED, paymentTransaction.WalkId, paymentTransaction.TargetAppUserId, paymentTransaction.TargetWalletId, string.Empty, string.Empty, paymentTransaction.Ammount, paymentTransaction.FromCredit, "EUR", paymentTransaction.PayInType);
_paymentTransactionService.Add(paymentTransactionSuccess);
await _paymentTransactionService.CommitAsync("System");
//_logger.LogWarning($"PayInReturn: PaymentTansaction with status SUCCEEDED created");
//Die Zahlung war erfolgreich. Also dies nun beim Walk ablegen und die Benutzer benachrichtigen
var walk = await _walkService.GetAsync(paymentTransactionSuccess.WalkId);
if (walk != null)
{
//_logger.LogWarning($"PayInReturn: Walk exists");
//Wenn noch ein Teil vom Guthabenkonto genommen werden muss
if (paymentTransactionSuccess.FromCredit > 0)
{
var tag = $"Walk_Authorize_{walk.Id}";
await _mangoPayService.TransferMoneyFromCreditToFeeAccountAsync(walk.DogOwnerId, paymentTransactionSuccess.FromCredit, tag);
//_logger.LogWarning($"PayInReturn: TransferMoneyFromCreditToFeeAccountAsync done");
}
walk.PaymentStatus = PaymentStatus.Authorized;
walk.UpdatedAt = DateTimeOffset.UtcNow;
await _walkService.CommitAsync("System");
//_logger.LogWarning($"PayInReturn: Paymentstatus set to Authorized");
//Wallets aktualisieren
await _mangoPayService.GetWalletBalanceAsync(walk.DogOwnerId, WalletType.Credits);
await _mangoPayService.GetWalletBalanceAsync(walk.DogOwnerId, WalletType.Fees);
//_logger.LogWarning($"PayInReturn: Wallets updated");
//Überlappende Walks die im Status "Request" sind, stornieren
await _walkService.CancelWalkRequestsAsync(walk.DogWalkerId, walk.Start, walk.End);
await _walkService.CommitAsync("System");
//_logger.LogWarning($"PayInReturn: CancelWalkRequestsAsync done");
//Walker informieren. TODO: pushnotification?
_systemMessageService.Add(walk.DogWalkerId, AppUserType.DogWalker, walk.Id, SystemMessageTables.Walk, SystemMessageType.WalkAdded, DateTimeOffset.UtcNow.AddDays(14));
await _systemMessageService.CommitAsync("System");
await _appHubSender.SystemMessageAddedAsync(walk.DogWalkerId);
await _pushNotificationService.SendNewWalkAsync(walk.DogWalkerId, walk.Id);
}
}
}
}
await Task.Delay(1);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
}
}
/// <summary>
/// Eine Einzahlung war nicht erfolgreich
/// </summary>
/// <param name="payinId">Id der Einzahlung</param>
/// <param name="resolver">IServiceScopeFactory</param>
/// <returns>Task</returns>
private async Task HandlePayInFailed(string payinId, IServiceScopeFactory resolver)
{
//30 Sekunden warten, falls der Event schneller kommen sollte als in der App
await Task.Delay(30000);
try
{
using var scope = resolver.CreateScope();
var svcProvider = scope.ServiceProvider;
var paymentTransactionService = (IPaymentTransactionService)svcProvider.GetService(typeof(IPaymentTransactionService));
var appUserService = (IAppUserService)svcProvider.GetService(typeof(IAppUserService));
var systemMessageService = (ISystemMessageService)svcProvider.GetService(typeof(ISystemMessageService));
var appHubSender = (IAppHubSender)svcProvider.GetService(typeof(IAppHubSender));
if (paymentTransactionService != null && appUserService != null && systemMessageService != null && appHubSender != null)
{
var paymentTransaction = await paymentTransactionService.GetAsync(payinId, PaymentTransactionType.PayIn);
if (paymentTransaction != null)
{
//Es muss zumindest eine Transaktion geben die den Status CREATED hat
if (paymentTransaction.Status == PaymentTransactionStatus.CREATED)
{
var paymentTransactionFailed = _paymentTransactionService.Create(payinId, PaymentTransactionType.PayIn, PaymentTransactionStatus.FAILED, paymentTransaction.WalkId, paymentTransaction.TargetAppUserId, paymentTransaction.TargetWalletId, string.Empty, string.Empty, paymentTransaction.Ammount, paymentTransaction.FromCredit, "EUR", paymentTransaction.PayInType);
_paymentTransactionService.Add(paymentTransactionFailed);
await _paymentTransactionService.CommitAsync("System");
//_logger.LogWarning($"PayInReturn: PaymentTansaction with status SUCCEEDED created");
//Die Zahlung war erfolgreich. Also dies nun beim Walk ablegen und die Benutzer benachrichtigen
var walk = await _walkService.GetAsync(paymentTransactionFailed.WalkId);
if (walk != null)
{
walk.PaymentStatus = PaymentStatus.Pending;
walk.UpdatedAt = DateTimeOffset.UtcNow;
await _walkService.CommitAsync("System");
//Owner informieren.
_systemMessageService.Add(walk.DogOwnerId, AppUserType.DogOwner, walk.Id, SystemMessageTables.Walk, SystemMessageType.WalkChanged, DateTimeOffset.UtcNow.AddDays(14));
await _systemMessageService.CommitAsync("System");
await _appHubSender.SystemMessageAddedAsync(walk.DogOwnerId);
await _pushNotificationService.SendWalkPaymentFailedAsync(walk.DogOwnerId, walk.Id);
}
}
}
}
await Task.Delay(1);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
}
}
#endregion
}
}