public async Task <bool> Handle(DirectPaymentCommand request, CancellationToken cancellationToken) { var id = Guid.NewGuid(); await AddAsync(async() => { var state = PaymentTransaction.Create(id.ToString(), request.Msisdn, request.OrderId, DateTime.Now); PaymentTransaction.SetMoney(state, request.Amount.Value); return(state); }, id); return(await Task.FromResult(true)); }
public async Task HandleCashInOperation(IAsset asset, double amount, string clientId, string clientAddress, string hash) { var id = Guid.NewGuid().ToString("N"); var pt = await _paymentTransactionsRepository.TryCreateAsync(PaymentTransaction.Create(hash, CashInPaymentSystem.Ethereum, clientId, amount, asset.DisplayId ?? asset.Id, status: PaymentStatus.Processing)); if (pt == null) { await _log.WriteWarningAsync(nameof(EthereumEventsQueue), nameof(HandleCashInOperation), hash, "Transaction already handled"); //return if was handled previously return; } var result = await _matchingEngineClient.CashInOutAsync(id, clientId, asset.Id, amount); if (result == null || result.Status != MeStatusCodes.Ok) { await _log.WriteWarningAsync(nameof(EthereumEventsQueue), nameof(HandleCashInOperation), "ME error", result.ToJson()); } else { var walletCreds = await _walletCredentialsRepository.GetAsync(clientId); await _cashOperationsRepository.RegisterAsync(new CashInOutOperation { Id = id, ClientId = clientId, Multisig = walletCreds.MultiSig, AssetId = asset.Id, Amount = amount, BlockChainHash = hash, DateTime = DateTime.UtcNow, AddressTo = clientAddress, State = TransactionStates.SettledOnchain }); var clientAcc = await _clientAccountsRepository.GetByIdAsync(clientId); await _srvEmailsFacade.SendNoRefundDepositDoneMail(clientAcc.Email, amount, asset.Id); await _paymentTransactionsRepository.SetStatus(hash, PaymentStatus.NotifyProcessed); } }
private async Task HandleCashInOperation(Asset asset, decimal amount, Guid clientId, string clientAddress, string hash, IEventPublisher eventPublisher, bool createPendingActions = false) { var exists = await _paymentTransactionsRepository.CheckExistsAsync(PaymentTransaction.Create(hash, CashInPaymentSystem.Ethereum, clientId.ToString(), (double)amount, asset.DisplayId ?? asset.Id, status: PaymentStatus.Processing)); if (exists) { return; } eventPublisher.PublishEvent(new CashinDetectedEvent { ClientId = clientId, ClientAddress = clientAddress, AssetId = asset.Id, Amount = amount, TransactionHash = hash, CreatePendingActions = createPendingActions }); }
//TODO: Split wth the help of the process management private async Task ProcessFailedCashout(ProcessEthCoinEventCommand queueMessage) { CashOutContextData context = await _transactionService.GetTransactionContext <CashOutContextData>(queueMessage.OperationId); if (context != null) { string transactionHandlerUserId = "auto redeem"; string clientId = context.ClientId; string hash = queueMessage.TransactionHash; string cashOperationId = context.CashOperationId; string assetId = context.AssetId; var amount = context.Amount; try { ChaosKitty.Meow(); var asset = await _assetsService.AssetGetAsync(assetId); await _cashOperationsRepositoryClient.UpdateBlockchainHashAsync(clientId, cashOperationId, hash); var pt = await _paymentTransactionsRepository.TryCreateAsync(PaymentTransaction.Create(hash, CashInPaymentSystem.Ethereum, clientId, (double)amount, asset.DisplayId ?? asset.Id, status: PaymentStatus.Processing)); if (pt == null) { _log.Warning($"{nameof(EthereumCoreCommandHandler)}:{nameof(ProcessFailedCashout)}", "Transaction already handled", context: hash); return; //if was handled previously } ChaosKitty.Meow(); var sign = "+"; var commentText = $"Balance Update: {sign}{amount} {asset.Name}. Cashout failed: {hash} {queueMessage.OperationId}"; var newComment = new ClientComment { ClientId = clientId, Comment = commentText, CreatedAt = DateTime.UtcNow, FullName = "Lykke.Job.TransactionHandler", UserId = transactionHandlerUserId }; var exResult = await _exchangeOperationsServiceClient.ExchangeOperations.ManualCashInAsync( new ManualCashInRequestModel { ClientId = clientId, AssetId = assetId, Amount = (double)amount, UserId = "auto redeem", Comment = commentText, }); if (!exResult.IsOk()) { _log.Warning($"{nameof(EthereumCoreCommandHandler)}:{nameof(ProcessFailedCashout)}", "ME operation failed", context: new { ExchangeServiceResponse = exResult, QueueMessage = queueMessage }.ToJson()); } await _clientCommentsRepository.AddClientCommentAsync(newComment); await _paymentTransactionsRepository.SetStatus(hash, PaymentStatus.NotifyProcessed); ChaosKitty.Meow(); } catch (Exception e) { _log.Error($"{nameof(EthereumCoreCommandHandler)}:{nameof(ProcessFailedCashout)}", e, context: queueMessage.ToJson()); throw; } } else { _log.Warning("Can't get a context", context: queueMessage.ToJson()); } }
public async Task <CommandHandlingResult> Handle(EnrollEthCashinToMatchingEngineCommand command, IEventPublisher eventPublisher) { try { var cashinId = command.CashinOperationId.ToString("N"); var clientId = command.ClientId; var hash = command.TransactionHash; var amount = command.Amount; var asset = await _assetsServiceWithCache.TryGetAssetAsync(command.AssetId); var createPendingActions = command.CreatePendingActions; var paymentTransaction = PaymentTransaction.Create(hash, CashInPaymentSystem.Ethereum, clientId.ToString(), (double)amount, asset.DisplayId ?? asset.Id, status: PaymentStatus.Processing); var exists = await _paymentTransactionsRepository.CheckExistsAsync(paymentTransaction); if (exists) { _log.Warning(command.TransactionHash ?? "Empty", $"Transaction already handled {hash}", context: command); return(CommandHandlingResult.Ok()); } if (createPendingActions && asset.IsTrusted) { await _ethererumPendingActionsRepository.CreateAsync(clientId.ToString(), Guid.NewGuid().ToString()); } ChaosKitty.Meow(); MeResponseModel result = null; await ExecuteWithTimeoutHelper.ExecuteWithTimeoutAsync(async() => { result = await _matchingEngineClient.CashInOutAsync(cashinId, clientId.ToString(), asset.Id, (double)amount); }, 5 * 60 * 1000); // 5 min in ms if (result == null || (result.Status != MeStatusCodes.Ok && result.Status != MeStatusCodes.Duplicate)) { _log.Warning(command.TransactionHash ?? "Empty", "ME error", context: result); return(CommandHandlingResult.Fail(TimeSpan.FromMinutes(1))); } eventPublisher.PublishEvent(new EthCashinEnrolledToMatchingEngineEvent() { TransactionHash = hash, }); ChaosKitty.Meow(); await _paymentTransactionsRepository.TryCreateAsync(paymentTransaction); return(CommandHandlingResult.Ok()); } catch (Exception e) { _log.Error(nameof(EnrollEthCashinToMatchingEngineCommand), e, context: command); throw; } }
public override async Task <PaymentUrlResponse> GetPaymentUrl(PaymentUrlRequest request, ServerCallContext context) { try { string errorMessage = string.Empty; ErrorDetails.Types.ErrorType?errorType = null; if (_supportedCurrencies.Any() && !_supportedCurrencies.Contains(request.Transaction.AssetId)) { errorMessage = $"Asset {request.Transaction.AssetId} is not supported"; errorType = ErrorDetails.Types.ErrorType.CurrencyNotSupported; } if (_supportedCountries.Any() && !string.IsNullOrEmpty(request.Details.CountryIso3) && !_supportedCountries.Contains(request.Details.CountryIso3)) { errorMessage = $"Country {request.Details.CountryIso3} is not supported"; errorType = ErrorDetails.Types.ErrorType.CountryNotSupported; } if (errorType != null) { _log.Warning(errorMessage); return(new PaymentUrlResponse { Error = new ErrorDetails { ErrorType = errorType.Value, Message = errorMessage } }); } var bankCardsFees = await _feeCalculatorClient.GetBankCardFees(); var feeAmount = Math.Round(request.Transaction.Amount * bankCardsFees.Percentage, 15); var totalAmount = (decimal)request.Transaction.Amount + (decimal)feeAmount; var url = await _link4PayApiService.GetPaymentUrlAsync(new CardPaymentRequest { Merchant = new MerchantInfo { CustomerId = request.Transaction.ExternalClientId, MerchantId = _link4PaySettings.ClientId }, Transaction = new TransactionInfo { TxnAmount = totalAmount.ToString("F2"), CurrencyCode = request.Transaction.AssetId, TxnReference = request.Transaction.TransactionId, Payout = false }, Customer = new CustomerInfo { BillingAddress = new AddressInfo { FirstName = request.Details?.FirstName, LastName = request.Details?.LastName, EmailId = request.Details?.Email, MobileNo = request.Details?.Phone } }, Url = new UrlInfo { SuccessUrl = $"{(string.IsNullOrEmpty(request.Urls?.OkUrl?.Trim()) ? _successUrl : request.Urls?.OkUrl)}?v=1", FailUrl = string.IsNullOrEmpty(request.Urls?.FailUrl?.Trim()) ? _failUrl : request.Urls?.FailUrl, CancelUrl = string.IsNullOrEmpty(request.Urls?.CancelUrl?.Trim()) ? _cancelUrl : request.Urls?.CancelUrl } }); if (string.IsNullOrEmpty(url)) { return(new PaymentUrlResponse { Error = new ErrorDetails { ErrorType = ErrorDetails.Types.ErrorType.Unknown, Message = "Error getting the payment url" } }); } await _rawLogRepository.RegisterEventAsync( RawLogEvent.Create("Payment Url has been created", request.ToJson()), request.Transaction.ClientId); var info = OtherPaymentInfo.Create( firstName: request.Details.FirstName, lastName: request.Details.LastName, city: string.Empty, zip: string.Empty, address: string.Empty, country: request.Details.CountryIso3, email: request.Details.Email, contactPhone: request.Details.Phone, dateOfBirth: string.Empty) .ToJson(); var pt = PaymentTransaction.Create( request.Transaction.TransactionId, CashInPaymentSystem.Link4Pay, request.Transaction.ClientId, request.Transaction.Amount, feeAmount, request.Transaction.AssetId, null, request.Transaction.AssetId, info ); await Task.WhenAll( _paymentTransactionsRepository.CreateAsync(pt), _paymentTransactionEventsLog.WriteAsync(PaymentTransactionLogEvent.Create(request.Transaction.TransactionId, "", "Registered", request.Transaction.ClientId)), _paymentTransactionEventsLog.WriteAsync(PaymentTransactionLogEvent.Create(request.Transaction.TransactionId, url, "Payment Url has created", request.Transaction.ClientId)) ); return(new PaymentUrlResponse { PaymentUrl = url, OkUrl = $"{(string.IsNullOrEmpty(request.Urls?.OkUrl?.Trim()) ? _successUrl : request.Urls?.OkUrl)}?v=1", FailUrl = string.IsNullOrEmpty(request.Urls?.FailUrl?.Trim()) ? _failUrl : request.Urls?.FailUrl, CancelUrl = string.IsNullOrEmpty(request.Urls?.CancelUrl?.Trim()) ? _cancelUrl : request.Urls?.CancelUrl }); } catch (Exception ex) { _log.Error(ex); return(new PaymentUrlResponse { Error = new ErrorDetails { ErrorType = ErrorDetails.Types.ErrorType.Unknown, Message = "Error getting the payment url" } }); } }