GithubHelp home page GithubHelp logo

plaid / plaid-java Goto Github PK

View Code? Open in Web Editor NEW
123.0 72.0 115.0 23.49 MB

Java bindings for Plaid

Home Page: https://plaid.com/docs

License: MIT License

Java 99.75% Dockerfile 0.01% Mustache 0.25%

plaid-java's Introduction

plaid-java Maven Central

Java Bindings for the Plaid API (https://www.plaid.com/docs). This library is generated from the Plaid OpenAPI spec.

Plaid API is defined in the PlaidApi interface.

Uses Retrofit and OkHttp under the hood. You may want to take a look at those libraries if you need to do anything out of the ordinary.

Table of Contents

Installation

Plaid-java is available at Maven Central.

<dependency>
  <groupId>com.plaid</groupId>
  <artifactId>plaid-java</artifactId>
  <!--Replace this version number with the latest verison, which can be found at https://github.com/plaid/plaid-java/tags-->
  <version>9.0.0</version>
</dependency>

Versioning

As of 9.0.0, the library is generated from the OpenAPI spec.

Each major version of plaid-java targets a specific version of the Plaid API:

API version plaid-java release
[2020-09-14][api-version-2020-09-14] (latest) 8.x.x and higher
[2019-05-29][api-version-2019-05-29] 7.x.x
[2018-05-22][api-version-2018-05-22] 4.x.x (and 3.x.x)
2017-03-08 2.x.x

The plaid-java client library is typically updated on a monthly basis. The canonical source for the latest version number is the client library changelog. New versions are published as GitHub tags, not as Releases. New versions can also be found on Maven Central.

All users are strongly recommended to use a recent version of the library, as older versions do not contain support for new endpoints and fields. For more details, see the Migration Guide.

Basic Usage Examples

For more examples of basic usage, see the test suites, Quickstart, or API Reference documentation.

Initialization, API call, and error handling

private PlaidApi plaidClient;

HashMap<String, String> apiKeys = new HashMap<String, String>();
apiKeys.put("clientId", plaidClientId);
apiKeys.put("secret", plaidSecret);
apiClient = new ApiClient(apiKeys);
apiClient.setPlaidAdapter(ApiClient.Sandbox); // or equivalent, depending on which environment you're calling into
plaidClient = apiClient.createService(PlaidApi.class);

// Synchronously exchange a Link public_token for an API access_token
// Required request parameters are always Request object constructor arguments
ItemPublicTokenExchangeRequest request = new ItemPublicTokenExchangeRequest().publicToken("the_link_public_token");
Response<ItemPublicTokenExchangeResponse> response = plaidClient()
    .itemPublicTokenExchange(request).execute();

if (response.isSuccessful()) {
  accessToken = response.body().getAccessToken();
}


// Asynchronously do the same thing. Useful for potentially long-lived calls.
ItemPublicTokenExchangeRequest request = new ItemPublicTokenExchangeRequest().publicToken(publicToken);
plaidClient()
    .itemPublicTokenExchange(request)
    .enqueue(new Callback<ItemPublicTokenExchangeResponse>() {
        @Override
        public void onResponse(Call<ItemPublicTokenExchangeResponse> call, Response<ItemPublicTokenExchangeResponse> response) {
          if (response.isSuccessful()) {
            accessToken = response.body.getAccessToken();
          }
        }

        @Override
        public void onFailure(Call<ItemPublicTokenExchangeResponse> call, Throwable t) {
          // handle the failure as needed
        }
    });

// Decoding an unsuccessful response
try {
  Gson gson = new Gson();
  PlaidError error = gson.fromJson(response.errorBody().string(), PlaidError.class);
} catch (Exception e) {
  throw new Exception(
    String.format(
      "Failed converting from API Response Error Body to Error %f",
      response.errorBody().string()
    )
  );
}

Dates

Dates and datetimes in requests, which are represented as strings in the API, are represented in this version of the Java client library as LocalDate or OffsetDateTime objects.

Time zone information is required for request fields that accept datetimes. Failing to include time zone information (or specifying a string, instead of an OffsetDateTime object) will result in an error.

If the API reference documentation for a request field specifies format: date, the following is acceptable:

import java.time.LocalDate;

LocalDate myDate = LocalDate.parse("2019-12-06");

If the API reference documentation for a request field specifies format: date-time, the following is acceptable:

import java.time.OffsetDateTime;

OffsetDateTime myDateTime = OffsetDateTime.parse("2019-12-06T22:35:49+00:00");

Migration guide

9.0.0 or later to latest

Migrating from a version released on or after August 2021 to a recent version should involve very minor integration changes. Many customers will not need to make changes to their integrations at all. To see a list of all potentially-breaking changes since your current version, see the client library changelog and search for "Breaking changes in this version". Breaking changes are annotated at the top of each major version header.

Pre-9.0.0 to latest

Version 9.0.0 of the client library was released in August 2021 and contains multiple interface changes, as described below.

Major changes

Change CountryCodes to enum:

  • from: Arrays.list("US")
  • to: Arrays.list(CountryCode.US)

Rename model imports:

  • from: com.plaid.request.ModelName and com.plaid.response.ModelName
  • to: com.plaid.model.ModelName

Rename products:

  • from: com.plaid.client.request.common.Product
  • to: com.plaid.model.Products

Rename Error model:

  • from: com.plaid.client.model.ErrorResponse
  • to: com.plaid.client.model.Error
  • from: ErrorResponse.ErrorType
  • to: Error.ErrorTypeEnum

Rename Account model:

  • from: import com.plaid.client.model.Account
  • to: import com.plaid.client.model.AccountBase

Rename Payment Initiation Models:

  • from: import com.plaid.client.model.paymentinitiation.
  • to: import com.plaid.client.model.PaymentInitiation${Model}

Request Model Structure:

  • All request models changed from having their options passed as function arguments new AuthGetRequest(accessToken) to now having builder syntax new AuthGetRequest().accessToken(accessToken).
  • All with$VARNAME chained setters have been converted to ${}options. E.g. .withEndDate(endDate) -> .endDate(endDate) See Optional Parameters for an example.

Response Model Structure:

  • Model response properties are no longer connected to their parent response.
  • Most other getters/setters have stayed the same outside of a few capitalization changes.

Plaid Client changes:

  • Remove all occurrences of service() attached to client() endpoint queries.
  • Endpoints that start with get are now ${Model}Get.

Date format changes

The date and date-time format has changed in this client library. See Dates for information on the new date format.

Enum changes

While the API represents enums using strings, and previous library versions used singletons, this current library uses enum types.

Old:

LinkTokenCreateRequest request = new LinkTokenCreateRequest(
   Collections.singletonList("auth"))
  .withCountryCodes(Collections.singletonList("US"))
...

Current:

LinkTokenCreateRequest request = new LinkTokenCreateRequest()
  .products(Arrays.asList(Products.AUTH))
  .countryCodes(Arrays.asList(CountryCode.US))
  ...

Initialization and error handling

See basic usage for examples of new-style initialization and error handling.

Method calling examples

Old:

// Pull real-time balance information for each account associated
// with the Item
Response<AccountsBalanceGetResponse> response = client().service().accountsBalanceGet(
  new AccountsBalanceGetRequest(accessToken))
  .execute();
List<Account> accounts = response.body().getAccounts();

New:

// Pull real-time balance information for each account associated
// with the Item
AccountsBalanceGetRequest request = new AccountsBalanceGetRequest()
  .accessToken(accessToken);
Response<AccountsGetResponse> response = client()
  .accountsBalanceGet(request)
  .execute();
List<Account> accounts = response.body().getAccounts();

Optional parameters

Old:

SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
startDate = simpleDateFormat.parse("2018-01-01");
endDate = simpleDateFormat.parse("2018-02-01");
// Pull transactions for a date range
Response<TransactionsGetResponse> response = client().service().transactionsGet(
  new TransactionsGetRequest(
    accessToken,
    startDate,
    endDate))
  .execute();

// Manipulate the count and offset parameters to paginate
// transactions and retrieve all available data
Response<TransactionsGetResponse> response = client().service().transactionsGet(
  new TransactionsGetRequest(
    accessToken,
    startDate,
    endDate)
    .withAccountIds(Arrays.asList(someAccountId))
    .withCount(numTxns)
    .withOffset(1)).execute();

for (TransactionsGetResponse.Transaction txn : response.body().getTransactions()) { ... }

New:

LocalDate startDate = LocalDate.now().minusDays(30);
LocalDate endDate = LocalDate.now();
TransactionsGetRequestOptions options = new TransactionsGetRequestOptions()
  .includePersonalFinanceCategory(true)
// Pull transactions for a date range

TransactionsGetRequest request = new TransactionsGetRequest()
  .accessToken(accessToken)
  .startDate(startDate)
  .endDate(endDate)
  .options(options)
Response<TransactionsGetResponse>
  response = plaidClient.transactionsGet(request).execute();

List<Transaction> transactions = new ArrayList <Transaction>();
transactions.addAll(response.body().getTransactions());

// Manipulate the offset parameter to paginate
// transactions and retrieve all available data
while (transactions.size() < response.body().getTotalTransactions()) {
  options = new TransactionsGetRequestOptions()
    .offset(transactions.size())
    .includePersonalFinanceCategory(true)
  TransactionsGetRequest request = new TransactionsGetRequest()
    .accessToken(accessToken)
    .startDate(startDate)
    .endDate(endDate)
    .options(options);

  Response<TransactionsGetResponse>
    response = plaidClient.transactionsGet(request).execute();
  transactions.addAll(response.body().getTransactions());
}

Contributing

Please see Contributing for guidelines and instructions for local development.

License

MIT.

plaid-java's People

Contributors

aarohmankad avatar adamlangsner avatar aeidelson avatar arjunpuri-plaid avatar awwalker avatar blockmar avatar cgfarmer4 avatar davidzhanghp avatar dsfish avatar dudehook avatar erimag avatar jacksonchen avatar jasonjia93 avatar jking-plaid avatar leekkww avatar mattnguyen1 avatar maxdjohnson avatar michaelckelly avatar notthefakestephen avatar otherchen avatar pbernasconi avatar peteraarum avatar phoenixy1 avatar skylarmb avatar souhaylmaronesy avatar stephenjayakar avatar thebobaguy avatar vanvlack avatar vorpus avatar webbsurfer avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

plaid-java's Issues

change repo slug to "plaid-java"

"plaid-javabindings" is pretty ugly, and we seem to be referring to the package as "plaid-java" elsewhere. Is there any reason for the inconsistency?

Transaction amount

Transaction amount is positive for expenses and negative for earnings/income. Shouldn't this be opposite? I verified this with checking account and credit card accounts and behavior is the same.

Dependency convergence error

Version
5.1.4

Error
The retrofit and okhttp dependencies have conflicting versions of okhttp, (3.3.0, 3.6.0), so the maven dependency cannot be installed.

convergence paths:

Dependency convergence error for com.squareup.okhttp3:okhttp:3.3.0 paths to dependency are:
+-com.**-SNAPSHOT
  +-com.plaid:plaid-java:5.1.4
    +-com.squareup.retrofit2:retrofit:2.1.0
      +-com.squareup.okhttp3:okhttp:3.3.0
and
+-com.**-SNAPSHOT
  +-com.plaid:plaid-java:5.1.4
    +-com.squareup.okhttp3:okhttp:3.6.0
and
+-com.**-SNAPSHOT
  +-com.plaid:plaid-java:5.1.4
    +-com.squareup.okhttp3:logging-interceptor:3.6.0
      +-com.squareup.okhttp3:okhttp:3.6.0

mvn package issue

After running mvn package the build failed because of a test failing. I will be emailing out the output.

updateTransactions seems inconsistent

The two calls named updateTransactions in the user client use different URLs, one uses /connect and the other uses /connect/get. The documentation suggests that retrieving transactions should use /connect/get and initial setup should use /connect.

I suggest that the updateTransactions (possibly renamed to getTransactions) use /connect/get.

I can change this if we agree.

IllegalAccessError and ClassNotFoundException exceptions in integration process

Hi,
I got two issues during integration process. I tried both version 2.1.6 which specified here and 2.2.0 which was used in your demo proj.

  1. Gson version incompatible with our already used gson version causing IllegalAccessError exception (In your pom.xml I couldn't find gson version specified so I guess it used ours)

2018-01-08 15:50:08.161 ERROR 13152 --- [nio-8012-exec-1] o.a.c.c.C.[.[.[.[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [/api] threw exception [Request processing failed; nested exception is java.lang.RuntimeException: java.util.concurrent.ExecutionException: com.google.common.util.concurrent.ExecutionError: java.lang.IllegalAccessError: tried to access method com.google.gson.Gson.newJsonWriter(Ljava/io/Writer;)Lcom/google/gson/stream/JsonWriter; from class retrofit2.converter.gson.GsonRequestBodyConverter] with root cause

java.lang.IllegalAccessError: tried to access method com.google.gson.Gson.newJsonWriter(Ljava/io/Writer;)Lcom/google/gson/stream/JsonWriter; from class retrofit2.converter.gson.GsonRequestBodyConverter
at retrofit2.converter.gson.GsonRequestBodyConverter.convert(GsonRequestBodyConverter.java:45)
at retrofit2.converter.gson.GsonRequestBodyConverter.convert(GsonRequestBodyConverter.java:30)
at retrofit2.ParameterHandler$Body.apply(ParameterHandler.java:297)
at retrofit2.ServiceMethod.toRequest(ServiceMethod.java:109)
at retrofit2.OkHttpCall.createRawCall(OkHttpCall.java:178)
at retrofit2.OkHttpCall.execute(OkHttpCall.java:162)

  1. ClassNotFoundException: okhttp3.internal.platform.Platform

2018-01-08 15:54:08.377 ERROR 13249 --- [nio-8012-exec-1] o.a.c.c.C.[.[.[.[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [/api] threw exception [Request processing failed; nested exception is java.lang.RuntimeException: java.util.concurrent.ExecutionException: com.google.common.util.concurrent.ExecutionError: java.lang.NoClassDefFoundError: okhttp3/internal/platform/Platform] with root cause

java.lang.ClassNotFoundException: okhttp3.internal.platform.Platform
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:335)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at okhttp3.logging.HttpLoggingInterceptor$Logger$1.log(HttpLoggingInterceptor.java:112)
at okhttp3.logging.HttpLoggingInterceptor.intercept(HttpLoggingInterceptor.java:160)
at okhttp3.RealCall$ApplicationInterceptorChain.proceed(RealCall.java:190)
at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:163)
at okhttp3.RealCall.execute(RealCall.java:57)
at retrofit2.OkHttpCall.execute(OkHttpCall.java:174)

Your assistance is appreciated.

Android Integration

I am wanting to use Plaid for an Android application, however it is improper to use the client id or secret in an end-user binary as it can be exposed via fairly trivial means. Would it be accurate for me to make the assumption that I would build a service that lives on my own web server to store these credentials and then have my Android application interface with that service via http/https requests or is there a way that I would be able to leverage the Java library directly and securely on Android devices?

java.lang.StackOverflowError

I updated to plaid-java version 2.2.2 and immediately started getting java.lang.StackOverflowErrors when calling transactionsGet. Looks like an issue with the json parsing? Reverting to version 2.1.6 made the errors go away.

java.lang.StackOverflowError
at java.lang.Class.isArray(Native Method)
at com.google.gson.internal.$Gson$Types.canonicalize($Gson$Types.java:98)
at com.google.gson.reflect.TypeToken.(TypeToken.java:72)
at com.google.gson.reflect.TypeToken.get(TypeToken.java:296)
at com.google.gson.Gson.toJson(Gson.java:661)
at com.google.gson.Gson.toJsonTree(Gson.java:562)
at com.google.gson.Gson.toJsonTree(Gson.java:541)
at com.google.gson.internal.bind.TreeTypeAdapter$GsonContextImpl.serialize(TreeTypeAdapter.java:155)
at com.plaid.client.internal.gson.ObjectSerializer.serialize(ObjectSerializer.java:15)
at com.plaid.client.internal.gson.ObjectSerializer.serialize(ObjectSerializer.java:12)
at com.google.gson.internal.bind.TreeTypeAdapter.write(TreeTypeAdapter.java:81)
at com.google.gson.Gson.toJson(Gson.java:669)
at com.google.gson.Gson.toJsonTree(Gson.java:562)
at com.google.gson.Gson.toJsonTree(Gson.java:541)
at com.google.gson.internal.bind.TreeTypeAdapter$GsonContextImpl.serialize(TreeTypeAdapter.java:155)
at com.plaid.client.internal.gson.ObjectSerializer.serialize(ObjectSerializer.java:15)
at com.plaid.client.internal.gson.ObjectSerializer.serialize(ObjectSerializer.java:12)
at com.google.gson.internal.bind.TreeTypeAdapter.write(TreeTypeAdapter.java:81)
at com.google.gson.Gson.toJson(Gson.java:669)
at com.google.gson.Gson.toJsonTree(Gson.java:562)
at com.google.gson.Gson.toJsonTree(Gson.java:541)
at com.google.gson.internal.bind.TreeTypeAdapter$GsonContextImpl.serialize(TreeTypeAdapter.java:155)
at com.plaid.client.internal.gson.ObjectSerializer.serialize(ObjectSerializer.java:15)
at com.plaid.client.internal.gson.ObjectSerializer.serialize(ObjectSerializer.java:12)
at com.google.gson.internal.bind.TreeTypeAdapter.write(TreeTypeAdapter.java:81)
at com.google.gson.Gson.toJson(Gson.java:669)
at com.google.gson.Gson.toJsonTree(Gson.java:562)
at com.google.gson.Gson.toJsonTree(Gson.java:541)
at com.google.gson.internal.bind.TreeTypeAdapter$GsonContextImpl.serialize(TreeTypeAdapter.java:155)
at com.plaid.client.internal.gson.ObjectSerializer.serialize(ObjectSerializer.java:15)
at com.plaid.client.internal.gson.ObjectSerializer.serialize(ObjectSerializer.java:12)
at com.google.gson.internal.bind.TreeTypeAdapter.write(TreeTypeAdapter.java:81)
at com.google.gson.Gson.toJson(Gson.java:669)
at com.google.gson.Gson.toJsonTree(Gson.java:562)
at com.google.gson.Gson.toJsonTree(Gson.java:541)
at com.google.gson.internal.bind.TreeTypeAdapter$GsonContextImpl.serialize(TreeTypeAdapter.java:155)
at com.plaid.client.internal.gson.ObjectSerializer.serialize(ObjectSerializer.java:15)
at com.plaid.client.internal.gson.ObjectSerializer.serialize(ObjectSerializer.java:12)
at com.google.gson.internal.bind.TreeTypeAdapter.write(TreeTypeAdapter.java:81)
at com.google.gson.Gson.toJson(Gson.java:669)
at com.google.gson.Gson.toJsonTree(Gson.java:562)
at com.google.gson.Gson.toJsonTree(Gson.java:541)
at com.google.gson.internal.bind.TreeTypeAdapter$GsonContextImpl.serialize(TreeTypeAdapter.java:155)
at com.plaid.client.internal.gson.ObjectSerializer.serialize(ObjectSerializer.java:15)
at com.plaid.client.internal.gson.ObjectSerializer.serialize(ObjectSerializer.java:12)
at com.google.gson.internal.bind.TreeTypeAdapter.write(TreeTypeAdapter.java:81)
at com.google.gson.Gson.toJson(Gson.java:669)
at com.google.gson.Gson.toJsonTree(Gson.java:562)
at com.google.gson.Gson.toJsonTree(Gson.java:541)
at com.google.gson.internal.bind.TreeTypeAdapter$GsonContextImpl.serialize(TreeTypeAdapter.java:155)
at com.plaid.client.internal.gson.ObjectSerializer.serialize(ObjectSerializer.java:15)
at com.plaid.client.internal.gson.ObjectSerializer.serialize(ObjectSerializer.java:12)
at com.google.gson.internal.bind.TreeTypeAdapter.write(TreeTypeAdapter.java:81)
at com.google.gson.Gson.toJson(Gson.java:669)
at com.google.gson.Gson.toJsonTree(Gson.java:562)
at com.google.gson.Gson.toJsonTree(Gson.java:541)
at com.google.gson.internal.bind.TreeTypeAdapter$GsonContextImpl.serialize(TreeTypeAdapter.java:155)
at com.plaid.client.internal.gson.ObjectSerializer.serialize(ObjectSerializer.java:15)
at com.plaid.client.internal.gson.ObjectSerializer.serialize(ObjectSerializer.java:12)
at com.google.gson.internal.bind.TreeTypeAdapter.write(TreeTypeAdapter.java:81)
at com.google.gson.Gson.toJson(Gson.java:669)
at com.google.gson.Gson.toJsonTree(Gson.java:562)
at com.google.gson.Gson.toJsonTree(Gson.java:541)
at com.google.gson.internal.bind.TreeTypeAdapter$GsonContextImpl.serialize(TreeTypeAdapter.java:155)
at com.plaid.client.internal.gson.ObjectSerializer.serialize(ObjectSerializer.java:15)
at com.plaid.client.internal.gson.ObjectSerializer.serialize(ObjectSerializer.java:12)
at com.google.gson.internal.bind.TreeTypeAdapter.write(TreeTypeAdapter.java:81)
at com.google.gson.Gson.toJson(Gson.java:669)
at com.google.gson.Gson.toJsonTree(Gson.java:562)

Caused by: java.io.EOFException: \n not found: size=0 content=

Not able to test the exchange token or any other APIService in sandbox or development. Am I missing something in the integration

`

        <dependency>
		<groupId>com.plaid</groupId>
		<artifactId>plaid-java</artifactId>
		<version>2.2.0</version>
	</dependency>

	<dependency>
		<groupId>com.squareup.retrofit2</groupId>
		<artifactId>retrofit</artifactId>
		<version>2.1.0</version>
	</dependency>
	<dependency>
		<groupId>com.squareup.retrofit2</groupId>
		<artifactId>converter-gson</artifactId>
		<version>2.1.0</version>
	</dependency>
	<dependency>
		<groupId>com.squareup.okhttp3</groupId>
		<artifactId>okhttp</artifactId>
		<version>3.6.0</version>
	</dependency>
	<dependency>
		<groupId>com.squareup.okhttp3</groupId>
		<artifactId>logging-interceptor</artifactId>
		<version>3.6.0</version>
	</dependency>

`

`
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Response;

public PlaidClient createPlaidClient() {
String clientId = env.getProperty("PLAID_CLIENT_ID");
String secret = env.getProperty("PLAID_SECRET");

return PlaidClient.newBuilder().clientIdAndSecret(clientId, secret).sandboxBaseUrl()
    .logLevel(HttpLoggingInterceptor.Level.BODY).build();

}

Response<ItemPublicTokenExchangeResponse> response = null;
try {
  response = createPlaidClient().service()
      .itemPublicTokenExchange(new ItemPublicTokenExchangeRequest(publicToken)).execute();

} catch (Exception e) {
}`

Error : java.io.IOException: unexpected end of stream on null at okhttp3.internal.http1.Http1Codec.readResponseHeaders(Http1Codec.java:205) at okhttp3.internal.connection.RealConnection.createTunnel(RealConnection.java:322) at okhttp3.internal.connection.RealConnection.connectTunnel(RealConnection.java:196) at okhttp3.internal.connection.RealConnection.connect(RealConnection.java:144) at okhttp3.internal.connection.StreamAllocation.findConnection(StreamAllocation.java:186) at okhttp3.internal.connection.StreamAllocation.findHealthyConnection(StreamAllocation.java:121) at okhttp3.internal.connection.StreamAllocation.newStream(StreamAllocation.java:100) at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:42) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67) at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.java:93) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67) at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.java:93) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92) at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:120) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67) at okhttp3.logging.HttpLoggingInterceptor.intercept(HttpLoggingInterceptor.java:212) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67) at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:179) at okhttp3.RealCall.execute(RealCall.java:63) at retrofit2.OkHttpCall.execute(OkHttpCall.java:174) at com.infrastructure.PlaidDaoServiceImpl.exchangePublicTokenForAccessToken(PlaidDaoServiceImpl.java:83) at com.domain.service.PlaidDomainServiceImpl.exchangeToken(PlaidDomainServiceImpl.java:36) at com.application.PlaidController.getAccountById(PlaidController.java:42) at com.application.PlaidController$$FastClassBySpringCGLIB$$a977c33d.invoke(<generated>) at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:738) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) at org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor.invoke(MethodBeforeAdviceInterceptor.java:52) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) at org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor.invoke(MethodBeforeAdviceInterceptor.java:52) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) at org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor.invoke(MethodBeforeAdviceInterceptor.java:52) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) at org.springframework.aop.framework.adapter.AfterReturningAdviceInterceptor.invoke(AfterReturningAdviceInterceptor.java:52) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:673) at com.pay.ats.application.PlaidController$$EnhancerBySpringCGLIB$$95b35a60.getAccountById(<generated>) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205) at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:133) at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:97) at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827) at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738) at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85) at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:967) at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901) at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861) at javax.servlet.http.HttpServlet.service(HttpServlet.java:621) at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846) at javax.servlet.http.HttpServlet.service(HttpServlet.java:728) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) at com.pay.ats.application.filter.CrossScriptingFilter.doFilter(CrossScriptingFilter.java:26) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) at com.pay.ats.application.configuration.CacheFilter.doFilter(CacheFilter.java:22) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) at com.pay.ats.application.configuration.CORSFilter.doFilter(CORSFilter.java:26) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100) at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408) at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1041) at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:603) at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310) at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) at java.lang.Thread.run(Unknown Source) Caused by: java.io.EOFException: \n not found: size=0 content=ล at okio.RealBufferedSource.readUtf8LineStrict(RealBufferedSource.java:215) at okhttp3.internal.http1.Http1Codec.readResponseHeaders(Http1Codec.java:189) ... 87 common frames omitted

