feat(third_party_api): 添加Dify工作流支持并优化API管理
重构UniversalAPIManager以支持Dify工作流API 添加DifyWorkflowRequest模型和控制器方法 优化API密钥管理和请求处理逻辑 修改JWT验证方式从HTTPBearer到Header 更新API配置以支持新的Dify端点
This commit is contained in:
parent
9779c79516
commit
107e90cbcb
@ -9,8 +9,10 @@ from app.schemas.valuation import (
|
||||
UserValuationOut,
|
||||
UserValuationDetail
|
||||
)
|
||||
from app.models.user import AppUser
|
||||
|
||||
from app.schemas.base import Success, SuccessExtra
|
||||
from app.utils.app_user_jwt import get_current_app_user_id
|
||||
from app.utils.app_user_jwt import get_current_app_user
|
||||
|
||||
app_valuations_router = APIRouter(tags=["用户端估值评估"])
|
||||
|
||||
@ -18,19 +20,70 @@ app_valuations_router = APIRouter(tags=["用户端估值评估"])
|
||||
@app_valuations_router.post("/", summary="创建估值评估")
|
||||
async def create_valuation(
|
||||
data: UserValuationCreate,
|
||||
user_id: int = Depends(get_current_app_user_id)
|
||||
current_user: AppUser = Depends(get_current_app_user)
|
||||
):
|
||||
"""
|
||||
用户创建估值评估申请
|
||||
"""
|
||||
try:
|
||||
result = await user_valuation_controller.create_valuation(
|
||||
user_id=user_id,
|
||||
user_id=current_user.id,
|
||||
data=data
|
||||
)
|
||||
# 使用model_dump_json()来正确序列化datetime,然后解析为dict
|
||||
import json
|
||||
result_dict = json.loads(result.model_dump_json())
|
||||
# 开始计算 估值 信息
|
||||
# 1 # 经济价值B1模块: EconomicValueB1Calculator | BasicValueB11Calculator | TrafficFactorB12Calculator | PolicyMultiplierB13Calculator
|
||||
# 1.1 EconomicValueB1Calculator
|
||||
# input_data = {
|
||||
# # 基础价值B11相关参数
|
||||
# 'three_year_income': data.three_year_income,
|
||||
# 'patent_score': data.pa, # 专利分
|
||||
# 'popularity_score': data.popularity_score, # 普及地域分值
|
||||
# 'infringement_score': data.infringement_score, # 侵权分
|
||||
# 'innovation_ratio': data.innovation_ratio,
|
||||
# 'esg_score':data.esg_score,
|
||||
# 'industry_coefficient':data.industry_coefficient,
|
||||
|
||||
# # 流量因子B12相关参数
|
||||
# 'search_index_s1': 4500.0,
|
||||
# 'industry_average_s2': 5000.0,
|
||||
# # 'social_media_spread_s3': social_media_spread_s3,
|
||||
# 'likes': 4, # 点赞
|
||||
# 'comments': 5, # 评论
|
||||
# 'shares': 6, # 转发
|
||||
# 'followers': 7, # 粉丝数
|
||||
|
||||
# 'click_count': 1000,# 点击量
|
||||
# 'view_count': 100, # 内容浏览量
|
||||
|
||||
# # 政策乘数B13相关参数
|
||||
# 'policy_match_score': 10.0, # 政策匹配度
|
||||
# 'implementation_stage': 10.0, # 实施阶段评分
|
||||
# 'funding_support': 10.0 # 资金支持度
|
||||
# }
|
||||
# 1.2 BasicValueB11Calculator
|
||||
# 1.3 TrafficFactorB12Calculator
|
||||
# 1.4 PolicyMultiplierB13Calculator
|
||||
|
||||
# 2 # 文化价值B2模块: CulturalValueB2Calculator | LivingHeritageB21Calculator | PatternGeneB22Calculator
|
||||
# 2.1 CulturalValueB2Calculator
|
||||
# 2.2 LivingHeritageB21Calculator
|
||||
# 2.3 PatternGeneB22Calculator
|
||||
|
||||
# 3 # 风险调整系数B3模块: RiskAdjustmentB3Calculator
|
||||
# 3.1 RiskAdjustmentB3Calculator
|
||||
|
||||
# 4 # 市场估值C模块: MarketValueCCalculator | MarketBiddingC1Calculator | HeatCoefficientC2Calculator | ScarcityMultiplierC3Calculator | TemporalDecayC4Calculator
|
||||
# 4.1 MarketValueCCalculator
|
||||
# 4.2 MarketBiddingC1Calculator
|
||||
# 4.3 HeatCoefficientC2Calculator
|
||||
# 4.4 ScarcityMultiplierC3Calculator
|
||||
# 4.5 TemporalDecayC4Calculator
|
||||
|
||||
# 5 # 最终估值A模块: FinalValueACalculator
|
||||
# 5.1 FinalValueACalculator
|
||||
return Success(data=result_dict, msg="估值评估申请提交成功")
|
||||
except Exception as e:
|
||||
raise HTTPException(
|
||||
@ -42,14 +95,15 @@ async def create_valuation(
|
||||
@app_valuations_router.get("/", summary="获取我的估值评估列表")
|
||||
async def get_my_valuations(
|
||||
query: UserValuationQuery = Depends(),
|
||||
user_id: int = Depends(get_current_app_user_id)
|
||||
current_user: AppUser = Depends(get_current_app_user)
|
||||
|
||||
):
|
||||
"""
|
||||
获取当前用户的估值评估列表
|
||||
"""
|
||||
try:
|
||||
result = await user_valuation_controller.get_user_valuations(
|
||||
user_id=user_id,
|
||||
user_id=current_user.id,
|
||||
query=query
|
||||
)
|
||||
# 使用model_dump_json()来正确序列化datetime,然后解析为dict列表
|
||||
@ -73,14 +127,14 @@ async def get_my_valuations(
|
||||
@app_valuations_router.get("/{valuation_id}", summary="获取估值评估详情")
|
||||
async def get_valuation_detail(
|
||||
valuation_id: int,
|
||||
user_id: int = Depends(get_current_app_user_id)
|
||||
current_user: AppUser = Depends(get_current_app_user)
|
||||
):
|
||||
"""
|
||||
获取指定估值评估的详细信息
|
||||
"""
|
||||
try:
|
||||
result = await user_valuation_controller.get_user_valuation_detail(
|
||||
user_id=user_id,
|
||||
user_id=current_user.id,
|
||||
valuation_id=valuation_id
|
||||
)
|
||||
|
||||
@ -105,14 +159,14 @@ async def get_valuation_detail(
|
||||
|
||||
@app_valuations_router.get("/statistics/overview", summary="获取我的估值评估统计")
|
||||
async def get_my_valuation_statistics(
|
||||
user_id: int = Depends(get_current_app_user_id)
|
||||
current_user: AppUser = Depends(get_current_app_user)
|
||||
):
|
||||
"""
|
||||
获取当前用户的估值评估统计信息
|
||||
"""
|
||||
try:
|
||||
result = await user_valuation_controller.get_user_valuation_statistics(
|
||||
user_id=user_id
|
||||
user_id=current_user.id
|
||||
)
|
||||
return Success(data=result, msg="获取统计信息成功")
|
||||
except Exception as e:
|
||||
|
||||
@ -11,6 +11,7 @@ from app.schemas.third_party_api import (
|
||||
OCRRequest,
|
||||
XiaohongshuNoteRequest,
|
||||
JizhiliaoSearchRequest,
|
||||
DifyWorkflowRequest,
|
||||
APIResponse,
|
||||
APIProviderInfo,
|
||||
APIEndpointInfo,
|
||||
@ -110,4 +111,22 @@ async def search_jizhiliao_index(request: JizhiliaoSearchRequest):
|
||||
return Fail(message=result.message)
|
||||
except Exception as e:
|
||||
logger.error(f"极致聊指数搜索失败: {e}")
|
||||
return Fail(message=f"极致聊指数搜索失败: {str(e)}")
|
||||
return Fail(message=f"极致聊指数搜索失败: {str(e)}")
|
||||
|
||||
@router.post("/dify/workflows/run", summary="运行Dify工作流")
|
||||
async def run_dify_workflow(request: DifyWorkflowRequest):
|
||||
"""运行Dify工作流"""
|
||||
try:
|
||||
result = await third_party_api_controller.run_dify_workflow(
|
||||
zl_img=request.zl_img,
|
||||
response_mode=request.response_mode,
|
||||
user=request.user
|
||||
)
|
||||
|
||||
if result.success:
|
||||
return Success(data=result.data, message=result.message)
|
||||
else:
|
||||
return Fail(message=result.message)
|
||||
except Exception as e:
|
||||
logger.error(f"运行Dify工作流失败: {e}")
|
||||
return Fail(message=f"运行Dify工作流失败: {str(e)}")
|
||||
@ -78,9 +78,9 @@ class ThirdPartyAPIController:
|
||||
endpoint="patent",
|
||||
params={
|
||||
"searchKey": company_name,
|
||||
"pageNo": 1,
|
||||
"range": 100,
|
||||
"searchType": 0,
|
||||
"pageNo": "1",
|
||||
"range": "100",
|
||||
"searchType": '1',
|
||||
"ChinazVer": chinaz_ver
|
||||
}
|
||||
)
|
||||
@ -125,6 +125,20 @@ class ThirdPartyAPIController:
|
||||
timeout=timeout
|
||||
)
|
||||
|
||||
async def run_dify_workflow(
|
||||
self,
|
||||
zl_img: str,
|
||||
response_mode: str = "blocking",
|
||||
user: str = "default_user"
|
||||
) -> APIResponse:
|
||||
"""运行Dify工作流"""
|
||||
params = {
|
||||
"inputs": {"zl_img": zl_img},
|
||||
"response_mode": response_mode,
|
||||
"user": user
|
||||
}
|
||||
return await self.make_api_request("dify", "workflows_run", params)
|
||||
|
||||
|
||||
# 创建全局控制器实例
|
||||
third_party_api_controller = ThirdPartyAPIController()
|
||||
@ -28,6 +28,12 @@ class JizhiliaoSearchRequest(BaseAPIRequest):
|
||||
page: int = Field(1, description="页码")
|
||||
size: int = Field(10, description="每页数量")
|
||||
|
||||
class DifyWorkflowRequest(BaseAPIRequest):
|
||||
"""Dify工作流请求模型"""
|
||||
zl_img: str = Field(..., description="资料图片字段")
|
||||
response_mode: str = Field("blocking", description="响应模式,blocking或streaming")
|
||||
user: str = Field(..., description="用户标识")
|
||||
|
||||
class APIResponse(BaseModel):
|
||||
"""API响应模型"""
|
||||
success: bool
|
||||
|
||||
@ -32,7 +32,7 @@ class APIConfig:
|
||||
"base_url": "https://openapi.chinaz.net",
|
||||
"endpoints": {
|
||||
"copyright_software": {
|
||||
"api_key": os.getenv("CHINAZ_COPYRIGHT_API_KEY", "YOUR_API_KEY"),
|
||||
"APIKey": os.getenv("CHINAZ_COPYRIGHT_API_KEY", "YOUR_API_KEY"),
|
||||
"path": "/v1/1036/copyrightsoftware",
|
||||
"method": "POST",
|
||||
"description": "企业软件著作权查询",
|
||||
@ -40,7 +40,7 @@ class APIConfig:
|
||||
"optional_params": ["sign"]
|
||||
},
|
||||
"patent": {
|
||||
"api_key": os.getenv("CHINAZ_PATENT_API_KEY", "YOUR_API_KEY"),
|
||||
"APIKey": os.getenv("CHINAZ_PATENT_API_KEY", "apiuser_quantity_045e9c832d253a1fdfd41edd1a85a254_4e9f3a38e384414e97fdbd33cca13124"),
|
||||
"path": "/v1/1036/patent",
|
||||
"method": "POST",
|
||||
"description": "企业专利信息查询",
|
||||
@ -48,7 +48,7 @@ class APIConfig:
|
||||
"optional_params": ["sign", "searchType"]
|
||||
},
|
||||
"judgement": {
|
||||
"api_key": os.getenv("CHINAZ_JUDGEMENT_API_KEY", "YOUR_API_KEY"),
|
||||
"APIKey": os.getenv("CHINAZ_JUDGEMENT_API_KEY", "YOUR_API_KEY"),
|
||||
"path": "/v1/1036/judgementdetailv4",
|
||||
"method": "POST",
|
||||
"description": "司法综合数据查询",
|
||||
@ -56,7 +56,7 @@ class APIConfig:
|
||||
"optional_params": ["sign", "q", "idCardNo", "datatype", "id", "pageNo"]
|
||||
},
|
||||
"recognition_ocr": {
|
||||
"api_key": os.getenv("CHINAZ_OCR_API_KEY", "YOUR_API_KEY"),
|
||||
"APIKey": os.getenv("CHINAZ_OCR_API_KEY", "apiuser_quantity_d0848e65f7b7ae50ff6f1ae37e413586_31466987e2ef402ba3142b72680a92fc"),
|
||||
"path": "/v1/1024/recognition_ocr",
|
||||
"method": "POST",
|
||||
"description": "图片OCR识别",
|
||||
@ -72,184 +72,75 @@ class APIConfig:
|
||||
"timeout": 30,
|
||||
"retries": 3,
|
||||
"endpoints": {
|
||||
"xiaohongshu": {
|
||||
"api_key": os.getenv("XIAOHONGSHU_TOKEN", "YNSbIjdU"),
|
||||
"base_url": "https://api.justoneapi.com",
|
||||
"timeout": 30,
|
||||
"retries": 3,
|
||||
"endpoints": {
|
||||
"xiaohongshu_note_detail": {
|
||||
"path": "/api/xiaohongshu/get-note-detail/v7",
|
||||
"method": "GET",
|
||||
"description": "小红书笔记详情查询",
|
||||
"required_params": ["noteId"],
|
||||
"optional_params": ["token"]
|
||||
},
|
||||
"xiaohongshu_user_info": {
|
||||
"path": "/api/xiaohongshu/get-user-info/v7",
|
||||
"method": "GET",
|
||||
"description": "小红书用户信息查询",
|
||||
"required_params": ["userId"],
|
||||
"optional_params": ["token"]
|
||||
},
|
||||
"xiaohongshu_search_notes": {
|
||||
"path": "/api/xiaohongshu/search-notes/v7",
|
||||
"method": "GET",
|
||||
"description": "小红书笔记搜索",
|
||||
"required_params": ["keyword"],
|
||||
"optional_params": ["page", "size", "token"]
|
||||
},
|
||||
"weibo_user_detail": {
|
||||
"path": "/api/weibo/get-user-detail/v1", # 微博只有粉丝数接口
|
||||
"method": "GET",
|
||||
"description": "获取用户信息 包括昵称、头像、用户ID、粉丝数、关注数、简介、认证状态等公开信息",
|
||||
"required_params": ["token", "uid"],
|
||||
"optional_params": ["token", "uid"]
|
||||
},
|
||||
"weixin_user_detail": {
|
||||
"path": "/api/weixin/get-user-post/v1",
|
||||
"method": "GET",
|
||||
"description": "公众号发布的文章内容,包括标题、作者、发布时间、内容摘要以及阅读数、点赞数与转发数等互动数据",
|
||||
"required_params": ["token", "wxid"],
|
||||
"optional_params": ["token", "wxid"]
|
||||
},
|
||||
"douyin_video_detail": {
|
||||
"path": "/api/douyin/get-video-detail/v2",
|
||||
"method": "GET",
|
||||
"description": "该接口用于获取指定抖音视频的详细信息,包括视频地址、描述文案、作者信息、发布时间、播放量、点赞数、评论数与分享数等",
|
||||
"required_params": ["token", "videoId"],
|
||||
"optional_params": ["token", "videoId"]
|
||||
},
|
||||
"kuaishou_video_detail": {
|
||||
"path": "/api/kuaishou/get-video-detail/v2",
|
||||
"method": "GET",
|
||||
"description": "该接口用于获取指定抖音视频的详细信息,包括视频地址、描述文案、作者信息、发布时间、播放量、点赞数、评论数与分享数等",
|
||||
"required_params": ["token", "videoId"],
|
||||
"optional_params": ["token", "videoId"]
|
||||
},
|
||||
"bilibili_video_detail": {
|
||||
"path": "/api/bilibili/get-video-detail/v2",
|
||||
"method": "GET",
|
||||
"description": "该接口用于获取指定抖音视频的详细信息,包括视频地址、描述文案、作者信息、发布时间、播放量、点赞数、评论数与分享数等",
|
||||
"required_params": ["token", "bvid"],
|
||||
"optional_params": ["token", "bvid"]
|
||||
}
|
||||
}
|
||||
"xiaohongshu_note_detail": {
|
||||
"path": "/api/xiaohongshu/get-note-detail/v7",
|
||||
"method": "GET",
|
||||
"description": "小红书笔记详情查询",
|
||||
"required_params": ["noteId"],
|
||||
"optional_params": ["token"]
|
||||
},
|
||||
"weibo": {
|
||||
"api_key": os.getenv("XIAOHONGSHU_TOKEN", "YNSbIjdU"),
|
||||
"base_url": "https://api.justoneapi.com",
|
||||
"timeout": 30,
|
||||
"retries": 3,
|
||||
"endpoints": {
|
||||
"weibo_user_detail": {
|
||||
"path": "/api/weibo/get-user-detail/v1", # 微博只有粉丝数接口
|
||||
"method": "GET",
|
||||
"description": "获取用户信息 包括昵称、头像、用户ID、粉丝数、关注数、简介、认证状态等公开信息",
|
||||
"required_params": ["token", "uid"],
|
||||
"optional_params": ["token", "uid"]
|
||||
},
|
||||
|
||||
}
|
||||
"xiaohongshu_user_info": {
|
||||
"path": "/api/xiaohongshu/get-user-info/v7",
|
||||
"method": "GET",
|
||||
"description": "小红书用户信息查询",
|
||||
"required_params": ["userId"],
|
||||
"optional_params": ["token"]
|
||||
},
|
||||
"weixin": {
|
||||
"api_key": os.getenv("XIAOHONGSHU_TOKEN", "YNSbIjdU"),
|
||||
"base_url": "https://api.justoneapi.com",
|
||||
"timeout": 30,
|
||||
"retries": 3,
|
||||
"endpoints": {
|
||||
"weixin_user_detail": {
|
||||
"path": "/api/weixin/get-user-post/v1",
|
||||
"method": "GET",
|
||||
"description": "公众号发布的文章内容,包括标题、作者、发布时间、内容摘要以及阅读数、点赞数与转发数等互动数据",
|
||||
"required_params": ["token", "wxid"],
|
||||
"optional_params": ["token", "wxid"]
|
||||
}
|
||||
}
|
||||
"xiaohongshu_search_notes": {
|
||||
"path": "/api/xiaohongshu/search-notes/v7",
|
||||
"method": "GET",
|
||||
"description": "小红书笔记搜索",
|
||||
"required_params": ["keyword"],
|
||||
"optional_params": ["page", "size", "token"]
|
||||
},
|
||||
"douyin": {
|
||||
"api_key": os.getenv("XIAOHONGSHU_TOKEN", "YNSbIjdU"),
|
||||
"base_url": "https://api.justoneapi.com",
|
||||
"timeout": 30,
|
||||
"retries": 3,
|
||||
"endpoints": {
|
||||
"douyin_video_detail": {
|
||||
"path": "/api/douyin/get-video-detail/v2",
|
||||
"method": "GET",
|
||||
"description": "该接口用于获取指定抖音视频的详细信息,包括视频地址、描述文案、作者信息、发布时间、播放量、点赞数、评论数与分享数等",
|
||||
"required_params": ["token", "videoId"],
|
||||
"optional_params": ["token", "videoId"]
|
||||
}
|
||||
}
|
||||
"weibo_user_detail": {
|
||||
"path": "/api/weibo/get-user-detail/v1",
|
||||
"method": "GET",
|
||||
"description": "获取用户信息 包括昵称、头像、用户ID、粉丝数、关注数、简介、认证状态等公开信息",
|
||||
"required_params": ["token", "uid"],
|
||||
"optional_params": []
|
||||
},
|
||||
"bilibili": {
|
||||
"api_key": os.getenv("XIAOHONGSHU_TOKEN", "YNSbIjdU"),
|
||||
"base_url": "https://api.justoneapi.com",
|
||||
"timeout": 30,
|
||||
"retries": 3,
|
||||
"endpoints": {
|
||||
"bilibili_video_detail": {
|
||||
"path": "/api/bilibili/get-video-detail/v2",
|
||||
"method": "GET",
|
||||
"description": "该接口用于获取指定抖音视频的详细信息,包括视频地址、描述文案、作者信息、发布时间、播放量、点赞数、评论数与分享数等",
|
||||
"required_params": ["token", "bvid"],
|
||||
"optional_params": ["token", "bvid"]
|
||||
}
|
||||
}
|
||||
"weixin_user_detail": {
|
||||
"path": "/api/weixin/get-user-post/v1",
|
||||
"method": "GET",
|
||||
"description": "公众号发布的文章内容,包括标题、作者、发布时间、内容摘要以及阅读数、点赞数与转发数等互动数据",
|
||||
"required_params": ["token", "wxid"],
|
||||
"optional_params": []
|
||||
},
|
||||
"kuaishou": {
|
||||
"api_key": os.getenv("XIAOHONGSHU_TOKEN", "YNSbIjdU"),
|
||||
"base_url": "https://api.justoneapi.com",
|
||||
"timeout": 30,
|
||||
"retries": 3,
|
||||
"endpoints": {
|
||||
"kuaishou_video_detail": {
|
||||
"path": "/api/kuaishou/get-video-detail/v2",
|
||||
"method": "GET",
|
||||
"description": "该接口用于获取指定抖音视频的详细信息,包括视频地址、描述文案、作者信息、发布时间、播放量、点赞数、评论数与分享数等",
|
||||
"required_params": ["token", "videoId"],
|
||||
"optional_params": ["token", "videoId"]
|
||||
}
|
||||
}
|
||||
"douyin_video_detail": {
|
||||
"path": "/api/douyin/get-video-detail/v2",
|
||||
"method": "GET",
|
||||
"description": "该接口用于获取指定抖音视频的详细信息,包括视频地址、描述文案、作者信息、发布时间、播放量、点赞数、评论数与分享数等",
|
||||
"required_params": ["token", "videoId"],
|
||||
"optional_params": []
|
||||
},
|
||||
"other_apis": {
|
||||
"jizhiliao": {
|
||||
"api_key": os.getenv("JIZHILIAO_API_KEY", "JZL089ef0b7d0315d96"),
|
||||
"base_url": "https://api.justoneapi.com",
|
||||
"timeout": 30,
|
||||
"retries": 3,
|
||||
"verifycode": os.getenv("JIZHILIAO_VERIFYCODE", ""),
|
||||
"endpoints": {
|
||||
"index_search": {
|
||||
"path": "/fbmain/monitor/v3/web_search",
|
||||
"method": "POST",
|
||||
"description": "极致聊指数搜索",
|
||||
"required_params": ["keyword", "mode", "BusinessType", "sub_search_type"],
|
||||
"optional_params": ["key", "verifycode"]
|
||||
},
|
||||
|
||||
}
|
||||
},
|
||||
"other": {
|
||||
# 可以添加其他第三方API配置
|
||||
|
||||
"example_api": {
|
||||
"api_key": os.getenv("EXAMPLE_API_KEY", ""),
|
||||
"base_url": "https://api.example.com",
|
||||
"endpoints": {}
|
||||
}
|
||||
"kuaishou_video_detail": {
|
||||
"path": "/api/kuaishou/get-video-detail/v2",
|
||||
"method": "GET",
|
||||
"description": "该接口用于获取指定快手视频的详细信息,包括视频地址、描述文案、作者信息、发布时间、播放量、点赞数、评论数与分享数等",
|
||||
"required_params": ["token", "videoId"],
|
||||
"optional_params": []
|
||||
},
|
||||
"common_settings": {
|
||||
"timeout": 60,
|
||||
"retries": 3,
|
||||
"sign_prefix": "634xz"
|
||||
"bilibili_video_detail": {
|
||||
"path": "/api/bilibili/get-video-detail/v2",
|
||||
"method": "GET",
|
||||
"description": "该接口用于获取指定B站视频的详细信息,包括视频地址、描述文案、作者信息、发布时间、播放量、点赞数、评论数与分享数等",
|
||||
"required_params": ["token", "bvid"],
|
||||
"optional_params": []
|
||||
},
|
||||
"jizhiliao_index_search": {
|
||||
"path": "/fbmain/monitor/v3/web_search",
|
||||
"method": "POST",
|
||||
"description": "极致聊指数搜索",
|
||||
"api_key": os.getenv("JIZHILIAO_API_KEY", "JZL089ef0b7d0315d96"),
|
||||
"verifycode": os.getenv("JIZHILIAO_VERIFYCODE", ""),
|
||||
"required_params": ["keyword", "mode", "BusinessType", "sub_search_type"],
|
||||
"optional_params": ["key", "verifycode"]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
# 微信指数
|
||||
"dajiala": {
|
||||
"api_key": "",
|
||||
"base_url": "https://www.dajiala.com",
|
||||
"timeout": 30,
|
||||
"retries": 3,
|
||||
@ -263,6 +154,26 @@ class APIConfig:
|
||||
}
|
||||
}
|
||||
},
|
||||
# dify
|
||||
"dify": {
|
||||
"base_url": "http://106.14.211.94",
|
||||
"api_key": "app-FJXEWdKv63oq1F4rHb4I8kvE",
|
||||
"timeout": 30,
|
||||
"retries": 3,
|
||||
"endpoints": {
|
||||
"workflows_run": {
|
||||
"path": "/v1/workflows/run",
|
||||
"method": "POST",
|
||||
"description": "运行工作流",
|
||||
"required_params": ["inputs", "response_mode", "user"],
|
||||
"optional_params": [],
|
||||
"headers": {
|
||||
"Authorization": "Bearer {api_key}",
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# 尝试从文件加载配置
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
from datetime import datetime, timedelta
|
||||
from typing import Optional
|
||||
import jwt
|
||||
from fastapi import HTTPException, status, Depends
|
||||
from fastapi.security import HTTPBearer
|
||||
from fastapi import HTTPException, status, Depends, Header
|
||||
from app.controllers.app_user import app_user_controller
|
||||
from app.schemas.app_user import AppUserJWTPayload
|
||||
from app.settings import settings
|
||||
@ -12,8 +11,6 @@ SECRET_KEY = settings.SECRET_KEY
|
||||
ALGORITHM = "HS256"
|
||||
ACCESS_TOKEN_EXPIRE_MINUTES = 60 * 24 * 7 # 7天
|
||||
|
||||
security = HTTPBearer()
|
||||
|
||||
|
||||
def create_app_user_access_token(user_id: int, phone: str) -> str:
|
||||
"""
|
||||
@ -51,7 +48,7 @@ def verify_app_user_token(token: str) -> Optional[AppUserJWTPayload]:
|
||||
return None
|
||||
|
||||
|
||||
def get_current_app_user_id(token: str = Depends(security)) -> int:
|
||||
def get_current_app_user_id(token: str = Header(None)) -> int:
|
||||
"""
|
||||
从令牌中获取当前AppUser ID
|
||||
"""
|
||||
@ -61,7 +58,10 @@ def get_current_app_user_id(token: str = Depends(security)) -> int:
|
||||
headers={"WWW-Authenticate": "Bearer"},
|
||||
)
|
||||
|
||||
payload = verify_app_user_token(token.credentials)
|
||||
if not token:
|
||||
raise credentials_exception
|
||||
|
||||
payload = verify_app_user_token(token)
|
||||
if payload is None:
|
||||
raise credentials_exception
|
||||
|
||||
|
||||
@ -53,7 +53,14 @@ class UniversalAPIManager:
|
||||
endpoint_config = self._get_endpoint_config(provider, endpoint)
|
||||
if not endpoint_config:
|
||||
return None
|
||||
return endpoint_config.get('api_key')
|
||||
|
||||
# 优先从端点配置中获取APIKey
|
||||
if 'APIKey' in endpoint_config:
|
||||
return endpoint_config['APIKey']
|
||||
|
||||
# 如果端点配置中没有,则从提供商配置中获取api_key
|
||||
provider_config = self._get_provider_config(provider)
|
||||
return provider_config.get('api_key')
|
||||
|
||||
def make_request(self, provider: str, endpoint: str, params: Dict[str, Any], timeout: Optional[int] = None) -> Dict[str, Any]:
|
||||
"""
|
||||
@ -89,7 +96,7 @@ class UniversalAPIManager:
|
||||
|
||||
# 添加API密钥到参数中
|
||||
params['APIKey'] = api_key
|
||||
|
||||
print(params)
|
||||
# 发送请求
|
||||
try:
|
||||
response = self.session.request(
|
||||
@ -156,6 +163,17 @@ class UniversalAPIManager:
|
||||
# 对于GET请求,将参数添加到URL中
|
||||
query_string = urllib.parse.urlencode(params)
|
||||
full_url = f"{full_url}?{query_string}"
|
||||
elif provider == 'chinaz' and method.upper() == 'POST':
|
||||
# 对于Chinaz POST请求,只将APIKey和ChinazVer添加到URL中
|
||||
url_params = {}
|
||||
if 'APIKey' in params:
|
||||
url_params['APIKey'] = params['APIKey']
|
||||
if 'ChinazVer' in params:
|
||||
url_params['ChinazVer'] = params['ChinazVer']
|
||||
|
||||
if url_params:
|
||||
query_string = urllib.parse.urlencode(url_params)
|
||||
full_url = f"{full_url}?{query_string}"
|
||||
|
||||
return full_url
|
||||
|
||||
@ -176,6 +194,9 @@ class UniversalAPIManager:
|
||||
|
||||
missing_params = []
|
||||
for param in required_params:
|
||||
# 如果参数在端点配置中已经定义(如APIKey),则跳过验证
|
||||
if param in endpoint_config:
|
||||
continue
|
||||
if param not in params or params[param] is None:
|
||||
missing_params.append(param)
|
||||
|
||||
@ -195,6 +216,7 @@ class UniversalAPIManager:
|
||||
Dict[str, Any]: 处理后的参数
|
||||
"""
|
||||
provider_config = self._get_provider_config(provider)
|
||||
endpoint_config = self._get_endpoint_config(provider, endpoint)
|
||||
prepared_params = params.copy()
|
||||
|
||||
# 根据不同的API提供商添加特定参数
|
||||
@ -202,6 +224,10 @@ class UniversalAPIManager:
|
||||
# 站长之家API需要签名
|
||||
if 'sign' not in prepared_params:
|
||||
prepared_params['sign'] = self._generate_chinaz_sign()
|
||||
|
||||
# 添加APIKey参数
|
||||
if 'APIKey' not in prepared_params and endpoint_config and 'APIKey' in endpoint_config:
|
||||
prepared_params['APIKey'] = endpoint_config['APIKey']
|
||||
|
||||
elif provider == 'xiaohongshu':
|
||||
# 小红书接口使用 JustOneAPI 平台,需要 token 参数
|
||||
@ -228,6 +254,11 @@ class UniversalAPIManager:
|
||||
if default_verifycode is not None:
|
||||
prepared_params['verifycode'] = default_verifycode
|
||||
|
||||
elif provider == 'dify':
|
||||
# Dify API需要在请求头中设置Authorization
|
||||
# 这里不需要修改params,Authorization会在make_request中处理
|
||||
pass
|
||||
|
||||
|
||||
return prepared_params
|
||||
|
||||
@ -264,16 +295,38 @@ class UniversalAPIManager:
|
||||
|
||||
# 构建URL
|
||||
url = self._build_url(provider, endpoint, prepared_params)
|
||||
|
||||
logger.info(f"发送{method}请求到: {url}")
|
||||
|
||||
# 发送请求
|
||||
for attempt in range(retries + 1):
|
||||
try:
|
||||
if method == 'GET':
|
||||
response = self.session.get(url, timeout=timeout)
|
||||
elif method == 'POST':
|
||||
response = self.session.post(url, json=prepared_params, timeout=timeout)
|
||||
if provider == 'chinaz':
|
||||
# 对于Chinaz API,从prepared_params中移除URL参数,只发送body参数
|
||||
body_params = prepared_params.copy()
|
||||
body_params.pop('APIKey', None)
|
||||
body_params.pop('ChinazVer', None)
|
||||
# Chinaz API使用application/x-www-form-urlencoded格式
|
||||
headers = {'Content-Type': 'application/x-www-form-urlencoded'}
|
||||
response = self.session.post(url, data=body_params, headers=headers, timeout=timeout)
|
||||
print(response.json())
|
||||
elif provider == 'dify':
|
||||
# 对于Dify API,需要设置Authorization头
|
||||
provider_config = self._get_provider_config(provider)
|
||||
endpoint_config = self._get_endpoint_config(provider, endpoint)
|
||||
|
||||
# 获取API密钥
|
||||
api_key = provider_config.get('api_key', 'app-FJXEWdKv63oq1F4rHb4I8kvE')
|
||||
|
||||
# 设置请求头
|
||||
headers = {
|
||||
'Authorization': f'Bearer {api_key}',
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
|
||||
response = self.session.post(url, json=prepared_params, headers=headers, timeout=timeout)
|
||||
else:
|
||||
response = self.session.post(url, json=prepared_params, timeout=timeout)
|
||||
else:
|
||||
raise ValueError(f"不支持的HTTP方法: {method}")
|
||||
|
||||
@ -349,7 +402,7 @@ class UniversalAPIManager:
|
||||
'searchKey': company_name,
|
||||
'pageNo': '1',
|
||||
'range': '100',
|
||||
'searchType': '0',
|
||||
'searchType': '1',
|
||||
'ChinazVer': chinaz_ver
|
||||
}
|
||||
return self.make_request('chinaz', 'patent', params)
|
||||
|
||||
4551
app/utils/专利.json
Normal file
4551
app/utils/专利.json
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user