private RefundResult PrepareRefundResult(IPaymentRequest paymentRequest,
                                                 TransferResult transferResult, DateTime refundDueDate)
        {
            var assetIds = transferResult.Transactions.Unique(x => x.AssetId).ToList();

            if (assetIds.MoreThanOne())
            {
                _log.Warning("Multiple assets are not expected", context: new
                {
                    PaymentResuest       = paymentRequest,
                    RefundTransferResult = transferResult
                });
            }

            return(new RefundResult
            {
                Amount = transferResult.GetSuccedeedTxs().Sum(x => x.Amount),
                AssetId = assetIds.Single(),
                PaymentRequestId = paymentRequest.Id,
                PaymentRequestWalletAddress = paymentRequest.WalletAddress,
                Transactions = transferResult.Transactions.Select(x => new RefundTransactionResult
                {
                    Amount = x.Amount,
                    AssetId = x.AssetId,
                    Blockchain = transferResult.Blockchain,
                    Hash = x.Hash,
                    SourceAddress = string.Join(";", x.Sources),
                    DestinationAddress = string.Join(";", x.Destinations)
                }),
                DueDate = refundDueDate,
                Timestamp = transferResult.Timestamp
            });
        }
示例#2
0
        public async Task <SettlementResult> SettleAsync(string merchantId, string paymentRequestId)
        {
            IPaymentRequest paymentRequest = await _paymentRequestRepository.GetAsync(merchantId, paymentRequestId);

            if (paymentRequest == null)
            {
                throw new PaymentRequestNotFoundException(merchantId, paymentRequestId);
            }

            if (!paymentRequest.StatusValidForSettlement())
            {
                throw new SettlementValidationException("Invalid status");
            }

            string sourceWalletAddress = await _walletsManager.ResolveBlockchainAddressAsync(
                paymentRequest.WalletAddress,
                paymentRequest.PaymentAssetId);

            string destWalletAddress;

            // check asset to settle to merchant wallet
            if (_autoSettleSettingsResolver.AllowToSettleToMerchantWallet(paymentRequest.PaymentAssetId))
            {
                destWalletAddress = (await _merchantWalletService.GetDefaultAsync(
                                         paymentRequest.MerchantId,
                                         paymentRequest.PaymentAssetId,
                                         PaymentDirection.Incoming))?.WalletAddress;
            }
            else
            {
                BlockchainType network = await _assetSettingsService.GetNetworkAsync(paymentRequest.PaymentAssetId);

                destWalletAddress = _autoSettleSettingsResolver.GetAutoSettleWallet(network);
            }

            if (string.IsNullOrEmpty(destWalletAddress))
            {
                throw new SettlementValidationException(
                          $"Destination wallet address is empty. Details: {new {paymentRequest.MerchantId, paymentRequest.PaymentAssetId}.ToJson()}");
            }

            TransferResult transferResult = await _settlementRetryPolicy
                                            .ExecuteAsync(() => _transferService.SettleThrowFail(
                                                              paymentRequest.PaymentAssetId,
                                                              sourceWalletAddress,
                                                              destWalletAddress));

            foreach (var transferResultTransaction in transferResult.Transactions)
            {
                IPaymentRequestTransaction settlementTx = await _transactionsService.CreateTransactionAsync(
                    new CreateTransactionCommand
                {
                    Amount                = transferResultTransaction.Amount,
                    Blockchain            = transferResult.Blockchain,
                    AssetId               = transferResultTransaction.AssetId,
                    WalletAddress         = paymentRequest.WalletAddress,
                    DueDate               = paymentRequest.DueDate,
                    IdentityType          = transferResultTransaction.IdentityType,
                    Identity              = transferResultTransaction.Identity,
                    Confirmations         = 0,
                    Hash                  = transferResultTransaction.Hash,
                    TransferId            = transferResult.Id,
                    Type                  = TransactionType.Settlement,
                    SourceWalletAddresses = transferResultTransaction.Sources.ToArray()
                });

                await _transactionPublisher.PublishAsync(settlementTx);
            }

            return(new SettlementResult
            {
                Blockchain = transferResult.Blockchain,
                WalletAddress = destWalletAddress,
                AssetId = paymentRequest.PaymentAssetId,
                Amount = transferResult.GetSuccedeedTxs().Sum(x => x.Amount)
            });
        }