Skip to content

Commit

Permalink
5.6.0
Browse files Browse the repository at this point in the history
  • Loading branch information
braintreeps committed May 10, 2021
1 parent 8278c80 commit ad287a6
Show file tree
Hide file tree
Showing 12 changed files with 215 additions and 16 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
## 5.6.0
- Add `PayPalMessages` to `Dispute`
- Add `TaxIdentifiers` to `CustomerRequest`
- Add webhook sample for `GrantedPaymentMethodRevoked`

## 5.5.0
- Add `StoreId` and `StoreIds` to `TransactionSearchRequest`
- Add support for `LocalPaymentReversed` webhook notifications
Expand Down
10 changes: 4 additions & 6 deletions src/Braintree/Braintree.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,17 @@
<PropertyGroup>
<Description>Braintree Client Library</Description>
<Copyright>Copyright © Braintree, a division of PayPal, Inc. 2021</Copyright>
<VersionPrefix>5.5.0</VersionPrefix>
<VersionPrefix>5.6.0</VersionPrefix>
<Authors>Braintree</Authors>
<!-- We target NET standard 2.0 so that we can support NET Core 2.1. When NET Core 2.1 reaches EOL, we can update to Net Standard 2.1 -->
<TargetFrameworks>net452;netstandard2.0</TargetFrameworks>
<AssemblyName>Braintree</AssemblyName>
<PackageId>Braintree</PackageId>
<PackageTags>braintree;paypal;venmo;intenational;payments;gateway;currencies;money;visa;mastercard;bitcoin;maestro;apple pay;android pay;amex;jcb;diners club;discover;american express</PackageTags>
<PackageReleaseNotes>
- Add `StoreId` and `StoreIds` to `TransactionSearchRequest`
- Add support for `LocalPaymentReversed` webhook notifications
- Add `Transaction.AdjustAuthorization` method to support for multiple authorizations for a single transaction
- Add `MerchantAccountId` to `TransactionRefundRequest`
- Add `PhoneNumber` to `Address`
- Add `PayPalMessages` to `Dispute`
- Add `TaxIdentifiers` to `CustomerRequest`
- Add webhook sample for `GrantedPaymentMethodRevoked`
</PackageReleaseNotes>
<PackageProjectUrl>https://github.com/braintree/braintree_dotnet</PackageProjectUrl>
<GenerateAssemblyTitleAttribute>false</GenerateAssemblyTitleAttribute>
Expand Down
11 changes: 9 additions & 2 deletions src/Braintree/CustomerRequest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ public class CustomerRequest : Request
public UsBankAccountRequest UsBankAccount { get; set; }
public RiskDataRequest RiskData { get; set; }
public CustomerOptionsRequest Options { get; set; }
public TaxIdentifierRequest[] TaxIdentifiers { get; set; }

public override string ToXml()
{
Expand All @@ -86,7 +87,7 @@ public override string ToQueryString(string root)

protected virtual RequestBuilder BuildRequest(string root)
{
return new RequestBuilder(root).
var request = new RequestBuilder(root).
AddElement("id", Id).
AddElement("first-name", FirstName).
AddElement("last-name", LastName).
Expand All @@ -102,7 +103,13 @@ protected virtual RequestBuilder BuildRequest(string root)
AddElement("risk-data", RiskData).
AddElement("device-data", DeviceData).
AddElement("options", Options);

if (TaxIdentifiers != null && TaxIdentifiers.Length > 0)
{
request.AddElement("tax-identifiers", TaxIdentifiers);
}

return request;
}
}
}

7 changes: 7 additions & 0 deletions src/Braintree/Dispute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ public class Dispute
public virtual DisputeTransaction Transaction { get; protected set; }
public List<DisputeStatusHistory> StatusHistory;
public List<DisputeEvidence> Evidence;
public List<DisputePayPalMessage> PayPalMessages;

public Dispute(NodeWrapper node)
{
Expand Down Expand Up @@ -103,6 +104,12 @@ public Dispute(NodeWrapper node)
Evidence.Add(new DisputeEvidence(evidenceResponse));
}