IllegalAccessError on version 2.2.0 of plaid-java

Called the plaidClient.service().itemPublicTokenExchange(request).execute() method and got this error:

java.lang.IllegalAccessError: tried to access method com.google.gson.Gson.newJsonWriter(Ljava/io/Writer;)Lcom/google/gson/stream/JsonWriter; from class retrofit2.converter.gson.GsonRequestBodyConverter

I am on version 2.2.0 of the plaid-java sdk. Please help.

Plaid generating public token in production mode

I am trying to generate public token in production environment ( using productionBaseUrl ) so that I can later invoke other endpoints. I am using curl request to generate the public token

curl -X POST https://production.plaid.com/link/item/create -H 'content-type: application/json' -d '{
"credentials": {
"username": "user_good",
"password": "pass_good"
},
"initial_products": [
"transactions"
],
"institution_id": "ins_4",
"public_key": "87ff65ae5aedc630bb08d00bb4ee64"
}'

Its works fine for sandbox. Maybe the credentials are dummy. But now I am getting the error

"display_message": null,
"error_code": "RECAPTCHA_REQUIRED",
"error_message": "This request requires additional verification via recaptcha. Please resubmit request
with recaptcha token included",
"error_type": "RECAPTCHA_ERROR",
"request_id": "W9gm9"

