- app_id
- app_secret
- open_corp_id
TopcentralMall ──→ 法大大API ──→ 客户签署
│ │
└─ 合同模板管理 └─ 签署状态回调
| 接口 | 用途 | 预估工作量 |
|---|
| 创建合同模板 | 上传PDF模板,设置签署位置 | 1天 |
| 发起签署 | 创建签署任务,发送给客户 | 1天 |
| 查询签署状态 | 轮询或回调获取结果 | 0.5天 |
| 下载合同 | 签署完成后下载归档 | 0.5天 |
按份计费:¥2-5/份
预估月合同量:10-50份
月费用:¥20-250
年费:¥0(无最低消费)
# backend/app/services/fadada_service.py
import httpx
import hashlib
import time
class FaDaDaService:
BASE_URL = "https://openapi.fadada.com/api/v5"
def __init__(self, app_id: str, app_secret: str, open_corp_id: str):
self.app_id = app_id
self.app_secret = app_secret
self.open_corp_id = open_corp_id
def _sign(self, params: dict) -> str:
"""生成签名"""
sorted_params = sorted(params.items())
sign_str = "&".join(f"{k}={v}" for k, v in sorted_params)
return hashlib.md5(f"{sign_str}{self.app_secret}".encode()).hexdigest()
async def create_template(self, template_name: str, pdf_url: str):
"""创建合同模板"""
params = {
"appId": self.app_id,
"timestamp": str(int(time.time())),
"openCorpId": self.open_corp_id,
"templateName": template_name,
"file": pdf_url,
}
params["sign"] = self._sign(params)
async with httpx.AsyncClient() as client:
resp = await client.post(f"{self.BASE_URL}/template/create", json=params)
return resp.json()
async def initiate_sign(self, template_id: str, signers: list, contract_no: str):
"""发起签署任务"""
params = {
"appId": self.app_id,
"timestamp": str(int(time.time())),
"openCorpId": self.open_corp_id,
"templateId": template_id,
"signers": signers,
"contractNo": contract_no,
}
params["sign"] = self._sign(params)
async with httpx.AsyncClient() as client:
resp = await client.post(f"{self.BASE_URL}/signTask/create", json=params)
return resp.json()
async def query_status(self, sign_task_id: str):
"""查询签署状态"""
params = {
"appId": self.app_id,
"timestamp": str(int(time.time())),
"openCorpId": self.open_corp_id,
"signTaskId": sign_task_id,
}
params["sign"] = self._sign(params)
async with httpx.AsyncClient() as client:
resp = await client.get(f"{self.BASE_URL}/signTask/detail", params=params)
return resp.json()
async def download_contract(self, sign_task_id: str):
"""下载已签署合同"""
params = {
"appId": self.app_id,
"timestamp": str(int(time.time())),
"openCorpId": self.open_corp_id,
"signTaskId": sign_task_id,
}
params["sign"] = self._sign(params)
async with httpx.AsyncClient() as client:
resp = await client.get(f"{self.BASE_URL}/signTask/download", params=params)
return resp.content
CREATE TABLE contracts (
id SERIAL PRIMARY KEY,
order_id INTEGER REFERENCES orders(id),
contract_no VARCHAR(64) UNIQUE NOT NULL,
template_id VARCHAR(64),
sign_task_id VARCHAR(64),
status VARCHAR(32) DEFAULT 'draft', -- draft/pending/signed/rejected/expired
fadada_response JSONB,
signed_at TIMESTAMP,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
CREATE INDEX idx_contracts_order ON contracts(order_id);
CREATE INDEX idx_contracts_status ON contracts(status);
订单金额 ≥ ¥50,000 → 自动创建电子合同
→ 发送给客户签署
→ 签署完成 → 订单进入「待发货」
→ 48h未签 → 催单Agent提醒
等你注册完法大大,把 app_id, app_secret, open_corp_id 发给我,我1天内完成API对接。