Code Monkey home page Code Monkey logo

sdk_java's Introduction

bunq Java SDK

Introduction

Hi developers!

Welcome to the bunq Java SDK! 👨‍💻

We're very happy to introduce yet another unique product: complete banking SDKs! Now you can build even bigger and better apps and integrate them with your bank of the free! 🌈

Before you dive into this brand new SDK, please consider:

Give us your feedback, create pull requests, build your very own bunq apps and most importantly: have fun! 💪

This SDK is in beta. We cannot guarantee constant availability or stability. Thanks to your feedback we will make improvements on it.

Installation

To install the package, please follow the instructions corresponding to your build tool under "How to" on the package page on JitPack: https://jitpack.io/#bunq/sdk_java

Usage

Creating an API context

In order to start making calls with the bunq API, you must first register your API key and device, and create a session. In the SDKs, we group these actions and call it "creating an API context". The context can be created by using the following code snippet:

ApiContext apiContext = ApiContext.create(ENVIRONMENT_TYPE, API_KEY,
  DEVICE_DESCRIPTION);
apiContext.save(API_CONTEXT_FILE_PATH);

Please note: initialising your application is a heavy task and it is recommended to do it only once per device.

After saving the context, you can restore it at any time:

ApiContext apiContext = ApiContext.restore(API_CONTEXT_FILE_PATH);
BunqContext.loadApiContext(apiContext);

Tip: both saving and restoring the context can be done without any arguments. In this case the context will be saved to/restored from the bunq.conf file in the same folder with your executable.

Example

See tinker/load_api_context

PSD2

It is possible to create an ApiContext as PSD2 Service Provider. Although this might seem a complex task, we wrote some helper implementations to get you started. You need to create a certificate and private key to get you started. Our sandbox environment currently accepts all certificates, if these criteria are met:

  • Up to 64 characters
  • PISP and/or AISP used in the end.

Make sure you have your unique eIDAS certificate number and certificates ready when you want to perform these tasks on our production environment.

Creating a PSD2 context is very easy:

ApiContext apiContext = ApiContext.createForPsd2(
    ENVIRONMENT_TYPE,
    SecurityUtils.getCertificateFromFile(PATH_TO_CERTIFICATE),
    SecurityUtils.getPrivateKeyFromFile(PATH_TO_PRIVATE_KEY),
    new Certificate[]{
            SecurityUtils.getCertificateFromFile(PATH_TO_CERTIFICATE_CHAIN)
    },
    DESCRIPTION
)

This context can be saved the same way as a normal ApiContext. After creating this context, create an OAuth client to get your users to grant you access. For a more detailed example, check the tinker_java repository.

Safety considerations

The file storing the context details (i.e. bunq.conf) is a key to your account. Anyone having access to it is able to perform any Public API actions with your account. Therefore, we recommend choosing a truly safe place to store it.

Making API calls

There is a class for each endpoint. Each class has functions for each supported action. These actions can be create, get, update, delete and list.

When making calls, The userId and monetaryAccountId needed to make calls will be determined by the SDK it. When no monetaryAccountId has been passed, the SDK will use the first active monetary account it can find. This is normally the monetary account used for billing.

Before you make a call, make sure that you have loaded ApiContext in to the BunqContext.

Creating objects

With the create method you can create new models. This method normally returns the id of the created model.

Payment.create(
	new Amount(amount, CURRENCY_EURO),
	new Pointer(POINTER_TYPE_EMAIL, recipient),
	description
);
Example

See tinker/make_payment

NotificationFilters / Callbacks

Note! Due to an in internal change in the way we handle NotificationFilters (Callbacks), you should not use the default classes included in this SDK. Please make sure you make use of the associated Internal-classes. For example when you need NotificationFilterUrlUser, make use of NotificationFilterUrlUserInternal. You can use every method of these classes, except for the create() method. Always use createWithListResponse() instead.

Example
NotificationFilterPushUserInternal.createWithListResponse(...)
NotificationFilterUrlUserInternal.createWithListResponse(...)
NotificationFilterUrlMonetaryAccountInternal.createWithListResponse(...)

Reading objects

Reading objects can be done via the get or list method.

These type of calls always returns the model or binary data.

Payment.list(
 	monetaryAccountBank.getId(),
    pagination.getUrlParamsCountOnly()
)
Example

See tinker/get_all_payment

Updating objects

Updating objects through the API goes the same way as creating objects, except that also the object to update identifier (ID or UUID) is needed.