How to I get hold of public tokens in production environment. So that I can test other endpoints in my integration using the plaid library.

Android Integration Issue

Getting error On

PlaidUserClient plaidUserClient = PlaidClients.testUserClient("test_id", "test_secret");

java.lang.NoClassDefFoundError: org.apache.http.impl.client.HttpClientBuilder
at com.plaid.client.PlaidClients.createHttpDelegate(PlaidClients.java:98)
at com.plaid.client.PlaidClients.testUserClient(PlaidClients.java:24)
at com.plaid.client.PlaidClients.testUserClient(PlaidClients.java:76)
at com.plaid.client.PlaidClients.testUserClient(PlaidClients.java:71)

updateAuth uses wrong endpoint

The endpoint hit by updateAuth is a POST to /auth/get but according to the API docs, this is actually the endpoint for "retrieve data". This should instead be called getAuth and an updateAuth method should instead submit a PATCH request to /auth as specified in the docs.

Error In Importing Project

Hello Plaid Team ,
I'm facing issues when importing the project into my work space .
I think its due to incorrect Library files.
Can you please send the the Library files in order to fix my issue

java.lang.NoSuchFieldError: INSTANCE

So I'm trying to use plaid-java and when i try to create a PlaidUserClient to test operations with account i have connected via tartan I get the ERROR in the TITLE above, right after trying the code below.

