|
@@ -1,11 +1,12 @@
|
|
|
-from fastapi import APIRouter
|
|
|
|
|
-from fastapi.params import Depends
|
|
|
|
|
|
|
+import datetime
|
|
|
|
|
+from fastapi import APIRouter, Depends, Query
|
|
|
from typing import Any
|
|
from typing import Any
|
|
|
import json
|
|
import json
|
|
|
|
|
+from datetime import datetime
|
|
|
from alien_store.api.deps import get_contract_service
|
|
from alien_store.api.deps import get_contract_service
|
|
|
from alien_store.schemas.request.contract_store import TemplatesCreate
|
|
from alien_store.schemas.request.contract_store import TemplatesCreate
|
|
|
from alien_store.services.contract_server import ContractServer
|
|
from alien_store.services.contract_server import ContractServer
|
|
|
-from common.esigntool.main import fill_in_template
|
|
|
|
|
|
|
+from common.esigntool.main import *
|
|
|
import re, urllib.parse
|
|
import re, urllib.parse
|
|
|
|
|
|
|
|
router = APIRouter()
|
|
router = APIRouter()
|
|
@@ -22,7 +23,6 @@ async def create_esign_templates(templates_data: TemplatesCreate, templates_serv
|
|
|
res_data = json.loads(res_text)
|
|
res_data = json.loads(res_text)
|
|
|
except json.JSONDecodeError:
|
|
except json.JSONDecodeError:
|
|
|
return {"success": False, "message": "e签宝返回非 JSON", "raw": res_text}
|
|
return {"success": False, "message": "e签宝返回非 JSON", "raw": res_text}
|
|
|
-
|
|
|
|
|
# 从返回结构提取下载链接,需与实际返回字段匹配
|
|
# 从返回结构提取下载链接,需与实际返回字段匹配
|
|
|
try:
|
|
try:
|
|
|
contract_url = res_data["data"]["fileDownloadUrl"]
|
|
contract_url = res_data["data"]["fileDownloadUrl"]
|
|
@@ -31,15 +31,18 @@ async def create_esign_templates(templates_data: TemplatesCreate, templates_serv
|
|
|
if m:
|
|
if m:
|
|
|
encoded_name = m.group(1)
|
|
encoded_name = m.group(1)
|
|
|
file_name = urllib.parse.unquote(encoded_name)
|
|
file_name = urllib.parse.unquote(encoded_name)
|
|
|
-
|
|
|
|
|
except Exception:
|
|
except Exception:
|
|
|
return {"success": False, "message": "e签宝返回缺少 fileDownloadUrl", "raw": res_data}
|
|
return {"success": False, "message": "e签宝返回缺少 fileDownloadUrl", "raw": res_data}
|
|
|
- # pydantic v2 使用 model_copy 更新字段
|
|
|
|
|
|
|
+
|
|
|
|
|
+ sign_data = create_by_file(file_id, file_name, templates_data.contact_phone, templates_data.merchant_name)
|
|
|
|
|
+ sign_json = json.loads(sign_data)
|
|
|
|
|
+ sing_id = sign_json["data"]["signFlowId"]
|
|
|
result_contract = {
|
|
result_contract = {
|
|
|
"contract_url": contract_url,
|
|
"contract_url": contract_url,
|
|
|
"file_name": file_name,
|
|
"file_name": file_name,
|
|
|
"file_id": file_id,
|
|
"file_id": file_id,
|
|
|
- "status": 0
|
|
|
|
|
|
|
+ "status": 0,
|
|
|
|
|
+ "sign_flow_id": sing_id,
|
|
|
}
|
|
}
|
|
|
list_contract = [result_contract]
|
|
list_contract = [result_contract]
|
|
|
# contract_url 字段为字符串,存储 JSON 字符串避免类型错误
|
|
# contract_url 字段为字符串,存储 JSON 字符串避免类型错误
|
|
@@ -53,4 +56,37 @@ async def create_esign_templates(templates_data: TemplatesCreate, templates_serv
|
|
|
async def list_contracts(store_id: int, templates_server: ContractServer = Depends(get_contract_service)) -> Any:
|
|
async def list_contracts(store_id: int, templates_server: ContractServer = Depends(get_contract_service)) -> Any:
|
|
|
"""根据 store_id 查询所有合同"""
|
|
"""根据 store_id 查询所有合同"""
|
|
|
rows = await templates_server.list_by_store(store_id)
|
|
rows = await templates_server.list_by_store(store_id)
|
|
|
- return rows
|
|
|
|
|
|
|
+ return rows
|
|
|
|
|
+
|
|
|
|
|
+@router.get("/get_all_templates")
|
|
|
|
|
+async def get_all_templates(
|
|
|
|
|
+ page: int = Query(1, ge=1, description="页码,从1开始"),
|
|
|
|
|
+ page_size: int = Query(10, ge=1, le=100, description="每页条数,默认10"),
|
|
|
|
|
+ templates_server: ContractServer = Depends(get_contract_service)
|
|
|
|
|
+) -> Any:
|
|
|
|
|
+ """分页查询所有合同"""
|
|
|
|
|
+ return await templates_server.list_all_paged(page, page_size)
|
|
|
|
|
+
|
|
|
|
|
+@router.post("/esign/callback")
|
|
|
|
|
+async def esign_callback(payload: dict, templates_server: ContractServer = Depends(get_contract_service)) -> Any:
|
|
|
|
|
+ """
|
|
|
|
|
+ e签宝签署结果回调
|
|
|
|
|
+ 需求:签署完成 -> 更新 signing_status=已签署,contract_url 中 status=1
|
|
|
|
|
+ """
|
|
|
|
|
+ sign_result = payload.get("signResult")
|
|
|
|
|
+ operator = payload.get("operator") or {}
|
|
|
|
|
+ psn_account = operator.get("psnAccount") or {}
|
|
|
|
|
+ contact_phone = psn_account.get("accountMobile")
|
|
|
|
|
+ # 取回调中的毫秒时间戳,优先 operateTime,其次 timestamp
|
|
|
|
|
+ ts_ms = payload.get("operateTime") or payload.get("timestamp")
|
|
|
|
|
+ signing_dt = None
|
|
|
|
|
+ if ts_ms:
|
|
|
|
|
+ try:
|
|
|
|
|
+ signing_dt = datetime.fromtimestamp(ts_ms / 1000)
|
|
|
|
|
+ except Exception:
|
|
|
|
|
+ signing_dt = None
|
|
|
|
|
+
|
|
|
|
|
+ if sign_result == 2 and contact_phone:
|
|
|
|
|
+ updated = await templates_server.mark_signed_by_phone(contact_phone, signing_dt)
|
|
|
|
|
+ return {"success": True, "updated": updated}
|
|
|
|
|
+ return {"success": False, "message": "未处理: signResult!=2 或手机号缺失"}
|