""" 阿里云号码认证服务工具类 用于一键登录:App 端获取 token → 后端用 token 换取真实手机号 """ import logging from django.conf import settings logger = logging.getLogger(__name__) try: from alibabacloud_dypnsapi20170525.client import Client from alibabacloud_tea_openapi.models import Config from alibabacloud_dypnsapi20170525.models import GetMobileRequest PHONE_AUTH_SDK_AVAILABLE = True except ImportError: PHONE_AUTH_SDK_AVAILABLE = False class PhoneAuthClient: """阿里云号码认证客户端(单例)""" _instance = None def __new__(cls): if cls._instance is None: cls._instance = super().__new__(cls) cls._instance._initialized = False return cls._instance def __init__(self): if self._initialized: return if not PHONE_AUTH_SDK_AVAILABLE: self.client = None self._initialized = True return auth_config = settings.ALIYUN_PHONE_AUTH if not auth_config.get('ACCESS_KEY_ID'): self.client = None self._initialized = True return config = Config( access_key_id=auth_config['ACCESS_KEY_ID'], access_key_secret=auth_config['ACCESS_KEY_SECRET'], endpoint='dypnsapi.aliyuncs.com', ) self.client = Client(config) self._initialized = True def get_mobile(self, access_token): """ 用 App 端 SDK 获取的 token 换取真实手机号 :param access_token: App 端 SDK 返回的 token :return: (phone: str|None, error_msg: str) """ if not self.client: logger.warning('号码认证 SDK 未配置') return None, '号码认证服务未配置' try: request = GetMobileRequest(access_token=access_token) response = self.client.get_mobile(request) if response.body.code == 'OK': mobile = response.body.get_mobile_result_dto.mobile logger.info('号码认证成功: %s', mobile) return mobile, '' else: msg = response.body.message or response.body.code logger.error('号码认证失败: %s', msg) return None, msg except Exception as e: logger.error('号码认证异常: %s', str(e)) return None, str(e) def get_phone_auth_client(): """获取号码认证客户端单例""" return PhoneAuthClient()