diff --git a/JudoPayDotNet/Http/VersioningHandler.cs b/JudoPayDotNet/Http/VersioningHandler.cs index 315c2cb..7fa321d 100644 --- a/JudoPayDotNet/Http/VersioningHandler.cs +++ b/JudoPayDotNet/Http/VersioningHandler.cs @@ -13,7 +13,7 @@ internal class VersioningHandler : DelegatingHandler { public const string API_VERSION_HEADER = "api-version"; - internal const string DEFAULT_API_VERSION = "5.4.0.0"; + internal const string DEFAULT_API_VERSION = "5.5.0.0"; private readonly string _apiVersionValue; diff --git a/JudoPayDotNet/JudoPayDotNet.csproj b/JudoPayDotNet/JudoPayDotNet.csproj index 55e423b..a76fe8f 100644 --- a/JudoPayDotNet/JudoPayDotNet.csproj +++ b/JudoPayDotNet/JudoPayDotNet.csproj @@ -6,11 +6,10 @@ JudoPay.Net - 2.0.0 - 2.0.0 + 2.1.0 JudoPay A .Net client for our JudoPay API, allowing you to quickly and easily process payments - Copyright 2017 + Copyright 2018 true http://opensource.org/licenses/MIT https://github.com/JudoPay/DotNetSDK @@ -18,7 +17,11 @@ https://github.com/JudoPay/DotNetSDK git judo;judopaypayment;gateway;credit;cards; - Updated to dotnet standard 2.0 + + Added Risk information associated with the transaction. + Changed CardType to CardBrand and CardFunding. + Updated to dotnet standard 2.0. + diff --git a/JudoPayDotNet/Models/CardDetails.cs b/JudoPayDotNet/Models/CardDetails.cs index 5f5e9f0..ae17be6 100644 --- a/JudoPayDotNet/Models/CardDetails.cs +++ b/JudoPayDotNet/Models/CardDetails.cs @@ -1,4 +1,5 @@ -using System.Runtime.Serialization; +using System; +using System.Runtime.Serialization; namespace JudoPayDotNet.Models { @@ -43,7 +44,26 @@ public class CardDetails /// The type of the card. /// [DataMember] + [Obsolete("Please use CardScheme and CardFunding instead")] public CardType CardType { get; set; } + + /// + /// Gets or sets the scheme of the card. + /// + /// + /// Possible values are Visa, Mastercard etc + /// + [DataMember] + public string CardScheme { get; set; } + + /// + /// Gets or sets the funding type of the card. + /// + /// + /// Possible values are Debit, Credit etc + /// + [DataMember] + public string CardFunding { get; set; } } // ReSharper restore UnusedAutoPropertyAccessor.Global } diff --git a/JudoPayDotNet/Models/PaymentReceiptModel.cs b/JudoPayDotNet/Models/PaymentReceiptModel.cs index 72eb541..4296995 100644 --- a/JudoPayDotNet/Models/PaymentReceiptModel.cs +++ b/JudoPayDotNet/Models/PaymentReceiptModel.cs @@ -190,11 +190,8 @@ public class PaymentReceiptModel : ITransactionResult public Consumer Consumer { get; set; } /// - /// Gets or sets the consumer. + /// Gets or sets the Device information. /// - /// - /// The consumer. - /// [DataMember] public Device Device { get; set; } @@ -229,7 +226,14 @@ public class PaymentReceiptModel : ITransactionResult [DataMember(EmitDefaultValue = false)] public bool? Recurring { get; set; } + + /// + /// Information about the risks associated with the transaction + /// + [DataMember] + public RiskModel Risks { get; set; } } + // ReSharper restore UnusedMember.Global // ReSharper restore UnusedAutoPropertyAccessor.Global } diff --git a/JudoPayDotNet/Models/RiskModel.cs b/JudoPayDotNet/Models/RiskModel.cs new file mode 100644 index 0000000..8f70819 --- /dev/null +++ b/JudoPayDotNet/Models/RiskModel.cs @@ -0,0 +1,26 @@ +using System.Runtime.Serialization; + +namespace JudoPayDotNet.Models +{ + [DataContract(Name = "Risks", Namespace = "")] + public class RiskModel + { + /// + /// The merchant suggestion from the amount of risk associated with the transaction + /// + /// + /// Possible values include Allow, Block, Review + /// + [DataMember] + public string MerchantSuggestion { get; set; } + + /// + /// If AVS is submitted, this will contain the postcode check result + /// + /// + /// Possible values include PASSED, NOTCHECKED and FAILED + /// + [DataMember] + public string PostcodeCheck { get; set; } + } +} \ No newline at end of file diff --git a/JudoPayDotNetIntegrationTests/PaymentTest.cs b/JudoPayDotNetIntegrationTests/PaymentTest.cs index 6a1c683..e3d643f 100644 --- a/JudoPayDotNetIntegrationTests/PaymentTest.cs +++ b/JudoPayDotNetIntegrationTests/PaymentTest.cs @@ -9,28 +9,44 @@ namespace JudoPayDotNetIntegrationTests public class PaymentTest : IntegrationTestsBase { [Test] - public void ASimplePayment() + public async Task ASimplePayment() { var paymentWithCard = GetCardPaymentModel(); - var result = JudoPayApi.Payments.Create(paymentWithCard); - var response = result.Result; + var response = await JudoPayApi.Payments.Create(paymentWithCard); Assert.IsNotNull(response); Assert.IsFalse(response.HasError); Assert.AreEqual("Success", response.Response.Result); + + var receipt = response.Response as PaymentReceiptModel; + Assert.That(receipt, Is.Not.Null); + Assert.That(receipt.CardDetails, Is.Not.Null, "Missing carddetails property on receipt"); + Assert.That(receipt.CardDetails.CardLastfour, Is.Not.Empty); + Assert.That(receipt.CardDetails.EndDate, Is.Not.Empty); + Assert.That(receipt.CardDetails.CardScheme, Is.EqualTo("Visa")); + Assert.That(receipt.CardDetails.CardFunding, Is.EqualTo("Debit")); + Assert.That(receipt.Message, Does.Match("AuthCode: \\d{6}"), $"Result message on receipt not in correct format AuthCode: xxxxxx. Was {receipt.Message}"); + Assert.That(receipt.MerchantName, Is.Not.Empty); + Assert.That(receipt.AppearsOnStatementAs, Is.Not.Empty); + Assert.That(receipt.CreatedAt, Is.Not.Null); + Assert.That(receipt.NetAmount, Is.GreaterThan(0)); + Assert.That(receipt.Amount, Is.GreaterThan(0)); + Assert.That(receipt.Currency, Is.EqualTo("GBP")); + + Assert.That(receipt.Risks.PostcodeCheck, Is.EqualTo("PASSED")); + Assert.That(receipt.Risks.MerchantSuggestion, Is.EqualTo("Allow")); } [Test] [Ignore("Till recurring flag is exposed on partnerapi")] - public void ARecurringPayment() + public async Task ARecurringPayment() { var paymentWithCard = GetCardPaymentModel(recurringPayment: true, judoId: Configuration.Cybersource_Judoid); var judoPay = UseCybersourceGateway(); - var result = judoPay.Payments.Create(paymentWithCard); - var response = result.Result; + var response = await judoPay.Payments.Create(paymentWithCard); Assert.IsNotNull(response); Assert.IsFalse(response.HasError); @@ -41,13 +57,12 @@ public void ARecurringPayment() } [Test] - public void ATokenPayment() + public async Task ATokenPayment() { var consumerReference = Guid.NewGuid().ToString(); - var paymentWithCard = GetCardPaymentModel(consumerReference); - var response = JudoPayApi.Payments.Create(paymentWithCard).Result; + var response = await JudoPayApi.Payments.Create(paymentWithCard); Assert.IsNotNull(response); Assert.IsFalse(response.HasError); @@ -62,21 +77,34 @@ public void ATokenPayment() var cardToken = receipt.CardDetails.CardToken; var paymentWithToken = GetTokenPaymentModel(cardToken, consumerReference, 26); - - response = JudoPayApi.Payments.Create(paymentWithToken).Result; - - paymentWithToken = GetTokenPaymentModel(cardToken, consumerReference, 27); - - response = JudoPayApi.Payments.Create(paymentWithToken).Result; + response = await JudoPayApi.Payments.Create(paymentWithToken); Assert.IsNotNull(response); Assert.IsFalse(response.HasError); Assert.AreEqual("Success", response.Response.Result); + + var cardTokenReceipt = response.Response as PaymentReceiptModel; + Assert.That(cardTokenReceipt, Is.Not.Null); + Assert.That(cardTokenReceipt.CardDetails, Is.Not.Null, "Missing carddetails property on receipt"); + Assert.That(cardTokenReceipt.CardDetails.CardLastfour, Is.Not.Empty); + Assert.That(cardTokenReceipt.CardDetails.EndDate, Is.Not.Empty); + Assert.That(cardTokenReceipt.CardDetails.CardScheme, Is.EqualTo("Visa")); + Assert.That(cardTokenReceipt.CardDetails.CardFunding, Is.EqualTo("Debit")); + Assert.That(cardTokenReceipt.Message, Does.Match("AuthCode: \\d{6}"), $"Result message on receipt not in correct format AuthCode: xxxxxx. Was {cardTokenReceipt.Message}"); + Assert.That(cardTokenReceipt.MerchantName, Is.Not.Empty); + Assert.That(cardTokenReceipt.AppearsOnStatementAs, Is.Not.Empty); + Assert.That(cardTokenReceipt.CreatedAt, Is.Not.Null); + Assert.That(cardTokenReceipt.NetAmount, Is.GreaterThan(0)); + Assert.That(cardTokenReceipt.Amount, Is.GreaterThan(0)); + Assert.That(cardTokenReceipt.Currency, Is.EqualTo("GBP")); + + Assert.That(receipt.Risks.PostcodeCheck, Is.EqualTo("PASSED")); + Assert.That(receipt.Risks.MerchantSuggestion, Is.EqualTo("Allow")); } [Test] [Ignore("Till recurring flag is exposed on partnerapi")] - public void ATokenRecurringPayment() + public async Task ATokenRecurringPayment() { var consumerReference = Guid.NewGuid().ToString(); @@ -84,7 +112,7 @@ public void ATokenRecurringPayment() var judoPay = UseCybersourceGateway(); - var response = judoPay.Payments.Create(paymentWithCard).Result; + var response = await judoPay.Payments.Create(paymentWithCard); Assert.IsNotNull(response); Assert.IsFalse(response.HasError); @@ -100,11 +128,11 @@ public void ATokenRecurringPayment() } [Test] - public void AOneTimePayment() + public async Task AOneTimePayment() { var oneTimePaymentModel = GetOneTimePaymentModel().Result; - var response = JudoPayApi.Payments.Create(oneTimePaymentModel).Result; + var response = await JudoPayApi.Payments.Create(oneTimePaymentModel); Assert.IsNotNull(response); Assert.IsFalse(response.HasError); @@ -116,11 +144,11 @@ public void AOneTimePayment() } [Test] - public void ADeclinedCardPayment() + public async Task ADeclinedCardPayment() { var paymentWithCard = GetCardPaymentModel("432438862", "4221690000004963", "125"); - var response = JudoPayApi.Payments.Create(paymentWithCard).Result; + var response = await JudoPayApi.Payments.Create(paymentWithCard); Assert.IsNotNull(response); Assert.IsFalse(response.HasError); @@ -128,27 +156,26 @@ public void ADeclinedCardPayment() } [Test] - public void DeDuplicationTest() + public async Task DeDuplicationTest() { var paymentWithCard = GetCardPaymentModel("432438862"); - var response1 = JudoPayApi.Payments.Create(paymentWithCard).Result; - - var response2 = JudoPayApi.Payments.Create(paymentWithCard).Result; - + var response1 = await JudoPayApi.Payments.Create(paymentWithCard); + + var response2 = await JudoPayApi.Payments.Create(paymentWithCard); + Assert.AreEqual(response1.Response.ReceiptId, response2.Response.ReceiptId); } [Test] - public void VisaCheckoutPayment() + public async Task VisaCheckoutPayment() { var callId = "2535293917395986901"; var encKey = "DL1znS1YD0D4L518up18ibGQK25jPiklD0k58PQQc775n/AOeBrXD292I1ywmXVjW10ngTGhuCW4ifEBfr1vxEe4vXHg7oXDY7+pO1tvNDV3G4Fkmy0Q3H8ieZ1RfD2y"; var encPaymentData = "EuWD12Sem0WTNRbIsCG6ATsABxssMvbPvFbR8SqK1Jj7YeU6a7s9Bs2Gk7I94E9p6ghEvl/wePm9nhamebj7vBzdLj/ezOqBgl41JUNq+uhRfS5zB9+7nAZkldwpT9TaLECbb+4JY1W9osUoZXL7XtnKz+OTeBG3apnjDomVf9kaNpbu0RkQFzclTyoeeODTDtpoZ+lqumR1E7yr/LsG5JtM+GvAdoULSgX3Xc4IaCRCWbGwKZaTm8PadXuyPiZXpcRCZd0I0KBDj8RGHW7wl3rPfpx4SxB4YMBieJNFbdj/AU2hWnU8fYEtgPaWKaA31a4csHFvQSBsmGAuJLEQ7CKb63k1EZV7rMJR/If/jNz17gtVHWjaEb/SNHybHe7MzDkmjhODfFR+ceaHb9b/NwD1X9QGBXSwrXwMZR06vdyao//T44NbhhfPngGORSz47sHx2o40ECIfo5HGB/BbZO48Sl61pNKommEjEj0JabbzOqNEdA7IJkf1I1eO0bPTW41Vd84Fgofe2aKy2987lPhMnJdHFaslo6DS8cclF7LySQWYjOZNSL+0tW9hLLV1DO1H0xvYA7CsvHyutyDxTVtiOkl5+MKeAzRsaWQTC4sbxrgWZjYbxGCeWOWED+xQRSeJmY1J4hpUjB7jwGymekBXVfiHvwM9sAgZ2+EU95j6kRYciKhLOMgYH68wRJqHR4wR4rjxiHrjwZARqnG/5vwYZ9qvJxyKUkE+lcMNLK8x18tT4N1nm2oPW08GnbkRXmr2SFnv3RwuxbIOyaKIJrNjeQ0ybG4+taQcdRyllNpKwY04sxN3seC5w4/85x302oVzpaJAM22SIqawTn20kKIQylJI3X/w+LoPHthrGdT56mLAntjIB0P4Wnz1l2APaXfgtvKyX5HoM7acgTucEFKfiWEeBMcamu9XqSBQWELTXQls6CDTNrcAM2X4oEJSUaacTarCVWUmrluuNr+AO3YF9NMil35ES+P6+/Z0ikWqi5OFxNTy3milrsyjwEakmRS7J3/hMhAkcVmG7vUeBqSYmqa+p3KcL+0R1pjv//eh6Zw5gj7LHmgEmsuNmdUyW/kw19ekCU2ToLUpFtS64PUUB0lvFXP/abX2zEjzEYmYwhtr1Bgt3AAlc+z4LucUFm9m2jYWW+dbv5ivHHlGcLD8qJi455rQGzu316mFYUeAQ6nQmza6MYWQ2UvaCm38f5F7VOzMWrW447whNtKpXAb8DUDGUiXglwChXeEyc7UEmYDuy2XD1iEt3x8s38pOGjePXVu5ItyD2IV4jD/U4DwzYvByRzErQLZglLeWoqoeGsINXecu4PIoNgfnt8VLVjVwsI54IuNkkjk9KPQ/BqYQoPV2SzAhGDV69BK9KntnlKhPsdLcPNLEXLHn9nYLobFpFj4Gha1oxSQ4KwU8oNYvypXWZ17cp2LPbbYeRpjygHGwIVait8x8ztF9EXDBFC28V6WpQKjlKpKcAQooZs3JjYPXqhaUrMEgpBCRthtB434SXQo3v82CltQYOXQiOgvrWWjf67vVSOojqJRzqzNqC2v7HNvAzjKXccCfO1SzomzHKan86hvDJBmjPR7UhV/qtNuIFL9bh/WBHZEKRDdNuGQMzAl9vO7V096tuCCtOlqjy4ICXY/eC7M3mtydSFyVrKShcUHwmBOaB2bnQcXd8sQaT9kcihjmRWd+P8t2O53vAavMmUSdGu0Hb+BS5uw/yW41ne3kUbhm6L6bFy/BiNEwNsKLyen4K1lvGsTgwFUD64lpPurWWzFTXhffqSKPIPqWxhoDMBWU46DmxsBXevzUNsq2mR5zWcB1kGpuR3uJHEZ4zc+CThqAPsKchFC+uGahCE+jldbcvGQE3RCzdzZRmyjxe4jttuExhLE="; var paymentWithCard = GetVisaCheckoutPaymentModel(callId, encKey, encPaymentData); - var result = JudoPayApi.Payments.Create(paymentWithCard); - var response = result.Result; + var response = await JudoPayApi.Payments.Create(paymentWithCard); Assert.IsNotNull(response); Assert.IsFalse(response.HasError); diff --git a/appveyor.yml b/appveyor.yml index 3e16ce1..46c4fa9 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,4 +1,4 @@ -version: 2.0.{build} +version: 2.1.{build} image: Visual Studio 2017 skip_branch_with_pr: true # if wanting to publish the package internally