The update method will also normally return the Id of the updated model.

 MonetaryAccountBank.update(Integer.parseInt(accountId), name);
Example

See tinker/update_monetary_account

Deleting objects

�Deleting object can be done via the delete method. This method also requires the object identifier which could be an Id or uuid.

This method normally returns an empty response.

CustomerStatementExport.delete(customerStatementId);

Running Examples

To have an idea on how the SDK works you can play around with the java tinker located at: https://github.com/bunq/tinker_java

Running tests

Information regarding the test cases can be found in the README.md located in test.

Exceptions

The SDK can throw multiple exceptions. For an overview of these exceptions please take a look at EXCEPTIONS.md

sdk_java's People

Contributors

andrederoos avatar angelomelonas avatar bunq-bot avatar davide-giordano avatar dnl-blkv avatar erwindeg avatar joosto avatar lexym avatar nickvandegroes avatar ogkevin avatar sandervdo avatar tubbynl 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

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

sdk_java's Issues

Better error handling

Steps to reproduce:

  1. Look at the exceptions that the SDK throws.

What should happen:

  1. The SDK should at least have/throw 1 exception per bad status code.

What happens:

  1. The SDK will only throw 2 exceptions.

Update Sandbox API key procedure

Steps to reproduce:

  1. Look at README.md

What should happen:

  1. It should not tell you to contact support for the Sandbox API key

What happens:

  1. It does tell you to ask support for an API key

More flexibility for sessionContext handling

Steps to reproduce:

  1. Try and find out if your session context is expired

What should happen:

  1. There is a way to know if your session has expired without resetting/calling ensureSesiosActive()

What happens:

  1. There is no way to achieve such thing

Extra info:

Why

  • This way you wont have to execute this code before each call but only if your session did expire
apiContext.ensureSessionActive();
apiContext.save();

Which means you will be saving an unchanged context on each call

Android issue: HttpClient was deprecated in API Level 22 and removed in API Level 23

The dependency "org.apache.httpcomponents.httpclient" is removed from API level 23+
Maybe a other HttpClient can be used, like "OkHttp"?

Steps to reproduce:

  1. Use SDK in app on Android 8.0

What should happen:

What happens:

I get this error when executing ApiContext.create:

java.lang.NoSuchFieldError: No static field INSTANCE of type Lorg/apache/http/conn/ssl/AllowAllHostnameVerifier; in class Lorg/apache/http/conn/ssl/AllowAllHostnameVerifier; or its superclasses (declaration of 'org.apache.http.conn.ssl.AllowAllHostnameVerifier' appears in /system/framework/framework.jar:classes2.dex) at org.apache.http.conn.ssl.SSLConnectionSocketFactory.<clinit>(SSLConnectionSocketFactory.java:146) at com.bunq.sdk.http.ApiClient.buildHttpClient(ApiClient.java:120) at com.bunq.sdk.http.ApiClient.<init>(ApiClient.java:113) at com.bunq.sdk.model.core.Installation.create(Installation.java:43) at com.bunq.sdk.context.ApiContext.initializeInstallation(ApiContext.java:173) at com.bunq.sdk.context.ApiContext.initialize(ApiContext.java:163) at com.bunq.sdk.context.ApiContext.create(ApiContext.java:127) at com.bunq.sdk.context.ApiContext.create(ApiContext.java:109) at com.bunq.sdk.context.ApiContext.create(ApiContext.java:101)

Traceback

SDK version and environment

Response id

  • Response id:

Extra info:

Cannot list draft payments for monetary account

Steps to reproduce:

  1. Make a draft payment for monetary account X
  2. List draft payments for monetary account X

What should happen:

  1. Draft payments are retrieved and deserialized into DraftPayment instances

What happens:

  1. Gson Error is thrown

Logs

com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected NULL but was NUMBER at path $.object.Payment.geolocation.latitude
        at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:224)
        at com.google.gson.internal.bind.TreeTypeAdapter.read(TreeTypeAdapter.java:63)
        at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:129)
        at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:220)
        at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:129)
        at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:220)
        at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:129)
        at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:220)
        at com.google.gson.Gson.fromJson(Gson.java:887)
        at com.google.gson.Gson.fromJson(Gson.java:952)
        at com.google.gson.Gson.fromJson(Gson.java:925)
        at com.bunq.sdk.model.core.BunqModel.fromJsonList(BunqModel.java:104)
        at com.bunq.sdk.model.generated.endpoint.DraftPayment.list(DraftPayment.java:151)
        at com.bunq.sdk.model.generated.endpoint.DraftPayment.list(DraftPayment.java:141)
        at com.bunq.sdk.model.generated.endpoint.DraftPayment.list(DraftPayment.java:137)

