破解实控人溯源痛点:从多级工商底稿核查到股权图谱数据穿透
在一级市场股权投资、Pre-IPO 尽职调查以及券商保荐机构核查拟上市公司股东适格性的业务场景中,构建一套“投研机构拟上市公司实控人溯源与多层股权图谱构建引擎”是合规风控与投研工程的核心基础设施。拟上市主体往往存在多层级的有限合伙持股平台、员工持股计划(ESOP)、契约型基金以及跨区域控股子公司,投研团队不仅需要向上溯源认定最终实际控制人(UBO)并核算其直接与间接合并持股比例,还需向下厘清控股子公司的经营存续状态。传统的尽调方式依赖研究员手工检索多份工商底稿并在电子表格中逐层折算持股乘积,不仅耗费大量工时,且在面对交叉持股、同名自然人股东消歧以及多层嵌套变更时极易出现核算偏差。
在取得尽调合规授权的前提下,基于天远股权穿透接口构建自动化图谱采集管道,能够将离散的工商登记信息转化为标准化的图数据模型。研发团队只需在请求中传入目标主体的ent_code(企业编码)、flag(穿透查询层次,最高支持 4 层)、dir(穿透方向,up向上溯源股东或down向下排查对外投资)以及股权比例过滤区间min_percent与max_percent。系统直连权威商事底层数据库并解密响应报文后,可直接提取图谱节点的核心拓扑属性:包括节点唯一标识id、主体名称name、用于区分法人与自然人的对象类型lable(Company、Human、Other)、跨企业同名自然人消歧标识pid、统一社会信用代码creditCode、企业当前经营状态regStatus、精确股权占比percent,以及标识节点在当前层级之外是否仍可继续向下或向上展开的open字段。这些结构化字段为构建 Neo4j 或 NetworkX 股权知识图谱、自动化折算累计受益股份以及识别非存续异常主体提供了客观的数据依据。
将这一加密股权穿透能力无缝嵌入 Python 投研数据工程流水线或准入风控网关中,能够使尽调系统在数秒内完成拟上市主体多层级股权树的递归拼装与前置准入校验,大幅压缩人工核对底稿的周期,让投研与合规团队将精力聚焦于核心商业逻辑与治理结构评估。
1. Python 加密通信集成:构建高可用审核管道
1. 核心参数与加密配置
- 接口地址:
https://api.tianyuanapi.com/api/v1/QYGLP0HT(需在 URL 附加?t=13位时间戳) - 请求方式:
POST - 请求头:
Access-Id: 账号的 Access-Id (必填)Content-Type:application/json
- 关键入参:
ent_code: 企业编码,支持统一社会信用代码或工商注册号(必填)flag: 穿透层次,数字类型,最大支持 4 层(必填)dir: 穿透方向,可选值:up(向上穿透查询股东)、down(向下穿透查询对外投资)(必填)min_percent: 股权穿透比例下限,大于等于该比例的节点才会被纳入图谱(必填)max_percent: 股权穿透比例上限,小于等于该比例的节点才会被纳入图谱(必填)
- 鉴权与加密机制: 使用账户的 16 进制 Access Key 作为密钥,采用 AES-128 算法的 CBC 模式。每次请求需动态生成 16 字节的 IV(初始化向量),并配合 PKCS7 填充,最终将 IV 与密文拼接后进行 Base64 编码放入请求体
data字段中。
2. 标准化调用代码 (Python)
以下代码展示了如何在投研股权图谱引擎中封装 AES-128-CBC 加解密通信模块,并将解密后的多层股权节点解析为可供图数据库(如 Neo4j)直接入库的实体节点与待延伸探索队列:
importosimportjsonimporttimeimportbase64importrequestsfromtypingimportDict,Any,List,OptionalfromCrypto.CipherimportAESfromCrypto.Util.Paddingimportpad,unpad# 投研图谱引擎网关配置(生产环境建议通过 KMS 或环境变量注入)ACCESS_ID=os.getenv("TIANYUAN_ACCESS_ID","您的_Access_Id")ACCESS_KEY_HEX=os.getenv("TIANYUAN_ACCESS_KEY_HEX","0123456789abcdef0123456789abcdef")API_ENDPOINT="https://api.tianyuanapi.com/api/v1/QYGLP0HT"classEquityPenetrationGraphEngine:"""拟上市公司实控人溯源与多层股权图谱构建引擎核心客户端"""def__init__(self,access_id:str,access_key_hex:str):self.access_id=access_id# 将 16 进制密钥字符串转换为 16 字节二进制密钥 (AES-128)self.key_bytes=bytes.fromhex(access_key_hex)def_encrypt_payload(self,params:Dict[str,Any])->str:""" 采用 AES-128-CBC 模式与 PKCS7 填充加密股权穿透查询参数 """plaintext=json.dumps(params,ensure_ascii=False).encode("utf-8")# 每次请求动态生成 16 字节安全随机 IViv=os.urandom(16)cipher=AES.new(self.key_bytes,AES.MODE_CBC,iv)ciphertext=cipher.encrypt(pad(plaintext,AES.block_size,style="pkcs7"))# 将 16 字节 IV 与密文拼接后执行 Base64 编码returnbase64.b64encode(iv+ciphertext).decode("utf-8")def_decrypt_response(self,encrypted_base64:str)->Any:""" 从 Base64 响应密文中剥离前 16 字节 IV,执行 AES-128-CBC 解密并还原 JSON 结构 """raw_bytes=base64.b64decode(encrypted_base64)iv=raw_bytes[:16]ciphertext=raw_bytes[16:]cipher=AES.new(self.key_bytes,AES.MODE_CBC,iv)decrypted_padded=cipher.decrypt(ciphertext)plaintext=unpad(decrypted_padded,AES.block_size,style="pkcs7").decode("utf-8")returnjson.loads(plaintext)deffetch_equity_layer(self,ent_code:str,flag:int=4,direction:str="up",min_percent:str="0.05",max_percent:str="1.00",timeout:int=10)->Optional[Dict[str,Any]]:""" 发起多层股权穿透请求并解密返回图谱数据 :param ent_code: 拟上市主体或中间层控股平台的企业编码 :param flag: 穿透层级深度(1~4) :param direction: 'up' 向上溯源实控人,'down' 向下梳理控股子公司 :param min_percent: 持股比例下限过滤阈值 :param max_percent: 持股比例上限过滤阈值 """ifflag<1orflag>4:raiseValueError("穿透层次 flag 必须在 1 到 4 之间")ifdirectionnotin("up","down"):raiseValueError("穿透方向 dir 仅支持 'up' 或 'down'")timestamp_ms=str(int(time.time()*1000))request_url=f"{API_ENDPOINT}?t={timestamp_ms}"business_params={"ent_code":ent_code,"flag":flag,"dir":direction,"min_percent":min_percent,"max_percent":max_percent}headers={"Access-Id":self.access_id,"Content-Type":"application/json"}body={"data":self._encrypt_payload(business_params)}try:resp=requests.post(request_url,json=body,headers=headers,timeout=timeout)resp.raise_for_status()resp_payload=resp.json()# 若响应中包含加密的 data 字符串,执行对称解密ifresp_payload.get("data")andisinstance(resp_payload["data"],str):resp_payload["data"]=self._decrypt_response(resp_payload["data"])returnresp_payloadexceptrequests.RequestExceptionasreq_err:print(f"[GraphEngine] 股权穿透网络通信异常:{req_err}")returnNoneexceptExceptionasdec_err:print(f"[GraphEngine] 报文加解密或解析异常:{dec_err}")returnNone@staticmethoddefparse_graph_entities(nodes:List[Dict[str,Any]])->Dict[str,List[Dict[str,Any]]]:""" 将穿透返回的节点列表归类为:自然人实控人候选池、法人股东节点、以及待继续延伸穿透队列 """ubo_candidates=[]corporate_nodes=[]expandable_queue=[]fornodeinnodes:# 注意:接口文档中对象类型字段名为 'lable'entity_type=node.get("lable","Other")share_ratio=float(node.get("percent")or0.0)is_expandable=str(node.get("open","false")).lower()=="true"ifentity_type=="Human":# 利用 pid 实现跨有限合伙平台的同名自然人消歧ubo_candidates.append({"node_id":node.get("id"),"person_pid":node.get("pid"),"name":node.get("name"),"direct_percent":share_ratio})elifentity_type=="Company":corp_item={"node_id":node.get("id"),"name":node.get("name"),"credit_code":node.get("creditCode"),"reg_status":node.get("regStatus"),"percent":share_ratio,"can_expand":is_expandable}corporate_nodes.append(corp_item)# 若到达第 4 层边界且 open 为 true,则将其 creditCode 加入下一轮递归穿透队列ifis_expandableandnode.get("creditCode"):expandable_queue.append(corp_item)return{"ubo_candidates":ubo_candidates,"corporate_nodes":corporate_nodes,"expandable_queue":expandable_queue}if__name__=="__main__":engine=EquityPenetrationGraphEngine(ACCESS_ID,ACCESS_KEY_HEX)# 示例:针对某拟科创板上市主体执行向上 4 层股权溯源,过滤持股 5% 以上的核心股东raw_response=engine.fetch_equity_layer(ent_code="91310000XXXXXXXXXX",flag=4,direction="up",min_percent="0.05",max_percent="1.00")print(json.dumps(raw_response,ensure_ascii=False,indent=2))3. 终端快捷验证 (cURL)
在接入图谱构建流水线前,研发人员可通过以下 cURL 命令在终端快速验证网关连通性与签名配置:
curl-XPOST"https://api.tianyuanapi.com/api/v1/QYGLP0HT?t=1727512000000"\-H"Access-Id: your_access_id_here"\-H"Content-Type: application/json"\-d'{ "data": "5rWL6K+VSVZfMTZCeXRlc19BbmRfYUVTX0NCQ19DaXBoZXJ0ZXh0X0Jhc2U2NA==" }'2. 核心股权图谱数据解析与业务映射
在构建拟上市公司多层股权图谱时,解密后的节点属性直接决定了图数据库(Vertex & Edge)的建模精度与实控人认定的准确性。以下为接口核心返回字段与投研图谱引擎的业务映射关系:
| 字段名称 | 字段类型 | 核心字段描述 | 投研实控人溯源与股权图谱业务映射 |
|---|---|---|---|
name | String | 公司或人名 (varchar(255)) | 图谱节点展示标签(主体名称),用于生成股权穿透树节点名称及投研尽调报告披露名称 |
id | Number | 公司或人 id | 图谱内部实体主键,用于在同一批次穿透结果中构建“股东 -> 被投资企业”的有向边(Edge)关联 |
pid | String | 自然人 pid (varchar(100)) | 实控人合并核算核心字段:当同一自然人通过多个员工持股平台或家族控股公司间接持股时,利用pid进行跨路径身份对齐与同名自然人消歧 |
lable | String | 对象类型 (varchar(20)) | 区分节点性质:Company(公司法人)、Human(自然人)、Other(其他组织/基金等)。注意对接时需严格匹配字段名拼写lable |
creditCode | String | 统一社会信用代码 (varchar(50)) | 法人节点的标准外部工商标识,用于关联外部司法涉诉、税务评级库,以及作为下一轮递归穿透的ent_code入参 |
regStatus | String | 企业状态 (varchar(50)) | 反映中间控股平台或下属子公司的工商存续状态(如存续、迁出、注销等),用于识别链条中的非存续异常主体 |
open | String | 延伸状态 (varchar(6)) | true代表该节点仍有未展开的上层股东或下层投资;false代表已穿透至终端叶子节点。用于驱动超 4 层架构的递归拉取 |
percent | double | 股权占比 | 直接持股比例。图引擎通过沿有向路径对各层percent求乘积并按同一pid求和,自动推算实控人最终受益比例 |
技术提示:在将股权穿透图谱落库至投研数据仓库或日志系统时,针对
lable为Human的自然人节点,其关联的pid及外部拓展的个人联系方式(如手机号138****0000)、证件号等 PII(个人敏感信息)必须执行掩码脱敏或加盐哈希存储。同时请注意接口返回的实体分类字段拼写为lable(而非label),在定义 Pydantic 数据校验模型或反序列化结构体时需保持严格一致。
3. 场景化应用:让核验数据赋能合规闭环
拟上市主体向上四层实控人(UBO)溯源与累计受益权折算
在 Pre-IPO 财务与法律尽调阶段,系统将拟上市主体的统一社会信用代码作为ent_code传入,设定dir="up"、flag=4、min_percent="0.01"。Python 图引擎解析返回的节点列表后,以lable="Human"的节点作为穿透终点,利用pid归并同一自然人在不同有限合伙企业及控股集团中的持股路径,自动计算∑(∏percenti)\sum (\prod \text{percent}_{i})∑(∏percenti)累计间接持股比例。若单一自然人或一致行动人累计受益比例超过认定阈值,系统自动标记其实控人候选地位;若发现顶层全部为lable="Other"或股权高度分散,则触发人工复核提醒,辅助保荐代表人核查是否存在无实控人情形或代持安排。突破 4 层复杂控股架构的增量递归图谱拼接
部分大型产业集团或红筹回归企业的股权架构往往深达 6 至 8 层,单次接口调用的最大层次flag=4无法一次性触达最顶层自然人。在此场景下,图谱构建引擎会扫描第 4 层边界处所有lable="Company"的节点:若某节点的open字段为"true"且percent高于核心关注阈值(如"0.10"),引擎会自动提取该节点的creditCode作为新的ent_code推入 Celery 异步任务队列,再次发起dir="up"的穿透请求,直至所有主干分支节点的open均收敛为"false",从而在 Neo4j 中完整还原任意深度的全景股权图谱。控股子公司向下穿透与合并报表主体存续合规巡检
在评估拟上市公司下属业务板块与关联方交易时,投研系统可将参数切换为dir="down"、flag=3、min_percent="0.20",快速拉取目标企业直接及间接参控股的子公司网络。系统在构建向下投资图谱的同时,自动校验每个Company节点的regStatus字段:若全部核心控股子公司均处于“存续”或“在业”状态,则自动通过前置准入校验;若发现重要参股或控股节点处于注销、吊销等非存续异常主体状态,系统立即在尽调工作台高亮该分支链路并生成合规问询清单。
4. 生产环境接入的安全与合规边界
- 合规尽调授权与数据最小化采集:在启动针对特定非公众企业或关联自然人的深度股权溯源前,投研平台需确保已具备合法的尽职调查授权文件或合规业务委托书。对于穿透所得的自然人
pid与持股明细,应严格限制在投研合规团队内部访问,遵循数据最小化与脱敏展示原则。 - 全链路 AES-128-CBC 密文传输:股权穿透查询涉及投研机构的重点关注标的与敏感立项信息。每次请求必须严格使用
os.urandom(16)生成高熵随机 IV,通过 AES-128-CBC 加密请求负载,防止中间人通过分析明文报文窥探机构的投研标的池。 - 递归图展开的限流与防环控制:在基于
open="true"进行跨层级递归穿透时,部分复杂集团可能存在交叉持股或环形持股结构。Python 工程侧必须在内存或 Redis 中维护已访问节点的creditCode集合(Visited Set)以阻断无限递归死循环,并结合令牌桶限流器控制并发请求速率,保障上游接口与本地图数据库写入通道的平稳运行。