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:
69
airwallex-sdk/airwallex/models/__init__.py
Normal file
69
airwallex-sdk/airwallex/models/__init__.py
Normal file
@@ -0,0 +1,69 @@
|
||||
"""
|
||||
Pydantic models for the Airwallex API.
|
||||
"""
|
||||
from .base import AirwallexModel
|
||||
from .account import Account as AccountModel
|
||||
from .payment import Payment as PaymentModel
|
||||
from .beneficiary import Beneficiary as BeneficiaryModel
|
||||
from .invoice import Invoice as InvoiceModel, InvoiceItem
|
||||
from .financial_transaction import FinancialTransaction as FinancialTransactionModel
|
||||
from .fx import FXConversion, FXQuote
|
||||
from .account_detail import (
|
||||
AccountDetailModel, AccountCreateRequest, AccountUpdateRequest,
|
||||
Amendment, AmendmentCreateRequest, WalletInfo, TermsAndConditionsRequest
|
||||
)
|
||||
|
||||
# Issuing API Models
|
||||
from .issuing_common import (
|
||||
Address,
|
||||
Name,
|
||||
Merchant,
|
||||
RiskDetails,
|
||||
DeviceInformation,
|
||||
TransactionUsage,
|
||||
DeliveryDetails,
|
||||
HasMoreResponse
|
||||
)
|
||||
from .issuing_authorization import Authorization as IssuingAuthorizationModel
|
||||
from .issuing_cardholder import Cardholder as IssuingCardholderModel
|
||||
from .issuing_card import Card as IssuingCardModel, CardDetails
|
||||
from .issuing_digital_wallet_token import DigitalWalletToken as IssuingDigitalWalletTokenModel
|
||||
from .issuing_transaction_dispute import TransactionDispute as IssuingTransactionDisputeModel
|
||||
from .issuing_transaction import Transaction as IssuingTransactionModel
|
||||
from .issuing_config import IssuingConfig as IssuingConfigModel
|
||||
|
||||
__all__ = [
|
||||
"AirwallexModel",
|
||||
"AccountModel",
|
||||
"PaymentModel",
|
||||
"BeneficiaryModel",
|
||||
"InvoiceModel",
|
||||
"InvoiceItem",
|
||||
"FinancialTransactionModel",
|
||||
"FXConversion",
|
||||
"FXQuote",
|
||||
"AccountDetailModel",
|
||||
"AccountCreateRequest",
|
||||
"AccountUpdateRequest",
|
||||
"Amendment",
|
||||
"AmendmentCreateRequest",
|
||||
"WalletInfo",
|
||||
"TermsAndConditionsRequest",
|
||||
# Issuing API
|
||||
"Address",
|
||||
"Name",
|
||||
"Merchant",
|
||||
"RiskDetails",
|
||||
"DeviceInformation",
|
||||
"TransactionUsage",
|
||||
"DeliveryDetails",
|
||||
"HasMoreResponse",
|
||||
"IssuingAuthorizationModel",
|
||||
"IssuingCardholderModel",
|
||||
"IssuingCardModel",
|
||||
"CardDetails",
|
||||
"IssuingDigitalWalletTokenModel",
|
||||
"IssuingTransactionDisputeModel",
|
||||
"IssuingTransactionModel",
|
||||
"IssuingConfigModel",
|
||||
]
|
||||
51
airwallex-sdk/airwallex/models/account.py
Normal file
51
airwallex-sdk/airwallex/models/account.py
Normal file
@@ -0,0 +1,51 @@
|
||||
"""
|
||||
Models for the Airwallex account API.
|
||||
"""
|
||||
from typing import Optional, List, Dict, Any
|
||||
from datetime import datetime
|
||||
from pydantic import Field
|
||||
from .base import AirwallexModel
|
||||
|
||||
|
||||
class AccountBalanceAmount(AirwallexModel):
|
||||
"""Model for account balance amount."""
|
||||
currency: str = Field(..., description="Currency code (ISO 4217)")
|
||||
value: float = Field(..., description="Balance amount value")
|
||||
|
||||
|
||||
class AccountBalance(AirwallexModel):
|
||||
"""Model for account balance."""
|
||||
available_amount: AccountBalanceAmount = Field(..., description="Available account balance")
|
||||
pending_amount: Optional[AccountBalanceAmount] = Field(None, description="Pending account balance")
|
||||
|
||||
|
||||
class Account(AirwallexModel):
|
||||
"""Model for an Airwallex account."""
|
||||
resource_name: str = "accounts"
|
||||
|
||||
id: str = Field(..., description="Unique account ID")
|
||||
account_name: str = Field(..., description="Account name")
|
||||
account_type: str = Field(..., description="Account type")
|
||||
account_currency: str = Field(..., description="Account currency (ISO 4217)")
|
||||
status: str = Field(..., description="Account status")
|
||||
swift_code: Optional[str] = Field(None, description="SWIFT/BIC code")
|
||||
iban: Optional[str] = Field(None, description="IBAN (International Bank Account Number)")
|
||||
routing_number: Optional[str] = Field(None, description="Routing number")
|
||||
account_number: Optional[str] = Field(None, description="Account number")
|
||||
bsb: Optional[str] = Field(None, description="BSB (Bank State Branch code) for AU accounts")
|
||||
sort_code: Optional[str] = Field(None, description="Sort code for UK accounts")
|
||||
created_at: datetime = Field(..., description="Account creation timestamp")
|
||||
updated_at: Optional[datetime] = Field(None, description="Account last update timestamp")
|
||||
balance: Optional[AccountBalance] = Field(None, description="Account balance")
|
||||
|
||||
|
||||
class AccountCreateRequest(AirwallexModel):
|
||||
"""Model for account creation request."""
|
||||
account_name: str = Field(..., description="Name for the account")
|
||||
account_currency: str = Field(..., description="Currency code (ISO 4217)")
|
||||
|
||||
|
||||
class AccountUpdateRequest(AirwallexModel):
|
||||
"""Model for account update request."""
|
||||
account_name: Optional[str] = Field(None, description="New name for the account")
|
||||
status: Optional[str] = Field(None, description="New status for the account")
|
||||
259
airwallex-sdk/airwallex/models/account_detail.py
Normal file
259
airwallex-sdk/airwallex/models/account_detail.py
Normal file
@@ -0,0 +1,259 @@
|
||||
"""
|
||||
Models for the Airwallex Account Detail API.
|
||||
"""
|
||||
from typing import Optional, List, Dict, Any, Union
|
||||
from datetime import datetime
|
||||
from pydantic import Field, EmailStr
|
||||
from .base import AirwallexModel
|
||||
|
||||
class Address(AirwallexModel):
|
||||
"""Model for an address."""
|
||||
address_line1: str = Field(..., description="Address line 1")
|
||||
address_line2: Optional[str] = Field(None, description="Address line 2")
|
||||
country_code: str = Field(..., description="Country code (ISO 3166-1 alpha-2)")
|
||||
postcode: str = Field(..., description="Postal code")
|
||||
state: Optional[str] = Field(None, description="State or province")
|
||||
suburb: Optional[str] = Field(None, description="Suburb or city")
|
||||
|
||||
class BusinessIdentifier(AirwallexModel):
|
||||
"""Model for a business identifier."""
|
||||
country_code: str = Field(..., description="Country code (ISO 3166-1 alpha-2)")
|
||||
number: str = Field(..., description="Identifier number")
|
||||
type: str = Field(..., description="Identifier type (e.g., 'BRN')")
|
||||
|
||||
class EstimatedMonthlyRevenue(AirwallexModel):
|
||||
"""Model for estimated monthly revenue."""
|
||||
amount: str = Field(..., description="Amount as string")
|
||||
currency: str = Field(..., description="Currency code (ISO 4217)")
|
||||
|
||||
class AccountUsage(AirwallexModel):
|
||||
"""Model for account usage information."""
|
||||
estimated_monthly_revenue: EstimatedMonthlyRevenue = Field(..., description="Estimated monthly revenue")
|
||||
product_reference: List[str] = Field(..., description="List of product references")
|
||||
|
||||
class BusinessDocument(AirwallexModel):
|
||||
"""Model for a business document."""
|
||||
description: Optional[str] = Field(None, description="Document description")
|
||||
file_id: str = Field(..., description="File ID")
|
||||
tag: str = Field(..., description="Document tag (e.g., 'BUSINESS_LICENSE')")
|
||||
|
||||
class BusinessDocuments(AirwallexModel):
|
||||
"""Model for business documents."""
|
||||
business_documents: List[BusinessDocument] = Field(..., description="List of business documents")
|
||||
|
||||
class BusinessAttachments(AirwallexModel):
|
||||
"""Model for business attachments."""
|
||||
business_documents: Optional[List[BusinessDocument]] = Field(None, description="List of business documents")
|
||||
|
||||
class BusinessDetails(AirwallexModel):
|
||||
"""Model for business details."""
|
||||
account_usage: AccountUsage = Field(..., description="Account usage information")
|
||||
as_trustee: Optional[bool] = Field(None, description="Whether the business acts as a trustee")
|
||||
attachments: Optional[BusinessAttachments] = Field(None, description="Business attachments")
|
||||
business_address: Address = Field(..., description="Business address")
|
||||
business_identifiers: List[BusinessIdentifier] = Field(..., description="Business identifiers")
|
||||
business_name: str = Field(..., description="Business name")
|
||||
business_name_english: Optional[str] = Field(None, description="Business name in English")
|
||||
business_name_trading: Optional[str] = Field(None, description="Trading name of the business")
|
||||
business_start_date: Optional[str] = Field(None, description="Business start date (YYYY-MM-DD)")
|
||||
business_structure: str = Field(..., description="Business structure (e.g., 'COMPANY')")
|
||||
contact_number: Optional[str] = Field(None, description="Contact phone number")
|
||||
description_of_goods_or_services: Optional[str] = Field(None, description="Description of goods or services")
|
||||
explanation_for_high_risk_countries_exposure: Optional[str] = Field(None, description="Explanation for high risk countries exposure")
|
||||
has_nominee_shareholders: Optional[bool] = Field(None, description="Whether the business has nominee shareholders")
|
||||
industry_category_code: str = Field(..., description="Industry category code")
|
||||
no_shareholders_with_over_25percent: Optional[bool] = Field(None, description="Whether there are no shareholders with over 25% ownership")
|
||||
operating_country: List[str] = Field(..., description="Operating countries (ISO 3166-1 alpha-2 codes)")
|
||||
registration_address: Address = Field(..., description="Registration address")
|
||||
registration_address_english: Optional[Address] = Field(None, description="Registration address in English")
|
||||
state_of_incorporation: Optional[str] = Field(None, description="State of incorporation")
|
||||
url: Optional[str] = Field(None, description="Business website URL")
|
||||
|
||||
class DriversLicense(AirwallexModel):
|
||||
"""Model for driver's license identification."""
|
||||
back_file_id: Optional[str] = Field(None, description="File ID for back of license")
|
||||
effective_at: str = Field(..., description="Effective date (YYYY-MM-DD)")
|
||||
expire_at: str = Field(..., description="Expiry date (YYYY-MM-DD)")
|
||||
front_file_id: str = Field(..., description="File ID for front of license")
|
||||
gender: Optional[str] = Field(None, description="Gender (e.g., 'F' for female)")
|
||||
issuing_state: Optional[str] = Field(None, description="Issuing state")
|
||||
number: str = Field(..., description="License number")
|
||||
version: Optional[str] = Field(None, description="License version")
|
||||
|
||||
class Passport(AirwallexModel):
|
||||
"""Model for passport identification."""
|
||||
effective_at: str = Field(..., description="Effective date (YYYY-MM-DD)")
|
||||
expire_at: str = Field(..., description="Expiry date (YYYY-MM-DD)")
|
||||
front_file_id: str = Field(..., description="File ID for passport")
|
||||
mrz_line1: Optional[str] = Field(None, description="MRZ line 1")
|
||||
mrz_line2: Optional[str] = Field(None, description="MRZ line 2")
|
||||
number: str = Field(..., description="Passport number")
|
||||
|
||||
class PersonalId(AirwallexModel):
|
||||
"""Model for personal ID identification."""
|
||||
back_file_id: Optional[str] = Field(None, description="File ID for back of ID")
|
||||
effective_at: str = Field(..., description="Effective date (YYYY-MM-DD)")
|
||||
expire_at: str = Field(..., description="Expiry date (YYYY-MM-DD)")
|
||||
front_file_id: str = Field(..., description="File ID for front of ID")
|
||||
number: str = Field(..., description="ID number")
|
||||
|
||||
class PrimaryIdentification(AirwallexModel):
|
||||
"""Model for primary identification."""
|
||||
drivers_license: Optional[DriversLicense] = Field(None, description="Driver's license details")
|
||||
identification_type: str = Field(..., description="Identification type (e.g., 'PASSPORT')")
|
||||
issuing_country_code: str = Field(..., description="Issuing country code (ISO 3166-1 alpha-2)")
|
||||
passport: Optional[Passport] = Field(None, description="Passport details")
|
||||
personal_id: Optional[PersonalId] = Field(None, description="Personal ID details")
|
||||
|
||||
class Identifications(AirwallexModel):
|
||||
"""Model for identifications."""
|
||||
primary: PrimaryIdentification = Field(..., description="Primary identification")
|
||||
|
||||
class BusinessPersonDocument(AirwallexModel):
|
||||
"""Model for a business person document."""
|
||||
description: Optional[str] = Field(None, description="Document description")
|
||||
file_id: str = Field(..., description="File ID")
|
||||
tag: str = Field(..., description="Document tag")
|
||||
|
||||
class BusinessPersonAttachments(AirwallexModel):
|
||||
"""Model for business person attachments."""
|
||||
business_person_documents: List[BusinessPersonDocument] = Field(..., description="List of business person documents")
|
||||
|
||||
class BusinessPersonDetails(AirwallexModel):
|
||||
"""Model for business person details."""
|
||||
attachments: Optional[BusinessPersonAttachments] = Field(None, description="Business person attachments")
|
||||
date_of_birth: str = Field(..., description="Date of birth (YYYY-MM-DD)")
|
||||
email: EmailStr = Field(..., description="Email address")
|
||||
first_name: str = Field(..., description="First name")
|
||||
first_name_english: Optional[str] = Field(None, description="First name in English")
|
||||
identifications: Identifications = Field(..., description="Identifications")
|
||||
last_name: str = Field(..., description="Last name")
|
||||
last_name_english: Optional[str] = Field(None, description="Last name in English")
|
||||
middle_name: Optional[str] = Field(None, description="Middle name")
|
||||
middle_name_english: Optional[str] = Field(None, description="Middle name in English")
|
||||
mobile: Optional[str] = Field(None, description="Mobile phone number")
|
||||
residential_address: Optional[Address] = Field(None, description="Residential address")
|
||||
residential_address_english: Optional[Address] = Field(None, description="Residential address in English")
|
||||
role: str = Field(..., description="Role (e.g., 'DIRECTOR')")
|
||||
title: Optional[str] = Field(None, description="Title (e.g., 'Mr')")
|
||||
|
||||
class AdditionalFile(AirwallexModel):
|
||||
"""Model for an additional file."""
|
||||
description: Optional[str] = Field(None, description="File description")
|
||||
file_id: str = Field(..., description="File ID")
|
||||
tag: str = Field(..., description="File tag")
|
||||
|
||||
class AccountAttachments(AirwallexModel):
|
||||
"""Model for account attachments."""
|
||||
additional_files: Optional[List[AdditionalFile]] = Field(None, description="List of additional files")
|
||||
|
||||
class AccountDetails(AirwallexModel):
|
||||
"""Model for account details."""
|
||||
attachments: Optional[AccountAttachments] = Field(None, description="Account attachments")
|
||||
business_details: BusinessDetails = Field(..., description="Business details")
|
||||
business_person_details: List[BusinessPersonDetails] = Field(..., description="Business person details")
|
||||
|
||||
class CustomerAgreements(AirwallexModel):
|
||||
"""Model for customer agreements."""
|
||||
tnc_accepted: bool = Field(..., description="Whether terms and conditions are accepted")
|
||||
marketing_emails_opt_in: Optional[bool] = Field(None, description="Whether marketing emails are opted in")
|
||||
|
||||
class PrimaryContact(AirwallexModel):
|
||||
"""Model for primary contact information."""
|
||||
email: EmailStr = Field(..., description="Email address")
|
||||
mobile: Optional[str] = Field(None, description="Mobile phone number")
|
||||
|
||||
class NextAction(AirwallexModel):
|
||||
"""Model for next action information."""
|
||||
type: str = Field(..., description="Action type")
|
||||
message: Optional[str] = Field(None, description="Action message")
|
||||
|
||||
class Requirements(AirwallexModel):
|
||||
"""Model for requirements information."""
|
||||
current_deadline: Optional[str] = Field(None, description="Current deadline (ISO 8601 format)")
|
||||
currently_due: List[str] = Field(..., description="List of currently due requirements")
|
||||
eventually_due: List[str] = Field(..., description="List of eventually due requirements")
|
||||
past_due: List[str] = Field(..., description="List of past due requirements")
|
||||
|
||||
class AccountDetailModel(AirwallexModel):
|
||||
"""Model for an Airwallex account detail."""
|
||||
resource_name: str = "accounts"
|
||||
|
||||
account_details: Optional[AccountDetails] = Field(None, description="Account details")
|
||||
created_at: str = Field(..., description="Account creation timestamp (ISO 8601 format)")
|
||||
customer_agreements: Optional[CustomerAgreements] = Field(None, description="Customer agreements")
|
||||
id: str = Field(..., description="Airwallex account ID")
|
||||
identifier: Optional[str] = Field(None, description="Platform identifier for the merchant")
|
||||
metadata: Optional[Dict[str, str]] = Field(None, description="Additional metadata")
|
||||
next_action: Optional[NextAction] = Field(None, description="Next action information")
|
||||
nickname: Optional[str] = Field(None, description="Human-friendly account name")
|
||||
primary_contact: Optional[PrimaryContact] = Field(None, description="Primary contact information")
|
||||
requirements: Optional[Requirements] = Field(None, description="Requirements information")
|
||||
status: str = Field(..., description="Account status (CREATED, SUBMITTED, ACTION_REQUIRED, ACTIVE, SUSPENDED)")
|
||||
view_type: Optional[str] = Field(None, description="View type information")
|
||||
|
||||
# Request Models
|
||||
class AccountCreateRequest(AirwallexModel):
|
||||
"""Model for account creation request."""
|
||||
account_details: Optional[AccountDetails] = Field(None, description="Account details")
|
||||
customer_agreements: Optional[CustomerAgreements] = Field(None, description="Customer agreements")
|
||||
identifier: Optional[str] = Field(None, description="Platform identifier for the merchant")
|
||||
metadata: Optional[Dict[str, str]] = Field(None, description="Additional metadata")
|
||||
nickname: Optional[str] = Field(None, description="Human-friendly account name")
|
||||
primary_contact: Optional[PrimaryContact] = Field(None, description="Primary contact information")
|
||||
|
||||
class AccountUpdateRequest(AirwallexModel):
|
||||
"""Model for account update request."""
|
||||
account_details: Optional[AccountDetails] = Field(None, description="Account details")
|
||||
metadata: Optional[Dict[str, str]] = Field(None, description="Additional metadata")
|
||||
nickname: Optional[str] = Field(None, description="Human-friendly account name")
|
||||
|
||||
# Amendments
|
||||
class StoreDetails(AirwallexModel):
|
||||
"""Model for store details."""
|
||||
cross_border_transaction_percent: Optional[str] = Field(None, description="Cross-border transaction percentage")
|
||||
dispute_percent: Optional[str] = Field(None, description="Dispute percentage")
|
||||
employee_size: Optional[int] = Field(None, description="Employee size")
|
||||
estimated_transaction_volume: Optional[Dict[str, Any]] = Field(None, description="Estimated transaction volume")
|
||||
financial_statements: Optional[List[Dict[str, str]]] = Field(None, description="Financial statements")
|
||||
fulfillment_days: Optional[int] = Field(None, description="Fulfillment days")
|
||||
industry_code: Optional[str] = Field(None, description="Industry code")
|
||||
mcc: Optional[str] = Field(None, description="Merchant Category Code")
|
||||
operating_models: Optional[List[str]] = Field(None, description="Operating models")
|
||||
payment_distribution: Optional[List[Dict[str, Any]]] = Field(None, description="Payment distribution")
|
||||
|
||||
class Amendment(AirwallexModel):
|
||||
"""Model for an account amendment."""
|
||||
resource_name: str = "account/amendments"
|
||||
|
||||
id: str = Field(..., description="Amendment ID")
|
||||
primary_contact: Optional[PrimaryContact] = Field(None, description="Primary contact information")
|
||||
status: str = Field(..., description="Amendment status (PENDING, APPROVED, REJECTED)")
|
||||
store_details: Optional[StoreDetails] = Field(None, description="Store details")
|
||||
target: str = Field(..., description="Amendment target")
|
||||
|
||||
class AmendmentCreateRequest(AirwallexModel):
|
||||
"""Model for amendment creation request."""
|
||||
primary_contact: Optional[PrimaryContact] = Field(None, description="Primary contact information")
|
||||
store_details: Optional[StoreDetails] = Field(None, description="Store details")
|
||||
target: str = Field(..., description="Amendment target")
|
||||
|
||||
# Wallet Info
|
||||
class WalletInfo(AirwallexModel):
|
||||
"""Model for wallet information."""
|
||||
resource_name: str = "account/wallet_info"
|
||||
|
||||
account_name: str = Field(..., description="Account name")
|
||||
account_number: str = Field(..., description="Account number")
|
||||
|
||||
# Terms and Conditions Agreement
|
||||
class DeviceData(AirwallexModel):
|
||||
"""Model for device data."""
|
||||
ip_address: Optional[str] = Field(None, description="IP address")
|
||||
user_agent: Optional[str] = Field(None, description="User agent")
|
||||
|
||||
class TermsAndConditionsRequest(AirwallexModel):
|
||||
"""Model for terms and conditions agreement request."""
|
||||
agreed_at: str = Field(..., description="Agreement timestamp (ISO 8601 format)")
|
||||
device_data: Optional[DeviceData] = Field(None, description="Device data")
|
||||
service_agreement_type: Optional[str] = Field("FULL", description="Service agreement type (FULL or RECIPIENT)")
|
||||
121
airwallex-sdk/airwallex/models/base.py
Normal file
121
airwallex-sdk/airwallex/models/base.py
Normal file
@@ -0,0 +1,121 @@
|
||||
"""
|
||||
Base Pydantic models for the Airwallex API.
|
||||
"""
|
||||
from typing import Any, Dict, List, Optional, ClassVar, Type, TypeVar, Generic, get_origin, get_args
|
||||
from datetime import datetime
|
||||
import re
|
||||
from pydantic import BaseModel, Field, ConfigDict, model_validator
|
||||
from ..utils import snake_to_camel_case, camel_to_snake_case
|
||||
|
||||
T = TypeVar('T', bound='AirwallexModel')
|
||||
|
||||
|
||||
class AirwallexModel(BaseModel):
|
||||
"""Base model for all Airwallex API models with camelCase conversion."""
|
||||
|
||||
model_config = ConfigDict(
|
||||
populate_by_name=True,
|
||||
extra='ignore',
|
||||
arbitrary_types_allowed=True
|
||||
)
|
||||
|
||||
# Class variable to store the API resource name
|
||||
resource_name: ClassVar[str] = ""
|
||||
|
||||
@model_validator(mode='before')
|
||||
@classmethod
|
||||
def _convert_keys_to_snake_case(cls, data: Any) -> Any:
|
||||
"""Convert camelCase keys to snake_case."""
|
||||
if not isinstance(data, dict):
|
||||
return data
|
||||
|
||||
result = {}
|
||||
for key, value in data.items():
|
||||
# Convert camelCase keys to snake_case
|
||||
snake_key = camel_to_snake_case(key)
|
||||
|
||||
# Handle nested dictionaries and lists
|
||||
if isinstance(value, dict):
|
||||
result[snake_key] = cls._convert_keys_to_snake_case(value)
|
||||
elif isinstance(value, list) and all(isinstance(item, dict) for item in value):
|
||||
result[snake_key] = [cls._convert_keys_to_snake_case(item) for item in value]
|
||||
else:
|
||||
result[snake_key] = value
|
||||
|
||||
return result
|
||||
|
||||
def to_api_dict(self) -> Dict[str, Any]:
|
||||
"""Convert the model to a dictionary with camelCase keys for API requests."""
|
||||
data = self.model_dump(exclude_unset=True)
|
||||
result: Dict[str, Any] = {}
|
||||
|
||||
for key, value in data.items():
|
||||
# Convert snake_case keys to camelCase
|
||||
camel_key = snake_to_camel_case(key)
|
||||
|
||||
# Handle nested models, dictionaries, and lists
|
||||
if isinstance(value, AirwallexModel):
|
||||
result[camel_key] = value.to_api_dict()
|
||||
elif isinstance(value, dict):
|
||||
# Convert dict keys to camelCase
|
||||
nested_dict = {}
|
||||
for k, v in value.items():
|
||||
if isinstance(v, AirwallexModel):
|
||||
nested_dict[snake_to_camel_case(k)] = v.to_api_dict()
|
||||
elif isinstance(v, list) and all(isinstance(item, AirwallexModel) for item in v):
|
||||
nested_dict[snake_to_camel_case(k)] = [item.to_api_dict() for item in v]
|
||||
else:
|
||||
nested_dict[snake_to_camel_case(k)] = v
|
||||
result[camel_key] = nested_dict
|
||||
elif isinstance(value, list):
|
||||
# Handle lists of models
|
||||
if all(isinstance(item, AirwallexModel) for item in value):
|
||||
result[camel_key] = [item.to_api_dict() for item in value]
|
||||
else:
|
||||
result[camel_key] = value
|
||||
elif isinstance(value, datetime):
|
||||
# Convert datetime to ISO format
|
||||
result[camel_key] = value.isoformat()
|
||||
else:
|
||||
result[camel_key] = value
|
||||
|
||||
return result
|
||||
|
||||
@classmethod
|
||||
def from_api_response(cls: Type[T], data: Dict[str, Any]) -> T:
|
||||
"""Create a model instance from API response data."""
|
||||
return cls.model_validate(cls._convert_keys_to_snake_case(data))
|
||||
|
||||
|
||||
# Common types used across the SDK
|
||||
class PaginationParams(AirwallexModel):
|
||||
"""Common pagination parameters."""
|
||||
page: Optional[int] = Field(None, description="Page number (1-indexed)")
|
||||
page_size: Optional[int] = Field(None, description="Number of items per page")
|
||||
|
||||
|
||||
class PaginatedResponse(AirwallexModel, Generic[T]):
|
||||
"""Base model for paginated responses."""
|
||||
items: List[T] = Field(..., description="List of items")
|
||||
page: int = Field(..., description="Current page number")
|
||||
page_size: int = Field(..., description="Number of items per page")
|
||||
total_count: int = Field(..., description="Total number of items")
|
||||
total_pages: int = Field(..., description="Total number of pages")
|
||||
|
||||
@classmethod
|
||||
def from_api_response(cls, data: Dict[str, Any], item_class: Type[T]) -> 'PaginatedResponse[T]':
|
||||
"""Create a paginated response with the correct item type."""
|
||||
# Extract the items and convert them to the specified model
|
||||
items_data = data.get("items", [])
|
||||
items = [item_class.from_api_response(item) for item in items_data]
|
||||
|
||||
# Create the paginated response with the converted items
|
||||
paginated_data = {
|
||||
"items": items,
|
||||
"page": data.get("page", 1),
|
||||
"page_size": data.get("pageSize", len(items)),
|
||||
"total_count": data.get("totalCount", len(items)),
|
||||
"total_pages": data.get("totalPages", 1)
|
||||
}
|
||||
|
||||
return cls.model_validate(paginated_data)
|
||||
70
airwallex-sdk/airwallex/models/beneficiary.py
Normal file
70
airwallex-sdk/airwallex/models/beneficiary.py
Normal file
@@ -0,0 +1,70 @@
|
||||
"""
|
||||
Models for the Airwallex beneficiary API.
|
||||
"""
|
||||
from typing import Optional, List, Dict, Any, Union
|
||||
from datetime import datetime
|
||||
from pydantic import Field, EmailStr
|
||||
from .base import AirwallexModel
|
||||
|
||||
|
||||
class BankDetails(AirwallexModel):
|
||||
"""Model for bank account details."""
|
||||
account_name: str = Field(..., description="Account holder name")
|
||||
account_number: Optional[str] = Field(None, description="Account number")
|
||||
swift_code: Optional[str] = Field(None, description="SWIFT/BIC code")
|
||||
iban: Optional[str] = Field(None, description="IBAN (International Bank Account Number)")
|
||||
bsb: Optional[str] = Field(None, description="BSB (Bank State Branch) for AU accounts")
|
||||
sort_code: Optional[str] = Field(None, description="Sort code for UK accounts")
|
||||
routing_number: Optional[str] = Field(None, description="ACH routing number for US accounts")
|
||||
bank_name: Optional[str] = Field(None, description="Bank name")
|
||||
bank_country_code: str = Field(..., description="Bank country code (ISO 3166-1 alpha-2)")
|
||||
bank_address: Optional[Dict[str, str]] = Field(None, description="Bank address details")
|
||||
|
||||
|
||||
class Address(AirwallexModel):
|
||||
"""Model for address details."""
|
||||
country_code: str = Field(..., description="Country code (ISO 3166-1 alpha-2)")
|
||||
state: Optional[str] = Field(None, description="State or province")
|
||||
city: str = Field(..., description="City")
|
||||
postcode: Optional[str] = Field(None, description="Postal or ZIP code")
|
||||
street_address: str = Field(..., description="Street address")
|
||||
street_address_2: Optional[str] = Field(None, description="Additional street address details")
|
||||
|
||||
|
||||
class Beneficiary(AirwallexModel):
|
||||
"""Model for an Airwallex beneficiary."""
|
||||
resource_name: str = "beneficiaries"
|
||||
|
||||
id: str = Field(..., description="Unique beneficiary ID")
|
||||
name: str = Field(..., description="Beneficiary name")
|
||||
type: str = Field(..., description="Beneficiary type (e.g., 'bank_account', 'email')")
|
||||
email: Optional[EmailStr] = Field(None, description="Beneficiary email address")
|
||||
bank_details: Optional[BankDetails] = Field(None, description="Bank account details for bank_account type")
|
||||
address: Optional[Address] = Field(None, description="Beneficiary address")
|
||||
company_name: Optional[str] = Field(None, description="Beneficiary company name")
|
||||
entity_type: Optional[str] = Field(None, description="Beneficiary entity type (individual/company)")
|
||||
payment_methods: List[str] = Field(default_factory=list, description="Supported payment methods")
|
||||
status: str = Field(..., description="Beneficiary status")
|
||||
created_at: datetime = Field(..., description="Beneficiary creation timestamp")
|
||||
updated_at: Optional[datetime] = Field(None, description="Beneficiary last update timestamp")
|
||||
|
||||
|
||||
class BeneficiaryCreateRequest(AirwallexModel):
|
||||
"""Model for beneficiary creation request."""
|
||||
name: str = Field(..., description="Beneficiary name")
|
||||
type: str = Field(..., description="Beneficiary type (e.g., 'bank_account', 'email')")
|
||||
email: Optional[EmailStr] = Field(None, description="Beneficiary email address")
|
||||
bank_details: Optional[BankDetails] = Field(None, description="Bank account details for bank_account type")
|
||||
address: Optional[Address] = Field(None, description="Beneficiary address")
|
||||
company_name: Optional[str] = Field(None, description="Beneficiary company name")
|
||||
entity_type: Optional[str] = Field(None, description="Beneficiary entity type (individual/company)")
|
||||
|
||||
|
||||
class BeneficiaryUpdateRequest(AirwallexModel):
|
||||
"""Model for beneficiary update request."""
|
||||
name: Optional[str] = Field(None, description="Updated beneficiary name")
|
||||
email: Optional[EmailStr] = Field(None, description="Updated beneficiary email address")
|
||||
bank_details: Optional[BankDetails] = Field(None, description="Updated bank account details")
|
||||
address: Optional[Address] = Field(None, description="Updated beneficiary address")
|
||||
company_name: Optional[str] = Field(None, description="Updated beneficiary company name")
|
||||
status: Optional[str] = Field(None, description="Updated beneficiary status")
|
||||
30
airwallex-sdk/airwallex/models/financial_transaction.py
Normal file
30
airwallex-sdk/airwallex/models/financial_transaction.py
Normal file
@@ -0,0 +1,30 @@
|
||||
"""
|
||||
Models for the Airwallex financial transaction API.
|
||||
"""
|
||||
from typing import Optional
|
||||
from datetime import datetime
|
||||
from pydantic import Field
|
||||
from .base import AirwallexModel
|
||||
|
||||
|
||||
class FinancialTransaction(AirwallexModel):
|
||||
"""Model for an Airwallex financial transaction."""
|
||||
resource_name: str = "financial_transactions"
|
||||
|
||||
id: str = Field(..., description="ID of the transaction")
|
||||
amount: float = Field(..., description="Gross amount of the transaction")
|
||||
net: float = Field(..., description="Net amount of the transaction")
|
||||
fee: float = Field(..., description="Fee paid for the transaction")
|
||||
currency: str = Field(..., description="Currency of the transaction (3-letter ISO-4217 code)")
|
||||
status: str = Field(..., description="Status of the transaction (PENDING, SETTLED, CANCELLED)")
|
||||
description: Optional[str] = Field(None, description="Description of the transaction")
|
||||
batch_id: Optional[str] = Field(None, description="Batch ID of the settlement the transaction belongs to")
|
||||
client_rate: Optional[float] = Field(None, description="Client rate for the transaction")
|
||||
currency_pair: Optional[str] = Field(None, description="Currency pair that the client_rate is quoted in")
|
||||
source_id: Optional[str] = Field(None, description="Source ID of the transaction")
|
||||
source_type: Optional[str] = Field(None, description="Type of the source transaction")
|
||||
transaction_type: Optional[str] = Field(None, description="Type of the transaction")
|
||||
funding_source_id: Optional[str] = Field(None, description="ID of the funding source")
|
||||
created_at: datetime = Field(..., description="Transaction creation timestamp")
|
||||
estimated_settled_at: Optional[datetime] = Field(None, description="Estimated settlement timestamp")
|
||||
settled_at: Optional[datetime] = Field(None, description="Actual settlement timestamp")
|
||||
58
airwallex-sdk/airwallex/models/fx.py
Normal file
58
airwallex-sdk/airwallex/models/fx.py
Normal file
@@ -0,0 +1,58 @@
|
||||
"""
|
||||
Models for the Airwallex FX API.
|
||||
"""
|
||||
from typing import Optional, List, Dict, Any
|
||||
from datetime import datetime
|
||||
from pydantic import Field
|
||||
from .base import AirwallexModel
|
||||
|
||||
|
||||
class ExchangeRate(AirwallexModel):
|
||||
"""Model for exchange rate information."""
|
||||
source_currency: str = Field(..., description="Source currency code (ISO 4217)")
|
||||
target_currency: str = Field(..., description="Target currency code (ISO 4217)")
|
||||
rate: float = Field(..., description="Exchange rate")
|
||||
timestamp: datetime = Field(..., description="Timestamp when the rate was fetched")
|
||||
|
||||
|
||||
class FXQuote(AirwallexModel):
|
||||
"""Model for FX quote."""
|
||||
id: str = Field(..., description="Quote ID")
|
||||
source_currency: str = Field(..., description="Source currency code (ISO 4217)")
|
||||
target_currency: str = Field(..., description="Target currency code (ISO 4217)")
|
||||
source_amount: Optional[float] = Field(None, description="Source amount")
|
||||
target_amount: Optional[float] = Field(None, description="Target amount")
|
||||
rate: float = Field(..., description="Exchange rate")
|
||||
fee: Optional[Dict[str, Any]] = Field(None, description="Fee details")
|
||||
expires_at: datetime = Field(..., description="Quote expiration timestamp")
|
||||
created_at: datetime = Field(..., description="Quote creation timestamp")
|
||||
|
||||
|
||||
class FXConversion(AirwallexModel):
|
||||
"""Model for an FX conversion."""
|
||||
resource_name: str = "fx/conversions"
|
||||
|
||||
id: str = Field(..., description="Conversion ID")
|
||||
request_id: str = Field(..., description="Client-generated request ID")
|
||||
source_currency: str = Field(..., description="Source currency code (ISO 4217)")
|
||||
target_currency: str = Field(..., description="Target currency code (ISO 4217)")
|
||||
source_amount: float = Field(..., description="Source amount")
|
||||
target_amount: float = Field(..., description="Target amount")
|
||||
rate: float = Field(..., description="Exchange rate")
|
||||
status: str = Field(..., description="Conversion status")
|
||||
created_at: datetime = Field(..., description="Conversion creation timestamp")
|
||||
updated_at: Optional[datetime] = Field(None, description="Conversion last update timestamp")
|
||||
account_id: str = Field(..., description="Source account ID")
|
||||
settlement_date: Optional[datetime] = Field(None, description="Settlement date")
|
||||
quote_id: Optional[str] = Field(None, description="Quote ID used for this conversion")
|
||||
|
||||
|
||||
class FXConversionCreateRequest(AirwallexModel):
|
||||
"""Model for FX conversion creation request."""
|
||||
request_id: str = Field(..., description="Client-generated unique ID for the request")
|
||||
source_currency: str = Field(..., description="Source currency code (ISO 4217)")
|
||||
target_currency: str = Field(..., description="Target currency code (ISO 4217)")
|
||||
source_amount: Optional[float] = Field(None, description="Source amount (required if target_amount is not provided)")
|
||||
target_amount: Optional[float] = Field(None, description="Target amount (required if source_amount is not provided)")
|
||||
account_id: str = Field(..., description="Source account ID")
|
||||
quote_id: Optional[str] = Field(None, description="Quote ID to use for this conversion")
|
||||
102
airwallex-sdk/airwallex/models/invoice.py
Normal file
102
airwallex-sdk/airwallex/models/invoice.py
Normal file
@@ -0,0 +1,102 @@
|
||||
"""
|
||||
Models for the Airwallex Invoice API.
|
||||
"""
|
||||
from typing import Optional, List, Dict, Any, Union
|
||||
from datetime import datetime
|
||||
from pydantic import Field, validator
|
||||
from .base import AirwallexModel
|
||||
|
||||
|
||||
class RecurringBilling(AirwallexModel):
|
||||
"""Model for recurring billing information."""
|
||||
period: int = Field(..., description="The length of the billing cycle")
|
||||
period_unit: str = Field(..., description="The unit of the billing cycle, e.g., 'MONTH', 'YEAR'")
|
||||
|
||||
|
||||
class PriceTier(AirwallexModel):
|
||||
"""Model for price tier information."""
|
||||
amount: float = Field(..., description="The price for this tier")
|
||||
upper_bound: Optional[float] = Field(None, description="The upper bound of this tier")
|
||||
|
||||
|
||||
class Price(AirwallexModel):
|
||||
"""Model for price information."""
|
||||
id: str = Field(..., description="Unique price ID")
|
||||
name: str = Field(..., description="Price name")
|
||||
description: Optional[str] = Field(None, description="Price description")
|
||||
active: bool = Field(..., description="Whether this price is active")
|
||||
currency: str = Field(..., description="Currency code (ISO 4217)")
|
||||
product_id: str = Field(..., description="ID of the associated product")
|
||||
pricing_model: str = Field(..., description="Pricing model type (e.g., 'tiered')")
|
||||
recurring: Optional[RecurringBilling] = Field(None, description="Recurring billing details")
|
||||
tiers: Optional[List[PriceTier]] = Field(None, description="Pricing tiers for tiered pricing")
|
||||
metadata: Optional[Dict[str, str]] = Field(None, description="Additional metadata")
|
||||
request_id: Optional[str] = Field(None, description="Request ID when creating this price")
|
||||
|
||||
|
||||
class InvoiceItem(AirwallexModel):
|
||||
"""Model for an Airwallex invoice item."""
|
||||
id: str = Field(..., description="Unique invoice item ID")
|
||||
invoice_id: str = Field(..., description="ID of the invoice this item belongs to")
|
||||
amount: float = Field(..., description="Amount for this invoice item")
|
||||
currency: str = Field(..., description="Currency code (ISO 4217)")
|
||||
period_start_at: datetime = Field(..., description="Billing period start (inclusive)")
|
||||
period_end_at: datetime = Field(..., description="Billing period end (exclusive)")
|
||||
price: Price = Field(..., description="Price details")
|
||||
quantity: Optional[float] = Field(None, description="Product quantity")
|
||||
|
||||
|
||||
class Invoice(AirwallexModel):
|
||||
"""Model for an Airwallex invoice."""
|
||||
resource_name: str = "invoices"
|
||||
|
||||
id: str = Field(..., description="Unique invoice ID")
|
||||
customer_id: str = Field(..., description="ID of the customer who will be charged")
|
||||
subscription_id: Optional[str] = Field(None, description="ID of the subscription which generated this invoice")
|
||||
currency: str = Field(..., description="Currency code (ISO 4217)")
|
||||
total_amount: float = Field(..., description="Total amount of the invoice")
|
||||
status: str = Field(..., description="Invoice status (SENT, PAID, PAYMENT_FAILED)")
|
||||
payment_intent_id: Optional[str] = Field(None, description="ID of the associated payment intent")
|
||||
period_start_at: datetime = Field(..., description="Billing period start (inclusive)")
|
||||
period_end_at: datetime = Field(..., description="Billing period end (exclusive)")
|
||||
created_at: datetime = Field(..., description="Invoice creation timestamp")
|
||||
updated_at: Optional[datetime] = Field(None, description="Invoice last update timestamp")
|
||||
paid_at: Optional[datetime] = Field(None, description="Timestamp when invoice was paid")
|
||||
last_payment_attempt_at: Optional[datetime] = Field(None, description="Timestamp of last payment attempt")
|
||||
next_payment_attempt_at: Optional[datetime] = Field(None, description="Timestamp of next scheduled payment attempt")
|
||||
past_payment_attempt_count: Optional[int] = Field(None, description="Number of payment attempts made so far")
|
||||
remaining_payment_attempt_count: Optional[int] = Field(None, description="Number of remaining payment attempts")
|
||||
items: Optional[List[InvoiceItem]] = Field(None, description="Invoice items")
|
||||
|
||||
@validator('status')
|
||||
def validate_status(cls, v):
|
||||
"""Validate invoice status."""
|
||||
valid_statuses = ['SENT', 'PAID', 'PAYMENT_FAILED']
|
||||
if v not in valid_statuses:
|
||||
raise ValueError(f"Status must be one of {valid_statuses}")
|
||||
return v
|
||||
|
||||
|
||||
class InvoicePreviewRequest(AirwallexModel):
|
||||
"""Model for invoice preview request."""
|
||||
customer_id: str = Field(..., description="ID of the customer for this invoice")
|
||||
subscription_id: Optional[str] = Field(None, description="ID of the subscription to preview the invoice for")
|
||||
trial_end_at: Optional[datetime] = Field(None, description="End of the trial period if applicable")
|
||||
recurring: Optional[RecurringBilling] = Field(None, description="Recurring billing details")
|
||||
|
||||
class SubscriptionItem(AirwallexModel):
|
||||
"""Model for subscription item in invoice preview."""
|
||||
price_id: str = Field(..., description="ID of the price")
|
||||
quantity: float = Field(1, description="Quantity of the product")
|
||||
|
||||
items: Optional[List[SubscriptionItem]] = Field(None, description="List of subscription items")
|
||||
|
||||
|
||||
class InvoicePreviewResponse(AirwallexModel):
|
||||
"""Model for invoice preview response."""
|
||||
customer_id: str = Field(..., description="ID of the customer for this invoice")
|
||||
subscription_id: Optional[str] = Field(None, description="ID of the subscription for this invoice")
|
||||
currency: str = Field(..., description="Currency code (ISO 4217)")
|
||||
total_amount: float = Field(..., description="Total amount of the invoice")
|
||||
created_at: datetime = Field(..., description="Expected invoice creation timestamp")
|
||||
items: List[InvoiceItem] = Field(..., description="Invoice items in the preview")
|
||||
41
airwallex-sdk/airwallex/models/issuing_authorization.py
Normal file
41
airwallex-sdk/airwallex/models/issuing_authorization.py
Normal file
@@ -0,0 +1,41 @@
|
||||
"""
|
||||
Models for the Airwallex Issuing Authorization API.
|
||||
"""
|
||||
from typing import Optional, List, Dict, Any
|
||||
from datetime import datetime
|
||||
from pydantic import Field
|
||||
from .base import AirwallexModel
|
||||
from .issuing_common import Merchant, RiskDetails, HasMoreResponse
|
||||
|
||||
|
||||
class Authorization(AirwallexModel):
|
||||
"""Model for an Airwallex issuing authorization."""
|
||||
resource_name: str = "issuing/authorizations"
|
||||
|
||||
acquiring_institution_identifier: Optional[str] = Field(None, description="Unique Identifier for acquiring institution")
|
||||
auth_code: Optional[str] = Field(None, description="Authorization Code")
|
||||
billing_amount: float = Field(..., description="Billing Amount")
|
||||
billing_currency: str = Field(..., description="Billing Currency")
|
||||
card_id: str = Field(..., description="Unique Identifier for card")
|
||||
card_nickname: Optional[str] = Field(None, description="The nickname of the card used")
|
||||
client_data: Optional[str] = Field(None, description="Client data stored against the card record")
|
||||
create_time: datetime = Field(..., description="The time this outstanding authorization was created")
|
||||
digital_wallet_token_id: Optional[str] = Field(None, description="Unique Identifier for digital token")
|
||||
expiry_date: Optional[datetime] = Field(None, description="The authorization will expire after this date if not posted")
|
||||
failure_reason: Optional[str] = Field(None, description="The reason why this authorization failed (if status is FAILED)")
|
||||
lifecycle_id: Optional[str] = Field(None, description="A identifier that links multiple related transactions")
|
||||
masked_card_number: Optional[str] = Field(None, description="Masked card number")
|
||||
merchant: Optional[Merchant] = Field(None, description="Merchant details")
|
||||
network_transaction_id: Optional[str] = Field(None, description="The transaction ID from network")
|
||||
retrieval_ref: Optional[str] = Field(None, description="Transaction retrieval reference number")
|
||||
risk_details: Optional[RiskDetails] = Field(None, description="Risk details")
|
||||
status: str = Field(..., description="The status of this authorization")
|
||||
transaction_amount: float = Field(..., description="Transaction amount")
|
||||
transaction_currency: str = Field(..., description="Transaction currency")
|
||||
transaction_id: str = Field(..., description="Unique id for transaction")
|
||||
updated_by_transaction: Optional[str] = Field(None, description="Id of the transaction which updated status of this transaction")
|
||||
|
||||
|
||||
class AuthorizationListResponse(HasMoreResponse):
|
||||
"""Model for authorization list response."""
|
||||
items: List[Authorization] = Field(..., description="List of authorizations")
|
||||
135
airwallex-sdk/airwallex/models/issuing_card.py
Normal file
135
airwallex-sdk/airwallex/models/issuing_card.py
Normal file
@@ -0,0 +1,135 @@
|
||||
"""
|
||||
Models for the Airwallex Issuing Card API.
|
||||
"""
|
||||
from typing import Optional, List, Dict, Any
|
||||
from datetime import datetime
|
||||
from pydantic import Field
|
||||
from .base import AirwallexModel
|
||||
from .issuing_common import Address, TransactionUsage, DeliveryDetails, HasMoreResponse
|
||||
|
||||
|
||||
class CardVersionInfo(AirwallexModel):
|
||||
"""Model for card version information."""
|
||||
card_number: str = Field(..., description="Masked card number")
|
||||
card_status: str = Field(..., description="Current card status")
|
||||
card_version: int = Field(..., description="Card version")
|
||||
created_at: datetime = Field(..., description="Creation time of the card version")
|
||||
|
||||
|
||||
class SpendLimit(AirwallexModel):
|
||||
"""Model for spend limit."""
|
||||
amount: float = Field(..., description="Limit amount")
|
||||
interval: str = Field(..., description="Limit interval (e.g., 'PER_TRANSACTION')")
|
||||
remaining: Optional[float] = Field(None, description="Remaining limit amount")
|
||||
|
||||
|
||||
class CardLimits(AirwallexModel):
|
||||
"""Model for card limits."""
|
||||
cash_withdrawal_limits: List[SpendLimit] = Field(..., description="Cash withdrawal limits")
|
||||
currency: str = Field(..., description="Currency of limits")
|
||||
limits: List[SpendLimit] = Field(..., description="Spending limits")
|
||||
|
||||
|
||||
class PrimaryContactDetails(AirwallexModel):
|
||||
"""Model for primary contact details."""
|
||||
email: Optional[str] = Field(None, description="Email address")
|
||||
name: Optional[str] = Field(None, description="Name")
|
||||
phone_number: Optional[str] = Field(None, description="Phone number")
|
||||
|
||||
|
||||
class CardProgram(AirwallexModel):
|
||||
"""Model for card program."""
|
||||
id: str = Field(..., description="Program ID")
|
||||
name: str = Field(..., description="Program name")
|
||||
|
||||
|
||||
class AuthorizationControls(AirwallexModel):
|
||||
"""Model for card authorization controls."""
|
||||
active_from: Optional[datetime] = Field(None, description="Start time for card validity")
|
||||
active_to: Optional[datetime] = Field(None, description="End time for card validity")
|
||||
allowed_currencies: Optional[List[str]] = Field(None, description="Allowed currencies")
|
||||
allowed_merchant_categories: Optional[List[str]] = Field(None, description="Allowed merchant category codes")
|
||||
allowed_transaction_count: Optional[str] = Field(None, description="Allowed transaction count (SINGLE or MULTIPLE)")
|
||||
blocked_transaction_usages: Optional[List[TransactionUsage]] = Field(None, description="Blocked transaction usages")
|
||||
country_limitations: Optional[List[str]] = Field(None, description="Country limitations")
|
||||
spend_limits: Optional[List[SpendLimit]] = Field(None, description="Spend limits")
|
||||
|
||||
|
||||
class CardCreateRequest(AirwallexModel):
|
||||
"""Model for card creation request."""
|
||||
activate_on_issue: Optional[bool] = Field(None, description="Activate on issue")
|
||||
additional_cardholder_ids: Optional[List[str]] = Field(None, description="Additional cardholder IDs")
|
||||
authorization_controls: AuthorizationControls = Field(..., description="Authorization controls")
|
||||
brand: Optional[str] = Field(None, description="Card brand")
|
||||
cardholder_id: str = Field(..., description="Cardholder ID")
|
||||
client_data: Optional[str] = Field(None, description="Client data")
|
||||
created_by: str = Field(..., description="Full legal name of user requesting new card")
|
||||
form_factor: str = Field(..., description="Form factor (PHYSICAL or VIRTUAL)")
|
||||
funding_source_id: Optional[str] = Field(None, description="Funding source ID")
|
||||
is_personalized: bool = Field(..., description="Whether the card is personalized")
|
||||
metadata: Optional[Dict[str, str]] = Field(None, description="Metadata")
|
||||
nick_name: Optional[str] = Field(None, description="Card nickname")
|
||||
note: Optional[str] = Field(None, description="Note")
|
||||
postal_address: Optional[Address] = Field(None, description="Postal address")
|
||||
program: CardProgram = Field(..., description="Card program")
|
||||
purpose: Optional[str] = Field(None, description="Card purpose")
|
||||
request_id: str = Field(..., description="Request ID")
|
||||
|
||||
|
||||
class CardUpdateRequest(AirwallexModel):
|
||||
"""Model for card update request."""
|
||||
additional_cardholder_ids: Optional[List[str]] = Field(None, description="Additional cardholder IDs")
|
||||
authorization_controls: Optional[AuthorizationControls] = Field(None, description="Authorization controls")
|
||||
card_status: Optional[str] = Field(None, description="Card status")
|
||||
cardholder_id: Optional[str] = Field(None, description="Cardholder ID")
|
||||
metadata: Optional[Dict[str, str]] = Field(None, description="Metadata")
|
||||
nick_name: Optional[str] = Field(None, description="Card nickname")
|
||||
purpose: Optional[str] = Field(None, description="Card purpose")
|
||||
|
||||
|
||||
class Card(AirwallexModel):
|
||||
"""Model for an Airwallex issuing card."""
|
||||
resource_name: str = "issuing/cards"
|
||||
|
||||
activate_on_issue: Optional[bool] = Field(None, description="Activate on issue")
|
||||
additional_cardholder_ids: Optional[List[str]] = Field(None, description="Additional cardholder IDs")
|
||||
all_card_versions: Optional[List[CardVersionInfo]] = Field(None, description="All card versions")
|
||||
authorization_controls: AuthorizationControls = Field(..., description="Authorization controls")
|
||||
brand: str = Field(..., description="Card brand")
|
||||
card_id: str = Field(..., description="Card ID")
|
||||
card_number: str = Field(..., description="Masked card number")
|
||||
card_status: str = Field(..., description="Card status")
|
||||
card_version: int = Field(..., description="Card version")
|
||||
cardholder_id: str = Field(..., description="Cardholder ID")
|
||||
client_data: Optional[str] = Field(None, description="Client data")
|
||||
created_at: datetime = Field(..., description="Creation time")
|
||||
created_by: str = Field(..., description="Created by")
|
||||
delivery_details: Optional[DeliveryDetails] = Field(None, description="Delivery details")
|
||||
form_factor: str = Field(..., description="Form factor")
|
||||
funding_source_id: Optional[str] = Field(None, description="Funding source ID")
|
||||
is_personalized: bool = Field(..., description="Whether the card is personalized")
|
||||
issue_to: str = Field(..., description="Who the card is issued to")
|
||||
metadata: Optional[Dict[str, str]] = Field(None, description="Metadata")
|
||||
name_on_card: Optional[str] = Field(None, description="Name on card")
|
||||
nick_name: Optional[str] = Field(None, description="Nickname")
|
||||
note: Optional[str] = Field(None, description="Note")
|
||||
postal_address: Optional[Address] = Field(None, description="Postal address")
|
||||
primary_contact_details: Optional[PrimaryContactDetails] = Field(None, description="Primary contact details")
|
||||
program: CardProgram = Field(..., description="Card program")
|
||||
purpose: Optional[str] = Field(None, description="Purpose")
|
||||
request_id: str = Field(..., description="Request ID")
|
||||
updated_at: datetime = Field(..., description="Last update time")
|
||||
|
||||
|
||||
class CardDetails(AirwallexModel):
|
||||
"""Model for sensitive card details."""
|
||||
card_number: str = Field(..., description="Full card number")
|
||||
cvv: str = Field(..., description="Card verification value")
|
||||
expiry_month: int = Field(..., description="Expiry month")
|
||||
expiry_year: int = Field(..., description="Expiry year")
|
||||
name_on_card: str = Field(..., description="Name on card")
|
||||
|
||||
|
||||
class CardListResponse(HasMoreResponse):
|
||||
"""Model for card list response."""
|
||||
items: List[Card] = Field(..., description="List of cards")
|
||||
52
airwallex-sdk/airwallex/models/issuing_cardholder.py
Normal file
52
airwallex-sdk/airwallex/models/issuing_cardholder.py
Normal file
@@ -0,0 +1,52 @@
|
||||
"""
|
||||
Models for the Airwallex Issuing Cardholder API.
|
||||
"""
|
||||
from typing import Optional, List, Dict, Any, Literal
|
||||
from pydantic import Field, EmailStr
|
||||
from .base import AirwallexModel
|
||||
from .issuing_common import Address, Name, Employer, HasMoreResponse
|
||||
|
||||
|
||||
class Individual(AirwallexModel):
|
||||
"""Model for individual cardholder details."""
|
||||
address: Address = Field(..., description="Address of the cardholder")
|
||||
cardholder_agreement_terms_consent_obtained: Optional[str] = Field(None, description="Whether consent was obtained")
|
||||
date_of_birth: str = Field(..., description="Date of birth in YYYY-MM-DD format")
|
||||
employers: Optional[List[Employer]] = Field(None, description="Employers")
|
||||
express_consent_obtained: Optional[str] = Field(None, description="Whether express consent was obtained")
|
||||
name: Name = Field(..., description="Name of the cardholder")
|
||||
|
||||
|
||||
class CardholderCreateRequest(AirwallexModel):
|
||||
"""Model for cardholder creation request."""
|
||||
email: EmailStr = Field(..., description="Email address of the cardholder")
|
||||
individual: Individual = Field(..., description="Details about the cardholder")
|
||||
mobile_number: Optional[str] = Field(None, description="Mobile number of the cardholder")
|
||||
postal_address: Optional[Address] = Field(None, description="Postal address of the cardholder")
|
||||
type: str = Field(..., description="The type of cardholder (INDIVIDUAL or DELEGATE)")
|
||||
|
||||
|
||||
class CardholderUpdateRequest(AirwallexModel):
|
||||
"""Model for cardholder update request."""
|
||||
individual: Optional[Individual] = Field(None, description="Details about the cardholder")
|
||||
mobile_number: Optional[str] = Field(None, description="Mobile number of the cardholder")
|
||||
postal_address: Optional[Address] = Field(None, description="Postal address of the cardholder")
|
||||
type: Optional[str] = Field(None, description="The type of cardholder (INDIVIDUAL or DELEGATE)")
|
||||
|
||||
|
||||
class Cardholder(AirwallexModel):
|
||||
"""Model for an Airwallex cardholder."""
|
||||
resource_name: str = "issuing/cardholders"
|
||||
|
||||
cardholder_id: str = Field(..., description="Unique Identifier for cardholder")
|
||||
email: EmailStr = Field(..., description="Email address of the cardholder")
|
||||
individual: Optional[Individual] = Field(None, description="Details about the cardholder")
|
||||
mobile_number: Optional[str] = Field(None, description="The mobile number of the cardholder")
|
||||
postal_address: Optional[Address] = Field(None, description="Postal address for the cardholder")
|
||||
status: str = Field(..., description="The status of the cardholder (PENDING, READY, DISABLED, INCOMPLETE)")
|
||||
type: str = Field(..., description="The type of cardholder (INDIVIDUAL or DELEGATE)")
|
||||
|
||||
|
||||
class CardholderListResponse(HasMoreResponse):
|
||||
"""Model for cardholder list response."""
|
||||
items: List[Cardholder] = Field(..., description="List of cardholders")
|
||||
83
airwallex-sdk/airwallex/models/issuing_common.py
Normal file
83
airwallex-sdk/airwallex/models/issuing_common.py
Normal file
@@ -0,0 +1,83 @@
|
||||
"""
|
||||
Common models for the Airwallex Issuing API.
|
||||
"""
|
||||
from typing import Optional, List, Dict, Any, Union
|
||||
from datetime import datetime
|
||||
from pydantic import Field, EmailStr
|
||||
from .base import AirwallexModel
|
||||
|
||||
|
||||
class Address(AirwallexModel):
|
||||
"""Model for address information."""
|
||||
city: str = Field(..., description="City")
|
||||
country: str = Field(..., description="Country code (ISO 3166-1 alpha-2)")
|
||||
line1: str = Field(..., description="Street address line 1")
|
||||
line2: Optional[str] = Field(None, description="Street address line 2")
|
||||
postcode: Optional[str] = Field(None, description="Postal or ZIP code")
|
||||
state: Optional[str] = Field(None, description="State or province")
|
||||
|
||||
|
||||
class Name(AirwallexModel):
|
||||
"""Model for person name."""
|
||||
first_name: str = Field(..., description="First name")
|
||||
last_name: str = Field(..., description="Last name")
|
||||
middle_name: Optional[str] = Field(None, description="Middle name")
|
||||
title: Optional[str] = Field(None, description="Title (Mr, Mrs, etc.)")
|
||||
|
||||
|
||||
class BusinessIdentifier(AirwallexModel):
|
||||
"""Model for business identifier."""
|
||||
country_code: str = Field(..., description="Country code (ISO 3166-1 alpha-2)")
|
||||
number: str = Field(..., description="Identifier number")
|
||||
type: str = Field(..., description="Identifier type (e.g., 'BRN')")
|
||||
|
||||
|
||||
class Employer(AirwallexModel):
|
||||
"""Model for employer information."""
|
||||
business_name: str = Field(..., description="Business name")
|
||||
business_identifiers: Optional[List[BusinessIdentifier]] = Field(None, description="Business identifiers")
|
||||
|
||||
|
||||
class Merchant(AirwallexModel):
|
||||
"""Model for merchant information."""
|
||||
category_code: Optional[str] = Field(None, description="Merchant category code")
|
||||
city: Optional[str] = Field(None, description="Merchant city")
|
||||
country: Optional[str] = Field(None, description="Merchant country")
|
||||
identifier: Optional[str] = Field(None, description="Merchant identifier")
|
||||
name: Optional[str] = Field(None, description="Merchant name")
|
||||
postcode: Optional[str] = Field(None, description="Merchant postal code")
|
||||
state: Optional[str] = Field(None, description="Merchant state")
|
||||
|
||||
|
||||
class RiskDetails(AirwallexModel):
|
||||
"""Model for risk details."""
|
||||
risk_actions_performed: Optional[List[str]] = Field(None, description="Risk actions performed")
|
||||
risk_factors: Optional[List[str]] = Field(None, description="Risk factors identified")
|
||||
three_dsecure_outcome: Optional[str] = Field(None, description="3D Secure outcome")
|
||||
|
||||
|
||||
class DeviceInformation(AirwallexModel):
|
||||
"""Model for device information."""
|
||||
device_id: Optional[str] = Field(None, description="Device identifier")
|
||||
device_type: Optional[str] = Field(None, description="Device type")
|
||||
|
||||
|
||||
class TransactionUsage(AirwallexModel):
|
||||
"""Model for transaction usage."""
|
||||
transaction_scope: str = Field(..., description="Transaction scope (e.g., 'MAGSTRIPE')")
|
||||
usage_scope: str = Field(..., description="Usage scope (e.g., 'INTERNATIONAL')")
|
||||
|
||||
|
||||
class DeliveryDetails(AirwallexModel):
|
||||
"""Model for delivery details."""
|
||||
delivery_method: Optional[str] = Field(None, description="Delivery method")
|
||||
tracking_number: Optional[str] = Field(None, description="Tracking number")
|
||||
courier: Optional[str] = Field(None, description="Courier")
|
||||
status: Optional[str] = Field(None, description="Delivery status")
|
||||
estimated_delivery_date: Optional[datetime] = Field(None, description="Estimated delivery date")
|
||||
|
||||
|
||||
class HasMoreResponse(AirwallexModel):
|
||||
"""Base model for paginated responses with has_more field."""
|
||||
has_more: bool = Field(..., description="Whether there are more items available")
|
||||
items: List[Any] = Field(..., description="List of items")
|
||||
62
airwallex-sdk/airwallex/models/issuing_config.py
Normal file
62
airwallex-sdk/airwallex/models/issuing_config.py
Normal file
@@ -0,0 +1,62 @@
|
||||
"""
|
||||
Models for the Airwallex Issuing Config API.
|
||||
"""
|
||||
from typing import Optional, List, Dict, Any
|
||||
from datetime import datetime
|
||||
from pydantic import Field
|
||||
from .base import AirwallexModel
|
||||
from .issuing_common import TransactionUsage
|
||||
|
||||
|
||||
class RemoteAuthSettings(AirwallexModel):
|
||||
"""Model for remote auth settings."""
|
||||
created_at: Optional[datetime] = Field(None, description="Creation timestamp")
|
||||
default_action: Optional[str] = Field(None, description="Default action when remote auth fails")
|
||||
enabled: Optional[bool] = Field(None, description="Whether remote auth is enabled")
|
||||
shared_secret: Optional[str] = Field(None, description="Shared secret key")
|
||||
updated_at: Optional[datetime] = Field(None, description="Last update timestamp")
|
||||
url: Optional[str] = Field(None, description="Remote auth endpoint URL")
|
||||
|
||||
|
||||
class RemoteCallMethod(AirwallexModel):
|
||||
"""Model for remote call method."""
|
||||
name: str = Field(..., description="Method name")
|
||||
path: str = Field(..., description="Method path")
|
||||
|
||||
|
||||
class RemoteCallConfig(AirwallexModel):
|
||||
"""Model for remote call configuration."""
|
||||
methods: List[RemoteCallMethod] = Field(..., description="Available methods")
|
||||
shared_secret: Optional[str] = Field(None, description="Shared secret key")
|
||||
url: str = Field(..., description="Base URL")
|
||||
|
||||
|
||||
class RemoteProvisioningConfig(AirwallexModel):
|
||||
"""Model for remote provisioning configuration."""
|
||||
activated: Optional[bool] = Field(None, description="Whether remote provisioning is activated")
|
||||
shared_secret: Optional[str] = Field(None, description="Shared secret key")
|
||||
url: Optional[str] = Field(None, description="Remote provisioning endpoint URL")
|
||||
|
||||
|
||||
class SpendingLimitSettings(AirwallexModel):
|
||||
"""Model for spending limit settings."""
|
||||
default_limits: Optional[Dict[str, Dict[str, float]]] = Field(None, description="Default limits")
|
||||
maximum_limits: Optional[Dict[str, Dict[str, float]]] = Field(None, description="Maximum limits")
|
||||
|
||||
|
||||
class IssuingConfig(AirwallexModel):
|
||||
"""Model for issuing configuration."""
|
||||
resource_name: str = "issuing/config"
|
||||
|
||||
blocked_transaction_usages: Optional[List[TransactionUsage]] = Field(None, description="Blocked transaction usages")
|
||||
remote_auth_settings: Optional[RemoteAuthSettings] = Field(None, description="Remote authorization settings")
|
||||
remote_call_config: Optional[RemoteCallConfig] = Field(None, description="Remote call configuration")
|
||||
remote_provisioning_config: Optional[RemoteProvisioningConfig] = Field(None, description="Remote provisioning configuration")
|
||||
spending_limit_settings: Optional[SpendingLimitSettings] = Field(None, description="Spending limit settings")
|
||||
|
||||
|
||||
class IssuingConfigUpdateRequest(AirwallexModel):
|
||||
"""Model for issuing config update request."""
|
||||
remote_auth: Optional[RemoteAuthSettings] = Field(None, description="Remote authorization configuration")
|
||||
remote_call_config: Optional[RemoteCallConfig] = Field(None, description="Remote call configuration")
|
||||
remote_provisioning_config: Optional[RemoteProvisioningConfig] = Field(None, description="Remote provisioning configuration")
|
||||
@@ -0,0 +1,38 @@
|
||||
"""
|
||||
Models for the Airwallex Issuing Digital Wallet Token API.
|
||||
"""
|
||||
from typing import Optional, List, Dict, Any
|
||||
from datetime import datetime
|
||||
from pydantic import Field
|
||||
from .base import AirwallexModel
|
||||
from .issuing_common import DeviceInformation, HasMoreResponse
|
||||
|
||||
|
||||
class RiskInformation(AirwallexModel):
|
||||
"""Model for token risk information."""
|
||||
wallet_provider_account_score: Optional[str] = Field(None, description="Wallet provider account score")
|
||||
wallet_provider_device_score: Optional[str] = Field(None, description="Wallet provider device score")
|
||||
|
||||
|
||||
class DigitalWalletToken(AirwallexModel):
|
||||
"""Model for an Airwallex digital wallet token."""
|
||||
resource_name: str = "issuing/digital_wallet_tokens"
|
||||
|
||||
card_id: str = Field(..., description="Unique identifier for card associated with the token")
|
||||
cardholder_id: str = Field(..., description="Unique identifier for cardholder associated with the token")
|
||||
create_time: datetime = Field(..., description="The time this token was created")
|
||||
device_information: Optional[DeviceInformation] = Field(None, description="Device information")
|
||||
expiry_month: int = Field(..., description="Token expiry month")
|
||||
expiry_year: int = Field(..., description="Token expiry year")
|
||||
masked_card_number: str = Field(..., description="Masked card number")
|
||||
pan_reference_id: str = Field(..., description="Unique identifier for the tokenization of this card")
|
||||
risk_information: Optional[RiskInformation] = Field(None, description="Risk information")
|
||||
token_id: str = Field(..., description="Unique Identifier for token")
|
||||
token_reference_id: str = Field(..., description="Unique identifier of the digital wallet token within the card network")
|
||||
token_status: str = Field(..., description="Status of the token")
|
||||
token_type: str = Field(..., description="The type of this token")
|
||||
|
||||
|
||||
class DigitalWalletTokenListResponse(HasMoreResponse):
|
||||
"""Model for digital wallet token list response."""
|
||||
items: List[DigitalWalletToken] = Field(..., description="List of digital wallet tokens")
|
||||
42
airwallex-sdk/airwallex/models/issuing_transaction.py
Normal file
42
airwallex-sdk/airwallex/models/issuing_transaction.py
Normal file
@@ -0,0 +1,42 @@
|
||||
"""
|
||||
Models for the Airwallex Issuing Transaction API.
|
||||
"""
|
||||
from typing import Optional, List, Dict, Any
|
||||
from datetime import datetime
|
||||
from pydantic import Field
|
||||
from .base import AirwallexModel
|
||||
from .issuing_common import Merchant, RiskDetails, HasMoreResponse
|
||||
|
||||
|
||||
class Transaction(AirwallexModel):
|
||||
"""Model for an Airwallex issuing transaction."""
|
||||
resource_name: str = "issuing/transactions"
|
||||
|
||||
acquiring_institution_identifier: Optional[str] = Field(None, description="Unique Identifier for acquiring institution")
|
||||
auth_code: Optional[str] = Field(None, description="Authorization Code")
|
||||
billing_amount: float = Field(..., description="Billing amount")
|
||||
billing_currency: str = Field(..., description="Billing Currency")
|
||||
card_id: str = Field(..., description="Unique Identifier for card")
|
||||
card_nickname: Optional[str] = Field(None, description="The nickname of the card used")
|
||||
client_data: Optional[str] = Field(None, description="Client data stored against the card record")
|
||||
digital_wallet_token_id: Optional[str] = Field(None, description="Unique Identifier for digital token")
|
||||
failure_reason: Optional[str] = Field(None, description="The reason why this transaction failed")
|
||||
lifecycle_id: Optional[str] = Field(None, description="Lifecycle ID")
|
||||
masked_card_number: str = Field(..., description="Masked card number")
|
||||
matched_authorizations: Optional[List[str]] = Field(None, description="Matched authorization IDs")
|
||||
merchant: Optional[Merchant] = Field(None, description="Merchant details")
|
||||
network_transaction_id: Optional[str] = Field(None, description="Network transaction ID")
|
||||
posted_date: Optional[datetime] = Field(None, description="Posted date")
|
||||
retrieval_ref: Optional[str] = Field(None, description="Retrieval reference number")
|
||||
risk_details: Optional[RiskDetails] = Field(None, description="Risk details")
|
||||
status: str = Field(..., description="Transaction status")
|
||||
transaction_amount: float = Field(..., description="Transaction amount")
|
||||
transaction_currency: str = Field(..., description="Transaction currency")
|
||||
transaction_date: datetime = Field(..., description="Transaction date")
|
||||
transaction_id: str = Field(..., description="Transaction ID")
|
||||
transaction_type: str = Field(..., description="Transaction type")
|
||||
|
||||
|
||||
class TransactionListResponse(HasMoreResponse):
|
||||
"""Model for transaction list response."""
|
||||
items: List[Transaction] = Field(..., description="List of transactions")
|
||||
@@ -0,0 +1,59 @@
|
||||
"""
|
||||
Models for the Airwallex Issuing Transaction Dispute API.
|
||||
"""
|
||||
from typing import Optional, List, Dict, Any
|
||||
from datetime import datetime
|
||||
from pydantic import Field
|
||||
from .base import AirwallexModel
|
||||
|
||||
|
||||
class DisputeUpdateHistory(AirwallexModel):
|
||||
"""Model for dispute update history."""
|
||||
evidence_files: Optional[List[str]] = Field(None, description="Evidence files")
|
||||
note: Optional[str] = Field(None, description="Note")
|
||||
updated_at: datetime = Field(..., description="Update timestamp")
|
||||
updated_by: str = Field(..., description="Entity that performed the update")
|
||||
|
||||
|
||||
class TransactionDisputeCreateRequest(AirwallexModel):
|
||||
"""Model for transaction dispute creation request."""
|
||||
amount: Optional[float] = Field(None, description="The amount to be disputed")
|
||||
evidence_files: Optional[List[str]] = Field(None, description="Evidence file IDs")
|
||||
notes: Optional[str] = Field(None, description="Explanation for the dispute")
|
||||
reason: str = Field(..., description="The reason for raising the dispute")
|
||||
reference: Optional[str] = Field(None, description="Internal reference")
|
||||
transaction_id: str = Field(..., description="The transaction ID to dispute")
|
||||
|
||||
|
||||
class TransactionDisputeUpdateRequest(AirwallexModel):
|
||||
"""Model for transaction dispute update request."""
|
||||
amount: Optional[float] = Field(None, description="The disputed amount")
|
||||
evidence_files: Optional[List[str]] = Field(None, description="Evidence file IDs")
|
||||
notes: Optional[str] = Field(None, description="Explanation for the dispute")
|
||||
reason: Optional[str] = Field(None, description="The reason for raising the dispute")
|
||||
request_id: str = Field(..., description="A unique request ID")
|
||||
|
||||
|
||||
class TransactionDispute(AirwallexModel):
|
||||
"""Model for an Airwallex transaction dispute."""
|
||||
resource_name: str = "issuing/transaction_disputes"
|
||||
|
||||
amount: float = Field(..., description="Dispute amount")
|
||||
created_at: datetime = Field(..., description="Creation timestamp")
|
||||
detailed_status: Optional[str] = Field(None, description="Detailed status")
|
||||
id: str = Field(..., description="Unique identifier")
|
||||
notes: Optional[str] = Field(None, description="Notes")
|
||||
reason: str = Field(..., description="Dispute reason")
|
||||
reference: Optional[str] = Field(None, description="Internal reference")
|
||||
status: str = Field(..., description="Status")
|
||||
transaction_id: str = Field(..., description="Transaction ID")
|
||||
update_history: List[DisputeUpdateHistory] = Field(..., description="Update history")
|
||||
updated_at: datetime = Field(..., description="Last update timestamp")
|
||||
updated_by: str = Field(..., description="Last updated by")
|
||||
|
||||
|
||||
class TransactionDisputeListResponse(AirwallexModel):
|
||||
"""Model for transaction dispute list response."""
|
||||
items: List[TransactionDispute] = Field(..., description="List of transaction disputes")
|
||||
page_after: Optional[str] = Field(None, description="Page bookmark for next page")
|
||||
page_before: Optional[str] = Field(None, description="Page bookmark for previous page")
|
||||
81
airwallex-sdk/airwallex/models/payment.py
Normal file
81
airwallex-sdk/airwallex/models/payment.py
Normal file
@@ -0,0 +1,81 @@
|
||||
"""
|
||||
Models for the Airwallex payment API.
|
||||
"""
|
||||
from typing import Optional, List, Dict, Any, Union
|
||||
from datetime import datetime
|
||||
from pydantic import Field, EmailStr
|
||||
from .base import AirwallexModel
|
||||
|
||||
|
||||
class PaymentAmount(AirwallexModel):
|
||||
"""Model for payment amount."""
|
||||
value: float = Field(..., description="Payment amount value")
|
||||
currency: str = Field(..., description="Currency code (ISO 4217)")
|
||||
|
||||
|
||||
class PaymentSourceDetails(AirwallexModel):
|
||||
"""Model for payment source details."""
|
||||
type: str = Field(..., description="Source type (e.g., 'account')")
|
||||
account_id: Optional[str] = Field(None, description="Account ID for account sources")
|
||||
card_id: Optional[str] = Field(None, description="Card ID for card sources")
|
||||
|
||||
|
||||
class PaymentBeneficiary(AirwallexModel):
|
||||
"""Model for payment beneficiary."""
|
||||
type: str = Field(..., description="Beneficiary type (e.g., 'bank_account', 'email')")
|
||||
id: Optional[str] = Field(None, description="Beneficiary ID for saved beneficiaries")
|
||||
name: Optional[str] = Field(None, description="Beneficiary name")
|
||||
email: Optional[EmailStr] = Field(None, description="Beneficiary email")
|
||||
country_code: Optional[str] = Field(None, description="Beneficiary country code (ISO 3166-1 alpha-2)")
|
||||
bank_details: Optional[Dict[str, Any]] = Field(None, description="Bank details for bank transfers")
|
||||
|
||||
|
||||
class Payment(AirwallexModel):
|
||||
"""Model for an Airwallex payment."""
|
||||
resource_name: str = "payments"
|
||||
|
||||
id: str = Field(..., description="Unique payment ID")
|
||||
request_id: Optional[str] = Field(None, description="Client-generated request ID")
|
||||
amount: PaymentAmount = Field(..., description="Payment amount")
|
||||
source: PaymentSourceDetails = Field(..., description="Payment source details")
|
||||
beneficiary: PaymentBeneficiary = Field(..., description="Payment beneficiary details")
|
||||
payment_method: str = Field(..., description="Payment method type")
|
||||
status: str = Field(..., description="Payment status")
|
||||
payment_date: Optional[datetime] = Field(None, description="Payment date")
|
||||
reference: Optional[str] = Field(None, description="Payment reference")
|
||||
description: Optional[str] = Field(None, description="Payment description")
|
||||
metadata: Optional[Dict[str, str]] = Field(None, description="Additional metadata")
|
||||
created_at: datetime = Field(..., description="Payment creation timestamp")
|
||||
updated_at: Optional[datetime] = Field(None, description="Payment last update timestamp")
|
||||
|
||||
|
||||
class PaymentCreateRequest(AirwallexModel):
|
||||
"""Model for payment creation request."""
|
||||
request_id: str = Field(..., description="Client-generated unique ID for the request")
|
||||
amount: PaymentAmount = Field(..., description="Payment amount")
|
||||
source: PaymentSourceDetails = Field(..., description="Payment source details")
|
||||
beneficiary: PaymentBeneficiary = Field(..., description="Payment beneficiary details")
|
||||
payment_method: str = Field(..., description="Payment method type")
|
||||
payment_date: Optional[datetime] = Field(None, description="Requested payment date")
|
||||
reference: Optional[str] = Field(None, description="Payment reference visible to the beneficiary")
|
||||
description: Optional[str] = Field(None, description="Internal payment description")
|
||||
metadata: Optional[Dict[str, str]] = Field(None, description="Additional metadata")
|
||||
|
||||
|
||||
class PaymentUpdateRequest(AirwallexModel):
|
||||
"""Model for payment update request."""
|
||||
status: Optional[str] = Field(None, description="New payment status (for cancellation)")
|
||||
payment_date: Optional[datetime] = Field(None, description="Updated payment date")
|
||||
reference: Optional[str] = Field(None, description="Updated payment reference")
|
||||
description: Optional[str] = Field(None, description="Updated payment description")
|
||||
metadata: Optional[Dict[str, str]] = Field(None, description="Updated metadata")
|
||||
|
||||
|
||||
class PaymentQuote(AirwallexModel):
|
||||
"""Model for payment quote details."""
|
||||
id: str = Field(..., description="Quote ID")
|
||||
source_amount: PaymentAmount = Field(..., description="Source amount")
|
||||
target_amount: PaymentAmount = Field(..., description="Target amount")
|
||||
fx_rate: float = Field(..., description="FX rate applied")
|
||||
fee: Optional[PaymentAmount] = Field(None, description="Fee amount")
|
||||
expires_at: datetime = Field(..., description="Quote expiration timestamp")
|
||||
Reference in New Issue
Block a user