Add more information to templates

Steps to reproduce:

  1. Create a new issue or pull request

What should happen:

  1. The issue template should include a template to list the SDK version number and link to its release.
  2. There are comments explaining some basic flows.
  3. The PR template should contain a Tested check box and says which issue the PR will close.

What happens:

  1. The template is to basic.

Logs

  • Logs no logs

Extra info:

References

Add more example scripts

This issue is meant to keep track of the example scripts included in the SDK.

  • ApiContext

    • Save/restore
    • Ensure that session is active
  • Attachments

  • Callbacks

  • Cards

    • Order card
  • Card payments

    • MasterCard action
  • Cash registers

  • Chat

  • Connects

  • Export statements

  • Invoices

  • Monetary accounts

  • Payment

    • Draft Payment
    • Scheduled Payment
    • Payment batch
    • Tab Payment
  • Request for payment / Request inquiry

  • User

SDK build fails on jitpack

How to Reproduce

  1. Try to get bunq Java SDK from Jitpack

What Should Happen

  1. The package is acquired smoothly

What Happens

  1. It fails, log show errors:
/home/jitpack/build/src/main/java/com/bunq/sdk/security/SecurityUtils.java:43: error: package org.jcp.xml.dsig.internal does not exist
import org.jcp.xml.dsig.internal.MacOutputStream;
                                ^
/home/jitpack/build/src/main/java/com/bunq/sdk/context/ApiContext.java:14: error: package com.sun.istack.internal does not exist
import com.sun.istack.internal.Nullable;

Introduce fromJson method

Steps to reproduce:

  1. Take a look at the methods inside BunqModel

What should happen:

  1. There is a method to convert a JSON to class defined like to_json

What happens:

  1. 👆 is not implemented

Logs

  • Logs no logs

Extra info:

References

Update read me with installation instructions

Steps to reproduce:

  1. Look at the read me of this project

What should happen:

  1. It should explain how you could install this SDK in to your project.

What happens:

  1. It’s still saying TBA

Serialization Error

Steps to reproduce:

  1. Make sure you have a geolocated payment on your account
  2. Request a list of Payments

What should happen:

  1. The list is returned

What happens:

  1. A serialization error occurs

Traceback

SDK version and environment

  • Tested on 0.12.4
  • Sandbox
  • Production

Response id

  • Response id: e68bcf3d-e12d-41ea-b119-d0ee4a8b2af6

Extra info:

Currently com.bunq.sdk.model.generated.object.Geolocation has three BigDecimal fields. However, there seems to be a mismatch. If you take a look at com.bunq.sdk.json.BigDecimalTypeAdapter it reads a BigDecimal from type String. Yet the api returns a value of type number.

I did not make the pull request myself because I don't know which fix you'd like me to make. I see a few options:

  1. Make sure the API returns a String. However, this is probably extremely impactful as it is a breaking api change.
  2. Revert the if statement in com.bunq.sdk.json.BigDecimalTypeAdapter so it becomes
         if (input.peek() == JsonToken.NULL) {
            input.nextNull();
            return null;
        } else {
            return new BigDecimal(input.nextString());
        }
  3. Have Geolocation use Doubles instead of BigIntegers

My personal preference would go to option 2 since in my opinion it is a more resilient solution. I am willing to make the pull request myself. Just give me your decision.

Improve decoder to recognise child object

Steps to reproduce:

  1. Try and decode a child object into a model that is expecting its parent

What should happen:

  1. The model is correctly populated with data.

What happens:

  1. All the fields, including the parent field will be null.

Logs

  • Logs no logs

Extra info:

Reference

Add missing fields for cvc endpoint

Steps to reproduce:

  1. Try and get id, created or updated from CardGeneratedCvc2

What should happen:

  1. These fields are there with getters/setters

What happens:

  1. There are no such fields

Logs

  • no logs

Extra info:

Allow saving context to JSON and restoring from it

How to Reproduce

  1. Look at the methods of ApiContext

What Should Happen

  1. toJson and fromJson methods allowing to save context to or load from JSON are present

What Happens

  1. There are no toJson nor fromJson

Return base class from createFromJsonString

Steps to reproduce:

  1. Create a class from JSON string by using the method createFromJsonString

What should happen:

  1. The return value is casted to the subclass.

