public void SecurePayGateway_PeriodicCharge_Setup_Then_Charge()
        {
            var p = new SecurePayPayment { Amount = ChargeAmount2, Currency = "AUD" };
            var id = SecurePayGateway.CreateClientId();
            var request = _gateway.CreateReadyToTriggerPaymentXml(ValidCard, id, p);
            DebugDisplay(request);

            var r = _gateway.SendMessage(request, "Setup_Then_Charge");

            Console.WriteLine("First Response");
            Console.WriteLine(r.Print());

            // Assert
            AssertStatusGoodSuccessMarkerNoConnectionIssuesForPeriodicPayment(r);

            request = _gateway.TriggerPeriodicPaymentXml(id, p);
            DebugDisplay(request);

            r = _gateway.SendMessage(request, "Setup_Then_Charge");

            Console.WriteLine("Second Response");
            Console.WriteLine(r.Print());

            // Assert
            AssertStatusGoodSuccessMarkerNoConnectionIssuesForPeriodicPayment(r);
        }
        public SecurePayMessage ChargeExistingCustomer(string clientId, SecurePayPayment payment)
        {
            var request = TriggerPeriodicPaymentXml(clientId, payment);

            var response = SendMessage(request, "ChargeExistingCustomer");

            return response;
        }
        public SecurePayMessage CreateCustomerWithCharge(string clientId, SecurePayCardInfo card, SecurePayPayment payment)
        {
            card.ValidateExpiry();

            var request = CreateReadyToTriggerPaymentXml(card, clientId, payment);

            var response = SendMessage(request, "CreateCustomerWithCharge");

            return response;
        }
        public SecurePayMessage SingleCharge(SecurePayCardInfo card, SecurePayPayment payment, string referenceId)
        {
            card.ValidateExpiry();

            var request = SinglePaymentXml(card, payment, referenceId);

            var response = SendMessage(request, "SingleCharge");

            return response;
        }
        public void GateWayReportsUnableToConnect_ScaleBackSlowlyFor5TriesToSeeIfItIsTransient()
        {
            // Arrange
            SecurePayMessage response = null;
            var clientId = SecurePayGateway.CreateClientId();

            var payment = new SecurePayPayment { Amount = 1151, Currency = "AUD" };

            const string Unable = "Unable To Connect To Server";
            // NOTE: we have max tries of 5, so set up 4 bad, then last will just work
            _fakeCommunicationMechanism.HttpPost("", "").ReturnsForAnyArgs(
                new SecurePayMessage { Status = new SecurePayStatus { StatusCode = 110, StatusDescription = Unable } },
                new SecurePayMessage { Status = new SecurePayStatus { StatusCode = 110, StatusDescription = Unable } },
                new SecurePayMessage { Status = new SecurePayStatus { StatusCode = 110, StatusDescription = Unable } },
                new SecurePayMessage { Status = new SecurePayStatus { StatusCode = 110, StatusDescription = Unable } },
                new SecurePayMessage { Status = new SecurePayStatus { StatusCode = 0, StatusDescription = "Normal" } });

            // Logic for retries
            const int MaxiumTries = 5;
            var tryCount = 0;
            var keepTrying = true;
            
            // RETRY CASES (see codes above)
            var validRetryCodes = new List<int> { 110, 123 };

            // Act
            while (keepTrying)
            {
                tryCount++;
                try
                {
                    Console.WriteLine("tryCount " + tryCount);
                    Console.WriteLine("Sleep for milliseconds before next try " + Math.Floor(Math.Pow((tryCount * 2 ), 1.5) * 2000));

                    response = _gateway.CreateCustomerWithCharge(clientId, _card, payment);

                    keepTrying = (response.Status.StatusCode != 0) || tryCount < MaxiumTries;
                }
                catch (SecurePayException ex)
                {
                    keepTrying = validRetryCodes.Contains((int)ex.StatusCode);
                }
            }

            Assert.True(tryCount == MaxiumTries);
            Assert.NotNull(response);
            Assert.That(response.Status.StatusCode, Is.EqualTo(0));
        }
        public void Periodic_CreateAndCharge_UnSuccessfulCase_InsufficientFunds()
        {
            // Arrange
            var clientId = SecurePayGateway.CreateClientId();

            var payment = new SecurePayPayment { Amount = 1051, Currency = "AUD" };

            _gateway.CreateCustomerWithCharge(clientId, _card, payment);

            // Act
            var exception = Assert.Throws<SecurePayException>(
                () => _gateway.ChargeExistingCustomer(clientId, payment));

            // Assert
            Assert.That(exception.StatusCode, Is.EqualTo(51));
            Assert.That(exception.StatusDescription, Is.EqualTo("Insufficient Funds"));
        }
        public void Periodic_CreateAndCharge_SuccessfulCase()
        {
            // Arrange
            var clientId = SecurePayGateway.CreateClientId();

            var payment = new SecurePayPayment { Amount = 1000, Currency = "AUD" };

            _gateway.CreateCustomerWithCharge(clientId, _card, payment);

            // Act
            var response = _gateway.ChargeExistingCustomer(clientId, payment);

            Console.WriteLine(response.Print());
            // Assert

            Assert.That(response.Status.StatusCode, Is.EqualTo(0));
            Assert.That(response.Status.StatusDescription, Is.EqualTo("Normal"));
        }
        public void SecurePayGateway_OneOffPayemt()
        {
            //NOTE: usage of separate instance of SecurePayGateway() with 'ApiPayment' and NOT 'ApiPeriodic'
            var oneOffPaymentGateway = new SecurePayGateway(new SecurePayWebCommunication(), "ABC0001", "abc123", ApiPayment);

            var p = new SecurePayPayment { Amount = ChargeAmount1, Currency = "AUD" };

            var oneOffPayment = oneOffPaymentGateway.SinglePaymentXml(ValidCard, p, "OneOffInc");
            DebugDisplay(oneOffPayment);

            var r = oneOffPaymentGateway.SendMessage(oneOffPayment, "unit test");

            // Assert
            Console.WriteLine("Response:");
            Console.WriteLine(r.Print());

            Assert.IsNotNull(r);
            Assert.That(r.Status.StatusDescription, Is.Not.ContainsSubstring("Unable to connect to server"));
            Assert.That(r.Status.StatusDescription, Is.EqualTo("Normal"));
            Assert.That(r.Status.StatusCode, Is.EqualTo(0));
        }
        private void ValidatePayment(SecurePayPayment payment)
        {
            if (payment.Amount <= 0)
            {
                throw new ArgumentException("payment.Amount was zero or negative", "payment");
            }

            if (string.IsNullOrWhiteSpace(payment.Currency) || payment.Currency.Length > 3)
            {
                throw new ArgumentException("payment.Currency is not valid", "payment");
            }
        }
        /// <summary>
        /// TODO: replace this with creation of a SecurePayMessage object
        /// </summary>
        public string SinglePaymentXml(SecurePayCardInfo card, SecurePayPayment payment, string purchaseOrderNo)
        {
            card.ValidateExpiry();

            return new XDocument(
                new XDeclaration("1.0", "utf-8", "no"),
                new XElement("SecurePayMessage",
                    new XElement("MessageInfo",
                        new XElement("messageID", "757a5be5b84b4d8ab84ec03ebd24af"),
                        new XElement("messageTimestamp", GetTimeStamp(DateTime.Now)),
                        new XElement("timeoutValue", _connectionTimeoutSeconds),
                        new XElement("apiVersion", "xml-4.2")),
                    new XElement("MerchantInfo",
                        new XElement("merchantID", _merchantId),
                        new XElement("password", _password)),
                    new XElement("RequestType", "Payment"),
                    new XElement("Payment",
                        new XElement("TxnList", new XAttribute("count", "1"),
                            new XElement("Txn", new XAttribute("ID", "1"),
                                new XElement("txnType", "0"),
                                new XElement("txnSource", "0"),
                                new XElement("amount", payment.Amount),
                                new XElement("currency", payment.Currency.ToUpper()),
                                new XElement("purchaseOrderNo", purchaseOrderNo),
                                    new XElement("CreditCardInfo",
                                        new XElement("cardNumber", card.Number),
                                        new XElement("expiryDate", card.GetExpiry())
                                    )))))).ToStringWithDeclaration();
        }
        public void TurnXmlStringIntoType()
        {
            // Arrange

            Console.WriteLine("Future Monthly");
            var p = new SecurePayPayment { Amount = 1000, Currency = "AUD" };
            var id = SecurePayGateway.CreateClientId();

            var request = _gateway.CreateScheduledPaymentXml(ValidCard, id, p, new DateTime());

            // Act
            var r = _gateway.SendMessage(request, "unit test");


            // Assert
            Assert.IsNotNull(r);
            Assert.IsNotNullOrEmpty(r.MessageInfo.MessageId);
        }
        public void SecurePayGateway_PeriodicCharge_Setup_ThenSetupForFuture_EditAmountByDoubling()
        {
            Console.WriteLine("Future Monthly");
            var p = new SecurePayPayment { Amount = ChargeAmount2, Currency = "AUD" };
            var id = SecurePayGateway.CreateClientId();
            var request = _gateway.CreateScheduledPaymentXml(ValidCard, id, p, new DateTime());
            DebugDisplay(request);

            var r = _gateway.SendMessage(request, "unit test");

            // Assert
            Console.WriteLine("First Response");
            Console.WriteLine(r.Print());

            AssertStatusGoodSuccessMarkerNoConnectionIssuesForPeriodicPayment(r);

            DebugDisplay(request);
            p.Amount *= 2;
            request = _gateway.TriggerPeriodicPaymentXml(id, p);
            r = _gateway.SendMessage(request, "unit test");

            Console.WriteLine("Second Response");
            Console.WriteLine(r.Print());

            // Assert
            AssertStatusGoodSuccessMarkerNoConnectionIssuesForPeriodicPayment(r);
        }
        public void SecurePayGateway_PeriodicCharge_1Setup_2ChargeFailsCustomerDoesntExist_ExpectException()
        {
            var p = new SecurePayPayment { Amount = ChargeAmount2, Currency = "AUD" };
            var request = _gateway.CreateReadyToTriggerPaymentXml(ValidCard, SecurePayGateway.CreateClientId(), p);
            DebugDisplay(request);

            var r = _gateway.SendMessage(request, "unit test");

            // Assert
            Console.WriteLine("First Response");
            Console.WriteLine(r.Print());

            AssertStatusGoodSuccessMarkerNoConnectionIssuesForPeriodicPayment(r);


            // NOTE: new id, so won't find customer
            request = _gateway.TriggerPeriodicPaymentXml(SecurePayGateway.CreateClientId(), p);
            DebugDisplay(request);

            var ex = Assert.Throws<SecurePayException>(() => _gateway.SendMessage(request, "unit test"));

            // Assert
            Assert.IsNotNull(ex);
            Assert.That(ex.StatusDescription, Is.StringContaining("Payment not found"));
        }
        public void SecurePayMessage_ReceiptNumbersWithData()
        {
            // Arrange
            var p = new SecurePayPayment { Amount = 1000, Currency = "AUD" };
            var r = _gateway.CreateReadyToTriggerPaymentXml(ValidCard, SecurePayGateway.CreateClientId(), p);

            // Act
            var m = r.As<SecurePayMessage>();
            m.Periodic.PeriodicList.PeriodicItem.Add(new SecurePayPeriodicItem
            {
                Receipt = "abc",
                Ponum = "123"
            });
            m.Periodic.PeriodicList.PeriodicItem.Add(new SecurePayPeriodicItem
            {
                Receipt = "def",
                Ponum = "456"
            });
            m.Periodic.PeriodicList.PeriodicItem.Add(new SecurePayPeriodicItem
            {
                Receipt = null
            });

            // Assert
            Assert.That(m.ReceiptNumbers(), Is.EqualTo("abc, def"));
            Assert.That(m.TransactionReference(), Is.EqualTo("123, 456"));
        }
        public void SecurePayMessage_ReceiptNumbersWithoutData()
        {
            // Arrange
            var p = new SecurePayPayment { Amount = 1000, Currency = "AUD" };
            var r = _gateway.CreateReadyToTriggerPaymentXml(ValidCard, SecurePayGateway.CreateClientId(), p);

            // Act
            var m = r.As<SecurePayMessage>();

            // Assert
            Assert.That(m.ReceiptNumbers(), Is.EqualTo(""));
            Assert.That(m.TransactionReference(), Is.EqualTo(""));
        }
        public string CreateReadyToTriggerPaymentXml(SecurePayCardInfo card, string customerId, SecurePayPayment payment)
        {
            ValidatePayment(payment);

            return new XDocument(
                new XDeclaration("1.0", "utf-8", "no"),
                new XElement("SecurePayMessage",
                    new XElement("MessageInfo",
                        new XElement("messageID", CreateMessageId()),
                        new XElement("messageTimestamp", GetTimeStamp(DateTime.Now)),
                        new XElement("timeoutValue", _connectionTimeoutSeconds),
                        new XElement("apiVersion", "spxml-3.0")), // NOTE <-- Different to Single payments
                    new XElement("MerchantInfo",
                        new XElement("merchantID", _merchantId),
                        new XElement("password", _password)),
                    new XElement("RequestType", "Periodic"), // NOTE <--DIFF
                    new XElement("Periodic",
                        new XElement("PeriodicList", new XAttribute("count", "1"),
                            new XElement("PeriodicItem", new XAttribute("ID", "1"),
                                new XElement("actionType", "add"),
                                new XElement("clientID", customerId),
                                new XElement("CreditCardInfo",
                                    new XElement("cardNumber", card.Number),
                                    new XElement("expiryDate", card.GetExpiry())),
                                new XElement("amount", payment.Amount),
                                new XElement("currency", payment.Currency.ToUpper()),
                                new XElement("periodicType", "4") // << Triggered Payment
                                ))))).ToStringWithDeclaration();
        }
        public void Test_BuildViaXdoc()
        {
            var p = new SecurePayPayment { Amount = 1000, Currency = "AUD" };
            var r = _gateway.CreateReadyToTriggerPaymentXml(ValidCard, SecurePayGateway.CreateClientId(), p);

            Console.WriteLine(r.Print());

            Assert.That(r, Is.StringContaining(@"<PeriodicList count=""1"""));
            Assert.That(r, Is.StringContaining(@"utf-8"));
            Assert.That(r, Is.StringContaining(@"<?xml version=""1.0"" encoding="));
            Assert.That(r, Is.StringContaining(@"<merchantID>ABC0001</merchantID>"));
            Assert.That(r, Is.StringContaining(@"<cardNumber>4444333322221111</cardNumber>"));
            Assert.That(r, Is.StringContaining(@"<RequestType>Periodic</RequestType>"));
        }