From 5b6c7bde1d8ea6a4b29ac1803dc65ab9df0b610c Mon Sep 17 00:00:00 2001 From: DJ Gillespie Date: Wed, 27 Sep 2023 21:54:33 -0600 Subject: [PATCH] added plaid_v2 client, started progress to migrate to LinkTokens from AuthTokens --- connection/connections/plaid_client_v2.py | 115 ++++++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100755 connection/connections/plaid_client_v2.py diff --git a/connection/connections/plaid_client_v2.py b/connection/connections/plaid_client_v2.py new file mode 100755 index 0000000..f692c39 --- /dev/null +++ b/connection/connections/plaid_client_v2.py @@ -0,0 +1,115 @@ +from .abstract import AbstractConnectionClient +from django.conf import settings +import os +import datetime + +from plaid.model.link_token_create_request import LinkTokenCreateRequest +from plaid.model.link_token_create_request_user import LinkTokenCreateRequestUser +from plaid.model.products import Products +from plaid.model.country_code import CountryCode + + +def format_error(e): + return { + 'error': { + 'display_message': e.display_message, + 'error_code': e.code, + 'error_type': e.type, + 'error_message': e.message}} + + +class Connection(AbstractConnectionClient): + + def __init__(self, credentials): + self.credentials = credentials.dict() + + # Fill in your Plaid API keys - + # https://dashboard.plaid.com/account/keys + self.PLAID_CLIENT_ID = settings.PLAID_CLIENT_ID + self.PLAID_SECRET = settings.PLAID_SECRET + self.PLAID_PUBLIC_KEY = settings.PLAID_PUBLIC_KEY + # Use 'sandbox' to test with Plaid's Sandbox environment (username: user_good, + # password: pass_good) + # Use `development` to test with live users and credentials and `production` + # to go live + self.PLAID_ENV = settings.PLAID_ENV + # PLAID_PRODUCTS is a comma-separated list of products to use when initializing + # Link. Note that this list must contain 'assets' in order for the app to be + # able to create and retrieve asset reports. + self.PLAID_PRODUCTS = settings.PLAID_PRODUCTS + + # PLAID_COUNTRY_CODES is a comma-separated list of countries for which users + # will be able to select institutions from. + self.PLAID_COUNTRY_CODES = settings.PLAID_COUNTRY_CODES + + client_user_id = user.id + # Create a link_token for the given user + request = LinkTokenCreateRequest( + products=[Products("auth")], + client_name="Qrtr Plaid", + country_codes=[CountryCode('US')], + redirect_uri='https://domainname.com/oauth-page.html', + language='en', + webhook='https://webhook.example.com', + user=LinkTokenCreateRequestUser( + client_user_id=client_user_id + ) + ) + response = client.link_token_create(request) + + self.credentials.update(response.to_dict()) + return self.credentials + + def get_auth_token(self, public_token): + try: + exchange_request = ItemPublicTokenExchangeRequest( + public_token=public_token + ) + exchange_response = self.client.item_public_token_exchange( + exchange_request) + except Exception as e: + print("Error Occurred") + print(e) + return format_error(e) + access_token = exchange_response['access_token'] + item_id = exchange_response['item_id'] + return {"access_token":access_token, "item_id":item_id} + + def get_accounts(self, auth_token=None): + if not auth_token: + auth_token = self.credentials.get('auth_token') + if not auth_token: + raise Exception("Missing Auth Token") + try: + acc_request = AccountsGetRequest(access_token=auth_token) + accounts = self.client.accounts_get(acc_request).to_dict() + except Exception as e: + print(e) + accounts = None + return accounts + + def get_transactions( + self, + start_date=None, + end_date=None, + auth_token=None): + if not auth_token: + auth_token = self.credentials.get('auth_token') + if not auth_token: + raise Exception("Missing Auth Token") + if not start_date: + start_date = '{:%Y-%m-%d}'.format( + datetime.datetime.now() + datetime.timedelta(-30)) + if not end_date: + end_date = '{:%Y-%m-%d}'.format(datetime.datetime.now()) + try: + transactions_req = TransactionsGetRequest( + access_token=auth_token, + start_date=start_date, + end_date=end_date + ) + transactions_resp = self.client.transactions_get( + transactions_req) + except plaid.errors.PlaidError as e: + return format_error(e) + return transactions_resp.get("transactions")