/// <inheritdoc />
        public virtual IGateway Provide(string gatewayName)
        {
            var descriptors = _services.GetServices <GatewayDescriptor>();

            var comparedDescriptors = descriptors
                                      .Where(descriptor => GatewayHelper.CompareName(descriptor.GatewayType, gatewayName))
                                      .ToList();

            if (comparedDescriptors.Count == 0)
            {
                throw new GatewayNotFoundException(gatewayName);
            }
            if (comparedDescriptors.Count > 1)
            {
                throw new InvalidOperationException($"More than one gateway with the name {gatewayName} found.");
            }

            var gateway = _services.GetService(comparedDescriptors[0].GatewayType);

            if (gateway == null)
            {
                throw new GatewayNotFoundException(gatewayName);
            }

            return((IGateway)gateway);
        }
Exemple #2
0
        public virtual IInvoiceBuilder SetGatewayType(Type gatewayType)
        {
            GatewayHelper.IsGateway(gatewayType, throwException: true);

            _gatewayType = gatewayType;

            return(this);
        }
        /// <summary>
        /// </summary>
        /// <param name="gatewayProvider"></param>
        /// <param name="gatewayName"></param>
        /// <exception cref="GatewayNotFoundException"></exception>
        /// <exception cref="ArgumentNullException"></exception>
        public static IGateway Provide(this IGatewayProvider gatewayProvider, string gatewayName)
        {
            if (gatewayProvider == null)
            {
                throw new ArgumentNullException(nameof(gatewayProvider));
            }

            return(gatewayProvider.Provide(GatewayHelper.FindGatewayTypeByName(gatewayName)));
        }
Exemple #4
0
        /// <inheritdoc />
        public virtual IGateway Provide(Type gatewayType)
        {
            GatewayHelper.IsGateway(gatewayType, throwException: true);

            var gateway = _services.GetService(gatewayType);

            if (gateway == null)
            {
                throw new GatewayNotFoundException(GatewayHelper.GetNameByType(gatewayType));
            }

            return((IGateway)gateway);
        }
