braintree / braintree_java

Braintree Java library
https://developer.paypal.com/braintree/docs/start/overview
MIT License
158 stars 99 forks source link

Client token generation does not raise validation error but returns null for nonexistent customers. #119

Open kmichalak opened 1 year ago

kmichalak commented 1 year ago

General information

Issue description

Hi, Following documentation for the client token generation available at https://developer.paypal.com/braintree/docs/reference/request/client-token/generate/java#specify-a-customer-id

If the customer can't be found, it will return a validation error.

Unfortunately it looks like the SDK does not do that. When calling the code from the example in the docs

ClientTokenRequest clientTokenRequest = new ClientTokenRequest()
  .customerId(aCustomerId);
// pass clientToken to your front-end
String clientToken = gateway.clientToken().generate(clientTokenRequest);

using customerId that cannot be matched in the Vault, the gateway.clientToken().generate(clientTokenRequest) returns null value instead of the validation error. I'm reporting this for SDK version 3.19.0, but I checked latest sources and the code is still the same

public String generate(ClientTokenRequest request) {
      NodeWrapper response = null;
      verifyOptions(request);
      response = http.post(configuration.getMerchantPath() + "/client_token", request);

      String token = response.findString("value");
      if (token != null) {
          token = StringUtils.unescapeUtf8(token);
      }
      return token;
    }
hollabaq86 commented 1 year ago

👋 @kmichalak thanks for reaching out. You're absolutely right! We should be sending error result objects if the request is not successful.

If you'd like to PR this fix, feel free! But otherwise we can look at fixing this up.

For internal tracking, issue 7173

kmichalak commented 1 year ago

I've prepared PR https://github.com/braintree/braintree_java/pull/120

saralvasquez commented 1 year ago

After taking a look at the code, it's true that calling clientToken().generate with a nonexistent customer id will return null rather than a ValidationError. In fact, there isn't any error handling built into the generate method and it's been like that for as long as the SDK has existed. Ideally, returning a validation error as the documentation states would be rather simple and is done elsewhere in the SDK, but that doesn't work in this case due to the return type of the generate() method. Unlike other methods in the SDK, clientToken().generate returns a String object. That string represents the generated token or null if it fails. The rest of the SDK returns a Result<> object that has ValidationError handling built in. Through some discussion, we've decided to change the generate() return type to a Result<ClientToken>. This would make the code base more consistent and take some of the burden of error handling off of the user. In that case, calling clientToken().generate with a nonexistent customer id would look something like the following

ValidationErrors errors = null;
ClientTokenRequest clientTokenRequest = new ClientTokenRequest()
  .customerId(fakeCustomerId);
Result<ClientToken> clientTokenResult = gateway.clientToken().generate(clientTokenRequest);
if(!clientTokenResult.isSuccess()) {
    errors = clientTokenResult.getErrors();
}

Unfortunately, these changes will have to wait for a while to adhere to semantic versioning. Changing the return type of this method would break user integrations, which requires a major version bump. The Java SDK is due for a major version release soon to get this issue and some other backlogged modifications resolved, but we don't have the bandwidth to get that out at the moment.

For now, we have updated the documentation so that it's consistent with what actually happens in the SDKs and have created tickets for the changes I discussed above.