/// <inheritdoc />
        /// <summary>
        /// Reads the json.
        /// </summary>
        /// <param name="reader">The reader.</param>
        /// <param name="objectType">Type of the object.</param>
        /// <param name="existingValue">The existing value.</param>
        /// <param name="serializer">The serializer.</param>
        /// <returns></returns>
        /// <exception cref="T:System.ArgumentException"></exception>
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            PaymentRequest target;
            var            token = JToken.Load(reader);

            switch (Enum.Parse(typeof(PaymentMethod), token["payment_method"].Value <string>()))
            {
            case PaymentMethod.iDEAL:
                target = new IdealPaymentRequest();
                break;

            case PaymentMethod.PayPal:
                target = new PayPalPaymentRequest();
                break;

            case PaymentMethod.AfterPay:
                target = new AfterPayPaymentRequest();
                break;

            case PaymentMethod.Creditcard:
                target = new CreditcardPaymentRequest();
                break;

            case PaymentMethod.Bancontact:
                target = new BancontactPaymentRequest();
                break;

            case PaymentMethod.WireTransfer:
                target = new WireTransferPaymentRequest();
                break;

            case PaymentMethod.SOFORT:
                target = new SofortPaymentRequest();
                break;

            case PaymentMethod.DirectDebit:
                target = new DirectDebitPaymentRequest();
                break;

            default:
                throw new ArgumentException();
            }

            serializer.Populate(token.CreateReader(), target);
            return(target);
        }
        public void AfterPayPaymentRequest()
        {
            var obj = new AfterPayPaymentRequest
            {
                Amount   = 72,
                Currency = "Lorum_192",
                Details  = new AfterPayDetailsRequest
                {
                    BankAccountNumber = "Lorum_153",
                    BillToAddress     = new AfterPayDetailsRequest.OrderAddress
                    {
                        City                = "Lorum_643",
                        HouseNumber         = 84,
                        HouseNumberAddition = "Lorum_605",
                        IsoCountryCode      = "Lorum_106",
                        PostalCode          = "Lorum_583",
                        Reference           = new AfterPayDetailsRequest.OrderAddress.ReferencePerson
                        {
                            DateOfBirth  = DateTime.Now,
                            EmailAddress = "Lorum_154",
                            Gender       = "Lorum_190",
                            Initials     = "Lorum_113",
                            IsoLanguage  = "Lorum_986",
                            LastName     = "Lorum_554",
                            PhoneNumber1 = "Lorum_674",
                            PhoneNumber2 = "Lorum_104"
                        },
                        Region     = "Lorum_431",
                        StreetName = "Lorum_909"
                    },
                    CallbackUrl   = "Lorum_253",
                    CancelledUrl  = "Lorum_581",
                    ExpiredUrl    = "Lorum_630",
                    FailedUrl     = "Lorum_739",
                    InvoiceNumber = "Lorum_55",
                    IpAddress     = "Lorum_712",
                    Orderline     = new List <AfterPayDetailsRequest.OrderLine>
                    {
                        new AfterPayDetailsRequest.OrderLine
                        {
                            ArticleDescription = "Lorum_128",
                            ArticleId          = "Lorum_122",
                            NetUnitPrice       = 98,
                            Quantity           = 7,
                            UnitPrice          = 7,
                            VatCategory        = AfterPayVatCategory.High
                        },
                        new AfterPayDetailsRequest.OrderLine
                        {
                            ArticleDescription = "Lorum_571",
                            ArticleId          = "Lorum_814",
                            NetUnitPrice       = 49,
                            Quantity           = 57,
                            UnitPrice          = 68,
                            VatCategory        = AfterPayVatCategory.Zero
                        }
                    },
                    OrderNumber   = "Lorum_864",
                    Password      = "******",
                    PortfolioId   = 45,
                    PurchaseId    = "Lorum_104",
                    ShipToAddress = new AfterPayDetailsRequest.OrderAddress
                    {
                        City                = "Lorum_258",
                        HouseNumber         = 23,
                        HouseNumberAddition = "Lorum_768",
                        IsoCountryCode      = "Lorum_238",
                        PostalCode          = "Lorum_676",
                        Reference           = new AfterPayDetailsRequest.OrderAddress.ReferencePerson
                        {
                            DateOfBirth  = DateTime.Now,
                            EmailAddress = "Lorum_830",
                            Gender       = "Lorum_631",
                            Initials     = "Lorum_224",
                            IsoLanguage  = "Lorum_737",
                            LastName     = "Lorum_825",
                            PhoneNumber1 = "Lorum_881",
                            PhoneNumber2 = "Lorum_70"
                        },
                        Region     = "Lorum_457",
                        StreetName = "Lorum_98"
                    },
                    SuccessUrl       = "Lorum_715",
                    TotalOrderAmount = 98
                },
                DueDate = DateTime.Now
            };
            var deserialized = ConversionTest(obj);

            Assert.IsNotNull(deserialized);
            Assert.AreEqual(obj.Amount, deserialized.Amount);
            Assert.AreEqual(obj.Currency, deserialized.Currency);
            Assert.AreEqual(obj.Details.BankAccountNumber, deserialized.Details.BankAccountNumber);
            Assert.AreEqual(obj.Details.BillToAddress.City, deserialized.Details.BillToAddress.City);
            Assert.AreEqual(obj.Details.BillToAddress.HouseNumber, deserialized.Details.BillToAddress.HouseNumber);
            Assert.AreEqual(obj.Details.BillToAddress.HouseNumberAddition, deserialized.Details.BillToAddress.HouseNumberAddition);
            Assert.AreEqual(obj.Details.BillToAddress.IsoCountryCode, deserialized.Details.BillToAddress.IsoCountryCode);
            Assert.AreEqual(obj.Details.BillToAddress.PostalCode, deserialized.Details.BillToAddress.PostalCode);
            // Check only date and time up to seconds.. Json.NET does not save milliseconds.
            Assert.AreEqual(
                new DateTime(obj.Details.BillToAddress.Reference.DateOfBirth.Year, obj.Details.BillToAddress.Reference.DateOfBirth.Month, obj.Details.BillToAddress.Reference.DateOfBirth.Day, obj.Details.BillToAddress.Reference.DateOfBirth.Hour, obj.Details.BillToAddress.Reference.DateOfBirth.Minute, obj.Details.BillToAddress.Reference.DateOfBirth.Second),
                new DateTime(deserialized.Details.BillToAddress.Reference.DateOfBirth.Year, deserialized.Details.BillToAddress.Reference.DateOfBirth.Month, deserialized.Details.BillToAddress.Reference.DateOfBirth.Day, deserialized.Details.BillToAddress.Reference.DateOfBirth.Hour, deserialized.Details.BillToAddress.Reference.DateOfBirth.Minute, deserialized.Details.BillToAddress.Reference.DateOfBirth.Second));
            Assert.AreEqual(obj.Details.BillToAddress.Reference.EmailAddress, deserialized.Details.BillToAddress.Reference.EmailAddress);
            Assert.AreEqual(obj.Details.BillToAddress.Reference.Gender, deserialized.Details.BillToAddress.Reference.Gender);
            Assert.AreEqual(obj.Details.BillToAddress.Reference.Initials, deserialized.Details.BillToAddress.Reference.Initials);
            Assert.AreEqual(obj.Details.BillToAddress.Reference.IsoLanguage, deserialized.Details.BillToAddress.Reference.IsoLanguage);
            Assert.AreEqual(obj.Details.BillToAddress.Reference.LastName, deserialized.Details.BillToAddress.Reference.LastName);
            Assert.AreEqual(obj.Details.BillToAddress.Reference.PhoneNumber1, deserialized.Details.BillToAddress.Reference.PhoneNumber1);
            Assert.AreEqual(obj.Details.BillToAddress.Reference.PhoneNumber2, deserialized.Details.BillToAddress.Reference.PhoneNumber2);
            Assert.AreEqual(obj.Details.BillToAddress.Region, deserialized.Details.BillToAddress.Region);
            Assert.AreEqual(obj.Details.BillToAddress.StreetName, deserialized.Details.BillToAddress.StreetName);
            Assert.AreEqual(obj.Details.CallbackUrl, deserialized.Details.CallbackUrl);
            Assert.AreEqual(obj.Details.CancelledUrl, deserialized.Details.CancelledUrl);
            Assert.AreEqual(obj.Details.ExpiredUrl, deserialized.Details.ExpiredUrl);
            Assert.AreEqual(obj.Details.FailedUrl, deserialized.Details.FailedUrl);
            Assert.AreEqual(obj.Details.InvoiceNumber, deserialized.Details.InvoiceNumber);
            Assert.AreEqual(obj.Details.IpAddress, deserialized.Details.IpAddress);
            Assert.AreEqual(obj.Details.Orderline?.Count(), deserialized.Details.Orderline?.Count());
            for (var orderlineIndex = 0; orderlineIndex < obj.Details.Orderline.Count(); orderlineIndex++)
            {
                var expectedOrderLineInOrderline = obj.Details.Orderline.ElementAt(orderlineIndex) as AfterPayDetailsRequest.OrderLine;
                var actualOrderLineInOrderline   = deserialized.Details.Orderline.ElementAt(orderlineIndex) as AfterPayDetailsRequest.OrderLine;
                Assert.AreEqual(expectedOrderLineInOrderline.ArticleDescription, actualOrderLineInOrderline.ArticleDescription);
                Assert.AreEqual(expectedOrderLineInOrderline.ArticleId, actualOrderLineInOrderline.ArticleId);
                Assert.AreEqual(expectedOrderLineInOrderline.NetUnitPrice, actualOrderLineInOrderline.NetUnitPrice);
                Assert.AreEqual(expectedOrderLineInOrderline.Quantity, actualOrderLineInOrderline.Quantity);
                Assert.AreEqual(expectedOrderLineInOrderline.UnitPrice, actualOrderLineInOrderline.UnitPrice);
                Assert.AreEqual(expectedOrderLineInOrderline.VatCategory, actualOrderLineInOrderline.VatCategory);
            }
            Assert.AreEqual(obj.Details.OrderNumber, deserialized.Details.OrderNumber);
            Assert.AreEqual(obj.Details.Password, deserialized.Details.Password);
            Assert.AreEqual(obj.Details.PortfolioId, deserialized.Details.PortfolioId);
            Assert.AreEqual(obj.Details.PurchaseId, deserialized.Details.PurchaseId);
            Assert.AreEqual(obj.Details.ShipToAddress.City, deserialized.Details.ShipToAddress.City);
            Assert.AreEqual(obj.Details.ShipToAddress.HouseNumber, deserialized.Details.ShipToAddress.HouseNumber);
            Assert.AreEqual(obj.Details.ShipToAddress.HouseNumberAddition, deserialized.Details.ShipToAddress.HouseNumberAddition);
            Assert.AreEqual(obj.Details.ShipToAddress.IsoCountryCode, deserialized.Details.ShipToAddress.IsoCountryCode);
            Assert.AreEqual(obj.Details.ShipToAddress.PostalCode, deserialized.Details.ShipToAddress.PostalCode);
            // Check only date and time up to seconds.. Json.NET does not save milliseconds.
            Assert.AreEqual(
                new DateTime(obj.Details.ShipToAddress.Reference.DateOfBirth.Year, obj.Details.ShipToAddress.Reference.DateOfBirth.Month, obj.Details.ShipToAddress.Reference.DateOfBirth.Day, obj.Details.ShipToAddress.Reference.DateOfBirth.Hour, obj.Details.ShipToAddress.Reference.DateOfBirth.Minute, obj.Details.ShipToAddress.Reference.DateOfBirth.Second),
                new DateTime(deserialized.Details.ShipToAddress.Reference.DateOfBirth.Year, deserialized.Details.ShipToAddress.Reference.DateOfBirth.Month, deserialized.Details.ShipToAddress.Reference.DateOfBirth.Day, deserialized.Details.ShipToAddress.Reference.DateOfBirth.Hour, deserialized.Details.ShipToAddress.Reference.DateOfBirth.Minute, deserialized.Details.ShipToAddress.Reference.DateOfBirth.Second));
            Assert.AreEqual(obj.Details.ShipToAddress.Reference.EmailAddress, deserialized.Details.ShipToAddress.Reference.EmailAddress);
            Assert.AreEqual(obj.Details.ShipToAddress.Reference.Gender, deserialized.Details.ShipToAddress.Reference.Gender);
            Assert.AreEqual(obj.Details.ShipToAddress.Reference.Initials, deserialized.Details.ShipToAddress.Reference.Initials);
            Assert.AreEqual(obj.Details.ShipToAddress.Reference.IsoLanguage, deserialized.Details.ShipToAddress.Reference.IsoLanguage);
            Assert.AreEqual(obj.Details.ShipToAddress.Reference.LastName, deserialized.Details.ShipToAddress.Reference.LastName);
            Assert.AreEqual(obj.Details.ShipToAddress.Reference.PhoneNumber1, deserialized.Details.ShipToAddress.Reference.PhoneNumber1);
            Assert.AreEqual(obj.Details.ShipToAddress.Reference.PhoneNumber2, deserialized.Details.ShipToAddress.Reference.PhoneNumber2);
            Assert.AreEqual(obj.Details.ShipToAddress.Region, deserialized.Details.ShipToAddress.Region);
            Assert.AreEqual(obj.Details.ShipToAddress.StreetName, deserialized.Details.ShipToAddress.StreetName);
            Assert.AreEqual(obj.Details.SuccessUrl, deserialized.Details.SuccessUrl);
            Assert.AreEqual(obj.Details.TotalOrderAmount, deserialized.Details.TotalOrderAmount);
            // Check only date and time up to seconds.. Json.NET does not save milliseconds.
            Assert.AreEqual(obj.DueDate.HasValue, deserialized.DueDate.HasValue);
            if (obj.DueDate.HasValue && deserialized.DueDate.HasValue)
            {
                Assert.AreEqual(
                    new DateTime(obj.DueDate.Value.Year, obj.DueDate.Value.Month, obj.DueDate.Value.Day, obj.DueDate.Value.Hour, obj.DueDate.Value.Minute, obj.DueDate.Value.Second),
                    new DateTime(deserialized.DueDate.Value.Year, deserialized.DueDate.Value.Month, deserialized.DueDate.Value.Day, deserialized.DueDate.Value.Hour, deserialized.DueDate.Value.Minute, deserialized.DueDate.Value.Second));
            }
        }