PlaidUserClient client = PlaidClients.testUserClient(_MYCUSTOMERID, _MYCUSTOMERSECRET);

Please let me know if you guys can point me in the right direction here. I'm coding in scala using this java repo in Intellij15 windows machine.

Access token migration

Plaid just announced that they will be migrating to a new access token format. For all existing users, a new_access_token field will be included in all responses from Plaid endpoints that are specific that user. This field will contain the user's new access token in the new format.

Newly created users will be given tokens in the new format to begin with and the new_access_token field will not be present in the responses for their API calls.

This migration period is live on Tartan and will be live in Production in a week. It was not announced when the old tokens will stop being supported.

The plaid-java library should make these new access tokens accessible in the response objects. I will work on this and submit a PR.

How can i implement Plaid in Java web application, i am getting NoSuchMethodError: com.google.gson.GsonBuilder.registerTypeAdapterFactory

Just i have added dependency in Maven pom.xml

<dependency>
  <groupId>com.plaid</groupId>
  <artifactId>plaid-java</artifactId>
  <version>2.1.4</version>
</dependency>

After that i just added the following code

PlaidClient plaidClient = PlaidClient.newBuilder()
  .clientIdAndSecret("your_client_id", "your_secret")
  .publicKey("your_public_key") // optional. only needed to call endpoints that require a public key
  .sandboxBaseUrl() // or equivalent, depending on which environment you're calling into
  .build();

