Skip to content

Commit 25043a3

Browse files
authored
Merge pull request #168 from WinkPascal/develop
bunq Update 28 | Update object naming, fix parsing and fix tests
2 parents 8c17f6b + bca279f commit 25043a3

39 files changed

+16330
-12453
lines changed

.gitignore

Lines changed: 7 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6,30 +6,11 @@
66
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
77

88
# User-specific stuff:
9-
.idea/**/workspace.xml
10-
.idea/**/tasks.xml
11-
.idea/dictionaries
12-
.idea/shelf
13-
14-
# Sensitive or high-churn files:
15-
.idea/**/dataSources/
16-
.idea/**/dataSources.ids
17-
.idea/**/dataSources.xml
18-
.idea/**/dataSources.local.xml
19-
.idea/**/sqlDataSources.xml
20-
.idea/**/dynamic.xml
21-
.idea/**/uiDesigner.xml
22-
23-
# Gradle:
24-
.idea/**/gradle.xml
25-
.idea/**/libraries
9+
.idea
2610

2711
# CMake
2812
cmake-build-debug/
2913

30-
# Mongo Explorer plugin:
31-
.idea/**/mongoSettings.xml
32-
3314
## File-based project format:
3415
*.iws
3516

@@ -97,3 +78,9 @@ connectQr.png
9778
bunq_sdk.egg-info
9879
.idea/codeStyles/
9980
venv
81+
82+
tests/bunq-oauth-psd2-test.conf
83+
tests/bunq-psd2-test.conf
84+
tests/key.pem
85+
tests/certificate.pem
86+

README.md

