Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 25043a3

Browse files
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)

AltStyle によって変換されたページ (->オリジナル) /