예제 #1
0
        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);
            }
        }
예제 #3
0
        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
            });
        }
예제 #4
0
        //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());
            }
        }
예제 #5
0
        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;
            }
        }
예제 #6
0
        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"
                    }
                });
            }
        }