Exemple #1
0
        public async Task <PaymentRequestResult> InitiatePartnerPaymentAsync(IPaymentRequest paymentRequest)
        {
            #region Validation

            if (string.IsNullOrEmpty(paymentRequest.CustomerId))
            {
                throw new ArgumentNullException(nameof(paymentRequest.CustomerId));
            }

            if (string.IsNullOrEmpty(paymentRequest.PartnerId))
            {
                throw new ArgumentNullException(nameof(paymentRequest.PartnerId));
            }

            if (string.IsNullOrEmpty(paymentRequest.Currency))
            {
                throw new ArgumentNullException(nameof(paymentRequest.Currency));
            }

            var isPartnerIdValidGuid = Guid.TryParse(paymentRequest.PartnerId, out var partnerId);

            if (!isPartnerIdValidGuid)
            {
                return(PaymentRequestResult.Failed(PaymentRequestErrorCodes.PartnerIdIsNotAValidGuid));
            }

            var isCustomerIdValidGuid = Guid.TryParse(paymentRequest.CustomerId, out var customerGuid);

            if (!isCustomerIdValidGuid)
            {
                return(PaymentRequestResult.Failed(PaymentRequestErrorCodes.CustomerIdIsNotAValidGuid));
            }

            //We can have either amount in Tokens or in Fiat
            if (paymentRequest.FiatAmount != null && paymentRequest.TokensAmount != null)
            {
                return(PaymentRequestResult.Failed(PaymentRequestErrorCodes.CannotPassBothFiatAndTokensAmount));
            }

            //Fiat or Tokens Amount must be provided
            if (paymentRequest.FiatAmount == null && paymentRequest.TokensAmount == null)
            {
                return(PaymentRequestResult.Failed(PaymentRequestErrorCodes.EitherFiatOrTokensAmountShouldBePassed));
            }

            if (paymentRequest.TokensAmount != null && paymentRequest.TokensAmount <= 0)
            {
                return(PaymentRequestResult.Failed(PaymentRequestErrorCodes.InvalidTokensAmount));
            }

            if (paymentRequest.FiatAmount != null && paymentRequest.FiatAmount <= 0)
            {
                return(PaymentRequestResult.Failed(PaymentRequestErrorCodes.InvalidFiatAmount));
            }

            if (paymentRequest.TotalBillAmount <= 0)
            {
                return(PaymentRequestResult.Failed(PaymentRequestErrorCodes.InvalidTotalBillAmount));
            }

            var customerProfile = await _customerProfileClient.CustomerProfiles.GetByCustomerIdAsync(paymentRequest.CustomerId);

            if (customerProfile.ErrorCode == CustomerProfileErrorCodes.CustomerProfileDoesNotExist)
            {
                return(PaymentRequestResult.Failed(PaymentRequestErrorCodes.CustomerDoesNotExist));
            }

            var customerWalletStatus =
                await _walletManagementClient.Api.GetCustomerWalletBlockStateAsync(paymentRequest.CustomerId);

            if (customerWalletStatus.Status == CustomerWalletActivityStatus.Blocked)
            {
                return(PaymentRequestResult.Failed(PaymentRequestErrorCodes.CustomerWalletBlocked));
            }

            var partnerDetails = await _partnerManagementClient.Partners.GetByIdAsync(partnerId);

            if (partnerDetails == null)
            {
                return(PaymentRequestResult.Failed(PaymentRequestErrorCodes.PartnerDoesNotExist));
            }

            if (!string.IsNullOrEmpty(paymentRequest.LocationId))
            {
                if (partnerDetails.Locations.All(x => x.Id.ToString() != paymentRequest.LocationId))
                {
                    return(PaymentRequestResult.Failed(PaymentRequestErrorCodes.NoSuchLocationForThisPartner));
                }
            }

            #endregion

            var paymentRequestId = Guid.NewGuid().ToString();

            paymentRequest.PaymentRequestId = paymentRequestId;

            //Blockchain does not accept null
            if (paymentRequest.LocationId == null)
            {
                paymentRequest.LocationId = "";
            }

            var convertOptimalByPartnerModel = new ConvertOptimalByPartnerRequest
            {
                CustomerId   = customerGuid,
                PartnerId    = partnerId,
                Amount       = paymentRequest.TokensAmount ?? paymentRequest.FiatAmount.Value,
                FromCurrency = paymentRequest.TokensAmount.HasValue ? _tokenSymbol : paymentRequest.Currency,
                ToCurrency   = paymentRequest.TokensAmount.HasValue ? paymentRequest.Currency : _tokenSymbol
            };

            var convertOptimalByPartnerResponse =
                await _eligibilityEngineClient.ConversionRate.ConvertOptimalByPartnerAsync(convertOptimalByPartnerModel);

            if (convertOptimalByPartnerResponse.ErrorCode != EligibilityEngineErrors.None)
            {
                if (convertOptimalByPartnerResponse.ErrorCode == EligibilityEngineErrors.PartnerNotFound)
                {
                    return(PaymentRequestResult.Failed(PaymentRequestErrorCodes.PartnerDoesNotExist));
                }
                if (convertOptimalByPartnerResponse.ErrorCode == EligibilityEngineErrors.ConversionRateNotFound)
                {
                    return(PaymentRequestResult.Failed(PaymentRequestErrorCodes.InvalidTokensOrCurrencyRateInPartner));
                }
            }

            paymentRequest.TokensToFiatConversionRate = convertOptimalByPartnerResponse.UsedRate;

            if (paymentRequest.FiatAmount == null)
            {
                paymentRequest.FiatAmount = (decimal)convertOptimalByPartnerResponse.Amount;
            }
            else
            {
                paymentRequest.TokensAmount = convertOptimalByPartnerResponse.Amount;
            }

            var now = DateTime.UtcNow;
            paymentRequest.CustomerActionExpirationTimestamp = paymentRequest.CustomerExpirationInSeconds.HasValue
                ? now.AddSeconds(paymentRequest.CustomerExpirationInSeconds.Value)
                : now.Add(_settingsService.GetRequestsExpirationPeriod());

            await _paymentsRepository.AddAsync(paymentRequest);

            await _paymentRequestCreatedPublisher.PublishAsync(new PartnerPaymentRequestCreatedEvent
            {
                PaymentRequestId = paymentRequestId,
                CustomerId       = paymentRequest.CustomerId,
                PartnerId        = paymentRequest.PartnerId,
                Timestamp        = DateTime.UtcNow
            });

            return(PaymentRequestResult.Succeeded(PaymentRequestStatus.Created, paymentRequestId));
        }