fix(sms): auth sms_send 接入 SendResult(修 cooldown_sec 500)+ 记 provider/fallback

批次2 将 send_code 返回类型 int→SendResult 后,sms_send 仍把它整体塞进
SmsSendResponse.cooldown_sec:int → pydantic ValidationError → 500。改为取
send_result.cooldown_sec;成功侧 EVENT_SMS_SEND details 加 provider/fallback。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
guke
2026-07-30 16:36:45 +08:00
parent 60c8fece23
commit ca206bccb2
2 changed files with 28 additions and 2 deletions
+5 -2
View File
@@ -207,7 +207,8 @@ def sms_send(req: SmsSendRequest, request: Request, db: DbSession) -> SmsSendRes
check_rate_limits(request, subject=req.device_id, rules=send_rules)
try:
cooldown = send_code(req.phone)
send_result = send_code(req.phone)
cooldown = send_result.cooldown_sec
except SmsError as e:
risk_repo.record_behavior_event(
db,
@@ -238,7 +239,9 @@ def sms_send(req: SmsSendRequest, request: Request, db: DbSession) -> SmsSendRes
phone=req.phone,
client_ip=_client_ip(request),
outcome="success",
details={"mock": settings.SMS_MOCK},
details={"mock": settings.SMS_MOCK,
"provider": send_result.provider,
"fallback": send_result.fallback},
evaluate_rule=risk_repo.RULE_SMS_HOURLY,
)
+23
View File
@@ -68,6 +68,29 @@ def test_sms_login_and_me_flow(client) -> None:
assert r.json()["ok"] is True
def test_sms_send_records_provider_and_fallback_in_details(client, monkeypatch) -> None:
"""批次3(Task 6):sms_send 成功后风控流水 details 带 provider/fallback。
mock 默认走极光主(SMS_FALLBACK_PROVIDER 空)→ provider=jiguang、fallback=False。
(回归:修复前 send_code 返回 SendResult 被塞进 cooldown_sec:int → 500,此处 200 断言即挡住。)"""
from app.repositories import risk as risk_repo
captured: dict = {}
orig = risk_repo.record_behavior_event
def _spy(db, **kw):
if kw.get("event_type") == risk_repo.EVENT_SMS_SEND and kw.get("outcome") == "success":
captured.update(kw.get("details") or {})
return orig(db, **kw)
monkeypatch.setattr(risk_repo, "record_behavior_event", _spy)
r = client.post("/api/v1/auth/sms/send",
json={"phone": "13800009999", "device_id": "dev-provider-test"})
assert r.status_code == 200, r.text
assert captured.get("provider") == "jiguang"
assert captured.get("fallback") is False
def test_sms_send_too_frequent(client) -> None:
phone = "13900139000"
assert client.post("/api/v1/auth/sms/send", json={"phone": phone}).status_code == 200