sms
This commit is contained in:
@@ -148,7 +148,8 @@ docker run -d -p 9090:9090 \
|
|||||||
|
|
||||||
### 短信服务
|
### 短信服务
|
||||||
|
|
||||||
- `POST /api/send-sms` - 发送短信
|
- `POST /api/send-sms` - 发送验证码
|
||||||
|
- `POST /api/send-sms/diy` - 发送定制短信
|
||||||
- `GET /api/sms-records` - 获取短信记录
|
- `GET /api/sms-records` - 获取短信记录
|
||||||
|
|
||||||
### OSS 服务
|
### OSS 服务
|
||||||
|
|||||||
109
main.py
109
main.py
@@ -7,20 +7,13 @@ from fastapi.middleware.cors import CORSMiddleware
|
|||||||
from fastapi.security import APIKeyHeader
|
from fastapi.security import APIKeyHeader
|
||||||
import uuid
|
import uuid
|
||||||
import os
|
import os
|
||||||
from typing import Optional, List
|
from typing import Optional, List, Dict, Any
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
from sms import SMS
|
from sms import SMS
|
||||||
from oss_service import oss_service
|
from oss_service import oss_service
|
||||||
from config import settings
|
from config import settings
|
||||||
|
|
||||||
class SMSRequest(BaseModel):
|
|
||||||
phone_number: str
|
|
||||||
code: Optional[str] = None
|
|
||||||
template_code: Optional[str] = settings.sms_template_code
|
|
||||||
sign_name: Optional[str] = settings.sms_sign_name
|
|
||||||
|
|
||||||
class Config:
|
|
||||||
extra = "allow"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -837,33 +830,95 @@ def update_user(phone: str, user_update: UserUpdate, current_user: dict = Depend
|
|||||||
pool.putconn(conn)
|
pool.putconn(conn)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class SMSCodeRequest(BaseModel):
|
||||||
|
phone_number: str
|
||||||
|
code: str
|
||||||
|
template_code: Optional[str] = settings.sms_template_code
|
||||||
|
sign_name: Optional[str] = settings.sms_sign_name
|
||||||
|
|
||||||
|
class SMSCustomRequest(BaseModel):
|
||||||
|
phone_number: str
|
||||||
|
template_code: str
|
||||||
|
sign_name: str
|
||||||
|
template_params: Optional[Dict[str, Any]] = None
|
||||||
|
|
||||||
|
class Config:
|
||||||
|
extra = "allow"
|
||||||
|
|
||||||
@app.post("/api/send-sms", tags=["短信服务"])
|
@app.post("/api/send-sms", tags=["短信服务"])
|
||||||
async def send_sms(sms_request: SMSRequest):
|
async def send_sms(request: SMSCodeRequest):
|
||||||
"""发送短信API"""
|
"""发送验证码API"""
|
||||||
|
sms = SMS()
|
||||||
|
|
||||||
|
# 构造参数
|
||||||
|
params = {"code": request.code}
|
||||||
|
|
||||||
|
print(f"Sending Verification Code to {request.phone_number}: {request.code}")
|
||||||
|
|
||||||
|
result = sms.main(
|
||||||
|
self=sms,
|
||||||
|
phone_number=request.phone_number,
|
||||||
|
template_code=request.template_code,
|
||||||
|
sign_name=request.sign_name,
|
||||||
|
**params
|
||||||
|
)
|
||||||
|
|
||||||
|
# 保存发送记录
|
||||||
|
_save_sms_record(request.phone_number, request.template_code, request.sign_name, params, result)
|
||||||
|
|
||||||
|
if not result or not result.get('success'):
|
||||||
|
return {"status": "failed", "message": result.get('error_message') if result else "发送失败"}
|
||||||
|
|
||||||
|
return {"status": "success", "message": "验证码发送请求已处理", "data": result}
|
||||||
|
|
||||||
|
@app.post("/api/send-sms/diy", tags=["短信服务"])
|
||||||
|
async def send_custom_sms(request: SMSCustomRequest):
|
||||||
|
"""通用短信发送API (支持自定义模板和参数)"""
|
||||||
sms = SMS()
|
sms = SMS()
|
||||||
|
|
||||||
# 获取所有参数
|
# 获取所有参数
|
||||||
request_data = sms_request.dict()
|
request_data = request.dict()
|
||||||
|
|
||||||
# 提取固定参数
|
# 提取已知字段
|
||||||
phone_number = request_data.pop('phone_number')
|
phone_number = request_data.pop('phone_number')
|
||||||
template_code = request_data.pop('template_code')
|
template_code = request_data.pop('template_code')
|
||||||
sign_name = request_data.pop('sign_name')
|
sign_name = request_data.pop('sign_name')
|
||||||
|
template_params = request_data.pop('template_params', None)
|
||||||
|
|
||||||
# 过滤掉值为 None 的参数,剩余的作为动态参数
|
# 剩下的作为动态参数
|
||||||
dynamic_params = {k: v for k, v in request_data.items() if v is not None}
|
dynamic_params = request_data
|
||||||
|
|
||||||
print(f"Sending SMS with template_code: {template_code}, sign_name: {sign_name}, params: {dynamic_params}")
|
# 如果有显式的 template_params,合并进去
|
||||||
|
if template_params:
|
||||||
|
dynamic_params.update(template_params)
|
||||||
|
|
||||||
|
# 特殊处理:兼容 Swagger UI 或某些客户端生成的 additionalProp1
|
||||||
|
if 'additionalProp1' in dynamic_params and isinstance(dynamic_params['additionalProp1'], dict):
|
||||||
|
extra_props = dynamic_params.pop('additionalProp1')
|
||||||
|
dynamic_params.update(extra_props)
|
||||||
|
|
||||||
|
print(f"Sending Custom SMS with template_code: {template_code}, params: {dynamic_params}")
|
||||||
|
|
||||||
result = sms.main(
|
result = sms.main(
|
||||||
self=sms,
|
self=sms,
|
||||||
phone_number=phone_number,
|
phone_number=phone_number,
|
||||||
template_code=template_code,
|
template_code=template_code,
|
||||||
sign_name=sign_name,
|
sign_name=sign_name,
|
||||||
**dynamic_params
|
**dynamic_params
|
||||||
)
|
)
|
||||||
|
|
||||||
# 保存发送记录到数据库
|
# 保存发送记录
|
||||||
|
_save_sms_record(phone_number, template_code, sign_name, dynamic_params, result)
|
||||||
|
|
||||||
|
if not result or not result.get('success'):
|
||||||
|
return {"status": "failed", "message": result.get('error_message') if result else "发送失败"}
|
||||||
|
|
||||||
|
return {"status": "success", "message": "短信发送请求已处理", "data": result}
|
||||||
|
|
||||||
|
def _save_sms_record(phone_number, template_code, sign_name, params, result):
|
||||||
|
"""辅助函数:保存短信记录到数据库"""
|
||||||
conn = pool.getconn()
|
conn = pool.getconn()
|
||||||
try:
|
try:
|
||||||
with conn.cursor() as cur:
|
with conn.cursor() as cur:
|
||||||
@@ -871,15 +926,7 @@ async def send_sms(sms_request: SMSRequest):
|
|||||||
biz_id = result.get('biz_id') if result else None
|
biz_id = result.get('biz_id') if result else None
|
||||||
error_message = result.get('error_message') if result else 'Unknown error'
|
error_message = result.get('error_message') if result else 'Unknown error'
|
||||||
|
|
||||||
# 将参数转换为字符串存储
|
saved_param = json.dumps(params, ensure_ascii=False) if params else ""
|
||||||
if dynamic_params:
|
|
||||||
# 如果只有 code 参数,为了保持兼容性,优先尝试只存 code 值(如果这是之前的习惯)
|
|
||||||
# 但考虑到现在支持多参数,存 JSON 更加通用。
|
|
||||||
# 这里为了直观,如果有多个参数或没有 code,存 JSON。
|
|
||||||
# 如果只有 code,也可以存 JSON,因为 sms.py 内部最终是转 JSON 发送的。
|
|
||||||
saved_param = json.dumps(dynamic_params, ensure_ascii=False)
|
|
||||||
else:
|
|
||||||
saved_param = ""
|
|
||||||
|
|
||||||
cur.execute("""
|
cur.execute("""
|
||||||
INSERT INTO sms_records (phone_number, template_code, template_param, sign_name, status, biz_id, error_message)
|
INSERT INTO sms_records (phone_number, template_code, template_param, sign_name, status, biz_id, error_message)
|
||||||
@@ -890,11 +937,7 @@ async def send_sms(sms_request: SMSRequest):
|
|||||||
print(f"Error saving SMS record: {e}")
|
print(f"Error saving SMS record: {e}")
|
||||||
finally:
|
finally:
|
||||||
pool.putconn(conn)
|
pool.putconn(conn)
|
||||||
|
|
||||||
if not result or not result.get('success'):
|
|
||||||
return {"status": "failed", "message": result.get('error_message') if result else "发送失败"}
|
|
||||||
|
|
||||||
return {"status": "success", "message": "短信发送请求已处理", "data": result}
|
|
||||||
|
|
||||||
class ConversationCreate(BaseModel):
|
class ConversationCreate(BaseModel):
|
||||||
user_phone: str | None = None
|
user_phone: str | None = None
|
||||||
|
|||||||
Reference in New Issue
Block a user