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,
|
UserValuationOut,
|
||||||
UserValuationDetail
|
UserValuationDetail
|
||||||
)
|
)
|
||||||
|
from app.models.user import AppUser
|
||||||
|
|
||||||
from app.schemas.base import Success, SuccessExtra
|
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=["用户端估值评估"])
|
app_valuations_router = APIRouter(tags=["用户端估值评估"])
|
||||||
|
|
||||||
@ -18,19 +20,70 @@ app_valuations_router = APIRouter(tags=["用户端估值评估"])
|
|||||||
@app_valuations_router.post("/", summary="创建估值评估")
|
@app_valuations_router.post("/", summary="创建估值评估")
|
||||||
async def create_valuation(
|
async def create_valuation(
|
||||||
data: UserValuationCreate,
|
data: UserValuationCreate,
|
||||||
user_id: int = Depends(get_current_app_user_id)
|
current_user: AppUser = Depends(get_current_app_user)
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
用户创建估值评估申请
|
用户创建估值评估申请
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
result = await user_valuation_controller.create_valuation(
|
result = await user_valuation_controller.create_valuation(
|
||||||
user_id=user_id,
|
user_id=current_user.id,
|
||||||
data=data
|
data=data
|
||||||
)
|
)
|
||||||
# 使用model_dump_json()来正确序列化datetime,然后解析为dict
|
# 使用model_dump_json()来正确序列化datetime,然后解析为dict
|
||||||
import json
|
import json
|
||||||
result_dict = json.loads(result.model_dump_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="估值评估申请提交成功")
|
return Success(data=result_dict, msg="估值评估申请提交成功")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
@ -42,14 +95,15 @@ async def create_valuation(
|
|||||||
@app_valuations_router.get("/", summary="获取我的估值评估列表")
|
@app_valuations_router.get("/", summary="获取我的估值评估列表")
|
||||||
async def get_my_valuations(
|
async def get_my_valuations(
|
||||||
query: UserValuationQuery = Depends(),
|
query: UserValuationQuery = Depends(),
|
||||||
user_id: int = Depends(get_current_app_user_id)
|
current_user: AppUser = Depends(get_current_app_user)
|
||||||
|
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
获取当前用户的估值评估列表
|
获取当前用户的估值评估列表
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
result = await user_valuation_controller.get_user_valuations(
|
result = await user_valuation_controller.get_user_valuations(
|
||||||
user_id=user_id,
|
user_id=current_user.id,
|
||||||
query=query
|
query=query
|
||||||
)
|
)
|
||||||
# 使用model_dump_json()来正确序列化datetime,然后解析为dict列表
|
# 使用model_dump_json()来正确序列化datetime,然后解析为dict列表
|
||||||
@ -73,14 +127,14 @@ async def get_my_valuations(
|
|||||||
@app_valuations_router.get("/{valuation_id}", summary="获取估值评估详情")
|
@app_valuations_router.get("/{valuation_id}", summary="获取估值评估详情")
|
||||||
async def get_valuation_detail(
|
async def get_valuation_detail(
|
||||||
valuation_id: int,
|
valuation_id: int,
|
||||||
user_id: int = Depends(get_current_app_user_id)
|
current_user: AppUser = Depends(get_current_app_user)
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
获取指定估值评估的详细信息
|
获取指定估值评估的详细信息
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
result = await user_valuation_controller.get_user_valuation_detail(
|
result = await user_valuation_controller.get_user_valuation_detail(
|
||||||
user_id=user_id,
|
user_id=current_user.id,
|
||||||
valuation_id=valuation_id
|
valuation_id=valuation_id
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -105,14 +159,14 @@ async def get_valuation_detail(
|
|||||||
|
|
||||||
@app_valuations_router.get("/statistics/overview", summary="获取我的估值评估统计")
|
@app_valuations_router.get("/statistics/overview", summary="获取我的估值评估统计")
|
||||||
async def get_my_valuation_statistics(
|
async def get_my_valuation_statistics(
|
||||||
user_id: int = Depends(get_current_app_user_id)
|
current_user: AppUser = Depends(get_current_app_user)
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
获取当前用户的估值评估统计信息
|
获取当前用户的估值评估统计信息
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
result = await user_valuation_controller.get_user_valuation_statistics(
|
result = await user_valuation_controller.get_user_valuation_statistics(
|
||||||
user_id=user_id
|
user_id=current_user.id
|
||||||
)
|
)
|
||||||
return Success(data=result, msg="获取统计信息成功")
|
return Success(data=result, msg="获取统计信息成功")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|||||||
@ -11,6 +11,7 @@ from app.schemas.third_party_api import (
|
|||||||
OCRRequest,
|
OCRRequest,
|
||||||
XiaohongshuNoteRequest,
|
XiaohongshuNoteRequest,
|
||||||
JizhiliaoSearchRequest,
|
JizhiliaoSearchRequest,
|
||||||
|
DifyWorkflowRequest,
|
||||||
APIResponse,
|
APIResponse,
|
||||||
APIProviderInfo,
|
APIProviderInfo,
|
||||||
APIEndpointInfo,
|
APIEndpointInfo,
|
||||||
@ -110,4 +111,22 @@ async def search_jizhiliao_index(request: JizhiliaoSearchRequest):
|
|||||||
return Fail(message=result.message)
|
return Fail(message=result.message)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"极致聊指数搜索失败: {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",
|
endpoint="patent",
|
||||||
params={
|
params={
|
||||||
"searchKey": company_name,
|
"searchKey": company_name,
|
||||||
"pageNo": 1,
|
"pageNo": "1",
|
||||||
"range": 100,
|
"range": "100",
|
||||||
"searchType": 0,
|
"searchType": '1',
|
||||||
"ChinazVer": chinaz_ver
|
"ChinazVer": chinaz_ver
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@ -125,6 +125,20 @@ class ThirdPartyAPIController:
|
|||||||
timeout=timeout
|
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()
|
third_party_api_controller = ThirdPartyAPIController()
|
||||||
@ -28,6 +28,12 @@ class JizhiliaoSearchRequest(BaseAPIRequest):
|
|||||||
page: int = Field(1, description="页码")
|
page: int = Field(1, description="页码")
|
||||||
size: int = Field(10, 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):
|
class APIResponse(BaseModel):
|
||||||
"""API响应模型"""
|
"""API响应模型"""
|
||||||
success: bool
|
success: bool
|
||||||
|
|||||||
@ -32,7 +32,7 @@ class APIConfig:
|
|||||||
"base_url": "https://openapi.chinaz.net",
|
"base_url": "https://openapi.chinaz.net",
|
||||||
"endpoints": {
|
"endpoints": {
|
||||||
"copyright_software": {
|
"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",
|
"path": "/v1/1036/copyrightsoftware",
|
||||||
"method": "POST",
|
"method": "POST",
|
||||||
"description": "企业软件著作权查询",
|
"description": "企业软件著作权查询",
|
||||||
@ -40,7 +40,7 @@ class APIConfig:
|
|||||||
"optional_params": ["sign"]
|
"optional_params": ["sign"]
|
||||||
},
|
},
|
||||||
"patent": {
|
"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",
|
"path": "/v1/1036/patent",
|
||||||
"method": "POST",
|
"method": "POST",
|
||||||
"description": "企业专利信息查询",
|
"description": "企业专利信息查询",
|
||||||
@ -48,7 +48,7 @@ class APIConfig:
|
|||||||
"optional_params": ["sign", "searchType"]
|
"optional_params": ["sign", "searchType"]
|
||||||
},
|
},
|
||||||
"judgement": {
|
"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",
|
"path": "/v1/1036/judgementdetailv4",
|
||||||
"method": "POST",
|
"method": "POST",
|
||||||
"description": "司法综合数据查询",
|
"description": "司法综合数据查询",
|
||||||
@ -56,7 +56,7 @@ class APIConfig:
|
|||||||
"optional_params": ["sign", "q", "idCardNo", "datatype", "id", "pageNo"]
|
"optional_params": ["sign", "q", "idCardNo", "datatype", "id", "pageNo"]
|
||||||
},
|
},
|
||||||
"recognition_ocr": {
|
"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",
|
"path": "/v1/1024/recognition_ocr",
|
||||||
"method": "POST",
|
"method": "POST",
|
||||||
"description": "图片OCR识别",
|
"description": "图片OCR识别",
|
||||||
@ -72,184 +72,75 @@ class APIConfig:
|
|||||||
"timeout": 30,
|
"timeout": 30,
|
||||||
"retries": 3,
|
"retries": 3,
|
||||||
"endpoints": {
|
"endpoints": {
|
||||||
"xiaohongshu": {
|
"xiaohongshu_note_detail": {
|
||||||
"api_key": os.getenv("XIAOHONGSHU_TOKEN", "YNSbIjdU"),
|
"path": "/api/xiaohongshu/get-note-detail/v7",
|
||||||
"base_url": "https://api.justoneapi.com",
|
"method": "GET",
|
||||||
"timeout": 30,
|
"description": "小红书笔记详情查询",
|
||||||
"retries": 3,
|
"required_params": ["noteId"],
|
||||||
"endpoints": {
|
"optional_params": ["token"]
|
||||||
"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"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"weibo": {
|
"xiaohongshu_user_info": {
|
||||||
"api_key": os.getenv("XIAOHONGSHU_TOKEN", "YNSbIjdU"),
|
"path": "/api/xiaohongshu/get-user-info/v7",
|
||||||
"base_url": "https://api.justoneapi.com",
|
"method": "GET",
|
||||||
"timeout": 30,
|
"description": "小红书用户信息查询",
|
||||||
"retries": 3,
|
"required_params": ["userId"],
|
||||||
"endpoints": {
|
"optional_params": ["token"]
|
||||||
"weibo_user_detail": {
|
|
||||||
"path": "/api/weibo/get-user-detail/v1", # 微博只有粉丝数接口
|
|
||||||
"method": "GET",
|
|
||||||
"description": "获取用户信息 包括昵称、头像、用户ID、粉丝数、关注数、简介、认证状态等公开信息",
|
|
||||||
"required_params": ["token", "uid"],
|
|
||||||
"optional_params": ["token", "uid"]
|
|
||||||
},
|
|
||||||
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"weixin": {
|
"xiaohongshu_search_notes": {
|
||||||
"api_key": os.getenv("XIAOHONGSHU_TOKEN", "YNSbIjdU"),
|
"path": "/api/xiaohongshu/search-notes/v7",
|
||||||
"base_url": "https://api.justoneapi.com",
|
"method": "GET",
|
||||||
"timeout": 30,
|
"description": "小红书笔记搜索",
|
||||||
"retries": 3,
|
"required_params": ["keyword"],
|
||||||
"endpoints": {
|
"optional_params": ["page", "size", "token"]
|
||||||
"weixin_user_detail": {
|
|
||||||
"path": "/api/weixin/get-user-post/v1",
|
|
||||||
"method": "GET",
|
|
||||||
"description": "公众号发布的文章内容,包括标题、作者、发布时间、内容摘要以及阅读数、点赞数与转发数等互动数据",
|
|
||||||
"required_params": ["token", "wxid"],
|
|
||||||
"optional_params": ["token", "wxid"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"douyin": {
|
"weibo_user_detail": {
|
||||||
"api_key": os.getenv("XIAOHONGSHU_TOKEN", "YNSbIjdU"),
|
"path": "/api/weibo/get-user-detail/v1",
|
||||||
"base_url": "https://api.justoneapi.com",
|
"method": "GET",
|
||||||
"timeout": 30,
|
"description": "获取用户信息 包括昵称、头像、用户ID、粉丝数、关注数、简介、认证状态等公开信息",
|
||||||
"retries": 3,
|
"required_params": ["token", "uid"],
|
||||||
"endpoints": {
|
"optional_params": []
|
||||||
"douyin_video_detail": {
|
|
||||||
"path": "/api/douyin/get-video-detail/v2",
|
|
||||||
"method": "GET",
|
|
||||||
"description": "该接口用于获取指定抖音视频的详细信息,包括视频地址、描述文案、作者信息、发布时间、播放量、点赞数、评论数与分享数等",
|
|
||||||
"required_params": ["token", "videoId"],
|
|
||||||
"optional_params": ["token", "videoId"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"bilibili": {
|
"weixin_user_detail": {
|
||||||
"api_key": os.getenv("XIAOHONGSHU_TOKEN", "YNSbIjdU"),
|
"path": "/api/weixin/get-user-post/v1",
|
||||||
"base_url": "https://api.justoneapi.com",
|
"method": "GET",
|
||||||
"timeout": 30,
|
"description": "公众号发布的文章内容,包括标题、作者、发布时间、内容摘要以及阅读数、点赞数与转发数等互动数据",
|
||||||
"retries": 3,
|
"required_params": ["token", "wxid"],
|
||||||
"endpoints": {
|
"optional_params": []
|
||||||
"bilibili_video_detail": {
|
|
||||||
"path": "/api/bilibili/get-video-detail/v2",
|
|
||||||
"method": "GET",
|
|
||||||
"description": "该接口用于获取指定抖音视频的详细信息,包括视频地址、描述文案、作者信息、发布时间、播放量、点赞数、评论数与分享数等",
|
|
||||||
"required_params": ["token", "bvid"],
|
|
||||||
"optional_params": ["token", "bvid"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"kuaishou": {
|
"douyin_video_detail": {
|
||||||
"api_key": os.getenv("XIAOHONGSHU_TOKEN", "YNSbIjdU"),
|
"path": "/api/douyin/get-video-detail/v2",
|
||||||
"base_url": "https://api.justoneapi.com",
|
"method": "GET",
|
||||||
"timeout": 30,
|
"description": "该接口用于获取指定抖音视频的详细信息,包括视频地址、描述文案、作者信息、发布时间、播放量、点赞数、评论数与分享数等",
|
||||||
"retries": 3,
|
"required_params": ["token", "videoId"],
|
||||||
"endpoints": {
|
"optional_params": []
|
||||||
"kuaishou_video_detail": {
|
|
||||||
"path": "/api/kuaishou/get-video-detail/v2",
|
|
||||||
"method": "GET",
|
|
||||||
"description": "该接口用于获取指定抖音视频的详细信息,包括视频地址、描述文案、作者信息、发布时间、播放量、点赞数、评论数与分享数等",
|
|
||||||
"required_params": ["token", "videoId"],
|
|
||||||
"optional_params": ["token", "videoId"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"other_apis": {
|
"kuaishou_video_detail": {
|
||||||
"jizhiliao": {
|
"path": "/api/kuaishou/get-video-detail/v2",
|
||||||
"api_key": os.getenv("JIZHILIAO_API_KEY", "JZL089ef0b7d0315d96"),
|
"method": "GET",
|
||||||
"base_url": "https://api.justoneapi.com",
|
"description": "该接口用于获取指定快手视频的详细信息,包括视频地址、描述文案、作者信息、发布时间、播放量、点赞数、评论数与分享数等",
|
||||||
"timeout": 30,
|
"required_params": ["token", "videoId"],
|
||||||
"retries": 3,
|
"optional_params": []
|
||||||
"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": {}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"common_settings": {
|
"bilibili_video_detail": {
|
||||||
"timeout": 60,
|
"path": "/api/bilibili/get-video-detail/v2",
|
||||||
"retries": 3,
|
"method": "GET",
|
||||||
"sign_prefix": "634xz"
|
"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": {
|
"dajiala": {
|
||||||
"api_key": "",
|
|
||||||
"base_url": "https://www.dajiala.com",
|
"base_url": "https://www.dajiala.com",
|
||||||
"timeout": 30,
|
"timeout": 30,
|
||||||
"retries": 3,
|
"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 datetime import datetime, timedelta
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
import jwt
|
import jwt
|
||||||
from fastapi import HTTPException, status, Depends
|
from fastapi import HTTPException, status, Depends, Header
|
||||||
from fastapi.security import HTTPBearer
|
|
||||||
from app.controllers.app_user import app_user_controller
|
from app.controllers.app_user import app_user_controller
|
||||||
from app.schemas.app_user import AppUserJWTPayload
|
from app.schemas.app_user import AppUserJWTPayload
|
||||||
from app.settings import settings
|
from app.settings import settings
|
||||||
@ -12,8 +11,6 @@ SECRET_KEY = settings.SECRET_KEY
|
|||||||
ALGORITHM = "HS256"
|
ALGORITHM = "HS256"
|
||||||
ACCESS_TOKEN_EXPIRE_MINUTES = 60 * 24 * 7 # 7天
|
ACCESS_TOKEN_EXPIRE_MINUTES = 60 * 24 * 7 # 7天
|
||||||
|
|
||||||
security = HTTPBearer()
|
|
||||||
|
|
||||||
|
|
||||||
def create_app_user_access_token(user_id: int, phone: str) -> str:
|
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
|
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
|
从令牌中获取当前AppUser ID
|
||||||
"""
|
"""
|
||||||
@ -61,7 +58,10 @@ def get_current_app_user_id(token: str = Depends(security)) -> int:
|
|||||||
headers={"WWW-Authenticate": "Bearer"},
|
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:
|
if payload is None:
|
||||||
raise credentials_exception
|
raise credentials_exception
|
||||||
|
|
||||||
|
|||||||
@ -53,7 +53,14 @@ class UniversalAPIManager:
|
|||||||
endpoint_config = self._get_endpoint_config(provider, endpoint)
|
endpoint_config = self._get_endpoint_config(provider, endpoint)
|
||||||
if not endpoint_config:
|
if not endpoint_config:
|
||||||
return None
|
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]:
|
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密钥到参数中
|
# 添加API密钥到参数中
|
||||||
params['APIKey'] = api_key
|
params['APIKey'] = api_key
|
||||||
|
print(params)
|
||||||
# 发送请求
|
# 发送请求
|
||||||
try:
|
try:
|
||||||
response = self.session.request(
|
response = self.session.request(
|
||||||
@ -156,6 +163,17 @@ class UniversalAPIManager:
|
|||||||
# 对于GET请求,将参数添加到URL中
|
# 对于GET请求,将参数添加到URL中
|
||||||
query_string = urllib.parse.urlencode(params)
|
query_string = urllib.parse.urlencode(params)
|
||||||
full_url = f"{full_url}?{query_string}"
|
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
|
return full_url
|
||||||
|
|
||||||
@ -176,6 +194,9 @@ class UniversalAPIManager:
|
|||||||
|
|
||||||
missing_params = []
|
missing_params = []
|
||||||
for param in required_params:
|
for param in required_params:
|
||||||
|
# 如果参数在端点配置中已经定义(如APIKey),则跳过验证
|
||||||
|
if param in endpoint_config:
|
||||||
|
continue
|
||||||
if param not in params or params[param] is None:
|
if param not in params or params[param] is None:
|
||||||
missing_params.append(param)
|
missing_params.append(param)
|
||||||
|
|
||||||
@ -195,6 +216,7 @@ class UniversalAPIManager:
|
|||||||
Dict[str, Any]: 处理后的参数
|
Dict[str, Any]: 处理后的参数
|
||||||
"""
|
"""
|
||||||
provider_config = self._get_provider_config(provider)
|
provider_config = self._get_provider_config(provider)
|
||||||
|
endpoint_config = self._get_endpoint_config(provider, endpoint)
|
||||||
prepared_params = params.copy()
|
prepared_params = params.copy()
|
||||||
|
|
||||||
# 根据不同的API提供商添加特定参数
|
# 根据不同的API提供商添加特定参数
|
||||||
@ -202,6 +224,10 @@ class UniversalAPIManager:
|
|||||||
# 站长之家API需要签名
|
# 站长之家API需要签名
|
||||||
if 'sign' not in prepared_params:
|
if 'sign' not in prepared_params:
|
||||||
prepared_params['sign'] = self._generate_chinaz_sign()
|
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':
|
elif provider == 'xiaohongshu':
|
||||||
# 小红书接口使用 JustOneAPI 平台,需要 token 参数
|
# 小红书接口使用 JustOneAPI 平台,需要 token 参数
|
||||||
@ -228,6 +254,11 @@ class UniversalAPIManager:
|
|||||||
if default_verifycode is not None:
|
if default_verifycode is not None:
|
||||||
prepared_params['verifycode'] = default_verifycode
|
prepared_params['verifycode'] = default_verifycode
|
||||||
|
|
||||||
|
elif provider == 'dify':
|
||||||
|
# Dify API需要在请求头中设置Authorization
|
||||||
|
# 这里不需要修改params,Authorization会在make_request中处理
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
return prepared_params
|
return prepared_params
|
||||||
|
|
||||||
@ -264,16 +295,38 @@ class UniversalAPIManager:
|
|||||||
|
|
||||||
# 构建URL
|
# 构建URL
|
||||||
url = self._build_url(provider, endpoint, prepared_params)
|
url = self._build_url(provider, endpoint, prepared_params)
|
||||||
|
|
||||||
logger.info(f"发送{method}请求到: {url}")
|
|
||||||
|
|
||||||
# 发送请求
|
# 发送请求
|
||||||
for attempt in range(retries + 1):
|
for attempt in range(retries + 1):
|
||||||
try:
|
try:
|
||||||
if method == 'GET':
|
if method == 'GET':
|
||||||
response = self.session.get(url, timeout=timeout)
|
response = self.session.get(url, timeout=timeout)
|
||||||
elif method == 'POST':
|
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:
|
else:
|
||||||
raise ValueError(f"不支持的HTTP方法: {method}")
|
raise ValueError(f"不支持的HTTP方法: {method}")
|
||||||
|
|
||||||
@ -349,7 +402,7 @@ class UniversalAPIManager:
|
|||||||
'searchKey': company_name,
|
'searchKey': company_name,
|
||||||
'pageNo': '1',
|
'pageNo': '1',
|
||||||
'range': '100',
|
'range': '100',
|
||||||
'searchType': '0',
|
'searchType': '1',
|
||||||
'ChinazVer': chinaz_ver
|
'ChinazVer': chinaz_ver
|
||||||
}
|
}
|
||||||
return self.make_request('chinaz', 'patent', params)
|
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