feat: Airwallex 发卡管理后台完整实现
- 后端: FastAPI + SQLAlchemy + SQLite, JWT认证, 代理支持的AirwallexClient - 前端: React 18 + Vite + Ant Design 5, 中文界面 - 功能: 卡片管理, 持卡人管理, 交易记录, API令牌, 系统设置, 审计日志 - 第三方API: X-API-Key认证, 权限控制 - Docker部署: docker-compose编排前后端
This commit is contained in:
469
airwallex-sdk/airwallex/api/account_detail.py
Normal file
469
airwallex-sdk/airwallex/api/account_detail.py
Normal file
@@ -0,0 +1,469 @@
|
||||
"""
|
||||
Airwallex Account Detail API.
|
||||
"""
|
||||
from typing import Dict, Any, List, Optional, Type, TypeVar, Union, cast
|
||||
from datetime import datetime
|
||||
from ..models.account_detail import (
|
||||
AccountDetailModel, AccountCreateRequest, AccountUpdateRequest,
|
||||
Amendment, AmendmentCreateRequest, WalletInfo, TermsAndConditionsRequest
|
||||
)
|
||||
from .base import AirwallexAPIBase
|
||||
|
||||
T = TypeVar("T", bound=AccountDetailModel)
|
||||
|
||||
|
||||
class AccountDetail(AirwallexAPIBase[AccountDetailModel]):
|
||||
"""
|
||||
Operations for Airwallex account details.
|
||||
|
||||
Account details represent the complete information about an Airwallex account,
|
||||
including business details, persons, and compliance information.
|
||||
"""
|
||||
endpoint = "accounts"
|
||||
model_class = cast(Type[AccountDetailModel], AccountDetailModel)
|
||||
|
||||
def get_my_account(self) -> AccountDetailModel:
|
||||
"""
|
||||
Retrieve account details for your own Airwallex account.
|
||||
|
||||
Returns:
|
||||
AccountDetailModel: Your account details.
|
||||
"""
|
||||
url = "/api/v1/account"
|
||||
|
||||
if not self.client.__class__.__name__.startswith('Async'):
|
||||
response = self.client._request("GET", url)
|
||||
return self.model_class.from_api_response(response.json())
|
||||
else:
|
||||
raise ValueError("Use get_my_account_async for async clients")
|
||||
|
||||
async def get_my_account_async(self) -> AccountDetailModel:
|
||||
"""
|
||||
Retrieve account details for your own Airwallex account asynchronously.
|
||||
|
||||
Returns:
|
||||
AccountDetailModel: Your account details.
|
||||
"""
|
||||
url = "/api/v1/account"
|
||||
|
||||
if self.client.__class__.__name__.startswith('Async'):
|
||||
response = await self.client._request("GET", url)
|
||||
return self.model_class.from_api_response(response.json())
|
||||
else:
|
||||
raise ValueError("Use get_my_account for sync clients")
|
||||
|
||||
def get_amendment(self, amendment_id: str) -> Amendment:
|
||||
"""
|
||||
Get an account amendment.
|
||||
|
||||
Args:
|
||||
amendment_id: The ID of the amendment to retrieve.
|
||||
|
||||
Returns:
|
||||
Amendment: The amendment.
|
||||
"""
|
||||
url = f"/api/v1/account/amendments/{amendment_id}"
|
||||
|
||||
if not self.client.__class__.__name__.startswith('Async'):
|
||||
response = self.client._request("GET", url)
|
||||
return Amendment.from_api_response(response.json())
|
||||
else:
|
||||
raise ValueError("Use get_amendment_async for async clients")
|
||||
|
||||
async def get_amendment_async(self, amendment_id: str) -> Amendment:
|
||||
"""
|
||||
Get an account amendment asynchronously.
|
||||
|
||||
Args:
|
||||
amendment_id: The ID of the amendment to retrieve.
|
||||
|
||||
Returns:
|
||||
Amendment: The amendment.
|
||||
"""
|
||||
url = f"/api/v1/account/amendments/{amendment_id}"
|
||||
|
||||
if self.client.__class__.__name__.startswith('Async'):
|
||||
response = await self.client._request("GET", url)
|
||||
return Amendment.from_api_response(response.json())
|
||||
else:
|
||||
raise ValueError("Use get_amendment for sync clients")
|
||||
|
||||
def create_amendment(self, amendment: AmendmentCreateRequest) -> Amendment:
|
||||
"""
|
||||
Create an account amendment.
|
||||
|
||||
Args:
|
||||
amendment: AmendmentCreateRequest model with amendment details.
|
||||
|
||||
Returns:
|
||||
Amendment: The created amendment.
|
||||
"""
|
||||
url = "/api/v1/account/amendments/create"
|
||||
|
||||
if not self.client.__class__.__name__.startswith('Async'):
|
||||
response = self.client._request("POST", url, json=amendment.to_api_dict())
|
||||
return Amendment.from_api_response(response.json())
|
||||
else:
|
||||
raise ValueError("Use create_amendment_async for async clients")
|
||||
|
||||
async def create_amendment_async(self, amendment: AmendmentCreateRequest) -> Amendment:
|
||||
"""
|
||||
Create an account amendment asynchronously.
|
||||
|
||||
Args:
|
||||
amendment: AmendmentCreateRequest model with amendment details.
|
||||
|
||||
Returns:
|
||||
Amendment: The created amendment.
|
||||
"""
|
||||
url = "/api/v1/account/amendments/create"
|
||||
|
||||
if self.client.__class__.__name__.startswith('Async'):
|
||||
response = await self.client._request("POST", url, json=amendment.to_api_dict())
|
||||
return Amendment.from_api_response(response.json())
|
||||
else:
|
||||
raise ValueError("Use create_amendment for sync clients")
|
||||
|
||||
def get_wallet_info(self) -> WalletInfo:
|
||||
"""
|
||||
Retrieve account wallet information.
|
||||
|
||||
Returns:
|
||||
WalletInfo: The wallet information.
|
||||
"""
|
||||
url = "/api/v1/account/wallet_info"
|
||||
|
||||
if not self.client.__class__.__name__.startswith('Async'):
|
||||
response = self.client._request("GET", url)
|
||||
return WalletInfo.from_api_response(response.json())
|
||||
else:
|
||||
raise ValueError("Use get_wallet_info_async for async clients")
|
||||
|
||||
async def get_wallet_info_async(self) -> WalletInfo:
|
||||
"""
|
||||
Retrieve account wallet information asynchronously.
|
||||
|
||||
Returns:
|
||||
WalletInfo: The wallet information.
|
||||
"""
|
||||
url = "/api/v1/account/wallet_info"
|
||||
|
||||
if self.client.__class__.__name__.startswith('Async'):
|
||||
response = await self.client._request("GET", url)
|
||||
return WalletInfo.from_api_response(response.json())
|
||||
else:
|
||||
raise ValueError("Use get_wallet_info for sync clients")
|
||||
|
||||
def create_account(self, account: AccountCreateRequest) -> AccountDetailModel:
|
||||
"""
|
||||
Create a new Airwallex account.
|
||||
|
||||
Args:
|
||||
account: AccountCreateRequest model with account creation details.
|
||||
|
||||
Returns:
|
||||
AccountDetailModel: The created account.
|
||||
"""
|
||||
url = "/api/v1/accounts/create"
|
||||
|
||||
if not self.client.__class__.__name__.startswith('Async'):
|
||||
response = self.client._request("POST", url, json=account.to_api_dict())
|
||||
return self.model_class.from_api_response(response.json())
|
||||
else:
|
||||
raise ValueError("Use create_account_async for async clients")
|
||||
|
||||
async def create_account_async(self, account: AccountCreateRequest) -> AccountDetailModel:
|
||||
"""
|
||||
Create a new Airwallex account asynchronously.
|
||||
|
||||
Args:
|
||||
account: AccountCreateRequest model with account creation details.
|
||||
|
||||
Returns:
|
||||
AccountDetailModel: The created account.
|
||||
"""
|
||||
url = "/api/v1/accounts/create"
|
||||
|
||||
if self.client.__class__.__name__.startswith('Async'):
|
||||
response = await self.client._request("POST", url, json=account.to_api_dict())
|
||||
return self.model_class.from_api_response(response.json())
|
||||
else:
|
||||
raise ValueError("Use create_account for sync clients")
|
||||
|
||||
def update_account(self, account_id: str, account: AccountUpdateRequest) -> AccountDetailModel:
|
||||
"""
|
||||
Update a connected account.
|
||||
|
||||
Args:
|
||||
account_id: The ID of the account to update.
|
||||
account: AccountUpdateRequest model with account update details.
|
||||
|
||||
Returns:
|
||||
AccountDetailModel: The updated account.
|
||||
"""
|
||||
url = f"/api/v1/accounts/{account_id}/update"
|
||||
|
||||
if not self.client.__class__.__name__.startswith('Async'):
|
||||
response = self.client._request("POST", url, json=account.to_api_dict())
|
||||
return self.model_class.from_api_response(response.json())
|
||||
else:
|
||||
raise ValueError("Use update_account_async for async clients")
|
||||
|
||||
async def update_account_async(self, account_id: str, account: AccountUpdateRequest) -> AccountDetailModel:
|
||||
"""
|
||||
Update a connected account asynchronously.
|
||||
|
||||
Args:
|
||||
account_id: The ID of the account to update.
|
||||
account: AccountUpdateRequest model with account update details.
|
||||
|
||||
Returns:
|
||||
AccountDetailModel: The updated account.
|
||||
"""
|
||||
url = f"/api/v1/accounts/{account_id}/update"
|
||||
|
||||
if self.client.__class__.__name__.startswith('Async'):
|
||||
response = await self.client._request("POST", url, json=account.to_api_dict())
|
||||
return self.model_class.from_api_response(response.json())
|
||||
else:
|
||||
raise ValueError("Use update_account for sync clients")
|
||||
|
||||
def submit_account(self, account_id: str) -> AccountDetailModel:
|
||||
"""
|
||||
Submit account for activation.
|
||||
|
||||
Args:
|
||||
account_id: The ID of the account to submit.
|
||||
|
||||
Returns:
|
||||
AccountDetailModel: The submitted account.
|
||||
"""
|
||||
url = f"/api/v1/accounts/{account_id}/submit"
|
||||
|
||||
if not self.client.__class__.__name__.startswith('Async'):
|
||||
response = self.client._request("POST", url)
|
||||
return self.model_class.from_api_response(response.json())
|
||||
else:
|
||||
raise ValueError("Use submit_account_async for async clients")
|
||||
|
||||
async def submit_account_async(self, account_id: str) -> AccountDetailModel:
|
||||
"""
|
||||
Submit account for activation asynchronously.
|
||||
|
||||
Args:
|
||||
account_id: The ID of the account to submit.
|
||||
|
||||
Returns:
|
||||
AccountDetailModel: The submitted account.
|
||||
"""
|
||||
url = f"/api/v1/accounts/{account_id}/submit"
|
||||
|
||||
if self.client.__class__.__name__.startswith('Async'):
|
||||
response = await self.client._request("POST", url)
|
||||
return self.model_class.from_api_response(response.json())
|
||||
else:
|
||||
raise ValueError("Use submit_account for sync clients")
|
||||
|
||||
def get_account(self, account_id: str) -> AccountDetailModel:
|
||||
"""
|
||||
Get account by ID.
|
||||
|
||||
Args:
|
||||
account_id: The ID of the account to retrieve.
|
||||
|
||||
Returns:
|
||||
AccountDetailModel: The account.
|
||||
"""
|
||||
url = f"/api/v1/accounts/{account_id}"
|
||||
|
||||
if not self.client.__class__.__name__.startswith('Async'):
|
||||
response = self.client._request("GET", url)
|
||||
return self.model_class.from_api_response(response.json())
|
||||
else:
|
||||
raise ValueError("Use get_account_async for async clients")
|
||||
|
||||
async def get_account_async(self, account_id: str) -> AccountDetailModel:
|
||||
"""
|
||||
Get account by ID asynchronously.
|
||||
|
||||
Args:
|
||||
account_id: The ID of the account to retrieve.
|
||||
|
||||
Returns:
|
||||
AccountDetailModel: The account.
|
||||
"""
|
||||
url = f"/api/v1/accounts/{account_id}"
|
||||
|
||||
if self.client.__class__.__name__.startswith('Async'):
|
||||
response = await self.client._request("GET", url)
|
||||
return self.model_class.from_api_response(response.json())
|
||||
else:
|
||||
raise ValueError("Use get_account for sync clients")
|
||||
|
||||
def list_accounts(
|
||||
self,
|
||||
account_status: Optional[str] = None,
|
||||
email: Optional[str] = None,
|
||||
from_created_at: Optional[Union[str, datetime]] = None,
|
||||
identifier: Optional[str] = None,
|
||||
metadata: Optional[str] = None,
|
||||
page_num: Optional[int] = None,
|
||||
page_size: Optional[int] = None,
|
||||
to_created_at: Optional[Union[str, datetime]] = None
|
||||
) -> List[AccountDetailModel]:
|
||||
"""
|
||||
Get list of connected accounts with filtering options.
|
||||
|
||||
Args:
|
||||
account_status: Filter by account status (CREATED, SUBMITTED, ACTION_REQUIRED, ACTIVE, SUSPENDED)
|
||||
email: Filter by email
|
||||
from_created_at: Filter by creation date (start, inclusive)
|
||||
identifier: Filter by identifier
|
||||
metadata: Filter by metadata (key:value format)
|
||||
page_num: Page number (0-indexed)
|
||||
page_size: Number of results per page (default 100, max 500)
|
||||
to_created_at: Filter by creation date (end, inclusive)
|
||||
|
||||
Returns:
|
||||
List[AccountDetailModel]: List of matching accounts.
|
||||
"""
|
||||
url = "/api/v1/accounts"
|
||||
params = {}
|
||||
|
||||
if account_status:
|
||||
params["account_status"] = account_status
|
||||
|
||||
if email:
|
||||
params["email"] = email
|
||||
|
||||
if from_created_at:
|
||||
if isinstance(from_created_at, datetime):
|
||||
from_created_at = from_created_at.isoformat()
|
||||
params["from_created_at"] = from_created_at
|
||||
|
||||
if identifier:
|
||||
params["identifier"] = identifier
|
||||
|
||||
if metadata:
|
||||
params["metadata"] = metadata
|
||||
|
||||
if page_num is not None:
|
||||
params["page_num"] = page_num
|
||||
|
||||
if page_size is not None:
|
||||
params["page_size"] = page_size
|
||||
|
||||
if to_created_at:
|
||||
if isinstance(to_created_at, datetime):
|
||||
to_created_at = to_created_at.isoformat()
|
||||
params["to_created_at"] = to_created_at
|
||||
|
||||
if not self.client.__class__.__name__.startswith('Async'):
|
||||
response = self.client._request("GET", url, params=params)
|
||||
data = response.json()
|
||||
return [self.model_class.from_api_response(item) for item in data.get("items", [])]
|
||||
else:
|
||||
raise ValueError("Use list_accounts_async for async clients")
|
||||
|
||||
async def list_accounts_async(
|
||||
self,
|
||||
account_status: Optional[str] = None,
|
||||
email: Optional[str] = None,
|
||||
from_created_at: Optional[Union[str, datetime]] = None,
|
||||
identifier: Optional[str] = None,
|
||||
metadata: Optional[str] = None,
|
||||
page_num: Optional[int] = None,
|
||||
page_size: Optional[int] = None,
|
||||
to_created_at: Optional[Union[str, datetime]] = None
|
||||
) -> List[AccountDetailModel]:
|
||||
"""
|
||||
Get list of connected accounts with filtering options asynchronously.
|
||||
|
||||
Args:
|
||||
account_status: Filter by account status (CREATED, SUBMITTED, ACTION_REQUIRED, ACTIVE, SUSPENDED)
|
||||
email: Filter by email
|
||||
from_created_at: Filter by creation date (start, inclusive)
|
||||
identifier: Filter by identifier
|
||||
metadata: Filter by metadata (key:value format)
|
||||
page_num: Page number (0-indexed)
|
||||
page_size: Number of results per page (default 100, max 500)
|
||||
to_created_at: Filter by creation date (end, inclusive)
|
||||
|
||||
Returns:
|
||||
List[AccountDetailModel]: List of matching accounts.
|
||||
"""
|
||||
url = "/api/v1/accounts"
|
||||
params = {}
|
||||
|
||||
if account_status:
|
||||
params["account_status"] = account_status
|
||||
|
||||
if email:
|
||||
params["email"] = email
|
||||
|
||||
if from_created_at:
|
||||
if isinstance(from_created_at, datetime):
|
||||
from_created_at = from_created_at.isoformat()
|
||||
params["from_created_at"] = from_created_at
|
||||
|
||||
if identifier:
|
||||
params["identifier"] = identifier
|
||||
|
||||
if metadata:
|
||||
params["metadata"] = metadata
|
||||
|
||||
if page_num is not None:
|
||||
params["page_num"] = page_num
|
||||
|
||||
if page_size is not None:
|
||||
params["page_size"] = page_size
|
||||
|
||||
if to_created_at:
|
||||
if isinstance(to_created_at, datetime):
|
||||
to_created_at = to_created_at.isoformat()
|
||||
params["to_created_at"] = to_created_at
|
||||
|
||||
if self.client.__class__.__name__.startswith('Async'):
|
||||
response = await self.client._request("GET", url, params=params)
|
||||
data = response.json()
|
||||
return [self.model_class.from_api_response(item) for item in data.get("items", [])]
|
||||
else:
|
||||
raise ValueError("Use list_accounts for sync clients")
|
||||
|
||||
def agree_to_terms(self, account_id: str, request: TermsAndConditionsRequest) -> AccountDetailModel:
|
||||
"""
|
||||
Agree to terms and conditions.
|
||||
|
||||
Args:
|
||||
account_id: The ID of the account agreeing to terms.
|
||||
request: TermsAndConditionsRequest model with agreement details.
|
||||
|
||||
Returns:
|
||||
AccountDetailModel: The updated account.
|
||||
"""
|
||||
url = f"/api/v1/accounts/{account_id}/terms_and_conditions/agree"
|
||||
|
||||
if not self.client.__class__.__name__.startswith('Async'):
|
||||
response = self.client._request("POST", url, json=request.to_api_dict())
|
||||
return self.model_class.from_api_response(response.json())
|
||||
else:
|
||||
raise ValueError("Use agree_to_terms_async for async clients")
|
||||
|
||||
async def agree_to_terms_async(self, account_id: str, request: TermsAndConditionsRequest) -> AccountDetailModel:
|
||||
"""
|
||||
Agree to terms and conditions asynchronously.
|
||||
|
||||
Args:
|
||||
account_id: The ID of the account agreeing to terms.
|
||||
request: TermsAndConditionsRequest model with agreement details.
|
||||
|
||||
Returns:
|
||||
AccountDetailModel: The updated account.
|
||||
"""
|
||||
url = f"/api/v1/accounts/{account_id}/terms_and_conditions/agree"
|
||||
|
||||
if self.client.__class__.__name__.startswith('Async'):
|
||||
response = await self.client._request("POST", url, json=request.to_api_dict())
|
||||
return self.model_class.from_api_response(response.json())
|
||||
else:
|
||||
raise ValueError("Use agree_to_terms for sync clients")
|
||||
Reference in New Issue
Block a user