PayPalMessages = new List<DisputePayPalMessage>();
foreach (var paypalMessageResponse in node.GetList("paypal-messages/paypal-messages"))
{
PayPalMessages.Add(new DisputePayPalMessage(paypalMessageResponse));
}

StatusHistory = new List<DisputeStatusHistory>();
foreach (var historyStatusResponse in node.GetList("status-history/status-history"))
{
Expand Down
21 changes: 21 additions & 0 deletions src/Braintree/DisputePayPalMessage.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using System;

namespace Braintree
{
public class DisputePayPalMessage
{
public virtual string Message { get; protected set; }
public virtual string Sender { get; protected set; }
public virtual DateTime? SentAt { get; protected set; }

public DisputePayPalMessage(NodeWrapper node)
{
Message = node.GetString("message");
Sender = node.GetString("sender");
SentAt = node.GetDateTime("sent-at");
}

[Obsolete("Mock Use Only")]
protected internal DisputePayPalMessage() { }
}
}
6 changes: 3 additions & 3 deletions src/Braintree/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
[assembly: AssemblyCulture("")]
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Braintree.Tests")]
[assembly: CLSCompliant(true)]
//[assembly: AssemblyKeyFileAttribute("../../../braintreeSgKey.snk")]
//[assembly: AssemblyKeyFile("../../braintreeSgKey.snk")]

// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
Expand All @@ -32,5 +32,5 @@
// Build Number
// Revision
//
[assembly: AssemblyVersion("5.5.0.0")]
[assembly: AssemblyFileVersion("5.5.0.0")]
[assembly: AssemblyVersion("5.6.0.0")]
[assembly: AssemblyFileVersion("5.6.0.0")]
25 changes: 25 additions & 0 deletions src/Braintree/TaxIdentifierRequest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
namespace Braintree
{
public class TaxIdentifierRequest: Request
{
public string CountryCode { get; set; }
public string Identifier { 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)
{
return new RequestBuilder(root)
.AddElement("countryCode", CountryCode)
.AddElement("identifier", Identifier);
}
}
}
20 changes: 19 additions & 1 deletion src/Braintree/WebhookTestingGateway.cs
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,9 @@ private string SubjectSampleXml(WebhookKind kind, string id)
return GrantedPaymentInstrumentUpdateSampleXml();
} else if (kind == WebhookKind.PAYMENT_METHOD_REVOKED_BY_CUSTOMER) {
return PaymentMethodRevokedByCustomerSampleXml(id);
} else if (kind == WebhookKind.LOCAL_PAYMENT_COMPLETED) {
} else if (kind == WebhookKind.GRANTED_PAYMENT_METHOD_REVOKED) {
return GrantedPaymentMethodRevokedSampleXml(id);
} else if (kind == WebhookKind.LOCAL_PAYMENT_COMPLETED) {
return LocalPaymentCompletedSampleXml();
} else if (kind == WebhookKind.LOCAL_PAYMENT_REVERSED) {
return LocalPaymentReversedSampleXml();
Expand Down Expand Up @@ -533,6 +535,22 @@ private static string PaymentMethodRevokedByCustomerSampleXml(string id) {
Node("limited-use-order-id", NIL_TRUE, ""),
NodeAttr("revoked-at", TYPE_DATE_TIME, "2019-01-02T12:00:00Z")
);
}

private static string GrantedPaymentMethodRevokedSampleXml(string id) {
return Node("venmo-account",
NodeAttr("created-at", TYPE_DATE_TIME, "2021-05-05T21:28:37Z"),
NodeAttr("updated-at", TYPE_DATE_TIME, "2021-05-05T21:28:37Z"),
NodeAttr("default", TYPE_BOOLEAN, "true"),
Node("image-url", "https://assets.braintreegateway.com/payment_method_logo/venmo.png?environment=test"),
Node("token", id),
Node("source-description", "Venmo Account: venmojoe"),
Node("username", "venmojoe"),
Node("venmo-user-id", "456"),
NodeAttr("subscriptions", TYPE_ARRAY),
Node("customer-id", "venmo_customer_id"),
Node("global-id", "cGF5bWVudG1ldGhvZF92ZW5tb2FjY291bnQ")
);
}