and i change my clientid, secret key and public key. This itself throws me the following exception

Sep 18, 2017 7:12:01 PM org.apache.catalina.core.StandardWrapperValve invoke SEVERE: Servlet.service() for servlet [mysample] in context with path [/mysample] threw exception [Handler processing failed; nested exception is java.lang.NoSuchMethodError: com.google.gson.GsonBuilder.registerTypeAdapterFactory(Lcom/google/gson/TypeAdapterFactory;)Lcom/google/gson/GsonBuilder;] with root cause java.lang.NoSuchMethodError: com.google.gson.GsonBuilder.registerTypeAdapterFactory(Lcom/google/gson/TypeAdapterFactory;)Lcom/google/gson/GsonBuilder; at com.plaid.client.PlaidClient$Builder.buildGson(PlaidClient.java:155) at com.plaid.client.PlaidClient$Builder.build(PlaidClient.java:145) at com.mysample.common.controller.MobileController.loginTz(MobileController.java:593) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) at org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:212) at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:126) at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:96) at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:617) at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:578) at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80) at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:900) at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:827) at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:882) at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:789) at javax.servlet.http.HttpServlet.service(HttpServlet.java:641) at javax.servlet.http.HttpServlet.service(HttpServlet.java:722) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) at com.mysample.security.filter.ValidationFilter.doFilter(ValidationFilter.java:359) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:311) at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:116) at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:83) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:323) at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:113) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:323) at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:113) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:323) at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:54) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:323) at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:45) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:323) at org.springframework.security.web.authentication.www.BasicAuthenticationFilter.doFilter(BasicAuthenticationFilter.java:201) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:323) at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:182) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:323) at com.mysample.security.filter.AuthenticationFilter.doFilter(AuthenticationFilter.java:167) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:323) at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:105) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:323) at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:323) at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:173) at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346) at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:259) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:225) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98) at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:927) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407) at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1001) at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:585) at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310) at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) at java.lang.Thread.run(Unknown Source)

