From 1d914fca6a7daaaf7466b6e9b3d9a0b62edd72ee Mon Sep 17 00:00:00 2001 From: Mike Ossig Date: Fri, 5 Apr 2024 11:45:14 -0400 Subject: [PATCH 1/4] removes duplicate method --- method/resources/Account.py | 6 ------ setup.py | 2 +- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/method/resources/Account.py b/method/resources/Account.py index 6acdf4e..9dcfb78 100644 --- a/method/resources/Account.py +++ b/method/resources/Account.py @@ -549,9 +549,3 @@ def get_payoff(self, _id: str, pyf_id: str) -> AccountPayoff: def create_payoff(self, _id: str) -> AccountPayoff: return super(AccountResource, self)._create_with_sub_path('{_id}/payoffs'.format(_id=_id), {}) - - def withdraw_consent(self, _id: str) -> Account: - return super(AccountResource, self)._create_with_sub_path( - '{_id}/consent'.format(_id=_id), - {'type': 'withdraw', 'reason': 'holder_withdrew_consent'} - ) diff --git a/setup.py b/setup.py index aee2d6e..a276f4b 100644 --- a/setup.py +++ b/setup.py @@ -2,7 +2,7 @@ setup( name='method-python', - version='0.0.43', + version='0.0.44', description='Python library for the Method API', long_description='Python library for the Method API', long_description_content_type='text/x-rst', From 80ba01382ebd2d4f4ae047b8c76432311849d661 Mon Sep 17 00:00:00 2001 From: Mike Ossig Date: Mon, 8 Apr 2024 10:48:50 -0400 Subject: [PATCH 2/4] rebase --- method/resources/{ => Account}/Account.py | 40 +-- method/resources/Account/ExternalTypes.py | 262 ++++++++++++++++++ method/resources/Account/Payoffs.py | 35 +++ .../{AccountSync.py => Account/Syncs.py} | 7 +- .../resources/Account/VerificationSessions.py | 161 +++++++++++ method/resources/Account/__init__.py | 4 + method/resources/Entity/Connect.py | 33 +++ method/resources/Entity/CreditScores.py | 47 ++++ method/resources/{ => Entity}/Entity.py | 79 ++---- method/resources/Entity/Identities.py | 34 +++ method/resources/Entity/Syncs.py | 36 +++ .../resources/Entity/VerificationSessions.py | 113 ++++++++ method/resources/Entity/__init__.py | 6 + method/resources/__init__.py | 7 +- 14 files changed, 772 insertions(+), 92 deletions(-) rename method/resources/{ => Account}/Account.py (93%) create mode 100644 method/resources/Account/ExternalTypes.py create mode 100644 method/resources/Account/Payoffs.py rename method/resources/{AccountSync.py => Account/Syncs.py} (81%) create mode 100644 method/resources/Account/VerificationSessions.py create mode 100644 method/resources/Account/__init__.py create mode 100644 method/resources/Entity/Connect.py create mode 100644 method/resources/Entity/CreditScores.py rename method/resources/{ => Entity}/Entity.py (81%) create mode 100644 method/resources/Entity/Identities.py create mode 100644 method/resources/Entity/Syncs.py create mode 100644 method/resources/Entity/VerificationSessions.py create mode 100644 method/resources/Entity/__init__.py diff --git a/method/resources/Account.py b/method/resources/Account/Account.py similarity index 93% rename from method/resources/Account.py rename to method/resources/Account/Account.py index 9dcfb78..b0b6b58 100644 --- a/method/resources/Account.py +++ b/method/resources/Account/Account.py @@ -4,7 +4,7 @@ from method.configuration import Configuration from method.errors import ResourceError from method.resources.Verification import VerificationResource -from method.resources.AccountSync import AccountSyncResource, AccountSync +from method.resources.Account import AccountSyncResource, AccountSync, AccountVerificationSessionResource, AccountPayoffsResource # Literals, keep ordered alphabetically @@ -127,12 +127,6 @@ 'over_120' ] -AccountPayoffStatusesLiterals = Literal[ - 'completed', - 'in_progress', - 'pending', - 'failed' -] class AccountACH(TypedDict): routing: int @@ -479,24 +473,19 @@ class AccountPaymentHistory(TypedDict): payment_history: List[CreditReportTradelinePaymentHistoryItem] -class AccountPayoff(TypedDict): - id: str - status: AccountPayoffStatusesLiterals - amount: Optional[int] - term: Optional[int] - per_diem_amount: Optional[int] - error: Optional[ResourceError] - created_at: str - updated_at: str - - class AccountSubResources: verification: VerificationResource - sync: AccountSyncResource + syncs: AccountSyncResource + payoffs: AccountPayoffsResource + verification_sessions: AccountVerificationSessionResource + def __init__(self, _id: str, config: Configuration): self.verification = VerificationResource(config.add_path(_id)) self.syncs = AccountSyncResource(config.add_path(_id)) + self.payoffs = AccountPayoffsResource(config.add_path(_id)) + self.verification_sessions = AccountVerificationSessionResource(config.add_path(_id)) + class AccountResource(Resource): def __init__(self, config: Configuration): @@ -505,7 +494,7 @@ def __init__(self, config: Configuration): def __call__(self, _id: str) -> AccountSubResources: return AccountSubResources(_id, self.config) - def get(self, _id: str) -> Account: + def retrieve(self, _id: str) -> Account: return super(AccountResource, self)._get_with_id(_id) def update(self, _id: str, opts: LiabilityUpdateOpts) -> Account: @@ -517,10 +506,10 @@ def list(self, params: Optional[AccountListOpts] = None) -> List[Account]: def create(self, opts: Union[AccountACHCreateOpts, AccountLiabilityCreateOpts, AccountClearingCreateOpts], request_opts: Optional[RequestOpts] = None) -> Account: return super(AccountResource, self)._create(opts, request_opts) - def get_payment_history(self, _id: str) -> AccountPaymentHistory: + def retrieve_payment_history(self, _id: str) -> AccountPaymentHistory: return super(AccountResource, self)._get_with_sub_path('{_id}/payment_history'.format(_id=_id)) - def get_details(self, _id: str) -> AccountDetail: + def retrieve_details(self, _id: str) -> AccountDetail: return super(AccountResource, self)._get_with_sub_path('{_id}/details'.format(_id=_id)) def bulk_sync(self, acc_ids: AccountCreateBulkSyncOpts) -> AccountCreateBulkSyncResponse: @@ -543,9 +532,4 @@ def unenroll_auto_syncs(self, _id: str) -> Account: def withdraw_consent(self, _id: str, data: AccountWithdrawConsentOpts = { 'type': 'withdraw', 'reason': 'holder_withdrew_consent' }) -> Account: return super(AccountResource, self)._create_with_sub_path('{_id}/consent'.format(_id=_id), data) - - def get_payoff(self, _id: str, pyf_id: str) -> AccountPayoff: - return super(AccountResource, self)._get_with_sub_path('{_id}/payoffs/{pyf_id}'.format(_id=_id, pyf_id=pyf_id)) - - def create_payoff(self, _id: str) -> AccountPayoff: - return super(AccountResource, self)._create_with_sub_path('{_id}/payoffs'.format(_id=_id), {}) + diff --git a/method/resources/Account/ExternalTypes.py b/method/resources/Account/ExternalTypes.py new file mode 100644 index 0000000..5ed9fbe --- /dev/null +++ b/method/resources/Account/ExternalTypes.py @@ -0,0 +1,262 @@ +from typing import TypedDict, Optional, List, Literal + + +PlaidTransactionTypesLiterals = Literal[ + 'digital', + 'place', + 'special', + 'unresolved' +] + + +PlaidTransactionPaymentChannelTypesLiterals = Literal[ + 'online', + 'in_store', + 'other' +] + + +PlaidTransactionCodeLiterals = Literal[ + 'adjustment', + 'atm', + 'bank charge', + 'bill payment', + 'cash', + 'cashback', + 'cheque', + 'direct debit', + 'interest', + 'purchase', + 'standing order', + 'transfer', + 'null' +] + + +PlaidCounterpartyTypeLiterals = Literal[ + 'merchant', + 'financial_institution', + 'payment_app', + 'marketplace', + 'payment_terminal', + 'income_source' +] + + +class PlaidBalance(TypedDict): + available: Optional[int] + current: Optional[int] + iso_currency_code: Optional[str] + limit: Optional[int] + unofficial_currency_code: Optional[str] + + +class PlaidLocation(TypedDict): + address: Optional[str] + city: Optional[str] + region: Optional[str] + postal_code: Optional[str] + country: Optional[str] + lat: Optional[int] + lon: Optional[int] + store_number: Optional[str] + + +class PlaidPaymentMeta(TypedDict): + reference_number: Optional[str] + ppd_id: Optional[str] + payee: Optional[str] + by_order_of: Optional[str] + payer: Optional[str] + payment_method: Optional[str] + payment_processor: Optional[str] + reason: Optional[str] + + +class PlaidPersonalFinanceCategory(TypedDict): + primary: str + detailed: str + confidence_level: Optional[str] + + +class PlaidTransactionCounterparty(TypedDict): + name: str + entity_id: Optional[str] + type: PlaidCounterpartyTypeLiterals; + website: Optional[str] + logo_url: Optional[str] + confidence_level: Optional[str] + + +class PlaidTransaction(TypedDict): + account_id: str + amount: int + iso_currency_code: Optional[str] + unofficial_currency_code: Optional[str] + category: Optional[List[str]] + category_id: Optional[str] + check_number: Optional[str] + date: str + location: PlaidLocation; + name: str + merchant_name: Optional[str] + original_description: Optional[str] + payment_meta: PlaidPaymentMeta; + pending: bool + pending_transaction_id: Optional[str] + account_owner: Optional[str] + transaction_id: str + transaction_type: Optional[PlaidTransactionTypesLiterals]; + logo_url: Optional[str] + website: Optional[str] + authorized_date: Optional[str] + authorized_datetime: Optional[str] + datetime: Optional[str] + payment_channel: PlaidTransactionPaymentChannelTypesLiterals + personal_finance_category: Optional[PlaidPersonalFinanceCategory] + transaction_code: Optional[PlaidTransactionCodeLiterals] + personal_finance_category_icon_url: str + counterparties: List[PlaidTransactionCounterparty] + merchant_entity_id: Optional[str] + + +class MXAccount(TypedDict): + account_number: str + account_ownership: str + annuity_policy_to_date: str + annuity_provider: str + annuity_term_year: int + apr: int + apy: int + available_balance: int + available_credit: int + balance: int + cash_balance: int + cash_surrender_value: int + created_at: str + credit_limit: int + currency_code: str + day_payment_is_due: int + death_benefit: int + guid: str + holdings_value: int + id: str + imported_at: str + interest_rate: int + institution_code: str + insured_name: str + is_closed: bool + is_hidden: bool + is_manual: bool + last_payment: int + last_payment_at: str + loan_amount: int + margin_balance: int + matures_on: str + member_guid: str + member_id: str + member_is_managed_by_user: bool + metadata: str + minimum_balance: int + minimum_payment: int + name: str + nickname: str + original_balance: int + pay_out_amount: int + payment_due_at: str + payoff_balance: int + premium_amount: int + property_type: str + routing_number: str + skip_webhook: bool + started_on: str + subtype: str + today_ugl_amount: int + today_ugl_percentage: int + total_account_value: int + type: str + updated_at: str + user_guid: str + user_id: str + + +class MXTransaction(TypedDict): + account_guid: str + account_id: str + amount: int + category: str + category_guid: str + check_number_string: str + created_at: str + currency_code: str + date: str + description: str + extended_transaction_type: str + guid: str + id: str + is_bill_pay: bool + is_direct_deposit: bool + is_expense: bool + is_fee: bool + is_income: bool + is_international: bool + is_overdraft_fee: bool + is_payroll_advance: bool + is_recurring: bool + is_subscription: bool + latitude: int + localized_description: str + localized_memo: str + longitude: int + member_guid: str + member_is_managed_by_user: bool + memo: str + merchant_category_code: int + merchant_guid: str + merchant_location_guid: str + metadata: str + original_description: str + posted_at: str + status: str + top_level_category: str + transacted_at: str + type: str + updated_at: str + user_guid: str + user_id: str + + +class TellerLinks(TypedDict): + account: str + self: str + + +class TellerBalance(TypedDict): + ledger: int + links: TellerLinks + account_id: str + available: int + + +class TellerTransactionCounterparty(TypedDict): + type: str + name: str + + +class TellerTransactionDetails(TypedDict): + category: str + counterparty: TellerTransactionCounterparty + processing_status: str + + +class TellerTransaction(TypedDict): + running_balance: Optional[int] + details: TellerTransactionDetails + description: str + account_id: str + date: str + id: str + links: TellerLinks + amount: int + type: str + status: str diff --git a/method/resources/Account/Payoffs.py b/method/resources/Account/Payoffs.py new file mode 100644 index 0000000..09a4a90 --- /dev/null +++ b/method/resources/Account/Payoffs.py @@ -0,0 +1,35 @@ +from typing import TypedDict, Optional, Literal + +from method.resource import Resource +from method.configuration import Configuration +from method.errors import ResourceError + + +AccountPayoffStatusesLiterals = Literal[ + 'completed', + 'in_progress', + 'pending', + 'failed' +] + + +class AccountPayoff(TypedDict): + id: str + status: AccountPayoffStatusesLiterals + amount: Optional[int] + term: Optional[int] + per_diem_amount: Optional[int] + error: Optional[ResourceError] + created_at: str + updated_at: str + + +class AccountPayoffsResource(Resource): + def __init__(self, config: Configuration): + super(AccountPayoffsResource, self).__init__(config.add_path('payoffs')) + + def retrieve(self, pyf_id: str) -> AccountPayoff: + return super(AccountPayoffsResource, self)._get_with_id(pyf_id) + + def create(self) -> AccountPayoff: + return super(AccountPayoffsResource, self)._create({}) \ No newline at end of file diff --git a/method/resources/AccountSync.py b/method/resources/Account/Syncs.py similarity index 81% rename from method/resources/AccountSync.py rename to method/resources/Account/Syncs.py index dba089e..f841230 100644 --- a/method/resources/AccountSync.py +++ b/method/resources/Account/Syncs.py @@ -1,9 +1,8 @@ from typing import TypedDict, Optional -from method.resource import Resource, RequestOpts +from method.resource import Resource from method.configuration import Configuration from method.errors import ResourceError -from method.resources.Verification import VerificationResource class AccountSync(TypedDict): @@ -14,14 +13,16 @@ class AccountSync(TypedDict): created_at: str updated_at: str + class AccountSyncCreateOpts(TypedDict): pass + class AccountSyncResource(Resource): def __init__(self, config: Configuration): super(AccountSyncResource, self).__init__(config.add_path('syncs')) - def get(self, _id: str) -> AccountSync: + def retrieve(self, _id: str) -> AccountSync: return super(AccountSyncResource, self)._get_with_id(_id) def create(self, opts: Optional[AccountSyncCreateOpts] = {}) -> AccountSync: diff --git a/method/resources/Account/VerificationSessions.py b/method/resources/Account/VerificationSessions.py new file mode 100644 index 0000000..b1455da --- /dev/null +++ b/method/resources/Account/VerificationSessions.py @@ -0,0 +1,161 @@ +from typing import TypedDict, Optional, List, Literal, Union + +from method.resource import Resource +from method.configuration import Configuration +from method.errors import ResourceError +from method.resources.Account.ExternalTypes import PlaidBalance, PlaidTransaction, MXAccount, MXTransaction, TellerBalance, TellerTransaction + + +AccountVerificationSessionStatusesLiterals = Literal[ + 'pending', + 'in_progress', + 'verified', + 'failed' +] + + +AccountVerificationSessionTypesLiterals = Literal[ + 'micro_deposits', + 'plaid', + 'mx', + 'teller', + 'standard', + 'instant', + 'pre_auth' +] + +AccountVerificationPassFailLiterals = Literal[ + 'pass', + 'fail' +] + + +class AccountVerificationSessionMicroDeposits(TypedDict): + amounts: List[int] + + +class AccountVerificationSessionPlaid(TypedDict): + balances: PlaidBalance + transactions: List[PlaidTransaction] + + +class AccountVerificationSessionMX(TypedDict): + accounts: MXAccount + transactions: List[MXTransaction] + + +class AccountVerificationSessionTeller(TypedDict): + balances: TellerBalance + transactions: List[TellerTransaction] + + +class AccountVerificationSessionTrustProvisioner(TypedDict): + pass + + +class AccountVerificationSessionAutoVerify(TypedDict): + pass + + +class AccountVerificationSessionThreeDS(TypedDict): + pass + + +class AccountVerificationSessionIssuer(TypedDict): + pass + + +class AccountVerificationSessionStandard(TypedDict): + number: str + + +class AccountVerificationSessionInstant(TypedDict): + exp_year: Optional[str] + exp_month: Optional[str] + exp_check: Optional[AccountVerificationPassFailLiterals] + number: Optional[str] + + +class AccountVerificationSessionPreAuth(AccountVerificationSessionInstant): + cvv: str + cvv_check: Optional[AccountVerificationPassFailLiterals] + billing_zip_code: str + billing_zip_code_check: Optional[AccountVerificationPassFailLiterals] + pre_auth_check: Optional[AccountVerificationPassFailLiterals] + + +class AccountVerificationSessionCreateOpts(TypedDict): + type: AccountVerificationSessionTypesLiterals + + +class AccountVerificationSessionMicroDepositsUpdateOpts(TypedDict): + micro_deposits: AccountVerificationSessionMicroDeposits + + +class AccountVerificationSessionPlaidUpdateOpts(TypedDict): + plaid: AccountVerificationSessionPlaid + + +class AccountVerificationSessionMXUpdateOpts(TypedDict): + mx: AccountVerificationSessionMX + + +class AccountVerificationSessionTellerUpdateOpts(TypedDict): + teller: AccountVerificationSessionTeller + + +class AccountVerificationSessionStandardUpdateOpts(TypedDict): + standard: AccountVerificationSessionStandard + + +class AccountVerificationSessionInstantUpdateOpts(TypedDict): + instant: AccountVerificationSessionInstant + + +class AccountVerificationSessionPreAuthUpdateOpts(TypedDict): + pre_auth: AccountVerificationSessionPreAuth + + +AccountVerificationSessionUpdateOpts = Union[ + AccountVerificationSessionMicroDepositsUpdateOpts, + AccountVerificationSessionPlaidUpdateOpts, + AccountVerificationSessionMXUpdateOpts, + AccountVerificationSessionTellerUpdateOpts, + AccountVerificationSessionStandardUpdateOpts, + AccountVerificationSessionInstantUpdateOpts, + AccountVerificationSessionPreAuthUpdateOpts +] + + +class AccountVerificationSession(TypedDict): + id: str + status: AccountVerificationSessionStatusesLiterals + type: AccountVerificationSessionTypesLiterals + error: Optional[ResourceError] + plaid: Optional[AccountVerificationSessionPlaid] + mx: Optional[AccountVerificationSessionMX] + teller: Optional[AccountVerificationSessionTeller] + micro_deposits: Optional[AccountVerificationSessionMicroDeposits] + trust_provisioner: Optional[AccountVerificationSessionTrustProvisioner] + auto_verify: Optional[AccountVerificationSessionAutoVerify] + standard: Optional[AccountVerificationSessionStandard] + instant: Optional[AccountVerificationSessionInstant] + pre_auth: Optional[AccountVerificationSessionPreAuth] + three_ds: Optional[AccountVerificationSessionThreeDS] + issuer: Optional[AccountVerificationSessionIssuer] + created_at: str + updated_at: str + + +class AccountVerificationSessionResource(Resource): + def __init__(self, config: Configuration): + super(AccountVerificationSessionResource, self).__init__(config.add_path('verification_sessions')) + + def create(self, opts: AccountVerificationSessionCreateOpts) -> AccountVerificationSession: + return super(AccountVerificationSessionResource, self)._create(opts) + + def retrieve(self, avs_id: str) -> AccountVerificationSession: + return super(AccountVerificationSessionResource, self)._get_with_id(avs_id) + + def update(self, avs_id: str, opts: AccountVerificationSessionUpdateOpts) -> AccountVerificationSession: + return super(AccountVerificationSessionResource, self)._update_with_id(avs_id, opts) \ No newline at end of file diff --git a/method/resources/Account/__init__.py b/method/resources/Account/__init__.py new file mode 100644 index 0000000..628149e --- /dev/null +++ b/method/resources/Account/__init__.py @@ -0,0 +1,4 @@ +from method.resources.Account.Account import Account, AccountResource +from method.resources.Account.Syncs import AccountSync, AccountSyncResource +from method.resources.Account.Payoffs import AccountPayoff, AccountPayoffsResource +from method.resources.Account.VerificationSessions import AccountVerificationSession, AccountVerificationSessionResource \ No newline at end of file diff --git a/method/resources/Entity/Connect.py b/method/resources/Entity/Connect.py new file mode 100644 index 0000000..f3ba10f --- /dev/null +++ b/method/resources/Entity/Connect.py @@ -0,0 +1,33 @@ +from typing import TypedDict, Optional, Literal, List + +from method.resource import Resource +from method.configuration import Configuration +from method.errors import ResourceError + + +EntityConnectResponseStatusLiterals = Literal[ + 'completed', + 'in_progress', + 'pending', + 'failed' +] + + +class EntityConnect(TypedDict): + id: str + status: EntityConnectResponseStatusLiterals + accounts: Optional[List[str]] + error: Optional[ResourceError] + created_at: str + updated_at: str + + +class EntityConnectResource(Resource): + def __init__(self, config: Configuration): + super(EntityConnectResource, self).__init__(config.add_path('connect')) + + def retrieve(self, cxn_id: str) -> EntityConnect: + return super(EntityConnectResource, self)._get_with_id(cxn_id) + + def create(self) -> EntityConnect: + return super(EntityConnectResource, self)._create({}) \ No newline at end of file diff --git a/method/resources/Entity/CreditScores.py b/method/resources/Entity/CreditScores.py new file mode 100644 index 0000000..2810843 --- /dev/null +++ b/method/resources/Entity/CreditScores.py @@ -0,0 +1,47 @@ +from typing import TypedDict, Optional, List, Literal + +from method.resource import Resource +from method.configuration import Configuration +from method.errors import ResourceError +from method.resources.Entity.Entity import EntityStatusesLiterals, CreditReportBureausLiterals + + +CreditScoresModelLiterals = Literal[ + 'vantage_4', + 'vantage_3' +] + + +class EntityCreditScoresFactorsType(TypedDict): + code: str + description: str + + +class EntityCreditScoresType(TypedDict): + score: int + source: CreditReportBureausLiterals + model: CreditScoresModelLiterals + factors: List[EntityCreditScoresFactorsType] + created_at: str + factors: EntityCreditScoresFactorsType + created_at: str + + +class EntityCreditScores(TypedDict): + id: str + status: EntityStatusesLiterals + credit_scores: Optional[List[EntityCreditScoresType]] + error: Optional[ResourceError] + created_at: str + updated_at: str + + +class EntityCreditScoresResource(Resource): + def __init__(self, config: Configuration): + super(EntityCreditScoresResource, self).__init__(config.add_path('credit_scores')) + + def retrieve_credit_scores(self, crs_id: str) -> EntityCreditScores: + return super(EntityCreditScoresResource, self)._get_with_id(crs_id) + + def create_credit_scores(self) -> EntityCreditScores: + return super(EntityCreditScoresResource, self)._create({}) \ No newline at end of file diff --git a/method/resources/Entity.py b/method/resources/Entity/Entity.py similarity index 81% rename from method/resources/Entity.py rename to method/resources/Entity/Entity.py index b55037c..3d6dfba 100644 --- a/method/resources/Entity.py +++ b/method/resources/Entity/Entity.py @@ -3,6 +3,7 @@ from method.resource import Resource, RequestOpts from method.configuration import Configuration from method.errors import ResourceError +from method.resources.Entity import EntityConnectResource, EntityCreditScoresResource, EntityIdentityResource, EntitySyncResource, EntityVerificationSessionResource EntityTypesLiterals = Literal[ @@ -55,12 +56,6 @@ ] -CreditScoresModelLiterals = Literal[ - 'vantage_4', - 'vantage_3' -] - - CreditReportBureausLiterals = Literal[ 'experian', 'equifax', @@ -186,47 +181,6 @@ class EntityCreditScoresFactorsType(TypedDict): description: str -class EntityCreditScoresType(TypedDict): - score: int - source: CreditReportBureausLiterals - model: CreditScoresModelLiterals - factors: List[EntityCreditScoresFactorsType] - created_at: str - factors: EntityCreditScoresFactorsType - created_at: str - - -class EntityCreditScoresResponse(TypedDict): - id: str - status: EntityStatusesLiterals - scores: Optional[List[EntityCreditScoresType]] - error: Optional[ResourceError] - created_at: str - updated_at: str - - -class EntityCreditScoresFactorsType(TypedDict): - code: str - description: str - - -class EntityCreditScoresType(TypedDict): - score: int - source: CreditReportBureausLiterals - model: str - factors: List[EntityCreditScoresFactorsType] - created_at: str - - -class EntityCreditScoresResponse(TypedDict): - id: str - status: EntityStatusesLiterals - credit_scores: Optional[List[EntityCreditScoresType]] - error: Optional[ResourceError] - created_at: str - updated_at: str - - class AnswerOpts(TypedDict): question_id: str answer_id: str @@ -305,17 +259,35 @@ class EntitySensitiveResponse(TypedDict): identities: List[EntityIdentity] +class EntitySubResources: + connect: EntityConnectResource + credit_scores: EntityCreditScoresResource + identities: EntityIdentityResource + syncs: EntitySyncResource + verification_sessions: EntityVerificationSessionResource + + def __init__(self, _id: str, config: Configuration): + self.connect = EntityConnectResource(config.add_path(_id)) + self.credit_scores = EntityCreditScoresResource(config.add_path(_id)) + self.identities = EntityIdentityResource(config.add_path(_id)) + self.syncs = EntitySyncResource(config.add_path(_id)) + self.verification_sessions = EntityVerificationSessionResource(config.add_path(_id)) + + class EntityResource(Resource): def __init__(self, config: Configuration): super(EntityResource, self).__init__(config.add_path('entities')) + def __call__(self, _id: str) -> EntitySubResources: + return EntitySubResources(_id, self.config) + def create(self, opts: EntityCreateOpts, request_opts: Optional[RequestOpts] = None) -> Entity: return super(EntityResource, self)._create(opts, request_opts) def update(self, _id: str, opts: EntityCreateOpts) -> Entity: return super(EntityResource, self)._update_with_id(_id, opts) - def get(self, _id: str) -> Entity: + def retrieve(self, _id: str) -> Entity: return super(EntityResource, self)._get_with_id(_id) def list(self, params: EntityListOpts = None) -> List[Entity]: @@ -324,15 +296,9 @@ def list(self, params: EntityListOpts = None) -> List[Entity]: def create_auth_session(self, _id: str) -> EntityQuestionResponse: return super(EntityResource, self)._create_with_sub_path('{_id}/auth_session'.format(_id=_id), {}) - def get_credit_score(self, _id: str) -> EntityQuestionResponse: + def retrieve_credit_score(self, _id: str) -> EntityQuestionResponse: return super(EntityResource, self)._get_with_sub_path('{_id}/credit_score'.format(_id=_id)) - def get_credit_scores(self, _id: str, crs_id: str) -> EntityCreditScoresResponse: - return super(EntityResource, self)._get_with_sub_path('{_id}/credit_scores/{crs_id}'.format(_id=_id, crs_id=crs_id)) - - def create_credit_scores(self, _id: str) -> EntityCreditScoresResponse: - return super(EntityResource, self)._create_with_sub_path('{_id}/credit_scores'.format(_id=_id), {}) - def update_auth_session(self, _id: str, opts: EntityUpdateAuthOpts) -> EntityUpdateAuthResponse: return super(EntityResource, self)._update_with_sub_path('{_id}/auth_session'.format(_id=_id), opts) @@ -345,9 +311,6 @@ def update_manual_auth_session(self, _id: str, opts: EntityManualAuthOpts) -> En def refresh_capabilities(self, _id: str) -> Entity: return super(EntityResource, self)._create_with_sub_path('{_id}/refresh_capabilities'.format(_id=_id), {}) - def get_credit_score(self, _id: str) -> EntityQuestionResponse: - return super(EntityResource, self)._get_with_sub_path('{_id}/credit_score'.format(_id=_id)) - def get_sensitive_fields(self, _id: str, fields: List[EntitySensitiveFieldsLiterals]) -> EntitySensitiveResponse: return super(EntityResource, self)._get_with_sub_path_and_params( '{_id}/sensitive'.format(_id=_id), diff --git a/method/resources/Entity/Identities.py b/method/resources/Entity/Identities.py new file mode 100644 index 0000000..f8344d1 --- /dev/null +++ b/method/resources/Entity/Identities.py @@ -0,0 +1,34 @@ +from typing import TypedDict, Optional, Literal, List + +from method.resource import Resource +from method.configuration import Configuration +from method.errors import ResourceError +from method.resources.Entity.Entity import EntityIdentity + + +EntityVerificationSessionStatusLiterals = Literal[ + 'completed', + 'in_progress', + 'pending', + 'failed' +] + + +class EntityIdentity(TypedDict): + id: str + status: EntityVerificationSessionStatusLiterals + identities: List[EntityIdentity] + error: Optional[ResourceError] + created_at: str + updated_at: str + + +class EntityIdentityResource(Resource): + def __init__(self, config: Configuration): + super(EntityIdentityResource, self).__init__(config.add_path('identities')) + + def retrieve(self, identity_id: str) -> EntityIdentity: + return super(EntityIdentityResource, self)._get_with_id(identity_id) + + def create(self, opts: Optional[EntityIdentity] = {}) -> EntityIdentity: + return super(EntityIdentityResource, self)._create(opts) \ No newline at end of file diff --git a/method/resources/Entity/Syncs.py b/method/resources/Entity/Syncs.py new file mode 100644 index 0000000..1f52818 --- /dev/null +++ b/method/resources/Entity/Syncs.py @@ -0,0 +1,36 @@ +from typing import TypedDict, Optional, Literal + +from method.resource import Resource +from method.configuration import Configuration +from method.errors import ResourceError + + +EntitySyncTypeLiterals = Literal[ + 'capabilities', + 'accounts' +] + + +class EntitySync(TypedDict): + id: str + acc_id: str + status: str + type: str + error: Optional[ResourceError] + created_at: str + updated_at: str + + +class EntitySyncCreateOpts(TypedDict): + type: EntitySyncTypeLiterals + + +class EntitySyncResource(Resource): + def __init__(self, config: Configuration): + super(EntitySyncResource, self).__init__(config.add_path('syncs')) + + def retrieve(self, acc_sync_id: str) -> EntitySync: + return super(EntitySyncResource, self)._get_with_id(acc_sync_id) + + def create(self, opts: Optional[EntitySyncCreateOpts] = {}) -> EntitySync: + return super(EntitySyncResource, self)._create(opts) diff --git a/method/resources/Entity/VerificationSessions.py b/method/resources/Entity/VerificationSessions.py new file mode 100644 index 0000000..3c8126a --- /dev/null +++ b/method/resources/Entity/VerificationSessions.py @@ -0,0 +1,113 @@ +from typing import TypedDict, Optional, List, Literal + +from method.resource import Resource +from method.configuration import Configuration +from method.errors import ResourceError + + +EntityVerificationSessionStatusLiterals = Literal[ + 'completed', + 'in_progress', + 'pending', + 'failed' +] + + +EntityVerificationSessionTypeLiterals = Literal[ + 'phone_method_sms', + 'phone_method_sna', + 'phone_byo_sms', + 'identity_byo_kyc', + 'identity_method_kba', + 'identity_method_auth_element' +] + + +EntityVerificationSessionCategoryLiterals = Literal[ + 'phone', + 'identity' +] + + +class EntityPhoneSmsVerification(TypedDict): + timestamp: str + + +class EntityPhoneSmsVerificationUpdate(TypedDict): + sms_code: str + + +class EntityPhoneSnaVerification(TypedDict): + urls: str + + +class EntityByoKycVerification(TypedDict): + authenticated: bool + + +class EntityKbaVerificationAnswer(TypedDict): + id: str + text: str + + +class EntityKbaVerificationAnswerUpdate(TypedDict): + question_id: str + answer_id: str + + +class EntityKbaVerificationQuestion(TypedDict): + selected_answer: Optional[str] + id: str + text: str + answers: List[EntityKbaVerificationAnswer] + + +class EntityKbaVerification(TypedDict): + questions: List[EntityKbaVerificationQuestion] + authenticated: bool + + +class EntityVerificationSessionCreateOpts(TypedDict): + type: EntityVerificationSessionTypeLiterals + phone_method_sms: Optional[object] + phone_method_sna: Optional[object] + phone_byo_sms: Optional[EntityPhoneSmsVerification] + identity_byo_kyc: Optional[object] + identity_method_kba: Optional[object] + + +class EntityVerificationSessionUpdateOpts(TypedDict): + type: EntityVerificationSessionTypeLiterals + phone_method_sms: Optional[EntityPhoneSmsVerificationUpdate] + phone_method_sma: Optional[object] + identity_method_kba: Optional[EntityKbaVerificationAnswerUpdate] + + +class EntityVerificationSession(TypedDict): + id: str + entity_id: str + status: EntityVerificationSessionStatusLiterals + type: EntityVerificationSessionTypeLiterals + category: EntityVerificationSessionCategoryLiterals + phone_method_sms: Optional[EntityPhoneSmsVerification] + phone_method_sna: Optional[EntityPhoneSnaVerification] + phone_byo_sms: Optional[EntityPhoneSmsVerification] + identity_byo_kyc: Optional[EntityByoKycVerification] + identity_method_kba: Optional[EntityKbaVerification] + error: Optional[ResourceError] + created_at: str + updated_at: str + + +class EntityVerificationSessionResource(Resource): + def __init__(self, config: Configuration): + super(EntityVerificationSessionResource, self).__init__(config.add_path('verification_sessions')) + + def retrieve(self, verification_session_id: str) -> EntityVerificationSession: + return super(EntityVerificationSessionResource, self)._get_with_id(verification_session_id) + + def create(self, opts: Optional[EntityVerificationSessionCreateOpts] = {}) -> EntityVerificationSession: + return super(EntityVerificationSessionResource, self)._create(opts) + + def update(self, verification_session_id: str, opts: EntityVerificationSessionUpdateOpts) -> EntityVerificationSession: + return super(EntityVerificationSessionResource, self)._update_with_id(verification_session_id, opts) diff --git a/method/resources/Entity/__init__.py b/method/resources/Entity/__init__.py new file mode 100644 index 0000000..1d08768 --- /dev/null +++ b/method/resources/Entity/__init__.py @@ -0,0 +1,6 @@ +from method.resources.Entity.Entity import Entity, EntityResource +from method.resources.Entity.Syncs import EntitySync, EntitySyncResource +from method.resources.Entity.CreditScores import EntityCreditScores, EntityCreditScoresResource +from method.resources.Entity.Identities import EntityIdentity, EntityIdentityResource +from method.resources.Entity.Connect import EntityConnect, EntityConnectResource +from method.resources.Entity.VerificationSessions import EntityVerificationSession, EntityVerificationSessionResource \ No newline at end of file diff --git a/method/resources/__init__.py b/method/resources/__init__.py index 01ae365..8e6a6a4 100644 --- a/method/resources/__init__.py +++ b/method/resources/__init__.py @@ -1,9 +1,10 @@ # type: ignore -from method.resources.Account import Account, AccountResource -from method.resources.AccountSync import AccountSyncResource +from method.resources.Account import Account, AccountResource, AccountPayoffsResource, \ + AccountSyncResource, AccountVerificationSessionResource from method.resources.Bin import Bin, BinResource from method.resources.Element import Element, ElementResource -from method.resources.Entity import Entity, EntityResource +from method.resources.Entity import Entity, EntityResource, EntityConnectResource, \ + EntityCreditScoresResource, EntityIdentityResource, EntitySyncResource, EntityVerificationSessionResource from method.resources.Merchant import Merchant, MerchantResource from method.resources.Payment import Payment, PaymentResource from method.resources.Report import Report, ReportResource From 4592b5177f150f54487b38af8d6027d5f1157e9a Mon Sep 17 00:00:00 2001 From: Mike Ossig Date: Mon, 8 Apr 2024 10:39:51 -0400 Subject: [PATCH 3/4] changed all gets to retrieve --- method/resources/Bin.py | 2 +- method/resources/Element.py | 2 +- method/resources/Entity/Entity.py | 2 +- method/resources/HealthCheck.py | 2 +- method/resources/Merchant.py | 2 +- method/resources/Payment.py | 2 +- method/resources/Report.py | 2 +- method/resources/Reversal.py | 2 +- method/resources/RoutingNumber.py | 2 +- method/resources/Transaction.py | 2 +- method/resources/Verification.py | 4 ++-- method/resources/Webhook.py | 2 +- 12 files changed, 13 insertions(+), 13 deletions(-) diff --git a/method/resources/Bin.py b/method/resources/Bin.py index 9bf7ce3..2a51794 100644 --- a/method/resources/Bin.py +++ b/method/resources/Bin.py @@ -33,5 +33,5 @@ class BinResource(Resource): def __init__(self, config: Configuration): super(BinResource, self).__init__(config.add_path('bins')) - def get(self, _id: str) -> Bin: + def retrieve(self, _id: str) -> Bin: return super(BinResource, self)._get_with_params({'bin': _id}) diff --git a/method/resources/Element.py b/method/resources/Element.py index 958a756..c2c0880 100644 --- a/method/resources/Element.py +++ b/method/resources/Element.py @@ -90,7 +90,7 @@ def __init__(self, config: Configuration): def create_token(self, opts: ElementTokenCreateOpts) -> Element: return super(ElementResource, self)._create_with_sub_path('token', opts) - def get_session_results(self, _id: str) -> TokenSessionResult: + def retrieve_session_results(self, _id: str) -> TokenSessionResult: return super(ElementResource, self)._get_with_sub_path('token/{_id}/results'.format(_id=_id)) def exchange_public_account_token(self, opts: ElementExchangePublicAccountOpts) -> Account: diff --git a/method/resources/Entity/Entity.py b/method/resources/Entity/Entity.py index 3d6dfba..8de94e4 100644 --- a/method/resources/Entity/Entity.py +++ b/method/resources/Entity/Entity.py @@ -311,7 +311,7 @@ def update_manual_auth_session(self, _id: str, opts: EntityManualAuthOpts) -> En def refresh_capabilities(self, _id: str) -> Entity: return super(EntityResource, self)._create_with_sub_path('{_id}/refresh_capabilities'.format(_id=_id), {}) - def get_sensitive_fields(self, _id: str, fields: List[EntitySensitiveFieldsLiterals]) -> EntitySensitiveResponse: + def retrieve_sensitive_fields(self, _id: str, fields: List[EntitySensitiveFieldsLiterals]) -> EntitySensitiveResponse: return super(EntityResource, self)._get_with_sub_path_and_params( '{_id}/sensitive'.format(_id=_id), {'fields[]': fields}, diff --git a/method/resources/HealthCheck.py b/method/resources/HealthCheck.py index 1388410..d670cd0 100644 --- a/method/resources/HealthCheck.py +++ b/method/resources/HealthCheck.py @@ -14,5 +14,5 @@ class HealthCheckResource(Resource): def __init__(self, config: Configuration): super(HealthCheckResource, self).__init__(config.add_path('ping')) - def get(self) -> PingResponse: + def retrieve(self) -> PingResponse: return super(HealthCheckResource, self)._get_raw() diff --git a/method/resources/Merchant.py b/method/resources/Merchant.py index 2fbea0e..c3ec20b 100644 --- a/method/resources/Merchant.py +++ b/method/resources/Merchant.py @@ -60,7 +60,7 @@ class MerchantResource(Resource): def __init__(self, config: Configuration): super(MerchantResource, self).__init__(config.add_path('merchants')) - def get(self, _id: str) -> Merchant: + def retrieve(self, _id: str) -> Merchant: return super(MerchantResource, self)._get_with_id(_id) def list(self, opts: Optional[MerchantListOpts] = None) -> List[Merchant]: diff --git a/method/resources/Payment.py b/method/resources/Payment.py index 404735a..e526b30 100644 --- a/method/resources/Payment.py +++ b/method/resources/Payment.py @@ -111,7 +111,7 @@ def __init__(self, config: Configuration): def __call__(self, _id: str) -> PaymentSubResources: return PaymentSubResources(_id, self.config) - def get(self, _id: str) -> Payment: + def retrieve(self, _id: str) -> Payment: return super(PaymentResource, self)._get_with_id(_id) def list(self, params: Optional[PaymentListOpts] = None) -> List[Payment]: diff --git a/method/resources/Report.py b/method/resources/Report.py index cae5593..7d7231d 100644 --- a/method/resources/Report.py +++ b/method/resources/Report.py @@ -44,7 +44,7 @@ class ReportResource(Resource): def __init__(self, config: Configuration): super(ReportResource, self).__init__(config.add_path('reports')) - def get(self, _id: str) -> Report: + def retrieve(self, _id: str) -> Report: return super(ReportResource, self)._get_with_id(_id) def create(self, opts: ReportCreateOpts, request_opts: Optional[RequestOpts] = None) -> Report: diff --git a/method/resources/Reversal.py b/method/resources/Reversal.py index ae4deff..e35f930 100644 --- a/method/resources/Reversal.py +++ b/method/resources/Reversal.py @@ -43,7 +43,7 @@ class ReversalResource(Resource): def __init__(self, config: Configuration): super(ReversalResource, self).__init__(config.add_path('reversals')) - def get(self, _id: str) -> Reversal: + def retrieve(self, _id: str) -> Reversal: return super(ReversalResource, self)._get_with_id(_id) def update(self, _id: str, opts: ReversalUpdateOpts) -> Reversal: diff --git a/method/resources/RoutingNumber.py b/method/resources/RoutingNumber.py index 220f65b..29fdbd1 100644 --- a/method/resources/RoutingNumber.py +++ b/method/resources/RoutingNumber.py @@ -33,5 +33,5 @@ class RoutingNumberResource(Resource): def __init__(self, config: Configuration): super(RoutingNumberResource, self).__init__(config.add_path('routing_numbers')) - def get(self, routing_number: str) -> RoutingNumber: + def retrieve(self, routing_number: str) -> RoutingNumber: return super(RoutingNumberResource, self)._get_with_params({'routing_number': routing_number}) diff --git a/method/resources/Transaction.py b/method/resources/Transaction.py index 4c52c10..98f82ae 100644 --- a/method/resources/Transaction.py +++ b/method/resources/Transaction.py @@ -26,5 +26,5 @@ def __init__(self, config: Configuration): def list(self) -> List[Transaction]: return super(TransactionResource, self)._list(None) - def get(self, _id: str) -> Transaction: + def retrieve(self, _id: str) -> Transaction: return super(TransactionResource, self)._get_with_id(_id) diff --git a/method/resources/Verification.py b/method/resources/Verification.py index c5083ab..a471406 100644 --- a/method/resources/Verification.py +++ b/method/resources/Verification.py @@ -73,7 +73,7 @@ class VerificationResource(Resource): def __init__(self, config: Configuration): super(VerificationResource, self).__init__(config.add_path('verification')) - def get(self) -> Verification: + def retrieve(self) -> Verification: return super(VerificationResource, self)._get() def update(self, opts: VerificationUpdateOpts) -> Verification: @@ -82,5 +82,5 @@ def update(self, opts: VerificationUpdateOpts) -> Verification: def create(self, opts: VerificationCreateOpts) -> Verification: return super(VerificationResource, self)._create(opts) - def get_test_amounts(self) -> VerificationTestAmountsResponse: + def retrieve_test_amounts(self) -> VerificationTestAmountsResponse: return super(VerificationResource, self)._get_with_sub_path('amounts') diff --git a/method/resources/Webhook.py b/method/resources/Webhook.py index ecd2740..642f0d9 100644 --- a/method/resources/Webhook.py +++ b/method/resources/Webhook.py @@ -50,7 +50,7 @@ class WebhookResource(Resource): def __init__(self, config: Configuration): super(WebhookResource, self).__init__(config.add_path('webhooks')) - def get(self, _id: str) -> Webhook: + def retrieve(self, _id: str) -> Webhook: return super(WebhookResource, self)._get_with_id(_id) def delete(self, _id: str) -> Webhook: From 5e712c7fcc8d1259e4217897e450e880ace1bd2d Mon Sep 17 00:00:00 2001 From: Michael Ossig Date: Tue, 9 Apr 2024 14:23:36 -0400 Subject: [PATCH 4/4] adds Balances to Account --- method/resources/Account/Account.py | 5 ++++- method/resources/Account/Balances.py | 30 ++++++++++++++++++++++++++++ method/resources/Account/__init__.py | 3 ++- 3 files changed, 36 insertions(+), 2 deletions(-) create mode 100644 method/resources/Account/Balances.py diff --git a/method/resources/Account/Account.py b/method/resources/Account/Account.py index b0b6b58..821dbe4 100644 --- a/method/resources/Account/Account.py +++ b/method/resources/Account/Account.py @@ -4,7 +4,8 @@ from method.configuration import Configuration from method.errors import ResourceError from method.resources.Verification import VerificationResource -from method.resources.Account import AccountSyncResource, AccountSync, AccountVerificationSessionResource, AccountPayoffsResource +from method.resources.Account import AccountSyncResource, AccountSync, \ + AccountVerificationSessionResource, AccountPayoffsResource, AccountBalancesResource # Literals, keep ordered alphabetically @@ -478,6 +479,7 @@ class AccountSubResources: syncs: AccountSyncResource payoffs: AccountPayoffsResource verification_sessions: AccountVerificationSessionResource + balances: AccountBalancesResource def __init__(self, _id: str, config: Configuration): @@ -485,6 +487,7 @@ def __init__(self, _id: str, config: Configuration): self.syncs = AccountSyncResource(config.add_path(_id)) self.payoffs = AccountPayoffsResource(config.add_path(_id)) self.verification_sessions = AccountVerificationSessionResource(config.add_path(_id)) + self.balances = AccountBalancesResource(config.add_path(_id)) class AccountResource(Resource): diff --git a/method/resources/Account/Balances.py b/method/resources/Account/Balances.py new file mode 100644 index 0000000..0ba7d69 --- /dev/null +++ b/method/resources/Account/Balances.py @@ -0,0 +1,30 @@ +from typing import TypedDict, Optional, Literal + +from method.resource import Resource +from method.configuration import Configuration +from method.errors import ResourceError + +AccountBalanceStatusLiterals = Literal[ + 'completed', + 'in_progress', + 'pending', + 'failed' +] + +class AccountBalances(TypedDict): + id: str + status: AccountBalanceStatusLiterals + balance: Optional[int] + error: Optional[ResourceError] + created_at: str + updated_at: str + +class AccountBalancesResource(Resource): + def __init__(self, config: Configuration): + super(AccountBalancesResource, self).__init__(config.add_path('balances')) + + def retrieve(self, bal_id: str) -> AccountBalances: + return super(AccountBalancesResource, self)._get_with_id(bal_id) + + def create(self) -> AccountBalances: + return super(AccountBalancesResource, self)._create({}) \ No newline at end of file diff --git a/method/resources/Account/__init__.py b/method/resources/Account/__init__.py index 628149e..03c0864 100644 --- a/method/resources/Account/__init__.py +++ b/method/resources/Account/__init__.py @@ -1,4 +1,5 @@ from method.resources.Account.Account import Account, AccountResource from method.resources.Account.Syncs import AccountSync, AccountSyncResource from method.resources.Account.Payoffs import AccountPayoff, AccountPayoffsResource -from method.resources.Account.VerificationSessions import AccountVerificationSession, AccountVerificationSessionResource \ No newline at end of file +from method.resources.Account.VerificationSessions import AccountVerificationSession, AccountVerificationSessionResource +from method.resources.Account.Balances import AccountBalance, AccountBalancesResource \ No newline at end of file