private static string LocalPaymentCompletedSampleXml() {
Expand Down
73 changes: 69 additions & 4 deletions test/Braintree.Tests.Integration/CustomerIntegrationTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -987,7 +987,7 @@ public void Create_WithThreeDSecureNonce()

[Test]
public void Create_WithPayPalPaymentMethodNonce()
{
{
string nonce = TestHelper.GenerateFuturePaymentPayPalNonce(gateway);
Result<Customer> result = gateway.Customer.Create(new CustomerRequest{
PaymentMethodNonce = nonce
Expand All @@ -1000,7 +1000,7 @@ public void Create_WithPayPalPaymentMethodNonce()

[Test]
public void Create_WithPayPalOrderPaymentMethodNonce()
{
{
string nonce = TestHelper.GenerateOrderPaymentPayPalNonce(gateway);
Result<Customer> result = gateway.Customer.Create(new CustomerRequest{
PaymentMethodNonce = nonce
Expand All @@ -1009,7 +1009,7 @@ public void Create_WithPayPalOrderPaymentMethodNonce()
var customer = result.Target;
Assert.AreEqual(1, customer.PayPalAccounts.Length);
Assert.AreEqual(customer.PayPalAccounts[0].Token, customer.DefaultPaymentMethod.Token);

}

[Test]
Expand Down Expand Up @@ -1500,7 +1500,7 @@ public void Update_UpdateCustomerWithThreeDSecurePassThruParams()

Assert.IsTrue(result.IsSuccess());
}

[Test]
public void Update_AcceptsNestedBillingAddressId()
{
Expand Down Expand Up @@ -2249,5 +2249,70 @@ public void Update_CustomerWithNonceAndInvalidMerchantCurrencyOption()
updatedCustomer.Errors.DeepAll()[0].Code
);
}

[Test]
public void Create_CustomerWithTaxIdentifiers()
{
var createRequest = new CustomerRequest()
{
TaxIdentifiers = new TaxIdentifierRequest[]
{
new TaxIdentifierRequest
{
CountryCode = "US",
Identifier = "123"
},
new TaxIdentifierRequest
{
CountryCode = "CL",
Identifier = "456"
},
}
};

Result<Customer> result = gateway.Customer.Create(createRequest);
Assert.IsTrue(result.IsSuccess());
}

[Test]
public void Update_CustomerWithTaxIdentifiers()
{
var createRequest = new CustomerRequest()
{
TaxIdentifiers = new TaxIdentifierRequest[]
{
new TaxIdentifierRequest
{
CountryCode = "US",
Identifier = "123"
},
new TaxIdentifierRequest
{
CountryCode = "CL",
Identifier = "456"
},
}
};

Result<Customer> createResult = gateway.Customer.Create(createRequest);
Assert.IsTrue(createResult.IsSuccess());

var id = createResult.Target.Id;

var updateRequest = new CustomerRequest()
{
TaxIdentifiers = new TaxIdentifierRequest[]
{
new TaxIdentifierRequest
{
CountryCode = "CL",
Identifier = "789"
},
}
};

Result<Customer> updateResult = gateway.Customer.Update(id, updateRequest);
Assert.IsTrue(updateResult.IsSuccess());
}
}
}
27 changes: 27 additions & 0 deletions test/Braintree.Tests/CustomerRequestTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,5 +52,32 @@ public void ToXml_Includes_DeviceData()
Assert.IsTrue(request.ToXml().Contains("fraud_merchant_id"));
Assert.IsTrue(request.ToXml().Contains("my_fmid"));
}

[Test]
public void ToXml_Includes_TaxIdentifiers()
{
var request = new CustomerRequest()
{
TaxIdentifiers = new TaxIdentifierRequest[]
{
new TaxIdentifierRequest
{
CountryCode = "US",
Identifier = "123"
},
new TaxIdentifierRequest
{
CountryCode = "CL",
Identifier = "456"
}
}
};

Assert.IsTrue(request.ToXml().Contains("US"));
Assert.IsTrue(request.ToXml().Contains("123"));

Assert.IsTrue(request.ToXml().Contains("CL"));
Assert.IsTrue(request.ToXml().Contains("456"));
}
}
}
11 changes: 11 additions & 0 deletions test/Braintree.Tests/DisputeTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,13 @@ public string Payload_attributes()
NodeAttr("effective-date", TYPE_DATE, "2013-04-10")
)
),
NodeAttr("paypal-messages", TYPE_ARRAY,
Node("paypal-messages",
Node("message", "message"),
Node("sender", "seller"),
NodeAttr("sent-at", TYPE_DATE, "2013-04-10T10:50:39Z")
)
),
NodeAttr("evidence", TYPE_ARRAY,
Node("evidence",
NodeAttr("created-at", TYPE_DATE, "2013-04-10T10:50:39Z"),
Expand Down Expand Up @@ -207,6 +214,9 @@ public void Constructor_populatesNewFields()
Assert.AreEqual(DisputeStatus.OPEN, result.StatusHistory[0].Status);
Assert.AreEqual(DateTime.Parse("2013-04-10T10:50:39Z"), result.StatusHistory[0].Timestamp);
Assert.AreEqual(DateTime.Parse("2013-04-10"), result.StatusHistory[0].EffectiveDate);
Assert.AreEqual("message", result.PayPalMessages[0].Message);
Assert.AreEqual("seller", result.PayPalMessages[0].Sender);
Assert.AreEqual(DateTime.Parse("2013-04-10T10:50:39Z"), result.PayPalMessages[0].SentAt);
Assert.AreEqual("evidence1", result.Evidence[0].Id);
Assert.AreEqual("url_of_file_evidence", result.Evidence[0].Url);
Assert.AreEqual(DateTime.Parse("2013-04-10T10:50:39Z"), result.Evidence[0].CreatedAt);
Expand All @@ -232,6 +242,7 @@ public void Constructor_handlesEmptyFields()
Assert.IsNull(result.DateOpened);
Assert.IsNull(result.DateWon);
Assert.IsEmpty(result.Evidence);
Assert.IsEmpty(result.PayPalMessages);
Assert.IsNull(result.ReplyByDate);
Assert.IsEmpty(result.StatusHistory);
}
Expand Down
15 changes: 15 additions & 0 deletions test/Braintree.Tests/WebhookNotificationTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -614,6 +614,21 @@ public void SampleNotification_ReturnsANotificationForGrantedVenmoAccountRevoked
Assert.IsTrue(metadata.RevokedPaymentMethod is VenmoAccount);
}

[Test]
public void WebhookTesting_SampleNotification_ReturnsANotificationForGrantedVenmoAccountRevoked()
{
Dictionary<string, string> sampleNotification = gateway.WebhookTesting.SampleNotification(WebhookKind.GRANTED_PAYMENT_METHOD_REVOKED, "granted_payment_method_revoked_id");

WebhookNotification notification = gateway.WebhookNotification.Parse(sampleNotification["bt_signature"], sampleNotification["bt_payload"]);

Assert.AreEqual(WebhookKind.GRANTED_PAYMENT_METHOD_REVOKED, notification.Kind);
RevokedPaymentMethodMetadata metadata = notification.RevokedPaymentMethodMetadata;

Assert.AreEqual("venmo_customer_id", metadata.CustomerId);
Assert.AreEqual("granted_payment_method_revoked_id", metadata.Token);
Assert.IsTrue(metadata.RevokedPaymentMethod is VenmoAccount);
}

[Test]
public void SampleNotification_ReturnsANotificationForPaymentMethodRevokedByCustomer()
{
Expand Down

0 comments on commit ad287a6

Please sign in to comment.