What happens:

  1. The return value is casted to BunqModel.

Logs

  • Logs No logs

Extra info:

Reference

Add header verification test 

Steps to reproduce:

  1. Response verification should be tested,

What should happen:

  1. Response verification is not tested.

What happens:

  1. Response verification is tested.

Logs

  • Logs no logs

Extra info:

References

  1. Response verification should be tested,

What should happen:

  1. Response verification is not tested.

What happens:

  1. Response verification is tested.

Logs

  • Logs no logs

Extra info:

References

Add Proxy Support

How to Reproduce

  1. Look for proxy in the SDK codebase

What Should Happen

  1. Proxy can be set in ApiContext

What Happens

  1. No proxy can be set in ApiContext

Remove guava 

Steps to reproduce:

  1. When using this SDK for android Guava might not behave

What should happen:

  1. No need to use guava.

What happens:

  1. Guava is used

Logs

  • Logs
Error:com.android.builder.dexing.DexArchiveBuilderException: Failed to process C:\Users\lenvovo\.gradle\caches\modules-2\files-2.1\com.google.guava\guava\22.0\3564ef3803de51fb0530a8377ec6100b33b0d073\guava-22.0.jar

Extra info:

References

  • #25 Clean dependencies
  • china1688/test_bunq#1

ScheduledPayment causes decode error due to Typo

There is a typo in the bunq\Model\Generated\Endpoint\SchedulePayment class. It has the constant const OBJECT_TYPE = 'SchedulePayment'; while the API returns an object of type ScheduledPayment. When I change the constant to this, it works fine.

Steps to reproduce:

  1. Run this piece of code: https://gist.github.com/mbernson/dd8c966e277b4acd820463335cd47e24

What should happen:

  1. I see a var_dump of my scheduled payments.

What happens:

  1. PHP Notice: Undefined index: SchedulePayment in /Users/mathijs/Code/bunqapibouwsel/vendor/bunq/sdk_php/src/Model/Core/BunqModel.php on line 115

Extra info:

Reference

Add test CI

Steps to reproduce:

  1. Make a PR

What should happen:

  1. There should be a test CI

What happens:

  1. There is no such thing.

reference bunq/sdk_php#126

Ignore generated code for reviews

How to Reproduce

  1. Look at the files in this project.

What Should Happen

  1. There is a .gitattributes file which lists generated code as generated.

What Happens

  1. There is no .gitattributes file.

Notes

  • This will make code review easier as of the generated code will be collapsed automatically .

[Java] Update examples in readme

Steps to reproduce:

  1. Take a look the readme

What should happen:

  1. The examples are accurate and references to tinker.

What happens:

  1. Examples is outdated

Improve Model Namespaces

How to Reproduce

  1. Look at the namespaces of the models

What Should Happen

  1. Model namespaces are clean and symmetrical

What Happens

  1. Objects are one namespace level higher than endpoints
  2. Core models are one level below the generated models

It is not possible to refresh userContext data

Steps to reproduce:

  1. Make a payment from your main account.
  2. Check the balance of the main account stored in user context.

What should happen:

  1. The balance is correct.

What happens:

  1. The balances is the old balance before the payment was mande.

Traceback

SDK version and environment

  • Tested on 0.13.0
  • Sandbox
  • Production

Response id

  • Response id:

Extra info:

Reference bunq/sdk_php#122

Callback models for holding callback data

Steps to reproduce:

  1. Receive a callback as described here: https://doc.bunq.com/api/1/page/callbacks

What should happen:

  1. There is a model available so that you can do the following:
$callbackModel = NotificationUrl::fromJson($CallbackJson);
$callbackModel->getReferencedObject();

if (!$callbackModel isntanceof CallbackModelImExcpeting) {
    throw new Exception();
}

What happens:

  1. Such thing is not possible yet

Logs

  • Logs no logs

Extra info:

Reference

TokenQrRequestIdeal returns the wrong type

Steps to reproduce:

  1. Try to create a TokenQrRequestIdeal using the SDK.

What should happen:

  1. The item is created and a TokenQrRequestIdeal object is returned.

What happens:

  1. The API returns a RequestResponse object, but the SDK tries to cast it to a TokenQrRequestIdeal, resulting in an error.

Extra info:

Reference

Add java 7 compatibility 

Steps to reproduce:

  1. Most android SDK's don't support java 8
  2. Try to use the bunq sdk on one of these android sdk's

What should happen:

  1. It works smoothly

What happens:

  1. A bunch of errors