am i doing anything wrong? or could anyone help me to implement this in my web app

Fixed precision data types for money representation.

Since the response data indicates a limited precision, which is appropriate for money, where we only have cent precision (at least for USD), is it a conscious decision that the types for decimal values are Double instead of something with fixed precision like BigDecimal?

Since we expect to handle this data as fixed precision data, it would be nice not to have to handle the risk of lost precision in adapting Doubles back to BigDecimals with the loss of precision.

Cannot instantiate PlaidClient

I am trying to create an instance of the PlaidClient but it's not working:

Here is the snippet:

plaidClient = PlaidClient.newBuilder()
                    .clientIdAndSecret(clientId, clientSecret)
                    .publicKey(publicKey)
                    .developmentBaseUrl() 
                    .build()

The weird part is it't not even throwing an exception.

I had to put logs in a finally block to see the plaidClient is null

I am using Java 1.7 & plaid-java 4.0.3

Am I missing something?

java.lang.IllegalAccessError: tried to access method com.google.gson.Gson.newJsonWriter(Ljava/io/Writer;)Lcom/google/gson/stream/JsonWriter; from class retrofit2.converter.gson.GsonRequestBodyConverter

Response response = plaidClient.service()
.itemPublicTokenExchange(new ItemPublicTokenExchangeRequest("the_link_public_token")).execute();

	        		if (response.isSuccessful()) {
	        		  String accessToken = response.body().getAccessToken();
	        		  System.out.println(accessToken);
	        		}