Lines changed: 1 addition & 148 deletions
Original file line numberDiff line numberDiff line change
@@ -1,148 +1 @@
1-
# bunq Python SDK
2-
3-
## Introduction
4-
Hi developers!
5-
6-
Welcome to the bunq Python SDK! 👨‍💻
7-
8-
We're very happy to introduce yet another unique product: complete banking SDKs!
9-
Now you can build even bigger and better apps and integrate them with your bank of the free! 🌈
10-
11-
Before you dive into this brand new SDK, please consider:
12-
- Learning how bunq works and what objects you will work with by reading [the intro to our API](https://github.com/bunq/doc/blob/develop/README.md) 🤓
13-
- Checking out [our developer portal](https://developer.bunq.com/) 🙌
14-
- Grabbing your Production API key from [our developer portal](https://developer.bunq.com/) or the bunq app 🗝
15-
- Generating a Sandbox API key using [our developer portal](https://developer.bunq.com/) or [Tinker](https://www.bunq.com/developer) 🗝
16-
- Visiting [our forum](https://together.bunq.com/t/api) where you can share your creations,
17-
questions and experience 🎤
18-
19-
Give us your feedback, create pull requests, build your very own bunq apps and most importantly:
20-
have fun! 💪
21-
22-
This SDK is in **beta**. We cannot guarantee constant availability or stability.
23-
Thanks to your feedback we will make improvements on it.
24-
25-
## Installation
26-
pip install bunq_sdk --upgrade
27-
28-
## Usage
29-
30-
### Creating an API context
31-
In order to start making calls with the bunq API, you must first register your API key and device,
32-
and create a session. In the SDKs, we group these actions and call it "creating an API context". The
33-
context can be created by using the following code snippet:
34-
35-
36-
apiContext = ApiContext.create(ENVIRONMENT_TYPE, API_KEY, DEVICE_DESCRIPTION)
37-
apiContext.save(API_CONTEXT_FILE_PATH)
38-
39-
40-
**Please note**: initialising your application is a heavy task and it is recommended to do it only once per device.
41-
42-
apiContext = ApiContext.restore(self.API_CONTEXT_FILE_PATH)
43-
BunqContext.loadApiContext(apiContext)
44-
45-
After saving the context, you can restore it at any time:
46-
47-
#### Example
48-
49-
See [`tinker/setup_context`](https://github.com/bunq/tinker_python/blob/2182b8be276fda921657ad22cfe0b8b48a585ccf/tinker/libs/bunq_lib.py#L44-L59)
50-
51-
#### PSD2
52-
It is possible to create an ApiContext as PSD2 Service Provider. Although this might seem a complex task, we wrote some
53-
helper implementations to get you started. You need to create a certificate and private key to get you started.
54-
Our sandbox environment currently accepts all certificates, if these criteria are met:
55-
56-
- Up to 64 characters
57-
- PISP and/or AISP used in the end.
58-
59-
Make sure you have your unique eIDAS certificate number and certificates ready when you want to perform these tasks on
60-
our production environment.
61-
62-
Creating a PSD2 context is very easy:
63-
64-
apiContext = ApiContext.create_for_psd2(ENVIRONMENT_TYPE, CERTIFICATE, PRIVATE_KEY, CERTIFICATE_CHAIN, DEVICE_DESCRIPTION)
65-
66-
#### Safety considerations
67-
The file storing the context details (i.e. `bunq.conf`) is a key to your account. Anyone having
68-
access to it is able to perform any Public API actions with your account. Therefore, we recommend
69-
choosing a truly safe place to store it.
70-
71-
### Making API calls
72-
There is a class for each endpoint. Each class has functions for each supported action. These
73-
actions can be `create`, `get`, `update`, `delete` and `list`.
74-
75-
Sometimes API calls have dependencies, for instance `MonetaryAccount`. Making changes to a monetary
76-
account always also needs a reference to a `User`. These dependencies are required as arguments when
77-
performing API calls. Take a look at [doc.bunq.com](https://doc.bunq.com) for the full
78-
documentation.
79-
80-
#### Creating objects
81-
Creating objects through the API requires an `ApiContext`, a `requestMap` and identifiers of all
82-
dependencies (such as User ID required for accessing a Monetary Account). Optionally, custom headers
83-
can be passed to requests.
84-
85-
payment_id = Payment.create(
86-
amount=Amount(amount_string, self._CURRENCY_EURL),
87-
counterparty_alias=Pointer(self._POINTER_TYPE_EMAIL, recipient),
88-
description=description
89-
)
90-
91-
##### Example
92-
See [`tinker/make_payment`](https://github.com/bunq/tinker_python/blob/2182b8be276fda921657ad22cfe0b8b48a585ccf/tinker/libs/bunq_lib.py#L140-L151)
93-
94-
#### Reading objects
95-
Reading objects through the API requires an `ApiContext`, identifiers of all dependencies (such as
96-
User ID required for accessing a Monetary Account), and the identifier of the object to read (ID or
97-
UUID) Optionally, custom headers can be passed to requests.
98-
99-
This type of calls always returns a model.
100-
101-
monetary_account = generated.MonetaryAccountBank.get(
102-
_MONETARY_ACCOUNT_ITEM_ID
103-
)
104-
105-
##### Example
106-
See [`tinker/list_all_payment`](https://github.com/bunq/tinker_python/blob/2182b8be276fda921657ad22cfe0b8b48a585ccf/tinker/libs/bunq_lib.py#L85-L103)
107-
108-
#### Updating objects
109-
Updating objects through the API goes the same way as creating objects, except that also the object to update identifier
110-
(ID or UUID) is needed.
111-
112-
Card.update(
113-
card_id=int(card_id),
114-
monetary_account_current_id=int(account_id)
115-
)
116-
117-
##### Example
118-
See [`tinker/update_card`](https://github.com/bunq/tinker_python/blob/2182b8be276fda921657ad22cfe0b8b48a585ccf/tinker/libs/bunq_lib.py#L167-L174)
119-
120-
#### Deleting objects
121-
Deleting objects through the API requires an `ApiContext`, identifiers of all dependencies (such as User ID required for
122-
accessing a Monetary Account), and the identifier of the object to delete (ID or UUID) Optionally, custom headers can be
123-
passed to requests.
124-
125-
Session.delete(self._SESSION_ID)
126-
127-
##### Example
128-
129-
#### Listing objects
130-
Listing objects through the API requires an `ApiContext` and identifiers of all dependencies (such as User ID required
131-
for accessing a Monetary Account). Optionally, custom headers can be passed to requests.
132-
133-
users = User.list(api_context)
134-
135-
##### Example
136-
See [`UserListExample.py`](./examples/user_list_example.py)
137-
138-
## Running Samples
139-
To get an indication on how the SDK works you can use the python tinker which is located at https://github.com/bunq/tinker_python
140-
141-
## Running Tests
142-
143-
Information regarding the test cases can be found in the [README.md](./tests/README.md)
144-
located in [test](/tests).
145-
146-
## Exceptions
147-
The SDK can raise multiple exceptions. For an overview of these exceptions please
148-
take a look at [EXCEPTIONS.md](./bunq/sdk/exception/EXCEPTIONS.md).
1+
📚 For full documentation about this sdk, visit [doc.bunq.com](https://doc.bunq.com/getting-started/tools/software-development-kits-sdks/python/usage).

bunq/__init__.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from bunq.sdk.http.pagination import Pagination
66
from bunq.sdk.json import converter
77
from bunq.sdk.model.core.anchor_object_interface import AnchorObjectInterface
8-
from bunq.sdk.model.generated.object_ import Geolocation, ShareDetail, MonetaryAccountReference
8+
from bunq.sdk.model.generated.object_ import GeolocationObject, ShareDetailObject, MonetaryAccountReference
99
from bunq.sdk.util.type_alias import T
1010

1111

@@ -37,9 +37,9 @@ def initialize_converter() -> None:
3737
converter.register_adapter(InstallationContext, InstallationContextAdapter)
3838
converter.register_adapter(ApiEnvironmentType, ApiEnvironmentTypeAdapter)
3939
converter.register_adapter(float, FloatAdapter)
40-
converter.register_adapter(Geolocation, GeolocationAdapter)
40+
converter.register_adapter(GeolocationObject, GeolocationAdapter)
4141
converter.register_adapter(MonetaryAccountReference, MonetaryAccountReferenceAdapter)
42-
converter.register_adapter(ShareDetail, ShareDetailAdapter)
42+
converter.register_adapter(ShareDetailObject, ShareDetailAdapter)
4343
converter.register_adapter(datetime.datetime, DateTimeAdapter)
4444
converter.register_adapter(Pagination, PaginationAdapter)
4545

bunq/sdk/context/api_context.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
from bunq.sdk.exception.bunq_exception import BunqException
1313
from bunq.sdk.json import converter
1414
from bunq.sdk.model.core.payment_service_provider_credential_internal import PaymentServiceProviderCredentialInternal
15-
from bunq.sdk.model.generated.endpoint import UserCredentialPasswordIp, Session
15+
from bunq.sdk.model.generated.endpoint import UserCredentialPasswordIpApiObject, SessionApiObject
1616
from bunq.sdk.security import security
1717

1818
if typing.TYPE_CHECKING:
@@ -115,7 +115,7 @@ def __initialize_installation(self) -> None:
115115
def __initialize_psd2_credential(self,
116116
certificate: str,
117117
private_key: str,
118-
all_chain_certificate: List[str]) -> UserCredentialPasswordIp:
118+
all_chain_certificate: List[str]) -> UserCredentialPasswordIpApiObject:
119119
session_token = self.installation_context.token
120120
client_key_pair = self.installation_context.private_key_client
121121

bunq/sdk/context/session_context.py

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,18 @@
66
from bunq.sdk.exception.bunq_exception import BunqException
77
from bunq.sdk.model.core.bunq_model import BunqModel
88
from bunq.sdk.model.core.session_token import SessionToken
9-
from bunq.sdk.model.generated.endpoint import UserPerson, UserCompany, UserApiKey, UserPaymentServiceProvider
9+
from bunq.sdk.model.generated.endpoint import UserPersonApiObject, UserCompanyApiObject, UserApiKeyApiObject, UserPaymentServiceProviderApiObject
1010

1111

1212
class SessionContext:
1313
"""
1414
:type _token: str
1515
:type _expiry_time: datetime.datetime
1616
:type _user_id: int
17-
:type _user_person: UserPerson|None
18-
:type _user_company: UserCompany|None
19-
:type _user_api_key: UserApiKey|None
20-
:type _user_payment_service_provider: UserPaymentServiceProvider|None
17+
:type _user_person: UserPersonApiObject|None
18+
:type _user_company: UserCompanyApiObject|None
19+
:type _user_api_key: UserApiKeyApiObject|None
20+
:type _user_payment_service_provider: UserPaymentServiceProviderApiObject|None
2121
"""
2222

2323
# Error constants
@@ -37,19 +37,19 @@ def user_id(self) -> int:
3737
return self._user_id
3838

3939
@property
40-
def user_person(self) -> Optional[UserPerson]:
40+
def user_person(self) -> Optional[UserPersonApiObject]:
4141
return self._user_person
4242

4343
@property
44-
def user_company(self) -> Optional[UserCompany]:
44+
def user_company(self) -> Optional[UserCompanyApiObject]:
4545
return self._user_company
4646

4747
@property
48-
def user_api_key(self) -> Optional[UserApiKey]:
48+
def user_api_key(self) -> Optional[UserApiKeyApiObject]:
4949
return self._user_api_key
5050

5151
@property
52-
def user_payment_service_provider(self) -> Optional[UserPaymentServiceProvider]:
52+
def user_payment_service_provider(self) -> Optional[UserPaymentServiceProviderApiObject]:
5353
return self._user_payment_service_provider
5454

5555
def __init__(self, token: SessionToken, expiry_time: datetime.datetime, user: BunqModel) -> None:
@@ -63,28 +63,28 @@ def __init__(self, token: SessionToken, expiry_time: datetime.datetime, user: Bu
6363
self.__set_user(user)
6464

6565
def __get_user_id(self, user: BunqModel) -> int:
66-
if isinstance(user, UserPerson):
66+
if isinstance(user, UserPersonApiObject):
6767
return user.id_
6868

69-
if isinstance(user, UserCompany):
69+
if isinstance(user, UserCompanyApiObject):
7070
return user.id_
7171

72-
if isinstance(user, UserApiKey):
72+
if isinstance(user, UserApiKeyApiObject):
7373
return user.id_
7474

75-
if isinstance(user, UserPaymentServiceProvider):
75+
if isinstance(user, UserPaymentServiceProviderApiObject):
7676
return user.id_
7777

7878
raise BunqException(self._ERROR_UNEXPECTED_USER_INSTANCE)
7979

8080
def __set_user(self, user: BunqModel):
81-
if isinstance(user, UserPerson):
81+
if isinstance(user, UserPersonApiObject):
8282
self._user_person = user
83-
elif isinstance(user, UserCompany):
83+
elif isinstance(user, UserCompanyApiObject):
8484
self._user_company = user
85-
elif isinstance(user, UserApiKey):
85+
elif isinstance(user, UserApiKeyApiObject):
8686
self._user_api_key = user
87-
elif isinstance(user, UserPaymentServiceProvider):
87+
elif isinstance(user, UserPaymentServiceProviderApiObject):
8888
self._user_payment_service_provider = user
8989
else:
9090
raise BunqException(self._ERROR_UNEXPECTED_USER_INSTANCE)

bunq/sdk/context/user_context.py

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from bunq.sdk.exception.bunq_exception import BunqException
22
from bunq.sdk.model.core.bunq_model import BunqModel
3-
from bunq.sdk.model.generated.endpoint import UserPerson, UserCompany, UserApiKey, MonetaryAccountBank, User, \
4-
UserPaymentServiceProvider
3+
from bunq.sdk.model.generated.endpoint import UserPersonApiObject, UserCompanyApiObject, UserApiKeyApiObject, MonetaryAccountBankApiObject, UserApiObject, \
4+
UserPaymentServiceProviderApiObject
55

66

77
class UserContext:
@@ -21,19 +21,19 @@ def __init__(self, user_id: int, user: BunqModel) -> None:
2121

2222
@staticmethod
2323
def __get_user_object() -> BunqModel:
24-
return User.list().value[0].get_referenced_object()
24+
return UserApiObject.list().value[0].get_referenced_object()
2525

2626
def _set_user(self, user: BunqModel) -> None:
27-
if isinstance(user, UserPerson):
27+
if isinstance(user, UserPersonApiObject):
2828
self._user_person = user
2929

30-
elif isinstance(user, UserCompany):
30+
elif isinstance(user, UserCompanyApiObject):
3131
self._user_company = user
3232

33-
elif isinstance(user, UserApiKey):
33+
elif isinstance(user, UserApiKeyApiObject):
3434
self._user_api_key = user
3535

36-
elif isinstance(user, UserPaymentServiceProvider):
36+
elif isinstance(user, UserPaymentServiceProviderApiObject):
3737
self._user_payment_service_provider = user
3838

3939
else:
@@ -44,7 +44,7 @@ def init_main_monetary_account(self) -> None:
4444
if self._user_payment_service_provider is not None:
4545
return
4646

47-
all_monetary_account = MonetaryAccountBank.list().value
47+
all_monetary_account = MonetaryAccountBankApiObject.list().value
4848

4949
for account in all_monetary_account:
5050
if account.status == self._STATUS_ACTIVE:
@@ -87,17 +87,17 @@ def refresh_user_context(self) -> None:
8787
self.init_main_monetary_account()
8888

8989
@property
90-
def user_company(self) -> UserCompany:
90+
def user_company(self) -> UserCompanyApiObject:
9191
return self._user_company
9292

9393
@property
94-
def user_person(self) -> UserPerson:
94+
def user_person(self) -> UserPersonApiObject:
9595
return self._user_person
9696

9797
@property
98-
def user_api_key(self) -> UserApiKey:
98+
def user_api_key(self) -> UserApiKeyApiObject:
9999
return self._user_api_key
100100

101101
@property
102-
def primary_monetary_account(self) -> MonetaryAccountBank:
102+
def primary_monetary_account(self) -> MonetaryAccountBankApiObject:
103103
return self._primary_monetary_account

0 commit comments

Comments
 (0)