From a6e113a051a33e40506a17ada124e6d426c37161 Mon Sep 17 00:00:00 2001 From: Braintree Date: Tue, 26 Jan 2021 20:13:48 +0000 Subject: [PATCH] 5.3.0 --- .github/CODEOWNERS | 1 + CHANGELOG.md | 13 + src/Braintree/Adjustment.cs | 32 ++ src/Braintree/Braintree.csproj | 17 +- src/Braintree/CreditCardOptionsRequest.cs | 2 + src/Braintree/CreditCardRequest.cs | 8 + src/Braintree/Installment.cs | 31 ++ src/Braintree/InstallmentRequest.cs | 25 ++ src/Braintree/PaymentMethodOptionsRequest.cs | 2 + src/Braintree/Properties/AssemblyInfo.cs | 4 +- src/Braintree/SandboxValues.cs | 2 + src/Braintree/Transaction.cs | 19 + src/Braintree/TransactionRequest.cs | 16 +- src/Braintree/ValidationErrorCode.cs | 5 + test/Braintree.TestUtil/MerchantAccountIDs.cs | 1 + .../CreditCardIntegrationTest.cs | 155 +++++++- .../CustomerIntegrationTest.cs | 369 ++++++++++++++++++ .../PaymentMethodIntegrationTest.cs | 116 ++++++ .../ThreeDSecureIntegrationTest.cs | 4 +- .../TransactionIntegrationTest.cs | 308 +++++++++++++-- test/Braintree.Tests/CreditCardRequestTest.cs | 2 + test/Braintree.Tests/CustomerRequestTest.cs | 1 + .../Braintree.Tests/TransactionRequestTest.cs | 16 + 23 files changed, 1104 insertions(+), 45 deletions(-) create mode 100644 src/Braintree/Adjustment.cs create mode 100644 src/Braintree/Installment.cs create mode 100644 src/Braintree/InstallmentRequest.cs diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 2654cd87..15eced64 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1 +1,2 @@ * @braintree/sdk +* @braintree/team-sdk-server diff --git a/CHANGELOG.md b/CHANGELOG.md index d673eb99..d8057715 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,16 @@ +## 5.3.0 +- Add `scaExemption` to `Transaction` +- Deprecate `DeviceSessionId` and `FraudMerchantId` in the `CreditCardRequest` and `TransactionRequest` classes +- Add `currencyIsoCode` field to `TransactionRequest` +- Add `verificationCurrencyIsoCode` field to `CreditCardOptionsRequest` and `PaymentMethodOptionsRequest` +- Add validation error codes: + - `CREDIT_CARD_OPTIONS_VERIFICATION_INVALID_PRESENTMENT_CURRENCY` + - `TRANSACTION_INVALID_PRESENTMENT_CURRENCY` +- Add `Installments` to `TransactionRequest` +- Add `Count` to `InstallmentRequest` +- Add `Installments` and `RefundedInstallments` to `Transaction` +- Add `Adjustment` to `Installment` + ## 5.2.0 - Add `AcquirerReferenceNumber` to `Transaction` - Add `BillingAgreementId` to `PayPalDetails` diff --git a/src/Braintree/Adjustment.cs b/src/Braintree/Adjustment.cs new file mode 100644 index 00000000..6a13533d --- /dev/null +++ b/src/Braintree/Adjustment.cs @@ -0,0 +1,32 @@ +using System; +using System.ComponentModel; + +namespace Braintree +{ + + public enum Kind + { + [Description("refund")] REFUND, + [Description("dispute")] DISPUTE, + [Description("unrecognized")] UNRECOGNIZED + } + + public class Adjustment + { + public virtual decimal? Amount { get; protected set; } + public virtual DateTime? ProjectedDisbursementDate { get; protected set; } + public virtual DateTime? ActualDisbursementDate { get; protected set; } + public virtual Kind Kind { get; protected set; } + + protected internal Adjustment(NodeWrapper node) + { + Amount = node.GetDecimal("amount"); + ProjectedDisbursementDate = node.GetDateTime("projected_disbursement_date"); + ActualDisbursementDate = node.GetDateTime("actual_disbursement_date"); + Kind = node.GetEnum("kind", Kind.UNRECOGNIZED); + } + + [Obsolete("Mock Use Only")] + protected internal Adjustment() { } + } +} diff --git a/src/Braintree/Braintree.csproj b/src/Braintree/Braintree.csproj index ffa2284d..d539ec95 100644 --- a/src/Braintree/Braintree.csproj +++ b/src/Braintree/Braintree.csproj @@ -4,7 +4,7 @@ Braintree Client Library Copyright © Braintree, a division of PayPal, Inc. 2020 - 5.2.0 + 5.3.0 Braintree net452;netstandard2.0 @@ -12,10 +12,17 @@ Braintree braintree;paypal;venmo;intenational;payments;gateway;currencies;money;visa;mastercard;bitcoin;maestro;apple pay;android pay;amex;jcb;diners club;discover;american express - - Add `AcquirerReferenceNumber` to `Transaction` - - Add `BillingAgreementId` to `PayPalDetails` - - Add `extensions` to `GraphQLResponse` - - Deprecate `Recurring` in TransactionRequest + - Add scaExemption to Transaction + - Deprecate DeviceSessionId and FraudMerchantId in the CreditCardRequest and TransactionRequest classes + - Add currencyIsoCode field to TransactionRequest + - Add verificationCurrencyIsoCode field to CreditCardOptionsRequest and PaymentMethodOptionsRequest + - Add validation error codes: + - CREDIT_CARD_OPTIONS_VERIFICATION_INVALID_PRESENTMENT_CURRENCY + - TRANSACTION_INVALID_PRESENTMENT_CURRENCY + - Add Installments to TransactionRequest + - Add Count to InstallmentRequest + - Add Installments and RefundedInstallments to Transaction + - Add Adjustment to Installment https://github.com/braintree/braintree_dotnet false diff --git a/src/Braintree/CreditCardOptionsRequest.cs b/src/Braintree/CreditCardOptionsRequest.cs index 5e94f1ee..8565b3c8 100644 --- a/src/Braintree/CreditCardOptionsRequest.cs +++ b/src/Braintree/CreditCardOptionsRequest.cs @@ -12,6 +12,7 @@ public class CreditCardOptionsRequest : Request public string UpdateExistingToken { get; set; } public string VenmoSdkSession { get; set; } public string VerificationAccountType { get; set; } + public string VerificationCurrencyIsoCode { get; set; } public override string ToXml(string root) { @@ -29,6 +30,7 @@ protected virtual RequestBuilder BuildRequest(string root) AddElement("make-default", MakeDefault). AddElement("verification-merchant-account-id", VerificationMerchantAccountId). AddElement("verification-account-type", VerificationAccountType). + AddElement("verification-currency-iso-code", VerificationCurrencyIsoCode). AddElement("verify-card", VerifyCard). AddElement("verification-amount", VerificationAmount). AddElement("fail-on-duplicate-payment-method", FailOnDuplicatePaymentMethod). diff --git a/src/Braintree/CreditCardRequest.cs b/src/Braintree/CreditCardRequest.cs index 0f0e7c6c..5923945c 100644 --- a/src/Braintree/CreditCardRequest.cs +++ b/src/Braintree/CreditCardRequest.cs @@ -1,5 +1,7 @@ #pragma warning disable 1591 +using System; + namespace Braintree { /// @@ -32,7 +34,9 @@ public class CreditCardRequest : BaseCreditCardRequest public ThreeDSecurePassThruRequest ThreeDSecurePassThru { get; set; } public string BillingAddressId { get; set; } public string DeviceData { get; set; } + [ObsoleteAttribute("use DeviceData instead", false)] public string DeviceSessionId { get; set; } + [ObsoleteAttribute("use DeviceData instead", false)] public string FraudMerchantId { get; set; } public CreditCardOptionsRequest Options { get; set; } public string PaymentMethodToken { get; set; } @@ -54,8 +58,12 @@ protected override RequestBuilder BuildRequest(string root) AddElement("billing-address-id", BillingAddressId). AddElement("device-data", DeviceData). AddElement("customer-id", CustomerId). +// Remove this pragma warning when we remove DeviceSessionId and FraudMerchantId. +// We have this so we can build the SDK without obsolete error messages +#pragma warning disable 618 AddElement("device-session-id", DeviceSessionId). AddElement("fraud-merchant-id", FraudMerchantId). +#pragma warning restore 618 AddElement("options", Options). AddElement("payment-method-nonce", PaymentMethodNonce). AddElement("venmo-sdk-payment-method-code", VenmoSdkPaymentMethodCode). diff --git a/src/Braintree/Installment.cs b/src/Braintree/Installment.cs new file mode 100644 index 00000000..2ca3f6b0 --- /dev/null +++ b/src/Braintree/Installment.cs @@ -0,0 +1,31 @@ +using System; +using System.ComponentModel; +using System.Collections.Generic; + +namespace Braintree +{ + + public class Installment + { + public virtual string Id { get; protected set; } + public virtual decimal? Amount { get; protected set; } + public virtual DateTime? ProjectedDisbursementDate { get; protected set; } + public virtual DateTime? ActualDisbursementDate { get; protected set; } + public virtual List Adjustments { get; protected set; } + + protected internal Installment(NodeWrapper node) + { + Amount = node.GetDecimal("amount"); + Id = node.GetString("id"); + ProjectedDisbursementDate = node.GetDateTime("projected_disbursement_date"); + ActualDisbursementDate = node.GetDateTime("actual_disbursement_date"); + Adjustments = new List(); + foreach (var adjustmentNode in node.GetList("adjustments/adjustment")) { + Adjustments.Add(new Adjustment(adjustmentNode)); + } + } + + [Obsolete("Mock Use Only")] + protected internal Installment() { } + } +} diff --git a/src/Braintree/InstallmentRequest.cs b/src/Braintree/InstallmentRequest.cs new file mode 100644 index 00000000..22456461 --- /dev/null +++ b/src/Braintree/InstallmentRequest.cs @@ -0,0 +1,25 @@ +namespace Braintree +{ + public class InstallmentRequest : Request + { + public string Count { get; set; } + + public override string ToXml(string root) + { + return BuildRequest(root).ToXml(); + } + + public override string ToQueryString(string root) + { + return BuildRequest(root).ToQueryString(); + } + + protected virtual RequestBuilder BuildRequest(string root) + { + var builder = new RequestBuilder(root); + builder.AddElement("count", Count); + return builder; + } + } +} + diff --git a/src/Braintree/PaymentMethodOptionsRequest.cs b/src/Braintree/PaymentMethodOptionsRequest.cs index 04d8017f..95c46684 100644 --- a/src/Braintree/PaymentMethodOptionsRequest.cs +++ b/src/Braintree/PaymentMethodOptionsRequest.cs @@ -10,6 +10,7 @@ public class PaymentMethodOptionsRequest : Request public string VerificationMerchantAccountId { get; set; } public string VerificationAmount { get; set; } public string VerificationAccountType { get; set; } + public string VerificationCurrencyIsoCode { get; set; } public PaymentMethodOptionsPayPalRequest OptionsPayPal { get; set; } public UsBankAccountVerificationMethod? UsBankAccountVerificationMethod { get; set; } @@ -29,6 +30,7 @@ protected virtual RequestBuilder BuildRequest(string root) AddElement("make-default", MakeDefault). AddElement("verification-merchant-account-id", VerificationMerchantAccountId). AddElement("verification-account-type", VerificationAccountType). + AddElement("verification-currency-iso-code", VerificationCurrencyIsoCode). AddElement("verify-card", VerifyCard). AddElement("us-bank-account-verification-method", UsBankAccountVerificationMethod.GetDescription()). AddElement("verification-amount", VerificationAmount). diff --git a/src/Braintree/Properties/AssemblyInfo.cs b/src/Braintree/Properties/AssemblyInfo.cs index 9871a4d1..4cde110e 100644 --- a/src/Braintree/Properties/AssemblyInfo.cs +++ b/src/Braintree/Properties/AssemblyInfo.cs @@ -32,5 +32,5 @@ // Build Number // Revision // -[assembly: AssemblyVersion("5.2.0.0")] -[assembly: AssemblyFileVersion("5.2.0.0")] +[assembly: AssemblyVersion("5.3.0.0")] +[assembly: AssemblyFileVersion("5.3.0.0")] diff --git a/src/Braintree/SandboxValues.cs b/src/Braintree/SandboxValues.cs index e351bd98..2c9110e7 100644 --- a/src/Braintree/SandboxValues.cs +++ b/src/Braintree/SandboxValues.cs @@ -7,10 +7,12 @@ public class SandboxValues public class CreditCardNumber { public const string VISA = "4111111111111111"; + public const string VISA_COUNTRY_OF_ISSUANCE_IE = "4023490000000008"; public const string MASTER_CARD = "5555555555554444"; public const string AMEX = "371449635392376"; public const string HIPER = "6370950000000005"; public const string HIPERCARD = "6062820524845321"; + public const string JCB = "3530111333300000"; public const string FRAUD = "4000111111111511"; public const string RISK_THRESHOLD = "4111130000000003"; diff --git a/src/Braintree/Transaction.cs b/src/Braintree/Transaction.cs index abcef77b..3cd01bda 100644 --- a/src/Braintree/Transaction.cs +++ b/src/Braintree/Transaction.cs @@ -173,6 +173,7 @@ public class Transaction public virtual ThreeDSecureInfo ThreeDSecureInfo { get; protected set; } public virtual FacilitatedDetails FacilitatedDetails { get; protected set; } public virtual FacilitatorDetails FacilitatorDetails { get; protected set; } + public virtual string ScaExemptionRequested { get; protected set; } public virtual decimal? DiscountAmount { get; protected set; } public virtual decimal? ShippingAmount { get; protected set; } public virtual string ShipsFromPostalCode { get; protected set; } @@ -180,6 +181,9 @@ public class Transaction public virtual DateTime? AuthorizationExpiresAt { get; protected set; } public virtual string RetrievalReferenceNumber { get; protected set; } public virtual string AcquirerReferenceNumber { get; protected set; } + public virtual decimal? InstallmentCount { get; protected set; } + public virtual List Installments { get; protected set; } + public virtual List RefundedInstallments { get; protected set; } private IBraintreeGateway Gateway; @@ -214,6 +218,7 @@ protected internal Transaction(NodeWrapper node, IBraintreeGateway gateway) } Type = node.GetEnum("type", TransactionType.UNRECOGNIZED); + ScaExemptionRequested = node.GetString("sca-exemption-requested"); MerchantAccountId = node.GetString("merchant-account-id"); ProcessedWithNetworkToken = node.GetBoolean("processed-with-network-token"); ProcessorAuthorizationCode = node.GetString("processor-authorization-code"); @@ -385,6 +390,20 @@ protected internal Transaction(NodeWrapper node, IBraintreeGateway gateway) RetrievalReferenceNumber = node.GetString("retrieval-reference-number"); AcquirerReferenceNumber = node.GetString("acquirer-reference-number"); + + InstallmentCount = node.GetDecimal("installment-count"); + + Installments = new List(); + foreach (var installment in node.GetList("installments/installment")) + { + Installments.Add(new Installment(installment)); + } + + RefundedInstallments = new List(); + foreach (var installment in node.GetList("refunded-installments/refunded-installment")) + { + RefundedInstallments.Add(new Installment(installment)); + } } /// diff --git a/src/Braintree/TransactionRequest.cs b/src/Braintree/TransactionRequest.cs index 426ab59f..5d2c31fb 100644 --- a/src/Braintree/TransactionRequest.cs +++ b/src/Braintree/TransactionRequest.cs @@ -37,7 +37,9 @@ public class TransactionRequest : Request public TransactionCreditCardRequest CreditCard { get; set; } public decimal Amount { get; set; } public string DeviceData { get; set; } + [ObsoleteAttribute("use DeviceData instead", false)] public string DeviceSessionId { get; set; } + [ObsoleteAttribute("use DeviceData instead", false)] public string FraudMerchantId { get; set; } public string Channel { get; set; } public string OrderId { get; set; } @@ -65,6 +67,7 @@ public class TransactionRequest : Request public string BillingAddressId { get; set; } public string VenmoSdkPaymentMethodCode { get; set; } public string PaymentMethodNonce { get; set; } + public string ScaExemption { get; set; } public decimal? ServiceFeeAmount { get; set; } public string SharedPaymentMethodToken { get; set; } public string SharedPaymentMethodNonce { get; set; } @@ -92,6 +95,9 @@ public string ThreeDSecureToken { // NEXT_MAJOR_VERSION Rename Android Pay to Google Pay public TransactionAndroidPayCardRequest AndroidPayCard { get; set; } public TransactionApplePayCardRequest ApplePayCard { get; set; } + public string CurrencyIsoCode { get; set; } + + public InstallmentRequest InstallmentRequest { get; set; } public TransactionRequest() { @@ -128,11 +134,11 @@ protected virtual RequestBuilder BuildRequest(string root) builder.AddElement("order-id", OrderId); builder.AddElement("product-sku", ProductSku); builder.AddElement("channel", Channel); - builder.AddElement("device-session-id", DeviceSessionId); - builder.AddElement("fraud-merchant-id", FraudMerchantId); -// Remove this pragma warning when we remove Recurring param. +// Remove this pragma warning when we remove DeviceSessionId, FraudMerchantId, and Recurring. // We have this so we can build the SDK without obsolete error messages #pragma warning disable 618 + builder.AddElement("device-session-id", DeviceSessionId); + builder.AddElement("fraud-merchant-id", FraudMerchantId); if (Recurring.HasValue) builder.AddElement("recurring", Recurring); #pragma warning restore 618 builder.AddElement("transaction-source", TransactionSource); @@ -152,6 +158,7 @@ protected virtual RequestBuilder BuildRequest(string root) if (CustomFields.Count != 0) builder.AddElement("custom-fields", CustomFields); + builder.AddElement("currency-iso-code", CurrencyIsoCode); builder.AddElement("credit-card", CreditCard); builder.AddElement("customer", Customer); builder.AddElement("descriptor", Descriptor); @@ -163,6 +170,7 @@ protected virtual RequestBuilder BuildRequest(string root) builder.AddElement("three-d-secure-pass-thru", ThreeDSecurePassThru); builder.AddElement("three-d-secure-authentication-id", ThreeDSecureAuthenticationId); builder.AddElement("venmo-sdk-payment-method-code", VenmoSdkPaymentMethodCode); + builder.AddElement("sca-exemption", ScaExemption); builder.AddElement("shared-payment-method-token", SharedPaymentMethodToken); builder.AddElement("shared-payment-method-nonce", SharedPaymentMethodNonce); builder.AddElement("shared-customer-id", SharedCustomerId); @@ -184,6 +192,8 @@ protected virtual RequestBuilder BuildRequest(string root) builder.AddElement("android-pay-card", AndroidPayCard); if (ApplePayCard != null) builder.AddElement("apple-pay-card", ApplePayCard); + if (InstallmentRequest != null) + builder.AddElement("installments", InstallmentRequest); return builder; } } diff --git a/src/Braintree/ValidationErrorCode.cs b/src/Braintree/ValidationErrorCode.cs index 1fd02c90..6c87a24b 100644 --- a/src/Braintree/ValidationErrorCode.cs +++ b/src/Braintree/ValidationErrorCode.cs @@ -120,6 +120,7 @@ public enum ValidationErrorCode CREDIT_CARD_OPTIONS_VERIFICATION_MERCHANT_ACCOUNT_CANNOT_BE_SUB_MERCHANT_ACCOUNT = 91755, CREDIT_CARD_OPTIONS_VERIFICATION_ACCOUNT_TYPE_IS_INVALID = 91757, CREDIT_CARD_OPTIONS_VERIFICATION_ACCOUNT_TYPE_NOT_SUPPORTED = 91758, + CREDIT_CARD_OPTIONS_VERIFICATION_INVALID_PRESENTMENT_CURRENCY = 91760, CREDIT_CARD_PAYMENT_METHOD_CONFLICT = 81725, CREDIT_CARD_PAYMENT_METHOD_IS_NOT_A_CREDIT_CARD = 91738, CREDIT_CARD_PAYMENT_METHOD_NONCE_CARD_TYPE_IS_NOT_ACCEPTED = 91734, @@ -282,6 +283,7 @@ public enum ValidationErrorCode TRANSACTION_SHIPS_FROM_POSTAL_CODE_IS_TOO_LONG = 915165, TRANSACTION_SHIPS_FROM_POSTAL_CODE_IS_INVALID = 915166, TRANSACTION_SHIPS_FROM_POSTAL_CODE_INVALID_CHARACTERS = 915167, + TRANSACTION_SCA_EXEMPTION_REQUEST_INVALID = 915213, TRANSACTION_LINE_ITEM_COMMODITY_CODE_IS_TOO_LONG = 95801, TRANSACTION_LINE_ITEM_DESCRIPTION_IS_TOO_LONG = 95803, @@ -315,6 +317,7 @@ public enum ValidationErrorCode TRANSACTION_EXTERNAL_VAULT_STATUS_IS_INVALID = 915175, TRANSACTION_EXTERNAL_VAULT_STATUS_WITH_PREVIOUS_NETWORK_TRANSACTION_ID_IS_INVALID = 915177, TRANSACTION_EXTERNAL_VAULT_PREVIOUS_NETWORK_TRANSACTION_ID_IS_INVALID = 915179, + // NEXT_MAJOR_VERSION remove invalid card type error, the API no longer returns this error TRANSACTION_EXTERNAL_VAULT_CARD_TYPE_IS_INVALID = 915178, MERCHANT_COUNTRY_CANNOT_BE_BLANK = 83603, @@ -582,6 +585,7 @@ public enum ValidationErrorCode TRANSACTION_OPTIONS_CREDIT_CARD_ACCOUNT_TYPE_IS_INVALID = 915184, TRANSACTION_OPTIONS_CREDIT_CARD_ACCOUNT_TYPE_NOT_SUPPORTED = 915185, TRANSACTION_OPTIONS_CREDIT_CARD_ACCOUNT_TYPE_DEBIT_DOES_NOT_SUPPORT_AUTHS = 915186, + TRANSACTION_INVALID_PRESENTMENT_CURRENCY = 915214, TRANSACTION_ORDER_ID_IS_TOO_LONG = 91501, TRANSACTION_PAY_PAL_AUTH_EXPIRED = 91579, TRANSACTION_PAY_PAL_VAULT_RECORD_MISSING_DATA = 91583, @@ -691,6 +695,7 @@ public enum ValidationErrorCode MERCHANT_ACOUNT_DOES_NOT_MATCH3_D_SECURE_MERCHANT_ACCOUNT = 94284, AMOUNT_DOES_NOT_MATCH3_D_SECURE_AMOUNT = 94285, + // NEXT_MAJOR_VERSION Remove CustomerBrowserIsTooLong code as it is no longer returned from the gateway RISK_DATA_CUSTOMER_BROWSER_IS_TOO_LONG = 94701, RISK_DATA_CUSTOMER_DEVICE_ID_IS_TOO_LONG = 94702, RISK_DATA_CUSTOMER_LOCATION_ZIP_INVALID_CHARACTERS = 94703, diff --git a/test/Braintree.TestUtil/MerchantAccountIDs.cs b/test/Braintree.TestUtil/MerchantAccountIDs.cs index 57e62b4a..0234dc0a 100644 --- a/test/Braintree.TestUtil/MerchantAccountIDs.cs +++ b/test/Braintree.TestUtil/MerchantAccountIDs.cs @@ -12,5 +12,6 @@ public class MerchantAccountIDs public static string ANOTHER_US_BANK_MERCHANT_ACCOUNT_ID = "another_us_bank_merchant_account"; public static string ADYEN_MERCHANT_ACCOUNT_ID = "adyen_ma"; public static string BRAZIL_MERCHANT_ACCOUNT_ID = "hiper_brl"; + public static string CARD_PROCESSOR_BRAZIL_MERCHANT_ACCOUNT_ID = "card_processor_brl"; } } diff --git a/test/Braintree.Tests.Integration/CreditCardIntegrationTest.cs b/test/Braintree.Tests.Integration/CreditCardIntegrationTest.cs index 85723c79..cd594f2f 100644 --- a/test/Braintree.Tests.Integration/CreditCardIntegrationTest.cs +++ b/test/Braintree.Tests.Integration/CreditCardIntegrationTest.cs @@ -161,6 +161,7 @@ public void Create_CreatesCreditCardWithAVenmoSdkPaymentMethodCode() } [Test] + [Obsolete] public void Create_CreatesCreditCardWithSecurityParams() { Customer customer = gateway.Customer.Create(new CustomerRequest()).Target; @@ -911,7 +912,7 @@ public void VerifyValidCreditCardWithVerificationRiskData() { VerifyCard = true }, - DeviceSessionId = "abc123" + DeviceData = "{\"device_session_id\":\"my_dsid\", \"fraud_merchant_id\":\"7\"}" }; Result result = gateway.CreditCard.Create(request); @@ -1698,5 +1699,157 @@ public void Find_WithNonNetworkTokenizedCard() CreditCard savedCreditCard = gateway.CreditCard.Find(creditCard.Token); Assert.IsFalse(savedCreditCard.IsNetworkTokenized); } + + [Test] + public void Update_WithMerchantCurrencyOption() + { + Customer customer = gateway.Customer.Create(new CustomerRequest()).Target; + + var creditCardCreateRequest = new CreditCardRequest + { + CustomerId = customer.Id, + Number = SandboxValues.CreditCardNumber.VISA, + ExpirationDate = "05/12", + CVV = "123", + }; + + CreditCard originalCreditCard = gateway.CreditCard.Create(creditCardCreateRequest).Target; + + var creditCardUpdateRequest = new CreditCardRequest + { + CustomerId = customer.Id, + Number = SandboxValues.CreditCardNumber.VISA, + ExpirationDate = "12/05", + CVV = "321", + Options = new CreditCardOptionsRequest() + { + VerificationCurrencyIsoCode = "USD" + }, + }; + + CreditCard creditCard = gateway.CreditCard.Update(originalCreditCard.Token, creditCardUpdateRequest).Target; + Assert.AreEqual("1111", creditCard.LastFour); + Assert.AreEqual("12", creditCard.ExpirationMonth); + Assert.AreEqual("2005", creditCard.ExpirationYear); + Assert.AreEqual(DateTime.Now.Year, creditCard.CreatedAt.Value.Year); + Assert.AreEqual(DateTime.Now.Year, creditCard.UpdatedAt.Value.Year); + } + + [Test] + public void Update_WithInvalidMerchantCurrencyOption() + { + Customer customer = gateway.Customer.Create(new CustomerRequest()).Target; + + var creditCardCreateRequest = new CreditCardRequest + { + CustomerId = customer.Id, + Number = SandboxValues.CreditCardNumber.VISA, + ExpirationDate = "05/12", + CVV = "123", + }; + + CreditCard originalCreditCard = gateway.CreditCard.Create(creditCardCreateRequest).Target; + + var creditCardUpdateRequest = new CreditCardRequest + { + CustomerId = customer.Id, + Number = SandboxValues.CreditCardNumber.VISA, + ExpirationDate = "12/05", + CVV = "321", + Options = new CreditCardOptionsRequest() + { + VerificationCurrencyIsoCode = "GBP" + }, + }; + + Result updateResult = gateway.CreditCard.Update(originalCreditCard.Token, creditCardUpdateRequest); + Assert.IsFalse(updateResult.IsSuccess()); + Assert.AreEqual( + ValidationErrorCode.CREDIT_CARD_OPTIONS_VERIFICATION_INVALID_PRESENTMENT_CURRENCY, + updateResult.Errors.DeepAll()[0].Code + ); + } + + [Test] + public void Create_WithMerchantCurrencyOption() + { + Customer customer = gateway.Customer.Create(new CustomerRequest()).Target; + + var creditCardRequest = new CreditCardRequest + { + CustomerId = customer.Id, + Number = "5105105105105100", + ExpirationDate = "05/12", + CVV = "123", + Options = new CreditCardOptionsRequest() + { + VerificationCurrencyIsoCode = "USD" + }, + CardholderName = "Michael Angelo", + BillingAddress = new CreditCardAddressRequest + { + FirstName = "John", + CountryName = "Chad", + CountryCodeAlpha2 = "TD", + CountryCodeAlpha3 = "TCD", + CountryCodeNumeric = "148" + } + }; + + CreditCard creditCard = gateway.CreditCard.Create(creditCardRequest).Target; + + Assert.AreEqual("510510", creditCard.Bin); + Assert.AreEqual("5100", creditCard.LastFour); + Assert.AreEqual("510510******5100", creditCard.MaskedNumber); + Assert.AreEqual("05", creditCard.ExpirationMonth); + Assert.AreEqual("2012", creditCard.ExpirationYear); + Assert.AreEqual("Michael Angelo", creditCard.CardholderName); + Assert.IsTrue(creditCard.IsDefault.Value); + Assert.IsFalse(creditCard.IsVenmoSdk.Value); + Assert.AreEqual(DateTime.Now.Year, creditCard.CreatedAt.Value.Year); + Assert.AreEqual(DateTime.Now.Year, creditCard.UpdatedAt.Value.Year); + Assert.IsNotNull(creditCard.ImageUrl); + + Address billingAddress = creditCard.BillingAddress; + Assert.AreEqual("Chad", billingAddress.CountryName); + Assert.AreEqual("TD", billingAddress.CountryCodeAlpha2); + Assert.AreEqual("TCD", billingAddress.CountryCodeAlpha3); + Assert.AreEqual("148", billingAddress.CountryCodeNumeric); + Assert.IsTrue(Regex.IsMatch(creditCard.UniqueNumberIdentifier, "\\A\\w{32}\\z")); + } + + [Test] + public void Create_WithInvalidMerchantCurrencyOption() + { + Customer customer = gateway.Customer.Create(new CustomerRequest()).Target; + + var creditCardRequest = new CreditCardRequest + { + CustomerId = customer.Id, + Number = "5105105105105100", + ExpirationDate = "05/12", + CVV = "123", + Options = new CreditCardOptionsRequest() + { + VerificationCurrencyIsoCode = "GBP" + }, + CardholderName = "Michael Angelo", + BillingAddress = new CreditCardAddressRequest + { + FirstName = "John", + CountryName = "Chad", + CountryCodeAlpha2 = "TD", + CountryCodeAlpha3 = "TCD", + CountryCodeNumeric = "148" + } + }; + + Result creditCard = gateway.CreditCard.Create(creditCardRequest); + Assert.IsFalse(creditCard.IsSuccess()); + Assert.AreEqual( + ValidationErrorCode.CREDIT_CARD_OPTIONS_VERIFICATION_INVALID_PRESENTMENT_CURRENCY, + creditCard.Errors.DeepAll()[0].Code + ); + } } } diff --git a/test/Braintree.Tests.Integration/CustomerIntegrationTest.cs b/test/Braintree.Tests.Integration/CustomerIntegrationTest.cs index a1504686..6a7e03a4 100644 --- a/test/Braintree.Tests.Integration/CustomerIntegrationTest.cs +++ b/test/Braintree.Tests.Integration/CustomerIntegrationTest.cs @@ -535,6 +535,7 @@ public void CreateAsync_CreatesCustomerWithSpecifiedValues() #endif [Test] + [Obsolete] public void Create_withSecurityParams() { var createRequest = new CustomerRequest() @@ -553,6 +554,25 @@ public void Create_withSecurityParams() Assert.IsTrue(result.IsSuccess()); } + [Test] + public void Create_withDeviceData() + { + var createRequest = new CustomerRequest() + { + CreditCard = new CreditCardRequest() + { + Number = "5105105105105100", + ExpirationDate = "05/12", + CVV = "123", + DeviceData = "{\"device_session_id\":\"my_dsid\", \"fraud_merchant_id\":\"7\"}" + } + }; + + Result result = gateway.Customer.Create(createRequest); + + Assert.IsTrue(result.IsSuccess()); + } + [Test] public void Create_withRiskDataParam() { @@ -1880,5 +1900,354 @@ public void Search_OnPayPalAccountEmail() Assert.AreEqual(1, gateway.Customer.Search(search).MaximumCount); } + + [Test] + public void Create_WithMerchantCurrencyOption() + { + var createRequest = new CustomerRequest() + { + FirstName = "Michael", + LastName = "Angelo", + Company = "Some Company", + Email = "hansolo64@example.com", + Phone = "312.555.1111", + Fax = "312.555.1112", + Website = "www.example.com", + CreditCard = new CreditCardRequest() + { + Number = "5105105105105100", + ExpirationDate = "05/12", + Options = new CreditCardOptionsRequest() + { + VerificationCurrencyIsoCode = "USD" + }, + BillingAddress = new CreditCardAddressRequest + { + CountryName = "Macau", + CountryCodeAlpha2 = "MO", + CountryCodeAlpha3 = "MAC", + CountryCodeNumeric = "446" + } + } + }; + + Customer customer = gateway.Customer.Create(createRequest).Target; + Assert.AreEqual("Michael", customer.FirstName); + Assert.AreEqual("Angelo", customer.LastName); + Assert.AreEqual("Some Company", customer.Company); + Assert.AreEqual("hansolo64@example.com", customer.Email); + Assert.AreEqual("312.555.1111", customer.Phone); + Assert.AreEqual("312.555.1112", customer.Fax); + Assert.AreEqual("www.example.com", customer.Website); + Assert.AreEqual(DateTime.Now.Year, customer.CreatedAt.Value.Year); + Assert.AreEqual(DateTime.Now.Year, customer.UpdatedAt.Value.Year); + + Assert.AreEqual(1, customer.CreditCards.Length); + Assert.AreEqual("510510", customer.CreditCards[0].Bin); + Assert.AreEqual("5100", customer.CreditCards[0].LastFour); + Assert.AreEqual("05", customer.CreditCards[0].ExpirationMonth); + Assert.AreEqual("2012", customer.CreditCards[0].ExpirationYear); + + Address billingAddress = customer.CreditCards[0].BillingAddress; + Assert.AreEqual("Macau", billingAddress.CountryName); + Assert.AreEqual("MO", billingAddress.CountryCodeAlpha2); + Assert.AreEqual("MAC", billingAddress.CountryCodeAlpha3); + Assert.AreEqual("446", billingAddress.CountryCodeNumeric); + } + + [Test] + public void Create_WithInvalidMerchantCurrencyOption() + { + var createRequest = new CustomerRequest() + { + FirstName = "Michael", + LastName = "Angelo", + Company = "Some Company", + Email = "hansolo64@example.com", + Phone = "312.555.1111", + Fax = "312.555.1112", + Website = "www.example.com", + CreditCard = new CreditCardRequest() + { + Number = "5105105105105100", + ExpirationDate = "05/12", + Options = new CreditCardOptionsRequest() + { + VerificationCurrencyIsoCode = "GBP" + }, + BillingAddress = new CreditCardAddressRequest + { + CountryName = "Macau", + CountryCodeAlpha2 = "MO", + CountryCodeAlpha3 = "MAC", + CountryCodeNumeric = "446" + } + } + }; + + Result customer = gateway.Customer.Create(createRequest); + Assert.IsFalse(customer.IsSuccess()); + Assert.AreEqual( + ValidationErrorCode.CREDIT_CARD_OPTIONS_VERIFICATION_INVALID_PRESENTMENT_CURRENCY, + customer.Errors.DeepAll()[0].Code + ); + } + + [Test] + public void Update_CustomerBySupplyingMerchantCurrencyOption() + { + string oldId = Guid.NewGuid().ToString(); + string newId = Guid.NewGuid().ToString(); + var createRequest = new CustomerRequest() + { + Id = oldId, + FirstName = "Old First", + LastName = "Old Last", + Company = "Old Company", + Email = "old@example.com", + Phone = "312.555.1111 xOld", + Fax = "312.555.1112 xOld", + Website = "old.example.com" + }; + + gateway.Customer.Create(createRequest); + + var updateRequest = new CustomerRequest() + { + Id = newId, + FirstName = "Michael", + LastName = "Angelo", + Company = "Some Company", + Email = "hansolo64@example.com", + Phone = "312.555.1111", + Fax = "312.555.1112", + Website = "www.example.com", + CreditCard = new CreditCardRequest() + { + Number = "5105105105105100", + ExpirationDate = "05/12", + Options = new CreditCardOptionsRequest() + { + VerificationCurrencyIsoCode = "USD" + } + } + }; + + Customer updatedCustomer = gateway.Customer.Update(oldId, updateRequest).Target; + Assert.AreEqual(newId, updatedCustomer.Id); + Assert.AreEqual("Michael", updatedCustomer.FirstName); + Assert.AreEqual("Angelo", updatedCustomer.LastName); + Assert.AreEqual("Some Company", updatedCustomer.Company); + Assert.AreEqual("hansolo64@example.com", updatedCustomer.Email); + Assert.AreEqual("312.555.1111", updatedCustomer.Phone); + Assert.AreEqual("312.555.1112", updatedCustomer.Fax); + Assert.AreEqual("www.example.com", updatedCustomer.Website); + Assert.AreEqual(DateTime.Now.Year, updatedCustomer.CreatedAt.Value.Year); + Assert.AreEqual(DateTime.Now.Year, updatedCustomer.UpdatedAt.Value.Year); + Assert.AreEqual(1, updatedCustomer.CreditCards.Length); + Assert.AreEqual("510510", updatedCustomer.CreditCards[0].Bin); + Assert.AreEqual("5100", updatedCustomer.CreditCards[0].LastFour); + Assert.AreEqual("05", updatedCustomer.CreditCards[0].ExpirationMonth); + Assert.AreEqual("2012", updatedCustomer.CreditCards[0].ExpirationYear); + } + + [Test] + public void Update_CustomerBySupplyingInvalidMerchantCurrencyOption() + { + string oldId = Guid.NewGuid().ToString(); + string newId = Guid.NewGuid().ToString(); + var createRequest = new CustomerRequest() + { + Id = oldId, + FirstName = "Old First", + LastName = "Old Last", + Company = "Old Company", + Email = "old@example.com", + Phone = "312.555.1111 xOld", + Fax = "312.555.1112 xOld", + Website = "old.example.com", + CreditCard = new CreditCardRequest() + { + Number = "5105105105105100", + ExpirationDate = "05/12", + } + }; + + gateway.Customer.Create(createRequest); + + var updateRequest = new CustomerRequest() + { + Id = newId, + FirstName = "Michael", + LastName = "Angelo", + Company = "Some Company", + Email = "hansolo64@example.com", + Phone = "312.555.1111", + Fax = "312.555.1112", + Website = "www.example.com", + CreditCard = new CreditCardRequest() + { + Number = "5105105105105100", + ExpirationDate = "05/11", + Options = new CreditCardOptionsRequest() + { + VerificationCurrencyIsoCode = "GBP" + } + } + }; + + Result updatedCustomer = gateway.Customer.Update(oldId, updateRequest); + Assert.IsFalse(updatedCustomer.IsSuccess()); + Assert.AreEqual( + ValidationErrorCode.CREDIT_CARD_OPTIONS_VERIFICATION_INVALID_PRESENTMENT_CURRENCY, + updatedCustomer.Errors.DeepAll()[0].Code + ); + } + + [Test] + public void Create_WithNonceAndMerchantCurrencyOption() + { + string nonce = TestHelper.GenerateUnlockedNonce(gateway); + Result result = gateway.Customer.Create(new CustomerRequest + { + CreditCard = new CreditCardRequest + { + PaymentMethodNonce = nonce, + Options = new CreditCardOptionsRequest() + { + VerificationCurrencyIsoCode = "USD" + } + } + }); + Assert.IsTrue(result.IsSuccess()); + Assert.AreEqual(1, result.Target.CreditCards.Length); + } + + + [Test] + public void Create_WithNonceAndInvalidMerchantCurrencyOption() + { + string nonce = TestHelper.GenerateUnlockedNonce(gateway); + Result result = gateway.Customer.Create(new CustomerRequest + { + CreditCard = new CreditCardRequest + { + PaymentMethodNonce = nonce, + Options = new CreditCardOptionsRequest() + { + VerificationCurrencyIsoCode = "GBP" + } + } + }); + Assert.IsFalse(result.IsSuccess()); + Assert.AreEqual( + ValidationErrorCode.CREDIT_CARD_OPTIONS_VERIFICATION_INVALID_PRESENTMENT_CURRENCY, + result.Errors.DeepAll()[0].Code + ); + } + + [Test] + public void Update_CustomerWithNonceAndMerchantCurrencyOption() + { + string oldId = Guid.NewGuid().ToString(); + string newId = Guid.NewGuid().ToString(); + var createRequest = new CustomerRequest() + { + Id = oldId, + FirstName = "Old First", + LastName = "Old Last", + Company = "Old Company", + Email = "old@example.com", + Phone = "312.555.1111 xOld", + Fax = "312.555.1112 xOld", + Website = "old.example.com" + }; + + gateway.Customer.Create(createRequest); + + string nonce = TestHelper.GenerateUnlockedNonce(gateway); + + var updateRequest = new CustomerRequest() + { + Id = newId, + FirstName = "Michael", + LastName = "Angelo", + Company = "Some Company", + Email = "hansolo64@example.com", + Phone = "312.555.1111", + Fax = "312.555.1112", + Website = "www.example.com", + CreditCard = new CreditCardRequest() + { + PaymentMethodNonce = nonce, + Options = new CreditCardOptionsRequest() + { + VerificationCurrencyIsoCode = "USD" + } + } + }; + + Customer updatedCustomer = gateway.Customer.Update(oldId, updateRequest).Target; + Assert.AreEqual(newId, updatedCustomer.Id); + Assert.AreEqual("Michael", updatedCustomer.FirstName); + Assert.AreEqual("Angelo", updatedCustomer.LastName); + Assert.AreEqual("Some Company", updatedCustomer.Company); + Assert.AreEqual("hansolo64@example.com", updatedCustomer.Email); + Assert.AreEqual("312.555.1111", updatedCustomer.Phone); + Assert.AreEqual("312.555.1112", updatedCustomer.Fax); + Assert.AreEqual("www.example.com", updatedCustomer.Website); + Assert.AreEqual(DateTime.Now.Year, updatedCustomer.CreatedAt.Value.Year); + Assert.AreEqual(DateTime.Now.Year, updatedCustomer.UpdatedAt.Value.Year); + Assert.AreEqual(1, updatedCustomer.CreditCards.Length); + } + + [Test] + public void Update_CustomerWithNonceAndInvalidMerchantCurrencyOption() + { + string oldId = Guid.NewGuid().ToString(); + string newId = Guid.NewGuid().ToString(); + var createRequest = new CustomerRequest() + { + Id = oldId, + FirstName = "Old First", + LastName = "Old Last", + Company = "Old Company", + Email = "old@example.com", + Phone = "312.555.1111 xOld", + Fax = "312.555.1112 xOld", + Website = "old.example.com" + }; + + gateway.Customer.Create(createRequest); + + string nonce = TestHelper.GenerateUnlockedNonce(gateway); + + var updateRequest = new CustomerRequest() + { + Id = newId, + FirstName = "Michael", + LastName = "Angelo", + Company = "Some Company", + Email = "hansolo64@example.com", + Phone = "312.555.1111", + Fax = "312.555.1112", + Website = "www.example.com", + CreditCard = new CreditCardRequest() + { + PaymentMethodNonce = nonce, + Options = new CreditCardOptionsRequest() + { + VerificationCurrencyIsoCode = "GBP" + } + } + }; + + Result updatedCustomer = gateway.Customer.Update(oldId, updateRequest); + Assert.IsFalse(updatedCustomer.IsSuccess()); + Assert.AreEqual( + ValidationErrorCode.CREDIT_CARD_OPTIONS_VERIFICATION_INVALID_PRESENTMENT_CURRENCY, + updatedCustomer.Errors.DeepAll()[0].Code + ); + } } } diff --git a/test/Braintree.Tests.Integration/PaymentMethodIntegrationTest.cs b/test/Braintree.Tests.Integration/PaymentMethodIntegrationTest.cs index a4b0a0ee..76f4bddd 100644 --- a/test/Braintree.Tests.Integration/PaymentMethodIntegrationTest.cs +++ b/test/Braintree.Tests.Integration/PaymentMethodIntegrationTest.cs @@ -1925,5 +1925,121 @@ public void Create_CreatesWithErrorAccountTypeNotSupported() paymentMethodResult.Errors.ForObject("CreditCard").ForObject("Options").OnField("VerificationAccountType")[0].Code ); } + + [Test] + public void Create_PaymentMethodWithNonceAndMerchantCurrencyOption() + { + string nonce = TestHelper.GenerateUnlockedNonce(gateway); + Result result = gateway.Customer.Create(new CustomerRequest()); + Assert.IsTrue(result.IsSuccess()); + + var request = new PaymentMethodRequest + { + CustomerId = result.Target.Id, + PaymentMethodNonce = nonce, + Options = new PaymentMethodOptionsRequest() + { + VerifyCard = true, + VerificationCurrencyIsoCode = "USD" + } + }; + Result paymentMethodResult = gateway.PaymentMethod.Create(request); + + Assert.IsTrue(paymentMethodResult.IsSuccess()); + Assert.IsNotNull(paymentMethodResult.Target.Token); + Assert.AreEqual(result.Target.Id, paymentMethodResult.Target.CustomerId); + Assert.IsInstanceOf(typeof(CreditCard), paymentMethodResult.Target); + } + + [Test] + public void Create_PaymentMethodWithNonceAndInvalidMerchantCurrencyOption() + { + string nonce = TestHelper.GenerateUnlockedNonce(gateway); + Result result = gateway.Customer.Create(new CustomerRequest()); + Assert.IsTrue(result.IsSuccess()); + + var request = new PaymentMethodRequest + { + CustomerId = result.Target.Id, + PaymentMethodNonce = nonce, + Options = new PaymentMethodOptionsRequest() + { + VerifyCard = true, + VerificationCurrencyIsoCode = "GBP" + } + }; + Result paymentMethodResult = gateway.PaymentMethod.Create(request); + + Assert.IsFalse(paymentMethodResult.IsSuccess()); + Assert.AreEqual( + ValidationErrorCode.CREDIT_CARD_OPTIONS_VERIFICATION_INVALID_PRESENTMENT_CURRENCY, + paymentMethodResult.Errors.DeepAll()[0].Code + ); + } + + [Test] + public void Update_UpdatePaymentMethodWithMerchantCurrencyOption() + { + var customer = gateway.Customer.Create().Target; + var creditCard = gateway.CreditCard.Create(new CreditCardRequest + { + CardholderName = "Original Holder", + CustomerId = customer.Id, + CVV = "123", + Number = SandboxValues.CreditCardNumber.VISA, + ExpirationDate = "05/2012", + }).Target; + + Result paymentMethodResult = gateway.PaymentMethod.Update( + creditCard.Token, + new PaymentMethodRequest + { + CardholderName = "New Holder", + CVV = "456", + Number = TestUtil.CreditCardNumbers.FailsSandboxVerification.MasterCard, + ExpirationDate = "06/2013", + Options = new PaymentMethodOptionsRequest + { + VerificationCurrencyIsoCode = "USD" + } + }); + + Assert.IsTrue(paymentMethodResult.IsSuccess()); + } + + [Test] + public void Update_UpdatePaymentMethodWithInvalidMerchantCurrencyOption() + { + var customer = gateway.Customer.Create().Target; + var creditCard = gateway.CreditCard.Create(new CreditCardRequest + { + CardholderName = "Original Holder", + CustomerId = customer.Id, + CVV = "123", + Number = SandboxValues.CreditCardNumber.VISA, + ExpirationDate = "05/2012", + }).Target; + + Result paymentMethodResult = gateway.PaymentMethod.Update( + creditCard.Token, + new PaymentMethodRequest + { + CardholderName = "New Holder", + CVV = "456", + Number = TestUtil.CreditCardNumbers.FailsSandboxVerification.MasterCard, + ExpirationDate = "06/2013", + Options = new PaymentMethodOptionsRequest + { + VerifyCard = true, + VerificationCurrencyIsoCode = "GBP" + } + }); + + Assert.IsFalse(paymentMethodResult.IsSuccess()); + Assert.AreEqual( + ValidationErrorCode.CREDIT_CARD_OPTIONS_VERIFICATION_INVALID_PRESENTMENT_CURRENCY, + paymentMethodResult.Errors.DeepAll()[0].Code + ); + } } } diff --git a/test/Braintree.Tests.Integration/ThreeDSecureIntegrationTest.cs b/test/Braintree.Tests.Integration/ThreeDSecureIntegrationTest.cs index e2c8649b..03fae785 100644 --- a/test/Braintree.Tests.Integration/ThreeDSecureIntegrationTest.cs +++ b/test/Braintree.Tests.Integration/ThreeDSecureIntegrationTest.cs @@ -51,7 +51,7 @@ public string GetClientDataString(BraintreeGateway gateway) { CustomerId = customer.Id, Number = "4111111111111111", ExpirationMonth = "12", - ExpirationYear = "2020" + ExpirationYear = "2030" }; CreditCard creditCard = gateway.CreditCard.Create(creditCardRequest).Target; var nonce = gateway.PaymentMethodNonce.Create(creditCard.Token).Target.Nonce; @@ -196,7 +196,7 @@ public void LookupThreeDSecure_HasValidationError() ThreeDSecureLookupAddress billingAddress = new ThreeDSecureLookupAddress { - GivenName = "Férst", + GivenName = "\x00", Surname = "Lést", PhoneNumber = "1234567890", Locality = "Oakland", diff --git a/test/Braintree.Tests.Integration/TransactionIntegrationTest.cs b/test/Braintree.Tests.Integration/TransactionIntegrationTest.cs index 25c9450e..41f7c812 100644 --- a/test/Braintree.Tests.Integration/TransactionIntegrationTest.cs +++ b/test/Braintree.Tests.Integration/TransactionIntegrationTest.cs @@ -1395,6 +1395,47 @@ public void Sale_ReturnsSuccessfulResponse() Assert.IsNull(transaction.AcquirerReferenceNumber); } + [Test] + public void Sale_ReturnsSuccessfulScaExemptionResponse() + { + var requestedScaExemption = "low_value"; + var request = new TransactionRequest + { + Amount = SandboxValues.TransactionAmount.AUTHORIZE, + ScaExemption = requestedScaExemption, + CreditCard = new TransactionCreditCardRequest + { + Number = SandboxValues.CreditCardNumber.VISA_COUNTRY_OF_ISSUANCE_IE, + ExpirationDate = "05/2009", + } + }; + + Result result = gateway.Transaction.Sale(request); + Assert.IsTrue(result.IsSuccess()); + Transaction transaction = result.Target; + + Assert.AreEqual(requestedScaExemption, transaction.ScaExemptionRequested); + } + + [Test] + public void Sale_ReturnsFailureScaExemptionResponse() + { + var request = new TransactionRequest + { + Amount = SandboxValues.TransactionAmount.AUTHORIZE, + ScaExemption = "invalid_sca_exemption", + CreditCard = new TransactionCreditCardRequest + { + Number = SandboxValues.CreditCardNumber.VISA_COUNTRY_OF_ISSUANCE_IE, + ExpirationDate = "05/2009", + } + }; + + Result result = gateway.Transaction.Sale(request); + Assert.IsFalse(result.IsSuccess()); + Assert.AreEqual(ValidationErrorCode.TRANSACTION_SCA_EXEMPTION_REQUEST_INVALID, result.Errors.ForObject("Transaction").OnField("ScaExemption")[0].Code); + } + [Test] public void Sale_ReturnsSuccessfulResponseWithNetworkResponseCodeText() { @@ -1864,7 +1905,7 @@ public void Sale_ReturnsSuccessfulResponseWithRiskData() Number = SandboxValues.CreditCardNumber.VISA, ExpirationDate = "05/2009", }, - DeviceSessionId = "abc123" + DeviceData = "{\"device_session_id\":\"my_dsid\", \"fraud_merchant_id\":\"7\"}" }; Result result = gateway.Transaction.Sale(request); @@ -1931,7 +1972,7 @@ public void Sale_WithRiskData() CustomerLocationZip = "91244", CustomerTenure = 20 }, - DeviceSessionId = "abc123" + DeviceData = "{\"device_session_id\":\"my_dsid\", \"fraud_merchant_id\":\"7\"}" }; Result result = gateway.Transaction.Sale(request); @@ -1962,7 +2003,7 @@ public void Sale_FailureResponseWithInvalidRiskData() CustomerLocationZip = "912$4", CustomerTenure = 20 }, - DeviceSessionId = "abc123" + DeviceData = "{\"device_session_id\":\"my_dsid\", \"fraud_merchant_id\":\"7\"}" }; Result result = gateway.Transaction.Sale(request); @@ -2275,6 +2316,7 @@ public void Sale_WithProductSkuInvalid() } [Test] + [Obsolete] public void Sale_WithSecurityParams() { var request = new TransactionRequest @@ -4946,7 +4988,7 @@ public void Sale_WithVisaReturnsNetworkTransactionIdentifier() } [Test] - public void Sale_WithAmexDoesNotReturnNetworkTransactionIdentifier() + public void Sale_WithAmexReturnsNetworkTransactionIdentifier() { var request = new TransactionRequest { @@ -4962,6 +5004,26 @@ public void Sale_WithAmexDoesNotReturnNetworkTransactionIdentifier() Assert.IsTrue(result.IsSuccess()); Transaction transaction = result.Target; + Assert.IsNotNull(transaction.NetworkTransactionId); + } + + [Test] + public void Sale_WithJCBDoesNotReturnNetworkTransactionIdentifier() + { + var request = new TransactionRequest + { + Amount = SandboxValues.TransactionAmount.AUTHORIZE, + CreditCard = new TransactionCreditCardRequest + { + Number = SandboxValues.CreditCardNumber.JCB, + ExpirationDate = "05/2009", + }, + }; + + Result result = gateway.Transaction.Sale(request); + Assert.IsTrue(result.IsSuccess()); + Transaction transaction = result.Target; + Assert.IsNull(transaction.NetworkTransactionId); } @@ -5008,7 +5070,7 @@ public void Sale_AmexWithExternalVaultStatus_ReturnsSuccessfulResponse() Result result = gateway.Transaction.Sale(request); Assert.IsTrue(result.IsSuccess()); Transaction transaction = result.Target; - Assert.IsNull(transaction.NetworkTransactionId); + Assert.IsNotNull(transaction.NetworkTransactionId); } [Test] @@ -5032,7 +5094,7 @@ public void Sale_AmexWithNullExternalVaultPreviousNetworkTransactionId_ReturnsSu Result result = gateway.Transaction.Sale(request); Assert.IsTrue(result.IsSuccess()); Transaction transaction = result.Target; - Assert.IsNull(transaction.NetworkTransactionId); + Assert.IsNotNull(transaction.NetworkTransactionId); } [Test] @@ -5166,32 +5228,6 @@ public void Sale_WithExternalVault_ValidationErrorStatusWithPreviousNetworkTrans ); } - [Test] - public void Sale_WithExternalVault_ValidationErrorCardTypeIsInvalid() - { - var request = new TransactionRequest - { - Amount = SandboxValues.TransactionAmount.AUTHORIZE, - CreditCard = new TransactionCreditCardRequest - { - Number = SandboxValues.CreditCardNumber.AMEX, - ExpirationDate = "05/2009", - }, - ExternalVault = new ExternalVaultRequest - { - Status = "vaulted", - PreviousNetworkTransactionId = "123456789012345", - } - }; - - Result result = gateway.Transaction.Sale(request); - Assert.IsFalse(result.IsSuccess()); - Assert.AreEqual( - ValidationErrorCode.TRANSACTION_EXTERNAL_VAULT_CARD_TYPE_IS_INVALID, - result.Errors.ForObject("Transaction").ForObject("ExternalVault").OnField("PreviousNetworkTransactionId")[0].Code - ); - } - [Test] public void Sale_HiperWithAccountTypeCredit_ReturnsSuccessfulResponse() { @@ -9698,5 +9734,213 @@ public void Sale_NonNetworkTokenizedTransaction() { Transaction transaction = transactionResult.Target; Assert.IsFalse(transaction.ProcessedWithNetworkToken); } + + [Test] + public void Sale_WithMerchantCurrency() + { + var request = new TransactionRequest + { + Amount = SandboxValues.TransactionAmount.AUTHORIZE, + CurrencyIsoCode = "USD", + CreditCard = new TransactionCreditCardRequest + { + Number = SandboxValues.CreditCardNumber.VISA, + ExpirationDate = "05/2009", + } + }; + + Result result = gateway.Transaction.Sale(request); + Assert.IsTrue(result.IsSuccess()); + Transaction transaction = result.Target; + + Assert.AreEqual(1000.00, transaction.Amount); + Assert.AreEqual(TransactionType.SALE, transaction.Type); + Assert.AreEqual(TransactionStatus.AUTHORIZED, transaction.Status); + Assert.IsNotNull(transaction.AuthorizationExpiresAt); + Assert.AreEqual(DateTime.Now.Year, transaction.CreatedAt.Value.Year); + Assert.AreEqual(DateTime.Now.Year, transaction.UpdatedAt.Value.Year); + Assert.IsNotNull(transaction.ProcessorAuthorizationCode); + Assert.AreEqual(TransactionGatewayRejectionReason.UNRECOGNIZED, transaction.GatewayRejectionReason); + + CreditCard creditCard = transaction.CreditCard; + Assert.AreEqual("411111", creditCard.Bin); + Assert.AreEqual("1111", creditCard.LastFour); + Assert.AreEqual("05", creditCard.ExpirationMonth); + Assert.AreEqual("2009", creditCard.ExpirationYear); + Assert.AreEqual("05/2009", creditCard.ExpirationDate); + Assert.IsNull(transaction.AcquirerReferenceNumber); + } + + [Test] + public void Sale_WithInvalidMerchantCurrency() + { + var request = new TransactionRequest + { + Amount = SandboxValues.TransactionAmount.AUTHORIZE, + CurrencyIsoCode = "GBP", + CreditCard = new TransactionCreditCardRequest + { + Number = SandboxValues.CreditCardNumber.VISA, + ExpirationDate = "05/2009", + } + }; + + Result result = gateway.Transaction.Sale(request); + Assert.IsFalse(result.IsSuccess()); + Assert.AreEqual( + ValidationErrorCode.TRANSACTION_INVALID_PRESENTMENT_CURRENCY, + result.Errors.DeepAll()[0].Code + ); + } + + [Test] + public void Sale_WithNonceAndMerchantCurrency() + { + var request = new TransactionRequest + { + Amount = SandboxValues.TransactionAmount.AUTHORIZE, + CurrencyIsoCode = "USD", + PaymentMethodNonce = TestHelper.GenerateUnlockedNonce(gateway) + }; + + Result result = gateway.Transaction.Sale(request); + Assert.IsTrue(result.IsSuccess()); + } + + [Test] + public void Sale_WithNonceAndInvalidMerchantCurrency() + { + var request = new TransactionRequest + { + Amount = SandboxValues.TransactionAmount.AUTHORIZE, + CurrencyIsoCode = "GBP", + PaymentMethodNonce = TestHelper.GenerateUnlockedNonce(gateway) + }; + + Result result = gateway.Transaction.Sale(request); + Assert.IsFalse(result.IsSuccess()); + Assert.AreEqual( + ValidationErrorCode.TRANSACTION_INVALID_PRESENTMENT_CURRENCY, + result.Errors.DeepAll()[0].Code + ); + } + + [Test] + public void Sale_WithPaymentMethodTokenAndMerchantCurrency() + { + Customer customer = gateway.Customer.Create(new CustomerRequest()).Target; + CreditCardRequest creditCardRequest = new CreditCardRequest + { + CustomerId = customer.Id, + CVV = "123", + Number = "5105105105105100", + ExpirationDate = "05/12" + }; + + CreditCard creditCard = gateway.CreditCard.Create(creditCardRequest).Target; + + TransactionRequest request = new TransactionRequest + { + Amount = SandboxValues.TransactionAmount.AUTHORIZE, + PaymentMethodToken = creditCard.Token, + CurrencyIsoCode = "USD" + }; + + Result result = gateway.Transaction.Sale(request); + Assert.IsTrue(result.IsSuccess()); + Transaction transaction = result.Target; + + Assert.AreEqual(creditCard.Token, transaction.CreditCard.Token); + Assert.AreEqual("510510", transaction.CreditCard.Bin); + Assert.AreEqual("05/2012", transaction.CreditCard.ExpirationDate); + } + + [Test] + public void Sale_WithPaymentMethodTokenAndInvalidMerchantCurrency() + { + Customer customer = gateway.Customer.Create(new CustomerRequest()).Target; + CreditCardRequest creditCardRequest = new CreditCardRequest + { + CustomerId = customer.Id, + CVV = "123", + Number = "5105105105105100", + ExpirationDate = "05/12" + }; + + CreditCard creditCard = gateway.CreditCard.Create(creditCardRequest).Target; + + TransactionRequest request = new TransactionRequest + { + Amount = SandboxValues.TransactionAmount.AUTHORIZE, + PaymentMethodToken = creditCard.Token, + CurrencyIsoCode = "GBP" + }; + + Result result = gateway.Transaction.Sale(request); + Assert.IsFalse(result.IsSuccess()); + Assert.AreEqual( + ValidationErrorCode.TRANSACTION_INVALID_PRESENTMENT_CURRENCY, + result.Errors.DeepAll()[0].Code + ); + } + + [Test] + public void Sale_TransactionWithInstallmentCount() { + var request = new TransactionRequest { + Amount = 100, + CreditCard = new TransactionCreditCardRequest + { + ExpirationDate = "05/2012", + Number = SandboxValues.CreditCardNumber.VISA + }, + MerchantAccountId = MerchantAccountIDs.CARD_PROCESSOR_BRAZIL_MERCHANT_ACCOUNT_ID, + InstallmentRequest = new InstallmentRequest { + Count = "4" + } + }; + + var transactionResult = gateway.Transaction.Sale(request); + Assert.IsTrue(transactionResult.IsSuccess()); + Transaction transaction = transactionResult.Target; + Assert.AreEqual(4, transaction.InstallmentCount); + } + + [Test] + public void Sale_TransactionWithInstallmentAdjustments() { + var request = new TransactionRequest { + Amount = 100.00M, + CreditCard = new TransactionCreditCardRequest + { + ExpirationDate = "05/2012", + Number = SandboxValues.CreditCardNumber.VISA + }, + MerchantAccountId = MerchantAccountIDs.CARD_PROCESSOR_BRAZIL_MERCHANT_ACCOUNT_ID, + InstallmentRequest = new InstallmentRequest { + Count = "4" + }, + Options = new TransactionOptionsRequest + { + SubmitForSettlement = true + } + }; + + var transactionResult = gateway.Transaction.Sale(request); + Assert.IsTrue(transactionResult.IsSuccess()); + Transaction transaction = transactionResult.Target; + gateway.TestTransaction.Settle(transaction.Id); + + Transaction refund = gateway.Transaction.Refund(transaction.Id, decimal.Parse("20.00")).Target; + for (int i = 0; i < transaction.Installments.Count; i++) + { + Assert.AreEqual($"{transaction.Id}_INST_{i+1}", transaction.Installments[i].Id); + Assert.AreEqual(25.00M, transaction.Installments[i].Amount); + } + + for (int i = 0; i < refund.RefundedInstallments.Count; i++) + { + Assert.AreEqual(-5.00M, refund.RefundedInstallments[i].Adjustments[0].Amount); + Assert.AreEqual(Kind.REFUND, refund.RefundedInstallments[i].Adjustments[0].Kind); + } + } } } diff --git a/test/Braintree.Tests/CreditCardRequestTest.cs b/test/Braintree.Tests/CreditCardRequestTest.cs index 8fd1e317..5bba1e08 100644 --- a/test/Braintree.Tests/CreditCardRequestTest.cs +++ b/test/Braintree.Tests/CreditCardRequestTest.cs @@ -6,6 +6,7 @@ namespace Braintree.Tests public class CreditCardRequestTest { [Test] + [System.Obsolete] public void ToXml_Includes_DeviceSessionId() { CreditCardRequest request = new CreditCardRequest(); @@ -15,6 +16,7 @@ public void ToXml_Includes_DeviceSessionId() } [Test] + [System.Obsolete] public void ToXml_Includes_FraudMerchantId() { CreditCardRequest request = new CreditCardRequest(); diff --git a/test/Braintree.Tests/CustomerRequestTest.cs b/test/Braintree.Tests/CustomerRequestTest.cs index ab7da933..03108ba4 100644 --- a/test/Braintree.Tests/CustomerRequestTest.cs +++ b/test/Braintree.Tests/CustomerRequestTest.cs @@ -6,6 +6,7 @@ namespace Braintree.Tests public class CustomerRequestTest { [Test] + [System.Obsolete] public void ToXml_Includes_DeviceSessionId() { var request = new CustomerRequest() diff --git a/test/Braintree.Tests/TransactionRequestTest.cs b/test/Braintree.Tests/TransactionRequestTest.cs index 228c8206..004aa4c5 100644 --- a/test/Braintree.Tests/TransactionRequestTest.cs +++ b/test/Braintree.Tests/TransactionRequestTest.cs @@ -7,6 +7,7 @@ namespace Braintree.Tests public class TransactionRequestTest { [Test] + [System.Obsolete] public void ToXml_Includes_DeviceSessionId() { TransactionRequest request = new TransactionRequest(); @@ -16,6 +17,7 @@ public void ToXml_Includes_DeviceSessionId() } [Test] + [System.Obsolete] public void ToXml_Includes_FraudMerchantId() { TransactionRequest request = new TransactionRequest(); @@ -62,5 +64,19 @@ public void ToXml_Includes_Level3SummaryData() Assert.AreEqual("2.00", doc.GetElementsByTagName("discount-amount")[0].InnerXml); Assert.AreEqual("12345", doc.GetElementsByTagName("ships-from-postal-code")[0].InnerXml); } + + [Test] + public void ToXml_IncludesInstallmentsCount() + { + TransactionRequest request = new TransactionRequest(); + request.InstallmentRequest = new InstallmentRequest(); + request.InstallmentRequest.Count = "4"; + + string xml = request.ToXml(); + XmlDocument doc = new XmlDocument(); + doc.LoadXml(xml); + + Assert.AreEqual("4", doc.SelectSingleNode("//installments/count").InnerText); + } } }