error getting

com.plaid.client.PlaidClient@6acdbdf5
Exception in thread "main" java.lang.IllegalAccessError: tried to access method com.google.gson.Gson.newJsonWriter(Ljava/io/Writer;)Lcom/google/gson/stream/JsonWriter; from class retrofit2.converter.gson.GsonRequestBodyConverter
at retrofit2.converter.gson.GsonRequestBodyConverter.convert(GsonRequestBodyConverter.java:45)
at retrofit2.converter.gson.GsonRequestBodyConverter.convert(GsonRequestBodyConverter.java:30)
at retrofit2.ParameterHandler$Body.apply(ParameterHandler.java:297)
at retrofit2.ServiceMethod.toRequest(ServiceMethod.java:109)
at retrofit2.OkHttpCall.createRawCall(OkHttpCall.java:178)
at retrofit2.OkHttpCall.execute(OkHttpCall.java:162)
at com.javainuse.SpringBatchApplication.main(SpringBatchApplication.java:34)

How to generate the link public token?

I'm looking in the docs and wondering how we actually generate the link public token. I was reading the integration tests, but seem to be missing a trivial idea here..

Response<ItemPublicTokenExchangeResponse> response = plaidClient.service()
    .itemPublicTokenExchange(new ItemPublicTokenExchangeRequest("the_link_public_token")).execute();

I see that I can create something maybe using the following, but not sure where the params are documented to generate this successfully:

        Response<ItemPublicTokenCreateResponse> createItemResp =
                plaidClient.service().itemPublicTokenCreate(new ItemPublicTokenCreateRequest(createItemCreateResponse(plaidClient).getAccessToken())).execute();

