feat(sms): 加 SendResult 结果类型(cooldown+provider+fallback)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
guke
2026-07-30 15:39:31 +08:00
parent 2399e56a45
commit cbe1d340d6
2 changed files with 41 additions and 0 deletions
+15
View File
@@ -5,6 +5,8 @@
"""
from __future__ import annotations
from dataclasses import dataclass
from app.core.config import settings
@@ -18,6 +20,19 @@ class SmsError(Exception):
self.status_code = status_code
@dataclass(frozen=True)
class SendResult:
"""发码结果:距下次可发秒数 + 实际发码的 provider 名 + 是否走了备(fallback)。
分派层 send_code 的返回类型(provider 各自的 send_code 仍返回 int cooldown
由分派层包装)。auth 层据此把渠道记入风控流水 details。
"""
cooldown_sec: int
provider: str
fallback: bool = False
def mock_verify(code: str) -> bool:
"""mock 模式校验:放行任意 SMS_CODE_LENGTH 位数字(provider 无关,测试/开发便利,不真校验)。"""
return len(code) == settings.SMS_CODE_LENGTH and code.isdigit()
+26
View File
@@ -0,0 +1,26 @@
"""SMS 共享基座类型 SendResult。"""
from __future__ import annotations
import dataclasses
import pytest
from app.integrations.sms.base import SendResult
def test_send_result_fields():
r = SendResult(cooldown_sec=60, provider="jiguang", fallback=True)
assert r.cooldown_sec == 60
assert r.provider == "jiguang"
assert r.fallback is True
def test_send_result_fallback_defaults_false():
r = SendResult(cooldown_sec=60, provider="jiguang")
assert r.fallback is False
def test_send_result_is_frozen():
r = SendResult(cooldown_sec=60, provider="jiguang")
with pytest.raises(dataclasses.FrozenInstanceError):
r.provider = "chuanglan"