import os from functools import lru_cache from typing import TYPE_CHECKING from pydantic import AliasChoices, Field from pydantic_settings import BaseSettings, SettingsConfigDict from app.config.path_conf import ENV_DIR if TYPE_CHECKING: from alipay.aop.api.AlipayClientConfig import AlipayClientConfig class AlipayConfig(BaseSettings): """支付宝SDK配置""" model_config = SettingsConfigDict( env_file=ENV_DIR / f".env.{os.getenv('ENVIRONMENT')}", env_file_encoding="utf-8", extra="ignore", case_sensitive=True, ) app_id: str = Field(default="", validation_alias=AliasChoices("ALIPAY_APPID", "ALIPAY_APP_ID"), description="支付宝应用ID") app_private_key: str = Field(default="", validation_alias=AliasChoices("ALIPAY_PRIVATE_KEY"), description="应用私钥(RSA2)") alipay_public_key: str = Field(default="", validation_alias=AliasChoices("ALIPAY_PUBLIC_KEY"), description="支付宝公钥(RSA2)") format: str = Field(default="json", validation_alias=AliasChoices("ALIPAY_FORMAT"), description="响应格式") charset: str = Field(default="UTF-8", validation_alias=AliasChoices("ALIPAY_CHARSET"), description="字符集") sign_type: str = Field(default="RSA2", validation_alias=AliasChoices("ALIPAY_SIGN_TYPE"), description="签名类型(RSA/RSA2)") sandbox: bool = Field(default=False, validation_alias=AliasChoices("ALIPAY_SANDBOX"), description="是否沙箱环境") notify_url: str = Field(default="", validation_alias=AliasChoices("ALIPAY_NOTIFY_URL"), description="异步通知地址") return_url: str = Field(default="", validation_alias=AliasChoices("ALIPAY_RETURN_URL"), description="同步跳转地址") max_retries: int = Field(default=3, description="最大重试次数") request_timeout: int = Field(default=30, description="请求超时时间(秒)") rate_limit: int = Field(default=100, description="限流阈值(每分钟)") # production_server_url: str = Field(default="https://openapi.alipay.com/gateway.do", description="生产环境网关地址") # sandbox_server_url: str = Field(default="https://openapi-sandbox.dl.alipaydev.com/gateway.do", description="沙箱环境网关地址") # # @property # def server_url(self) -> str: # """获取支付宝网关地址""" # if self.sandbox: # return self.sandbox_server_url # return self.production_server_url @property def is_valid(self) -> bool: """检查配置是否有效""" return bool(self.app_id and self.app_private_key and self.alipay_public_key) def to_alipay_client_config(self) -> "AlipayClientConfig": """转换为官方AlipayClientConfig""" from alipay.aop.api.AlipayClientConfig import AlipayClientConfig config = AlipayClientConfig(sandbox_debug=self.sandbox) config.app_id = self.app_id config.app_private_key = self.app_private_key config.alipay_public_key = self.alipay_public_key config.format = self.format config.charset = self.charset config.sign_type = self.sign_type return config @lru_cache(maxsize=1) def get_alipay_config() -> AlipayConfig: """获取支付宝配置单例""" return AlipayConfig()