I've done pretty much a replication of the abstractintegrationtest file to build up the token call.

    public ItemCreateResponse createItemCreateResponse (PlaidClient client) throws Exception {
        Response<ItemCreateResponse> response =
                client.service()
                        .itemCreate(new ItemCreateRequest(
                                "ins_109511",
                                Arrays.asList(Product.INCOME))
                                .withCredentials("username", "user_good")
                                .withCredentials("password", "pass_good")).execute();
        return response.body();

Support Account.verification_status

Hello!

According to the Plaid docs here, the account object should have a nullable field called verification_status, which is an enum with 4 values

pending_automatic_verification | An Item is pending automated microdeposit verficiation
automatically_verified | An Item was successfully automically verified
pending_manual_verification | An Item is pending manual microdeposit verficiation
manually_verified | An Item was successfully manually verified

https://plaid.com/docs/#account-verification-status

Any chance we can bump the library forward to include these entries in the response?

Thanks! Let me know how I can help.

Get Apex Processor Token returns `null` always

Hi!

I'm using plaid-java version 2.1.3. I'm trying to get an apex processor token. I think there's a bug in the response class. When I enable HTTP logging for my client I see a response come back that looks like:

{
  "processor_token": "...",
  "request_id": "..."
}

but when I use the deserialized response and do .getApexProcessorToken() I get null.

I am not familiar with the HTTP client framework being used in this project, but should getApexProcessorToken() be named getProcessorToken()?

PlaidClient cannot be used with @Inject in Wildfly

If I try and use @Produces to create instances of PlaidClient via the following code

@Produces
@RequestScoped
public PlaidClient getPlaidClient()
{
	return PlaidClient.newBuilder()
			.clientIdAndSecret(CLIENT_ID, CLIENT_SECRET)
			.publicKey(PUBLIC_KEY)
			.sandboxBaseUrl()
			.build();
}

I get the following error pertaining to Weld:

Caused by: org.jboss.weld.exceptions.UnproxyableResolutionException: WELD-001437: Normal scoped bean class com.plaid.client.PlaidClient is not proxyable because the type is final or it contains a final method class com.plaid.client.PlaidClient - Producer Method [PlaidClient] with qualifiers [@Any @Default] declared as [[BackedAnnotatedMethod] @Produces @RequestScoped public com.toshl.api.utils.Resources.getPlaidClient()].
 	at org.jboss.weld.util.Proxies.getUnproxyableClassException(Proxies.java:214)
 	at org.jboss.weld.util.Proxies.getUnproxyableTypeException(Proxies.java:178)
 	at org.jboss.weld.bootstrap.Validator.validateInjectionPointForDeploymentProblems(Validator.java:378)
 	... 12 more

According to their documentation classes which are declared final or have a final method cannot be proxied.

Is there a reason PlaidClient is defined as final?

Android TransactionsGetResponse not working

I tried following the code on this https://plaid.com/docs/api/#transactions

but I keep getting this message when getting Response<TransactionsGetResponse>

TransactionsGetRequest request =
               new TransactionsGetRequest(token, startDate, endDate)
                       .withCount(100);
    txnResponse = plaidClient.service()
                           .transactionsGet(request).execute();

accesstoken was successfully acquired, but after passing the token to the request and getting the response, I get this message

Response{protocol=http/1.1, code=400, message=Bad Request, url=https://sandbox.plaid.com/transactions/get}

{
  "display_message": null,
  "error_code": "NOT_FOUND",
  "error_message": "invalid route: /transactions/get",
  "error_type": "INVALID_REQUEST",
  "request_id": "Q1NY6"
}

I don't see what kind of this error "invalid route" means.
Am I missing something?

I am getting NoClassDefFoundError exception

// Use builder to create a client
PlaidClient plaidClient = PlaidClient.newBuilder()
.clientIdAndSecret("your_client_id", "your_secret")
.publicKey("your_public_key") // optional. only needed to call endpoints that require a public key
.sandboxBaseUrl() // or equivalent, depending on which environment you're calling into
.build();

This code throwing the following error trace

java.lang.NoClassDefFoundError: com/google/gson/TypeAdapterFactory
com.plaid.client.PlaidClient.newBuilder(PlaidClient.java:103)

income/get

Hi,
Is there a reason why the api endpoint "income/get" is not included ? How should I proceed if I want to include the endpoint in the code ?

Exclude clientId and secret in BaseClientRequest

We would like to audit requests and responses we get from you.
Is there a way to exclude clientId and secret in BaseClientRequest?
In current implementation it is being saved with the request data.
Is there a way to make it transient so it wont be persistent in our data base?
Thanks!

Mark optional response fields as so

There are many fields in the API response JSON that can be null, but these are in no way annotated in the client library. Since the using code has to specifically handle nulls in every one of the fields that are being used, it would be nice if all of those used Optional or were annotated by @Nullable to mark that that is necessary to do that handling.

Relatedly, when a field that's a JSON array is missing, the API also returns it as null, which means that the consuming code has to handle null instead of the empty list. It would be nice if the JSON deserializer converted nulls to empty lists for list fields, since there's no semantic difference, both mean nothing is there.

InfoResponse

How do I get an InfoResponse from Link, I don't have the username/password for credentials?

InfoResponse info(Credentials credentials, String type, InfoOptions options);

Calling plaidClient.parseError fails (or reading raw error body after call)

When calling plaidClient.parseError() the buffer of the Error Body is drained. Making a second call to the same method (for the same response) fail/empty.

To solve this the response need to be cloned before read.

Something like:

final ResponseBody responseBody = response.errorBody();
final Buffer bufferClone = responseBody.source().buffer().clone();
final ResponseBody errorBodyCody = ResponseBody.create(responseBody.contentType(), responseBody.contentLength(), bufferClone);

return responseBodyObjectConverter.convert(errorBodyCody);

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.