public async Task Business_Checking_AuthCapture_Successfully_Debit_Test()
        {
            var services = new ServiceCollection();

            services.AddSingleton(_configuration);
            services.AddLogging(b => b.AddXunit(_output));
            services.AddAuthorizeNet();
            var sp = services.BuildServiceProvider();

            var client  = sp.GetRequiredService <ITransactionClient>();
            var options = sp.GetRequiredService <IOptions <AuthorizeNetOptions> >();

            var randomAccountNumber = new Random().Next(10000, int.MaxValue);

            var request = new CreateTransactionRequest
            {
                TransactionRequest = new TransactionRequestType
                {
                    TransactionType = Enum.GetName(typeof(TransactionTypeEnum), TransactionTypeEnum.AuthCaptureTransaction),
                    Amount          = 13.01m,
                    Payment         = new PaymentType
                    {
                        BankAccount = new BankAccountType
                        {
                            BankName      = "Bank of China",
                            AccountType   = BankAccountTypeEnum.BusinessChecking,
                            RoutingNumber = "125008547",
                            AccountNumber = randomAccountNumber.ToString(),

                            // CheckNumber = "",
                            NameOnAccount = "Biden",
                            EcheckType    = EcheckTypeEnum.CCD
                        },
                    },
                    CustomerIP = options.Value.IpAddress,
                    Order      = new OrderType
                    {
                        InvoiceNumber = "BC-Invoice-789",
                        Description   = "Business Checking e-Check purchase"
                    },
                },
            };

            var response = await client.CreateAsync(request);

            _output.WriteLine($"{response.TransactionResponse.ResponseCode} - {response.TransactionResponse.TransId}");

            Assert.Equal(MessageTypeEnum.Ok, response.Messages.ResultCode);

            var code = response.Messages.Message[0].Code;
            var text = response.Messages.Message[0].Text;

            Assert.Equal("I00001", code);
            Assert.Equal("Successful.", text);

            var tcode = response.TransactionResponse.Messages[0].Code;
            var ttext = response.TransactionResponse.Messages[0].Description;

            Assert.Equal("1", tcode);
            Assert.Equal("This transaction has been approved.", ttext);

            // 1 success
            Assert.Equal("1", response.TransactionResponse.ResponseCode);
            Assert.True(!string.IsNullOrEmpty(response.TransactionResponse.TransId));
            Assert.False(response.TransactionResponse.Errors.Any());
        }
Exemple #2
0
 public Task CreatePaymentTransactionAsync(CreateTransactionRequest request)
 {
     return(_runner.RunWithDefaultErrorHandlingAsync(() => _payInternalApi.CreatePaymentTransactionAsync(request)));
 }
        public async Task ExecuteAsync()
        {
            IEnumerable <WalletState> cacheState = await _cacheMaintainer.GetAsync();

            foreach (var walletState in cacheState)
            {
                if (walletState.Blockchain != BlockchainType.Bitcoin)
                {
                    continue;
                }

                BalanceModel balance;

                try
                {
                    balance = await _qBitNinjaClient.GetBalance(BitcoinAddress.Create(walletState.Address));
                }
                catch (Exception ex)
                {
                    _log.Error(ex, "Getting balance from ninja", walletState.ToDetails());

                    continue;
                }

                IEnumerable <PaymentBcnTransaction> bcnTransactions =
                    GetIncomingPaymentOperations(balance, walletState.Address)?.ToList() ??
                    new List <PaymentBcnTransaction>();

                IEnumerable <PaymentBcnTransaction> cacheTransactions = walletState.Transactions;

                IEnumerable <DiffResult <PaymentBcnTransaction> > diff = _diffService.Diff(cacheTransactions, bcnTransactions);

                // catching case when ninja returns no transactions but should
                if (cacheTransactions.Any() && !bcnTransactions.Any())
                {
                    _log.Info("There are no transactions from ninja, but there are transactions in cache",
                              $"wallet: {walletState.Address}, walletState: {walletState.ToJson()}");
                }

                // catching case when there are any differences between ninja state and local cache state
                if (diff.Any())
                {
                    _log.Info("The difference between cache state and ninja detected",
                              $"wallet: {walletState.Address}, old txs: {walletState.Transactions.ToJson()}, new txs: {bcnTransactions.ToJson()}");
                }

                // approach to exit loop with switch statement inside
                bool isSyncError = false;

                foreach (var diffResult in diff)
                {
                    var tx = diffResult.Object;

                    switch (diffResult.CompareState)
                    {
                    case DiffState.New:

                        CreateTransactionRequest createRequest = null;

                        try
                        {
                            var txDetails = await _qBitNinjaClient.GetTransaction(new uint256(tx.Id));

                            createRequest = tx.ToCreateRequest(txDetails, _bitcoinNetwork);

                            _log.Info("New transaction detected",
                                      $"wallet: {walletState.Address}, Hash: {tx.Id}, FirstSeen: {txDetails.FirstSeen}");

                            await _log.LogPayInternalExceptionIfAny(() =>
                                                                    _payInternalClient.CreatePaymentTransactionAsync(createRequest));
                        }
                        catch (Exception ex)
                        {
                            _log.Error(ex, context: createRequest.ToDetails());

                            isSyncError = true;
                        }

                        break;

                    case DiffState.Updated:

                        UpdateTransactionRequest updateRequest = null;

                        try
                        {
                            updateRequest = tx.ToUpdateRequest();

                            _log.Info("Transaction update detected",
                                      $"wallet: {walletState.Address}, new tx state: {tx.ToJson()}");

                            await _log.LogPayInternalExceptionIfAny(() =>
                                                                    _payInternalClient.UpdateTransactionAsync(updateRequest));
                        }
                        catch (Exception ex)
                        {
                            _log.Error(ex, context: updateRequest.ToDetails());

                            isSyncError = true;
                        }

                        break;

                    default: throw new Exception("Unknown transactions diff state");
                    }

                    // stop changes processing in case there is PayInternal sync error
                    if (isSyncError)
                    {
                        break;
                    }
                }

                if (bcnTransactions.Any())
                {
                    walletState.Transactions = bcnTransactions;
                }

                // will sync internal cache with blockchain only if there were no errors while processing changes
                // otherwise the changes will be processed again in the next job cycle
                // WARNING: the approach will work only for single transactions update
                if (!isSyncError)
                {
                    try
                    {
                        await _cacheMaintainer.SetItemAsync(walletState);
                    }
                    catch (Exception ex)
                    {
                        _log.Error(ex, "Updating wallets cache", walletState.ToDetails());

                        continue;
                    }
                }
            }
        }
Exemple #4
0
 public CreateTransactionCommand(Guid id, CreateTransactionRequest transaction) : base(id)
 {
     Transaction = transaction;
 }