Exemple #5
0
        /// <inheritdoc />
        public virtual async Task <IPaymentRequestResult> RequestAsync(Invoice invoice, CancellationToken cancellationToken = default)
        {
            if (invoice == null)
            {
                throw new ArgumentNullException(nameof(invoice));
            }


            _logger.LogInformation(LoggingEvents.RequestPayment, $"New payment request with the tracking number {invoice.TrackingNumber} is started." +
                                   $"{nameof(invoice.Amount)}:{invoice.Amount}" +
                                   $"GatewayName:{GatewayHelper.GetNameByType(invoice.GatewayType)}");

            //  Check the tracking number
            if (await _database.Payments
                .AnyAsync(model => model.TrackingNumber == invoice.TrackingNumber, cancellationToken)
                .ConfigureAwaitFalse())
            {
                _logger.LogInformation(LoggingEvents.RequestPayment, _messagesOptions.Value.DuplicateTrackingNumber);

                return(new PaymentRequestResult
                {
                    TrackingNumber = invoice.TrackingNumber,
                    IsSucceed = false,
                    Message = _messagesOptions.Value.DuplicateTrackingNumber,
                    GatewayTransporter = new NullGatewayTransporter()
                });
            }

            //  Check the payment token
            var paymentToken = await _tokenProvider
                               .ProvideTokenAsync(invoice, cancellationToken)
                               .ConfigureAwaitFalse();

            if (await _database.Payments
                .AnyAsync(model => model.Token == paymentToken, cancellationToken)
                .ConfigureAwaitFalse())
            {
                var message = $"The payment token \"{paymentToken}\" already exists.";

                _logger.LogError(LoggingEvents.RequestPayment, message);

                throw new PaymentTokenProviderException(message);
            }

            var gateway = _gatewayProvider.Provide(invoice.GatewayType);

            //  Add database
            var newPayment = new Payment
            {
                TrackingNumber = invoice.TrackingNumber,
                Amount         = invoice.Amount,
                IsCompleted    = false,
                IsPaid         = false,
                Token          = paymentToken,
                GatewayName    = gateway.GetName(),
                CreatedOn      = DateTime.UtcNow
            };

            _database.Payments.Add(newPayment);

            if (await _database.SaveChangesAsync(cancellationToken).ConfigureAwaitFalse() == 0)
            {
                _logger.LogError(LoggingEvents.RequestPayment, "Nothing is saved into the database.");
                throw new DatabaseSaveRecordException();
            }

            _logger.LogInformation(LoggingEvents.RequestPayment, $"The payment with tracking number {invoice.TrackingNumber} is about to processing." +
                                   $"{nameof(invoice.Amount)}:{invoice.Amount}" +
                                   $"GatewayName:{GatewayHelper.GetNameByType(invoice.GatewayType)}");

            PaymentRequestResult requestResult;

            try
            {
                requestResult = await gateway
                                .RequestAsync(invoice, cancellationToken)
                                .ConfigureAwaitFalse() as PaymentRequestResult;

                if (requestResult == null)
                {
                    throw new Exception($"Gateway {gateway.GetName()} returns null instead of a result.");
                }
            }
            catch (Exception exception)
            {
                string exceptionMessage;

                if (exception is OptionsValidationException)
                {
                    exceptionMessage = $"Gateway {gateway.GetName()} is not configured or has some validation errors.";
                }
                else
                {
                    exceptionMessage = exception.Message;
                }

                _logger.LogError(exception, exceptionMessage);

                newPayment.IsCompleted = true;
                newPayment.IsPaid      = false;
                newPayment.UpdatedOn   = DateTime.UtcNow;

                requestResult = PaymentRequestResult.Failed(exceptionMessage);
            }

            requestResult.TrackingNumber = invoice.TrackingNumber;
            requestResult.Amount         = invoice.Amount;
            requestResult.GatewayName    = gateway.GetName();

            newPayment.Transactions.Add(new Transaction
            {
                Amount         = invoice.Amount,
                Type           = TransactionType.Request,
                IsSucceed      = requestResult.IsSucceed,
                Message        = requestResult.Message,
                AdditionalData = AdditionalDataConverter.ToJson(requestResult),
                CreatedOn      = DateTime.UtcNow
            });

            if (await _database.SaveChangesAsync(cancellationToken).ConfigureAwaitFalse() == 0)
            {
                _logger.LogError(LoggingEvents.RequestPayment, "Nothing is saved into database.");
                throw new DatabaseSaveRecordException();
            }

            return(requestResult);
        }
        /// <inheritdoc />
        public virtual async Task <IPaymentRequestResult> RequestAsync(Invoice invoice, CancellationToken cancellationToken = default)
        {
            if (invoice == null)
            {
                throw new ArgumentNullException(nameof(invoice));
            }

            _logger.LogInformation(LoggingEvents.RequestPayment, $"New payment request with the tracking number {invoice.TrackingNumber} is started." +
                                   $"{nameof(invoice.Amount)}:{invoice.Amount}" +
                                   $"GatewayName:{GatewayHelper.GetNameByType(invoice.GatewayType)}");

            //  Check the tracking number
            if (await _storageManager.DoesPaymentExistAsync(invoice.TrackingNumber, cancellationToken).ConfigureAwaitFalse())
            {
                _logger.LogInformation(LoggingEvents.RequestPayment, _messagesOptions.Value.DuplicateTrackingNumber);

                return(new PaymentRequestResult
                {
                    TrackingNumber = invoice.TrackingNumber,
                    IsSucceed = false,
                    Message = _messagesOptions.Value.DuplicateTrackingNumber,
                    GatewayTransporter = new NullGatewayTransporter()
                });
            }

            // Create a payment token
            var paymentToken = await _tokenProvider
                               .ProvideTokenAsync(invoice, cancellationToken)
                               .ConfigureAwaitFalse();

            //  Check the created payment token
            if (await _storageManager.DoesPaymentExistAsync(paymentToken, cancellationToken).ConfigureAwaitFalse())
            {
                var message = $"The payment token \"{paymentToken}\" already exists.";

                _logger.LogError(LoggingEvents.RequestPayment, message);

                throw new PaymentTokenProviderException(message);
            }

            var gateway = _gatewayProvider.Provide(invoice.GatewayType);

            var newPayment = new Payment
            {
                TrackingNumber = invoice.TrackingNumber,
                Amount         = invoice.Amount,
                IsCompleted    = false,
                IsPaid         = false,
                Token          = paymentToken,
                GatewayName    = gateway.GetName()
            };

            await _storageManager.CreatePaymentAsync(newPayment, cancellationToken).ConfigureAwaitFalse();

            _logger.LogInformation(LoggingEvents.RequestPayment, $"The payment with tracking number {invoice.TrackingNumber} is about to processing." +
                                   $"{nameof(invoice.Amount)}:{invoice.Amount}" +
                                   $"GatewayName:{GatewayHelper.GetNameByType(invoice.GatewayType)}");

            PaymentRequestResult requestResult;

            try
            {
                requestResult = await gateway
                                .RequestAsync(invoice, cancellationToken)
                                .ConfigureAwaitFalse() as PaymentRequestResult;

                if (requestResult == null)
                {
                    throw new Exception($"Gateway {gateway.GetName()} returns null instead of a result.");
                }
            }
            catch (Exception exception)
            {
                _logger.LogError(exception, exception.Message);

                newPayment.IsCompleted = true;
                newPayment.IsPaid      = false;

                requestResult = PaymentRequestResult.Failed(exception.Message);
            }

            requestResult.TrackingNumber = invoice.TrackingNumber;
            requestResult.Amount         = invoice.Amount;
            requestResult.GatewayName    = gateway.GetName();

            newPayment.GatewayAccountName = requestResult.GatewayAccountName;

            await _storageManager.UpdatePaymentAsync(newPayment, cancellationToken).ConfigureAwaitFalse();

            var newTransaction = new Transaction
            {
                Amount         = invoice.Amount,
                Type           = TransactionType.Request,
                IsSucceed      = requestResult.IsSucceed,
                Message        = requestResult.Message,
                AdditionalData = AdditionalDataConverter.ToJson(requestResult),
                PaymentId      = newPayment.Id
            };

            await _storageManager.CreateTransactionAsync(newTransaction, cancellationToken).ConfigureAwaitFalse();

            return(requestResult);
        }