Logs

Error:com.android.builder.dexing.DexArchiveBuilderException: Failed to process C:\Users\lenvovo\.gradle\caches\modules-2\files-2.1\com.github.bunq\sdk_java\b5c97e4\e70d9e73b467b9e46cd315e2d40182b175385b38\sdk_java-b5c97e4.jar

Error:com.android.builder.dexing.DexArchiveBuilderException: Error while dexing com/bunq/sdk/security/SecurityUtils.class

Error:com.android.dx.cf.code.SimException: invalid opcode ba (invokedynamic requires --min-sdk-version >= 26)

Error:Execution failed for task ':app:transformClassesWithDexBuilderForDebug'.

> com.android.build.api.transform.TransformException: com.android.builder.dexing.DexArchiveBuilderException: com.android.builder.dexing.DexArchiveBuilderException: Failed to process C:\Users\lenvovo\.gradle\caches\modules-2\files-2.1\com.github.bunq\sdk_java\b5c97e4\e70d9e73b467b9e46cd315e2d40182b175385b38\sdk_java-b5c97e4.jar

Extra info:

Monetary account joint cannot be retrieved.

Steps to reproduce:

  1. Create a new joint account
  2. try something like MonetaryAccount.list

What should happen:

  1. Monetary account joints are also listed

What happens:

  1. you will get all accounts except the new joint accounts

Logs

  • Logs no logs

Extra info:

Reference

Response is missing response headers and pagination

How to Reproduce

  1. Make a valid listing request to bunq API via the Java SDK
  2. Make a valid get/put/post/delete request to bunq API via the Java SDK

What Should Happen

  1. The response contains response headers and pagination
  2. The response contains response headers

What Happens

  1. The response does not contain response header nor pagination
  2. The response does not contain response header

Notes

  1. The structural fix would be to introduce BunqResponse object which, besides the response model, includes the response headers and pagination

Optimise test framework

Steps to reproduce:

  1. Try and execute tests

What should happen:

  1. It should be easy and fast

What happens:

  1. It is hard to set up and can take up to 10 mins to complete.

Traceback

SDK version and environment

  • Tested on 0.12.4
  • Sandbox
  • Production

Response id

  • Response id:

Extra info:

Reference: bunq/sdk_php#120

provide non-static API access

Currently the java client API is purely based on static access and is based on a SingleTon ApiContext

Static functions don't give a lot of flexibility in usage, i would like the ApiClient to with it's own private final context and providing access to the different API's using that context.

Would you guys consider providing a BunqApiClient having methods-per-concept?
for example:
https://github.com/stil4m/mollie-api/blob/master/src/main/java/nl/stil4m/mollie/Client.java

current static API can be retained for backwards compatibility via these concepts

It would enable better integration in inversion-of-control / dependency injection (spring beans..) scenario's

Add zappr integration for better quality control 

The purpose of this issue is to introduce https://zappr.opensource.zalan.do so that quality control on pull requests can be assured.

The following configuration should be used:

autobranch:
  pattern: 'bunq/sdk_java#{number}-{title}'
  length: 100
commit:
  message:
    patterns:
      - '([A-Za-z0-9 ]+)\. (\(bunq\/sdk_java#[0-9]+\))'
specification:
  title:
    minimum-length:
      enabled: true
      length: 8
  body:
    minimum-length:
      enabled: true
      length: 8
    contains-url: true
    contains-issue-number: true
  template:
    differs-from-body: true
pull-request:
  labels:
    additional: true
    required:
      - Reviewed by André
      - Can be merged

DraftPayment object field causes converter error

Steps to reproduce:

  1. Use the PHP Pub API SDK
  2. Make a draft payment via the SDK
  3. Accept this draft payment
  4. Retrieve this draft payment

What should happen:

  1. The SDK will raise and error as described here bunq/sdk_php#63

What happens:

  1. No error is raised

Extra info:

  • Tested on SDK release 0.12.1
  • This is an issue with all SDK's

Auto save the session after automatic session reset has been executed 

Steps to reproduce:

  1. Make a request with an expired session

What should happen:

  1. The session gets automatically reset before the actual call is made.
  2. The reset session should be saved after the reset. So that the next call has a fresh new session, instead of resetting the session again.
  3. The user should be able to turn the automatic session save off.

What happens:

  1. If implemented incorrectly, users will make 6 calls to session-server within 2 seconds because on each call the session needs to be reset.

Logs

  • Logs no logs

Extra info:

Reference

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.