From ae27f6f0c969fe9915b78ad6e6e341acfc23aec3 Mon Sep 17 00:00:00 2001 From: Patrick Ruckstuhl Date: Wed, 10 Nov 2021 18:34:27 +0000 Subject: [PATCH] update for nordigen api v2 --- docs/importers.rst | 10 +- .../importers/nordigen/importer.py | 19 +++- .../importers/nordigen/nordigen_config.py | 93 +++++++++++-------- 3 files changed, 76 insertions(+), 46 deletions(-) diff --git a/docs/importers.rst b/docs/importers.rst index a80d97f..7d55311 100644 --- a/docs/importers.rst +++ b/docs/importers.rst @@ -106,9 +106,10 @@ all be listed in the end. .. code-block:: console - nordigen-conf list_banks --token YOURTOKEN --country DE - nordigen-conf create_link --token YOURTOKEN --bank REVOLUT_REVOGB21 - nordigen-conf list_accounts --token YOURTOKEN list_accounts + nordigen-conf list_banks --secret_id YOURSECRET_ID --secret_key YOURSECRET_KEY --country DE + nordigen-conf create_link --secret_id YOURSECRET_ID --secret_key YOURSECRET_KEY --bank REVOLUT_REVOGB21 --reference myref + nordigen-conf list_accounts --secret_id YOURSECRET_ID --secret_key YOURSECRET_KEY + nordigen-conf delete_link --secret_id YOURSECRET_ID --secret_key YOURSECRET_KEY --reference myref .. code-block:: python @@ -121,7 +122,8 @@ Create a file called nordigen.yaml in your import location (e.g. download folder .. code-block:: yaml - token: + secret_id: + secret_key: accounts: - id: diff --git a/src/tariochbctools/importers/nordigen/importer.py b/src/tariochbctools/importers/nordigen/importer.py index 2f8ec57..ed754a6 100644 --- a/src/tariochbctools/importers/nordigen/importer.py +++ b/src/tariochbctools/importers/nordigen/importer.py @@ -24,15 +24,28 @@ def file_account(self, file): def extract(self, file, existing_entries): with open(file.name, "r") as f: config = yaml.safe_load(f) - token = config["token"] - headers = {"Authorization": "Token " + token} + + r = requests.post( + "https://ob.nordigen.com/api/v2/token/new/", + data={ + "secret_id": config["secret_id"], + "secret_key": config["secret_key"], + }, + ) + try: + r.raise_for_status() + except requests.exceptions.HTTPError as e: + raise HttpServiceException(e, e.response.text) + + token = r.json()["access"] + headers = {"Authorization": "Bearer " + token} entries = [] for account in config["accounts"]: accountId = account["id"] assetAccount = account["asset_account"] r = requests.get( - f"https://ob.nordigen.com/api/accounts/{accountId}/transactions/", + f"https://ob.nordigen.com/api/v2/accounts/{accountId}/transactions/", headers=headers, ) try: diff --git a/src/tariochbctools/importers/nordigen/nordigen_config.py b/src/tariochbctools/importers/nordigen/nordigen_config.py index 027d9e2..da93398 100644 --- a/src/tariochbctools/importers/nordigen/nordigen_config.py +++ b/src/tariochbctools/importers/nordigen/nordigen_config.py @@ -5,7 +5,7 @@ def build_header(token): - return {"Authorization": "Token " + token} + return {"Authorization": "Bearer " + token} def check_result(result): @@ -15,9 +15,22 @@ def check_result(result): raise Exception(e, e.response.text) +def get_token(secret_id, secret_key): + r = requests.post( + "https://ob.nordigen.com/api/v2/token/new/", + data={ + "secret_id": secret_id, + "secret_key": secret_key, + }, + ) + check_result(r) + + return r.json()["access"] + + def list_bank(token, country): r = requests.get( - "https://ob.nordigen.com/api/aspsps/", + "https://ob.nordigen.com/api/v2/institutions/", params={"country": country}, headers=build_header(token), ) @@ -27,51 +40,46 @@ def list_bank(token, country): print(asp["name"] + ": " + asp["id"]) -def create_link(token, userId, bank): +def create_link(token, reference, bank): if not bank: raise Exception("Please specify --bank it is required for create_link") - headers = build_header(token) - requisitionId = _find_requisition_id(token, userId) - if not requisitionId: + requisitionId = _find_requisition_id(token, reference) + if requisitionId: + print(f"Link for for reference {reference} already exists.") + else: r = requests.post( - "https://ob.nordigen.com/api/requisitions/", + "https://ob.nordigen.com/api/v2/requisitions/", data={ "redirect": "http://localhost", - "enduser_id": userId, - "reference": userId, + "institution_id": bank, + "reference": reference, }, headers=build_header(token), ) check_result(r) - requisitionId = r.json()["id"] - - r = requests.post( - f"https://ob.nordigen.com/api/requisitions/{requisitionId}/links/", - data={"aspsp_id": bank}, - headers=headers, - ) - check_result(r) - link = r.json()["initiate"] - print(f"Go to {link} for connecting to your bank.") + link = r.json()["link"] + print(f"Go to {link} for connecting to your bank.") def list_accounts(token): headers = build_header(token) - r = requests.get("https://ob.nordigen.com/api/requisitions/", headers=headers) + r = requests.get("https://ob.nordigen.com/api/v2/requisitions/", headers=headers) + print(r.json()) check_result(r) for req in r.json()["results"]: - print(req["enduser_id"] + ": " + req["id"]) + reference = req["reference"] + print(f"Reference: {reference}") for account in req["accounts"]: ra = requests.get( - f"https://ob.nordigen.com/api/accounts/{account}", headers=headers + f"https://ob.nordigen.com/api/v2/accounts/{account}", headers=headers ) check_result(ra) acc = ra.json() - asp = acc["aspsp_identifier"] + asp = acc["institution_id"] iban = acc["iban"] ra = requests.get( - f"https://ob.nordigen.com/api/accounts/{account}/details", + f"https://ob.nordigen.com/api/v2/accounts/{account}/details", headers=headers, ) check_result(ra) @@ -82,11 +90,11 @@ def list_accounts(token): print(f"{account}: {asp} {owner} {iban} {currency}") -def delete_user(token, userId): - requisitionId = _find_requisition_id(token, userId) +def delete_link(token, reference): + requisitionId = _find_requisition_id(token, reference) if requisitionId: r = requests.delete( - f"https://ob.nordigen.com/api/requisitions/{requisitionId}", + f"https://ob.nordigen.com/api/v2/requisitions/{requisitionId}", headers=build_header(token), ) check_result(r) @@ -94,10 +102,10 @@ def delete_user(token, userId): def _find_requisition_id(token, userId): headers = build_header(token) - r = requests.get("https://ob.nordigen.com/api/requisitions/", headers=headers) + r = requests.get("https://ob.nordigen.com/api/v2/requisitions/", headers=headers) check_result(r) for req in r.json()["results"]: - if req["enduser_id"] == userId: + if req["reference"] == userId: return req["id"] return None @@ -106,9 +114,14 @@ def _find_requisition_id(token, userId): def parse_args(args): parser = argparse.ArgumentParser(description="nordigen-config") parser.add_argument( - "--token", + "--secret_id", required=True, - help="API Token, can be generated on Nordigen website", + help="API secret id, can be generated on Nordigen website", + ) + parser.add_argument( + "--secret_key", + required=True, + help="API secret key, can be generated on Nordigen website", ) parser.add_argument( "--country", @@ -116,9 +129,9 @@ def parse_args(args): help="Country Code for list_bank", ) parser.add_argument( - "--userId", + "--reference", default="beancount", - help="UserId for create_link and delete_user", + help="reference for add_bank and delete_bank, needs to be unique", ) parser.add_argument( "--bank", @@ -130,7 +143,7 @@ def parse_args(args): "list_banks", "create_link", "list_accounts", - "delete_user", + "delete_link", ], ) return parser.parse_args(args) @@ -139,14 +152,16 @@ def parse_args(args): def main(args): args = parse_args(args) + token = get_token(args.secret_id, args.secret_key) + if args.mode == "list_banks": - list_bank(args.token, args.country) + list_bank(token, args.country) elif args.mode == "create_link": - create_link(args.token, args.userId, args.bank) + create_link(token, args.reference, args.bank) elif args.mode == "list_accounts": - list_accounts(args.token) - elif args.mode == "delete_user": - delete_user(args.token, args.userId) + list_accounts(token) + elif args.mode == "delete_link": + delete_link(token, args.reference) def run():