欢迎使用保全网API文档

简介

欢迎使用保全网的应用编程接口Baoquan API v2.0! 通过API您可以接入保全网提供的大部分服务。

Baoquan API v2.0基本遵循RESTful style。请求中的业务数据以JSON格式传递,认证数据以普通HTTP参数传递。处理结果HTTP Status Code表示请求成功(2xx)或者失败,如果失败,会在response body中给出JSON格式的详细错误信息。

概述

为了更好的使用保全网的API,您首先需要对涉及到的概念有一个基本的了解。

客户 - Member

客户是保全网的签约客户,也是保全网API的使用者。客户需要在保全网上注册,然后通过API将需要保全的数据传送给保全网,实现数据存证。

客户可以是企业,组织,或者个人。

用户 - User

用户是保全对应的所有者。用户可以通过保全号在保全网站查询保全内容,用户在保全网注册并通过身份认证后,还可以通过手机号、身份证号等身份标识查询到自己的保全数据。

用户可以是企业,组织,或者个人。

保全 - Attestation

保全是一份用户数据存证。每一份保全拥有一个唯一的保全号,对应一位所有人。通过保全号用户可以查询到存证数据,申请公证。

每一份保全都有自己的关联模板,客户可以通过模板定义保全的样式。

保全的主要数据项包括:保全号,身份事项,模板ID,陈述集合。

身份标识 - Identity

在创建保全时需要提供身份标识。身份标识是保全所有人的身份信息,您可以通过身份标识将保全所有人的身份信息,例如身份证号、电话号码、统一社会信用代码等与该保全关联起来,以便将来用户检索自己拥有的保全数据。一位用户也可以拥有多个身份标识。

Identity代码表:

代码 类型
ID 身份证
MO 手机号
USCID 统一社会信用代码

模板 - Template

模板是客户在保全网上使用模板编辑器编写的数据结构,模板可以方便客户定义一份有法律效力的电子数据。

_images/template.png

陈述 - Factoid

陈述是保全网接收到的与某个保全关联的数据片段。一个保全可以只包含一个陈述,也可以包含多个陈述。通过API客户可以一次性将一份保全所有相关陈述发送给保全网,也可以通过多次API调用分开发送。

请求

访问保全网的API需要使用https协议,并进行数字签名。

路径

保全网会提供向后兼容的API,不同的API版本会以比如v2、v2.1这样的字符串标记,当前的版本为v2。

API地址:https://baoquan.com/api/v2

请求路径=API地址+接口名称,比如保全接口的名称是/attestations,则请求路径为 https://baoquan.com/api/v2/attestations

方法

所有的请求均为HTTP POST方法

参数

参数名 描述
request_id 请求号,由接入客户创建唯一字符串,长度不超过32位
access_key 访问识别码,当您在保全网成功上传RSA公钥后会获得一个access_key
tonce 请求时间, 必须以 Unix Time 的格式发送, tonce与服务器时间不得超过正负300秒,否则请求将视为无效
payload 被签名的数据体部分,用JSON进行编码,不同的请求的payload数据一般不同
signature 使用你的RSA私钥进行签名后的字符串,具体签名的方法后面会进一步描述

例如:

{
        "request_id": "2XiTgZ2oVrBgGqKQ1ruCKh",
        "access_key": "2y7cg8kmoGDrDBXJLaizoD",
        "tonce": 1464594744,
        "payload": {
                "template_id": "2hSWTZ4oqVEJKAmK2RiyT4",
        }
        "signature": "moGDrDBXJLaizoD2hSWTZ4oqVEJKAmK2RiyT4"
}

返回结果

保全网API的返回结果是一个Json字符串,正常返回时的Http status code为2xx,其它code均表示异常。

正常返回

正常返回的结果有两种情况,一般情况下是返回一个json,如下表所示:

字段名 描述
request_id 客户请求id
data 有效数据,具体在接口里面描述

例如:

{
        "request_id": "2XiTgZ2oVrBgGqKQ1ruCKh",
        "data": {
                "attestation_id": "nXiTrBgQ1ruCKhgZ2oV"
        }
}

另外一种是返回一个文件,比如下载保全文件时。

异常返回

异常返回的结果如下表所示:

字段名 描述
request_id 客户请求id
message 错误原因
timestamp 时间戳,精确到毫秒

异常的Http Status Code

Code 描述
400 请求错误,比如参数不符合格式
404 请求路径不存在
405 请求方法错误
413 请求数据过大,比如上传文件过大
429 请求次数太多
500 请求失败,比如数字签名未通过

例如:

{
        "request_id": "2XiTgZ2oVrBgGqKQ1ruCKh",
        "message": "数字签名校验失败",
        "timestamp": 1464672264000
}

签名

通过API请求保全网时,每一个请求的payload都要用RSA私钥进行签名,这样保全网也无法伪造您的数据。

第一步:注册保全网企业账号,在账户信息-基本设置中先完成企业实名认证。

_images/key_1.png

第二步:进入账户信息-密钥管理,新建秘钥(测试时使用测试密钥,正式上线后转为生产密钥)。

_images/key_2.png

第三步:上传RSA公钥,上传成功后的结果如下:

_images/key_3.png

可以参考如下shell命令制作自己的证书,openssl版本要求>=1.0.2:

openssl req -x509 -newkey rsa:1024 -nodes -keyout key.pem -out cert.pem

将cert.pem中的内容粘贴到文本框中,然后选择是沙盒还是正式。 在正式环境下编辑好的模板可以在沙盒环境下使用,但沙盒环境下的数据会被定期清除。所以在您的开发环境和测试环境下请使用沙盒的access key,在生产环境使用正式的access key。

注解

请保管好自己的私钥,另外强烈推荐在正式环境下使用CA机构签发的证书作为公钥。

假定待签名数据为:

{
        "request_id": "2XiTgZ2oVrBgGqKQ1ruCKh",
        "access_key": "2y7cg8kmoGDrDBXJLaizoD",
        "tonce": 1464594744,
        "payload": {
                "template_id": "2hSWTZ4oqVEJKAmK2RiyT4",
        }
}

签名过程用Java代码描述如下:

// RSA私钥文件路径
String keyFile = "/path/to/rsa_key.pem";

// 请求数据
String requestId = "2XiTgZ2oVrBgGqKQ1ruCKh";
String accessKey = "2y7cg8kmoGDrDBXJLaizoD";
String tonce = 1464594744;
String payload = "{\"template_id\": \"2hSWTZ4oqVEJKAmK2RiyT4\"}";

// API path
String apiVersion = "v2";
String apiName = "attestations";
String path = String.format("/api/%s/%s", apiVersion, apiName);

// 待签名数据 = 请求方法+API路径+requestId+accessKey+tonce+payload
String data = "".concat("POST").concat(path).concat(requestId).concat(accessKey).concat(tonce).concat(payload);

// 构造签名
PEMReader pemReader = new PEMReader(new InputStreamReader(new FileInputStream(keyFile)));
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(pemReader.readPemObject().getContent());
pemReader.close();
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
Signature signature = Signature.getInstance("SHA256WithRSA");
signature.initSign(privateKey);
signature.update(data.getBytes("UTF-8"));

// 签名使用Base64编码后得到的值即为请求数据中signature字段的值
String signatureEncoded = Base64.getEncoder().encodeToString(signature.sign());

注解

签名所用的方法是SHA256WithRSA,签名数据字符串转换成bytes时要用UTF-8编码格式

接口

初始化客户端

::
BaoquanClient client = new BaoquanClient();
//设置api地址,比如保全网的测试环境地址
client.setHost("https://baoquan.com");
// 设置access key
client.setAccessKey("fsBswNzfECKZH9aWyh47fc");
// 设置rsa私钥文件的绝对路径
client.setPemPath("path/to/rsa_private.pem");
// 设置版本
client.setVersion("v2");

保全 - /attestations

客户在保全网站上建好模板之后通过该接口传输模板渲染需要的数据。

payload

参数名 描述 是否可选
unique_id String字符串,不超过255位,保全唯一码 必选
template_id String字符串,模板id 必选
identities Object对象,身份事项 必选
factoids 数组对象,陈述集 必选
completed Boolean值,是否完成陈述集的上传 可选,默认为true
attachments 附件信息数组对象 可选

unique_id是保全唯一码,这个唯一码的作用是避免在网络超时或者其它异常的情况下接入方重复上传相同内容的保全数据。如果同样unique_id的保全内容多次上传,保全网只进行1次保全,并返回相同的保全号。

陈述 是一个Object对象,包含unique_id,type和data三个字段,例如:

{
        "unique_id": "9de7be94-a697-4398-945a-678d3f916b9f",
        "type": "hash",
        "data": {
                "userName": "张三",
                "idCard": "42012319800127691X"
        }
}

陈述的unique_id的作用跟保全的unique_id类似,如果某次保全过程中同样unique_id的陈述内容多次上传到保全网,保全网只处理1次。

type是客户定义的陈述名称,data是陈述的字段值,如下图所示:

_images/use_template.png

模板中包含common和hash两个陈述。common中的attestation_no(保全号)、attestation_at(保全时间)、product_name(产品名称)、organization_name(组织名称)在模板渲染时由保全网提供。hash这个陈述是客户自己定义的,所以需要客户通过API上传。

注解

在添加陈述对象是要保证陈述对象跟编辑模板时的要求一致。以下几种情况会导致保全失败:

  • 上传了模板中没有的陈述对象,比如模板中没有type为product的对象却上传了。
  • 模板中有字段是必要的,但是完成陈述上传时并没有上传该字段,比如user.name需要上传且不能为空, 但是没有上传type为user的data或者data中没有name这个字段。
  • 上传的字段的格式不符,比如模板中要求user.money是int型,但是上传的user.money值是"$100"

模板中可能包含多个客户自定义的陈述,比如factoA和factoB,此时客户可以选择分两次上传,第一次上传factoA,并设置completed为false,第二次上传factoB,并设置completed为true。

注解

一旦completed设置为true,则不再接受陈述上传。

假定payload如下所示:

{
        "unique_id": "acafa00d-5579-4fe5-93c1-de89ec82006e",
        "template_id": "2hSWTZ4oqVEJKAmK2RiyT4",
        "identities": {
                "MO": "15857112383",
                "ID": "42012319800127691X"
        },
        "factoids": [
                {
                        "unique_id": "9de7be94-a697-4398-945a-678d3f916b9f",
                        "type": "hash",
                        "data": {
                                "userName": "李三",
                                "idCard": "330124199501017791",
                                "buyAmount": 0.3,
                                "incomeStartTime": "2015-12-02",
                                "incomeEndTime": "2016-01-01",
                                "createTime": "2015-12-01 14:33:44",
                                "payTime": "2015-12-01 14:33:59",
                                "payAmount": 600
                        }
                }
        ],
        "completed": true
}

经过保全后,在保全网上可以通过保全号查看经过渲染后的内容,类似下图所示:

_images/render_template.png

附件

在上传陈述数据的时候可以同时上传跟该陈述相关的附件,在payload中 attachments 存放的是附件的校验码。

form表单形式上传单个附件:

<form method='post' enctype='multipart/form-data'>
  ...
  <input type=file name="attachments[0][]">
</form>

payload = {
        "unique_id": "...",
        "template_id": "...",
        "identities": {...},
        "factoids": [
                {
                        "unique_id": "...",
                        "type": "...",
                        "data": {...}
                }
        ],
        "completed": true,
        "attachments": {
                "0": ["checkSum"]
        }
}

form表单形式上传多个附件:

<form method='post' enctype='multipart/form-data'>
  ...
  <input type=file name="attachments[0][]">
  <input type=file name="attachments[0][]">
  <input type=file name="attachments[1][]">
</form>

payload = {
        "unique_id": "...",
        "template_id": "...",
        "identities": {...},
        "factoids": [
                {
                        "unique_id": "...",
                        "type": "...",
                        "data": {...}
                },
                {
                        "unique_id": "...",
                        "type": "...",
                        "data": {...}
                }
        ],
        "completed": true,
        "attachments": {
                "0": [
                        "checkSum1",
                        {
                                "checksum": "checkSum2",
                                "sign": {
                                        "F98F99A554E944B6996882E8A68C60B2": ["甲方(签章)", "甲方法人(签章)"],
                                        "0A68783469E04CAC95ADEAE995A92E65": ["乙方(签章)"]
                                }
                        }
                ],
                "1": ["checkSum3"]
        }
}

attachments中的key对应的是factoids数组的下标,比如"0"对应的是factoid为factoids[0]。attachments中的value是一个数组,每个数组元素表示对应附件的附件信息。

附件信息有两种:校验码和电子签名信息,其中校验码是必须提供。当附件信息只有校验码时可以用字符串对象,当包含电子签名信息时需要使用object对象。

注解

只有pdf附件才能进行电子签名。

校验码(checksum)是对文件进行SHA256产生的,以Java为例:

String file = "/path/to/file";
InputStream in = new FileInputStream(new File(file));

// 使用SHA256对文件进行hash
bytes[] digestBytes = DigestUtils.getDigest("SHA256").digest(StreamUtils.copyToByteArray(in));

// 将bytes转换成16进制
String checkSum = Hex.encodeHexString(digestBytes);

电子签名信息(sign)是一个object对象,key值是caId(客户调用申请ca证书接口时会返回caId),value值是签名关键字数组。比如“张三”和“李四”需要在“xxx合同.pdf”附件上进行电子签名,调用ca证书申请接口为“张三”申请得到的caId是"F98F99A554E944B6996882E8A68C60B2",为“李四”申请得到的caId是"0A68783469E04CAC95ADEAE995A92E65",其中“张三”需要在"甲方(签章)", "甲方法人(签章)"两个位置进行电子签名,”李四“只需要在"乙方(签章)"进行电子签名,那么sign对象可以表示为:

"sign": {
        "F98F99A554E944B6996882E8A68C60B2": ["甲方(签章)", "甲方法人(签章)"],
        "0A68783469E04CAC95ADEAE995A92E65": ["乙方(签章)"]
}

注解

同一个用户可以在多处进行电子签名,但关键字要保证唯一,不能跟正文内容重复。

返回的data

调用保全接口成功后会返回保全号

字段名 描述
no String字符串,保全号

例如:

{
        "request_id": "2XiTgZ2oVrBgGqKQ1ruCKh",
        "data": {
                "no": "rBgGqKQ1ruCKhXiTgZ2oVr",
        }
}

追加陈述 - /factoids

客户可以使用追加陈述接口上传陈述集

当上传保全时completed参数为false(未设置默认为true)可追加陈述,陈述接口不产生新的保全号。

payload

参数名 描述 是否可选
ano String字符串,保全号 必选
factoids 数组对象,陈述集 必选
completed Boolean值,是否完成陈述集的上传 可选,默认为true
attachments 数组对象,附件的校验码,可选 可选

ano需要追加陈述的保全号,上传保全成功后会得到应答保全号(请注意上传保全时completed参数的设置,已完成后不可追加陈述)。 factoids具体描述请参考保全接口, 例如:

{
        "ano": "2hSWTZ4oqVEJKAmK2RiyT4",
        "factoids": [
                {
                        "unique_id": "9de7be94-a697-4398-945a-678d3f916b9f",
                        "type": "hash",
                        "data": {
                                "userName": "李三",
                                "idCard": "330124199501017791",
                                "buyAmount": 0.3,
                                "incomeStartTime": "2015-12-02",
                                "incomeEndTime": "2016-01-01",
                                "createTime": "2015-12-01 14:33:44",
                                "payTime": "2015-12-01 14:33:59",
                                "payAmount": 600
                        }
                }
        ],
        "completed": false
}

返回的data

字段名 描述
success 是否成功,布尔值

例如:

{
        "request_id": "2XiTgZ2oVrBgGqKQ1ruCKh",
        "data": {
                "success": true,
        }
}

保全(sha256) - /attestation/hash

客户在保全网站上建好模板(文件HASH上传)之后通过该接口传输模板渲染需要的数据。

payload

参数名 描述 是否可选
unique_id String字符串,不超过255位,保全唯一码 必选
template_id String字符串,模板(文件HASH模板)id 必选
identities Object对象,身份事项 必选
factoids 数组对象,陈述集 必选
sha256 文件的sha256值 必选

unique_id是保全唯一码,这个唯一码的作用是避免在网络超时或者其它异常的情况下接入方重复上传相同内容的保全数据。如果同样unique_id的保全内容多次上传,保全网只进行1次保全,并返回相同的保全号。

sha256的算法为SHA256WithRSA。

陈述 是一个Object对象,包含unique_id,type和data三个字段,例如:

{
        "unique_id": "9de7be94-a697-4398-333a-678d3f916b9f",
        "type": "file",
        "data": {
                "owner_name": "张三",
                "owner_id": "330124199501017791"
        }
}

陈述的unique_id的作用跟保全的unique_id类似,如果某次保全过程中同样unique_id的陈述内容多次上传到保全网,保全网只处理1次。

type建议采用系统模板提供的默认值file,data是陈述的字段值,如下图所示:

_images/use_template_hash.png

模板中包含common和file两个陈述。common中的attestation_no(保全号)、attestation_at(保全时间)、product_name(产品名称)、organization_name(组织名称)在模板渲染时由保全网提供。

file这个陈述为系统默认陈述,数据需要客户通过API上传。

注解

  • 文件HASH上传只允许上传一次,不可追加陈述。
  • 该接口不接收附件。
  • 调用该接口时,模板必须为系统提供的文件HASH模板的子模板。

注解

在添加陈述对象是要保证陈述对象跟编辑模板时的要求一致。以下几种情况会导致保全失败:

  • 上传了模板中没有的陈述对象,比如模板中没有type为product的对象却上传了。
  • 模板必须为系统提供的文件HASH模板的子模板,否则,上传失败。

假定payload如下所示:

{
        "unique_id": "acafa00d-5579-4fe5-93c1-de89ec82006e",
        "template_id": "2hSWTZ4oqVEJKAmK2RiyT4",
        "identities": {
                "MO": "15857112383",
                "ID": "42012319800127691X"
        },
        "factoids": [
                {
                        "unique_id": "9de7be94-a697-4398-945a-678d3f916b9f",
                        "type": "file",
                        "data": {
                                "owner_name": "李三",
                                "owner_id": "330124199501017791"
                        }
                }
        ],
        "sha256": "654c71176b207401445fdd471f5e023f65af50d7361bf828e5b1c19c89b977b0"
}

经过保全后,在保全网上可以通过保全号查看经过渲染后的内容,类似下图所示:

_images/render_template_hash.png

返回的data

调用保全接口成功后会返回保全号

字段名 描述
no String字符串,保全号

例如:

{
        "request_id": "2XiTgZ2oVrBgGqKQ1ruCKh",
        "data": {
                "no": "rBgGqKQ1ruCKhXiTgZ2oVr",
        }
}

网页取证 - /attestations/url

根据网页地址固定证据

payload

参数名 描述 是否可选
unique_id String字符串,不超过255位,保全唯一码 必选
template_id String字符串,模板id 必选
identities Object对象,身份事项 必选
factoids 数组对象,陈述集 必选
completed Boolean值,是否完成陈述集的上传 可选,默认为true
url String字符串,网页地址 可选

陈述 是一个Object对象,包含unique_id,type和data三个字段,例如:

{
        "unique_id": "9de7be94-a697-4398-333a-678d3f916b9f",
        "type": "file",
        "data": {
                "owner_name": "张三",
                "owner_id": "330124199501017791"
        }
}

陈述的unique_id的作用跟保全的unique_id类似,如果某次保全过程中同样unique_id的陈述内容多次上传到保全网,保全网只处理1次。

type建议采用系统模板提供的默认值file,data是陈述的字段值,如下图所示:

假定payload如下所示:

{
        "unique_id": "acafa00d-5579-4fe5-93c1-de89ec82006e",
        "template_id": "2hSWTZ4oqVEJKAmK2RiyT4",
        "identities": {
                "MO": "15857112383",
                "ID": "42012319800127691X"
        },
        "factoids": [
                {
                        "unique_id": "9de7be94-a697-4398-945a-678d3f916b9f",
                        "type": "file",
                        "data": {
                                "owner_name": "李三",
                                "owner_id": "330124199501017791"
                        }
                }
        ],
        "url": "https://www.baidu.com"
}

返回的data

调用保全接口成功后会返回保全号

字段名 描述
no String字符串,保全号

例如:

{
        "request_id": "2XiTgZ2oVrBgGqKQ1ruCKh",
        "data": {
                "no": "rBgGqKQ1ruCKhXiTgZ2oVr",
        }
}

获取保全数据 - /attestation

客户可以通过该接口获取上传的保全数据,比如身份标识、陈述列表等

payload

参数名 描述 是否可选
ano String字符串,保全号 必选
fields 数组对象,希望返回的字段 可选,默认为null

由于获取identities、factoids、attachments等字段需要连接数据库、对数据进行解密,耗时较长,所以提供fields进行返回字段的设置。

返回的data

字段名 描述
no 保全号
template_id 模板id
identities 身份标识
factoids 陈述列表
completed 陈述是否上传完成
attachments 附件列表
blockchain_hash 区块链hash,当尚未hash到区块链时为空

attachments是一个数组,其中key是factoids中陈述的角标,value是一个附件id数组

(1)当fields为null时会获取所有的字段值,返回的结果例如:

{
        "request_id": "2XiTgZ2oVrBgGqKQ1ruCKh",
        "data": {
                "no": "DB0C8DB14E3C44C7B9FBBE30EB179241",
                "unique_id": "acafa00d-5579-4fe5-93c1-de89ec82006e",
                "template_id" : "5Yhus2mVSMnQRXobRJCYgt",
                "identities": {
                        "ID": "42012319800127691X",
                        "MO": "15857112383"
                },
                "factoids": [
                        {
                                "unique_id": "28fcdf56-bff3-4ed9-9f87-c8d35ad49e0c",
                                "type": "product",
                                "data": {
                                        "name:: "浙金网",
                                        "description": "p2g理财平台""
                                }
                        },
                        {
                                "unique_id": "e68eb8bc-3d7a-4e22-be47-d7999fb40c9a",
                                "type": "user",
                                "data": {
                                        "name": "张三",
                                        "phone_number": "13234568732",
                                        "registered_at": "1466674609",
                                        "username": "tom"
                                }
                        }
                ],
                "completed": true,
                "attachments": {
                        "1": [
                                "2EHJQPs5j4SZpEKQXQ7r6C",
                                "2F81ZJXosNjzrPJsXKywAu"
                        ]
                },
                "blockchain_hash": "s5j4SZpEKQXQ7r6C2F81ZJXosNjzrPJsXKywAu"
        }
}

(2)当fields为一个空数组时不会获取identities、factoids和attachments的值,返回的结果例如:

{
        "request_id": "2XiTgZ2oVrBgGqKQ1ruCKh",
        "data": {
                "no": "DB0C8DB14E3C44C7B9FBBE30EB179241",
                "unique_id": "acafa00d-5579-4fe5-93c1-de89ec82006e",
                "template_id" : "5Yhus2mVSMnQRXobRJCYgt",
                "identities": null,
                "factoids": null,
                "completed": true,
                "attachments": null,
                "blockchain_hash": "s5j4SZpEKQXQ7r6C2F81ZJXosNjzrPJsXKywAu"
        }
}

因此当需要快速获取blockchain_hash时可以设置fields为一个空数组。

(3)当fields为一个非空数组,比如["identities"],返回的结果例如:

{
        "request_id": "2XiTgZ2oVrBgGqKQ1ruCKh",
        "data": {
                "no": "DB0C8DB14E3C44C7B9FBBE30EB179241",
                "unique_id": "acafa00d-5579-4fe5-93c1-de89ec82006e",
                "template_id" : "5Yhus2mVSMnQRXobRJCYgt",
                "identities": {
                        "ID": "42012319800127691X",
                        "MO": "15857112383"
                },
                "factoids": null,
                "completed": true,
                "attachments": null,
                "blockchain_hash": "s5j4SZpEKQXQ7r6C2F81ZJXosNjzrPJsXKywAu"
        }
}

下载保全文件 - /attestation/download

客户上传到保全数据会经过一定的处理(比如模板渲染)生成一份保全文件,这份保全文件才是最终会hash到区块链上的数据,也是最终能通过公证处出公证书或者通过司法鉴定中心出司法鉴定书的数据。

payload

参数名 描述 是否可选
ano String字符串,保全号 必选

返回的文件

该接口会返回保全文件以及文件名,文件就是http返回结果的body,文件名存放在http的header中,header的名称是Content-Disposition,header值形如:

form-data; name=Content-Disposition; filename=5Yhus2mVSMnQRXobRJCYgt.zip

以java为例:

// 此处省略使用apache http client构造http请求的过程
// closeableHttpResponse是一个CloseableHttpResponse实例
HttpEntity httpEntity = closeableHttpResponse.getEntity();
Header header = closeableHttpResponse.getFirstHeader(MIME.CONTENT_DISPOSITION);
Pattern pattern = Pattern.compile(".*filename=\"(.*)\".*");
Matcher matcher = pattern.matcher(header.getValue());
String fileName = "";
if (matcher.matches()) {
        fileName = matcher.group(1);
}
FileOutputStream fileOutputStream = new FileOutputStream(fileName);
IOUtils.copy(httpEntity.getContent(), fileOutputStream);
fileOutputStream.close();

用户认证信息同步 - /users/kyc

客户可以通过该接口同步实名认证信息到保全网,并自动生成一个用户,同步用户信息后, 创建保全数据的时候,identities 可以使用USERID

payload

参数名 描述 是否可选
name 用户姓名 必选
phone 用户手机号 必选
idCard 用户身份证号 必选

返回的data

字段名 描述
userId 同步认证信息后,返回保全网自动注册的USERID

例如:

{
        "request_id": "2XiTgZ2oVrBgGqKQ1ruCKh",
        "data": {
                "userId": "avbjetsfgyuyrryjetyDFs",
        }
}

企业认证信息同步 - /organizations/kyc

客户可以通过该接口同步企业认证信息到保全网,并自动生成一个用户与此企业关联

payload

参数名 描述 是否可选
name 企业名称 必选
phone 企业关联用户手机号 必选
accountName 企业开户名称 必选
bank 企业开户银行 必选
bankAccount 企业银行账号 必选
orgcode 统一社会信用代码 必选
contactCode 联系人身份证号码 必选
contactName 联系人姓名 必选
businessFile 营业执照 必选

一个用户只能关联一个企业

返回的data

字段名 描述
kycEnterprise 企业认证信息的键值对

例如:

    {
        "kycEnterprise": {
                "bankAccount": "111111111111",
                "organizationId": "r7qyAncCDN1wDJJL6AotQb",
                "bank": "中国银行",
                "rejectReason": null,
                "accountName": "潇潇公司",
                "orgcode": "123456",
                "name": "xxxxx公司",
        "businessFile": "https://baoquan-pub.oss-cn-hangzhou.aliyuncs.com/staging/trust/uploads/kycEnterprise/716d1ff2-e631-4c61-8ced-4553a8d58de4.png",
                "status": "PASS"
        }
}

上传签章图片 - /contract/signature

客户在保全网电子签章之前上传用来签章的签章图片。

附件

同保全附件上传,暂只支持单个签章图片,附件必须是png格式

form表单形式上传单个附件:

<form method='post' enctype='multipart/form-data'>
  ...
  <input type=file name="attachments[0][]">
</form>

返回的data

调用接口成功后会返回签章图片id

字段名 描述
signatureId String字符串,签章图片id

例如:

{
       "signatureId":"ejDVGiGeCQ5Ndn6dzsnWx9"
}

设置默认签章图片 - /contract/signature/default

客户在保全网电子签章之前设置用来签章的默认签章图片。

payload

参数名 描述 是否可选
signature_id 签章图片id 必选

假定payload如下所示:

    {
             "signatureId":"ejDVGiGeCQ5Ndn6dzsnWx9"
}

返回的data

调用接口成功后会返回是否成功

字段名 描述
result String字符串,设置的结果

例如:

{
     "result":"success"
 }

列出签章图片 - /contract/signature/list

客户在保全网电子签章时查看自己所有的签章图片。

返回的data

调用接口成功后会返回是否成功

字段类型 描述
Map key-value,key为签章图片id,value为签章图片地址

例如:

{
         "ejDVGiGeCQ5Ndn6dzsnWx9": "https://eagle-p1.oss-cn-szfinance.aliyuncs.com/production/trust/uploads/userSignature/1b338bba-64c1-47d8-bb34-dcb2dbfd7e48.png",
         "cey4FBLpqbsUNaLp3SENdp": "https://eagle-p1.oss-cn-szfinance.aliyuncs.com/production/trust/uploads/userSignature/5f80cd17-016e-4266-9c35-13266767edb7.png",
         "gHuVuR2EfvJXAF6D1AqEix": "https://eagle-p1.oss-cn-szfinance.aliyuncs.com/production/trust/uploads/userSignature/fb4a28b2-0d1e-4a61-8913-6a259d06ca5a.png"
 }

上传合同 - /contract/uploadPdf

电签接口调用步骤 : 准备工作:1、个人信息同步(必选)2、企业信息同步(必选)3、上传签章图片(可选)4、设置默认签章图片(可选) 签章步骤:1、上传合同 2、发送验证码 3、签署合同(如有多个签署人则重复第二三步)

客户在保全网电子签章时上传用来签章合同pdf。

附件

同保全附件上传,暂只支持单个合同,附件必须是pdf格式

payload

参数名 描述 是否可选
title String字符串,合同标题 必选
end_at Date类型,合同可以签署的截止时间 必选
remark String字符串,合同备注 必选

例如:

{
    "title": "这是xx合同的标题",
    "end_at": "TueAug1418: 08: 29CST2018",
    "remark": "这是xx合同的备注信息"
}

form表单形式上传单个附件:

<form method='post' enctype='multipart/form-data'>
  ...
  <input type=file name="attachments[0][]">
</form>

返回的data

调用接口成功后会返回签章图片id

字段名 描述
contractId String字符串,合同id

例如:

{
       "contractId":"4imixswKjEUU2rzintD3Vx"
}

发送验证码 - /contract/verifyCode

客户在保全网电子签章时按顺序发送验证码。

payload

参数名 描述 是否可选
contract_id String字符串,合同id 必选
phone String字符串,当前签署人手机号 必选
type String字符串,签署人类型 必选,(可填"personal","enterprise")

type必须根据预申请证书类型填写,personal请事先完成个人实名,enterprise请事先完成企业实名

假定payload如下所示:

{
    "phone": "15861111111",
    "contract_id": "4imixswKjEUU2rzintD3Vx",
     "type":"personal",
}

返回的data

字段名 描述
result String字符串,设置的结果

例如:

{
    "result": "success"
}

签署合同和设置签署合同状态 - /contract/sign

客户在保全网签署合同和设置签署合同状态。

payload

参数名 描述 是否可选
contract_id String字符串,合同id 必选
phone String字符串,当前签署人手机号 必选
verify_code String字符串,收到的验证码 必选
ecs_status 枚举值,合同状态 必选(当前可选"DONE"签署)
page String字符串,签署位置所在页码 必选
posX String字符串,签署横坐标位置 必选
posY String字符串,签署纵坐标位置 必选
template_id String字符串,模板id 可选(completed为true必填,可登录保全网创建模板)
identities Object对象,身份事项 可选(completed为true必填)
factoids 数组对象,陈述集 可选(completed为true必填)
completed Boolean值,是否完成合同签署 必选,false或true
signature_id String字符串,签章id 可选,可不填
type String字符串,签署类型 必选,("personal","enterprise")

template_id为生成的保全证书模板id(可到官网设置自己的模板) signature_id为签章图片得id,设置则使用此签章图片签章,不设置则根据企业实名认证信息或个人实名认证信息生成签章图片 type为签署类型,现有"personal"个人签章,使用个人证书签名;"enterprise"企业签章,默认会使用用户上传的签章图片,如未上传签章图片则根据此账户企业认证名称生成签章图片,使用企业证书签名。 假定payload如下所示:

{
 "phone": "15811111111",
 "verify_code": "1525",
 "ecs_status": "DONE",
 "contract_id": "4imixswKjEUU2rzintD3Vx",
 "page": "4",
 "posX": "400",
 "posY": "500",
 "template_id": "2hSWTZ4oqVEJKAmK2RiyT4",
 "identities": {
     "MO": "15857112383",
     "ID": "42012319800127691X"
 },
 "factoids": [
     {
         "unique_id": "9de7be94-a697-4398-945a-678d3f916b9f",
         "type": "hash",
         "data": {
             "userName": "李三",
             "idCard": "330124199501017791",
             "buyAmount": 0.3,
             "incomeStartTime": "2015-12-02",
             "incomeEndTime": "2016-01-01",
             "createTime": "2015-12-01 14:33:44",
             "payTime": "2015-12-01 14:33:59",
             "payAmount": 600
         }
     }
 ],
 "completed": false,
 "signature_id":"",
 "type":"",

}

返回的data

字段名 描述
result String字符串,合同签署结果

例如:

{
        "result": "success"
}

获取合同列表 - /contract/list

客户在保全网获取合同列表。

payload

参数名 描述 是否可选
status 枚举值,合同状态 可选
keyWord String字符串,合同标题或签署方 可选
start Date类型,合同创建开始时间 可选
end Date类型,合同创建结束时间 可选

假定payload如下所示:

{
 "status": "DONE",
 "keyWord": "张三",
 "start": "TueAug1418: 08: 29CST2018",
 "end": "TueAug1418: 08: 29CST2018"

}

返回的data

调用接口成功后会返回合同列表

字段名 描述
Map key-value,value为数组集合

例如:

{
  "list": [
               {
                "attestationId": "FDD989DBC9894C94B3AD26CE7D85FEA2",
                "signUser": "张三,李四",
                "id": "5j1ugSoK5EzkTmkTypH58u",
                "title": "xxx合同",
                "endAt": "1534505604000",
                "userId": "isxaH5d3EAo3KkBWs1bCLC",
                "createAt": "1502969589000",
                "status": "DONE"
             },{
                "attestationId": "EB56D19A331E48D78B37250B05563C60",
                "signUser": "张三,王五",
                "id": "vFBB2sXbZDeWVSd91sVUTk",
                "title": "xx合同",
                "endAt": "1534386299000",
                "userId": "isxaH5d3EAo3KkBWs1bCLC",
                "createAt": "1502850267000",
                "status": "DONE"
                }
        ]
}

获取合同签署详情信息 - /contract/detail

客户在保全网获取合同签署详情信息。

payload

参数名 描述 是否可选
contract_id String字符串,合同id 必选

假定payload如下所示:

{
 "contract_id": "jVef7CWtiFTvGRZ9ZG6ndD"

}

返回的data

调用接口成功后会返回合同签署信息

字段名 描述
Map key-value,value为合同详情

例如:

{
   "detail": {
        "signList": [
                       {
                        "id": "isSpr9bHLZj6CuiZobYgvU",
                        "eContractId": "jVef7CWtiFTvGRZ9ZG6ndD",
                        "eContractSignId": "cf6cbNnZ4ZAP8stXD4NG5G",
                        "userId": "isxaH5d3EAo3KkBWs1bCLC",
                        "name": "张三",
                        "phoneNumber": "18311111111",
                        "signOrder": "1",
                        "status": "DONE",
                        "createdAt": "1505700143000"
                       },{
                        "id": "we1FxES4e4YMNPMp7HZJEq",
                        "eContractId": "jVef7CWtiFTvGRZ9ZG6ndD",
                        "eContractSignId": "kKFr7E9hT88honVeXkLHLW",
                        "userId": "48JGfksQ3LZATZs3TmPTeV",
                        "name": "李四",
                        "phoneNumber": "18322222222",
                        "signOrder": "2",
                        "status": "WAIT",
                        "createdAt": "1505700140000"
                        }
                    ],
                        "endDate": "1537279284000",
                        "id": "jVef7CWtiFTvGRZ9ZG6ndD",
                        "attestationId": "EB56D19A331E48D78B37250B05563C60",
                        "startDate": "1505700065000",
                        "isCreator": false,
                        "status": "WAIT_OTHERS",
                        "token": "aa5JMXFiv-6_upl81M8Xzp2cgENyf_HkVKVie40Ouw4plZAVRPpfxSjwF4PMLSTTn0qbsE9wuWsoDwkQ-4D1RAJ1-                                          POJAs6hU8yCEufmj45j_SyO4zYcFW0kHPIMjWbJ"
           }
}

签署合同下载 - /contract/download

客户在保全网下载签署合同文件。

payload

参数名 描述 是否可选
contract_id String字符串,合同id 必选

假定payload如下所示:

{
 "contract_id": "jVef7CWtiFTvGRZ9ZG6ndD"

}

返回的文件

该接口会返回合同文件以及文件名,文件就是http返回结果的body,文件名存放在http的header中,header的名称是Content-Disposition,header值形如:

form-data; name=Content-Disposition; filename=jVef7CWtiFTvGRZ9ZG6ndD.pdf

以java为例:

// 此处省略使用apache http client构造http请求的过程
// closeableHttpResponse是一个CloseableHttpResponse实例
HttpEntity httpEntity = closeableHttpResponse.getEntity();
Header header = closeableHttpResponse.getFirstHeader(MIME.CONTENT_DISPOSITION);
Pattern pattern = Pattern.compile(".*filename=\"(.*)\".*");
Matcher matcher = pattern.matcher(header.getValue());
String fileName = "";
if (matcher.matches()) {
        fileName = matcher.group(1);
}
FileOutputStream fileOutputStream = new FileOutputStream(fileName);
IOUtils.copy(httpEntity.getContent(), fileOutputStream);
fileOutputStream.close();

客户免验证码签约授权发送验证码 - /authorization/verifyCode

客户在保全网电子签章时免发验证码授权验证码。

payload

参数名 描述 是否可选
phone String字符串,授权人手机号 必选
type String字符串,签署类型 必选,("personal","enterprise")

phone 为合同组的创建人 假定payload如下所示:

{
    "phone": "15861111111",
    "type":"personal"
}

返回的data

字段名 描述
result String字符串,设置的结果

例如:

{
    "result": "success"
}

客户免验证码签约授权确认 - /authorization

客户在保全网电子签章时免发验证码授权确认。

payload

参数名 描述 是否可选
phone String字符串,授权人手机号 必选
verfiy_code String字符串,验证码 必选
type String字符串,签署类型 必选,("personal","enterprise")

phone 为合同组的创建人 假定payload如下所示:

{
    "phone": "15861111111",
    "verfiy_code": "1111",
    "type":"personal"
}

返回的data

字段名 描述
result String字符串,设置的结果

例如:

{
    "result": "success"
}

SDK

保全网目前提供多种语言的SDK,包括Java、PHP、Python,后续会增加更多。

Java

如果使用maven,可以加入如下依赖:

<dependency>
    <groupId>com.baoquan</groupId>
    <artifactId>eagle-sdk</artifactId>
    <version>2.0.2</version>
</dependency>

如果使用gradle,可以加入如下依赖:

compile group: 'com.baoquan', name: 'eagle-sdk', version: '2.0.2'

初始化客户端

BaoquanClient client = new BaoquanClient();
// 设置api地址,比如保全网的测试环境地址
client.setHost("https://baoquan.com");
// 设置access key
client.setAccessKey("fsBswNzfECKZH9aWyh47fc");
// 设置rsa私钥文件的绝对路径
client.setPemPath("path/to/rsa_private.pem");
// 设置版本
client.setVersion("v2");

rsa私钥文件应该以 -----BEGIN PRIVATE KEY----- 开头和 -----END PRIVATE KEY----- 结尾,比如:

-----BEGIN PRIVATE KEY-----
MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBALS8adG98pHSLEq6
kOT6PG25GMBzpiSs1oXwnPLTOVOYarffF0xSB7nk5yxbqx5BseJNz2NxyTpeJOk8
FXEI7qTbS6oYAgyH/2HMr5Az3pKGLRdIjJQrpu3qpJkzRw82qGP2MkmVkUYeOl9B
ZEUpk1GmziwrhbD0zcJITA0mnUqnAgMBAAECgYBnetUPjLTcvrwzURxyrb95hxff
4JdIuljdOUVzVnKlJUg83JOHVBQuYBvn7thLq4uAqdJK+rQfIhX6IDeaj2WqsO7Y
d4YoVxFAlfaHIICJKur15KOXuPMpdm3ilZ0c2yCTrJ0m3Xm6mpwd4blDDSupmlj4
HEXXiInGZgwfTqONAQJBAOlX3EyvE2NvzYMh39wz11fmOi0UiyIvz0immjed4dhV
0YvPjx8Gj7XGwCkzbuNwr7tlkMTaSiYR8cw1QzV4QoECQQDGSOlgAJC8oUP2+u4H
+A83jfSLlhQ8XKAJn5Din9kBvs4eKMSjTpJiDBgA7NUAhUfCqS2/m5TiTiS3X3Ij
ZKknAkEA2iaQCQks4SvnQI9s0FuPGdhdz0ODiCSWb9+CEjkCqdQhococje7+b/0u
Ldat9uilAlfD7qX96HWiTz4EZXrXAQJBAJ+CbgMl0Ul9bcBUsoHEovEtCEn2TIcW
eEPlkldNAfSuev+2CiHZhlbLpc+wtdU6YrUNBdl7HjVDabP+W0JvqscCQQDBoUR8
Y3NUOdGRcaSgwT56tP5J1cZxg1b4vCyr+YfvcEGSBrEaxEugDUjxbON4etMVflh/
H3QNSvRf4XQ44wQO
-----END PRIVATE KEY-----
其它初始化设置

还有些其它可选的初始化设置,比如设置api版本,设置request id生成器,默认情况下你无需进行这些设置:

// 设置request id生成器,生成器需要实现RequestIdGenerator接口中的createRequestId方法
client.setRequestIdGenerator(CustomRequestGenerator)

// sdk中默认的request id生成器
public class DefaultRequestIdGenerator implements RequestIdGenerator {

        @Override
        public String createRequestId() {
                return UUID.randomUUID().toString();
        }
}

客户端初始化完成后即可调用客户端中的方法发送请求

创建保全

CreateAttestationPayload payload = new CreateAttestationPayload();
// 设置保全唯一码
payload.setUniqueId("e68eb8bc-3d7a-4e22-be47-d7999fb40c9a");
// 设置模板id
payload.setTemplateId("5Yhus2mVSMnQRXobRJCYgt");
// 设置陈述是否上传完成,如果设置成true,则后续不能继续追加陈述
payload.setCompleted(false);
// 设置保全所有者的身份标识,标识类型定义在IdentityType中
Map<IdentityType, String> identities = new HashMap<>();
identities.put(IdentityType.ID, "42012319800127691X");
identities.put(IdentityType.MO, "15857112383");
payload.setIdentities(identities);
// 添加陈述对象列表
List<Factoid> factoids = new ArrayList<>();
// 添加product陈述
Factoid factoid = new Factoid();
Product product = new Product();
product.setName("xxx科技有限公司");
product.setDescription("p2g理财平台");
factoid.setUnique_id("e13912e2-ccce-47df-997a-9f44eb2c7b6c");
factoid.setType("product");
factoid.setData(product);
factoids.add(factoid);
// 添加user陈述
factoid = new Factoid();
User user = new User();
user.setName("张三");
user.setRegistered_at("1466674609");
user.setUsername("tom");
user.setPhone_number("13452345987");
factoid.setUnique_id("5bf54bc4-ec69-4a5d-b6e4-a3f670f795f3");
factoid.setType("user");
factoid.setData(user);
factoids.add(factoid);
payload.setFactoids(factoids);
// 调用创建保全接口,如果成功则返回保全号,如果失败则返回失败消息
try {
        CreateAttestationResponse response = client.createAttestation(payload);
        System.out.println(response.getData().getNo());
} catch (ServerException e) {
        System.out.println(e.getMessage());
}

如果创建保全时需要给陈述上传对应的附件:

// 创建3个附件,每个附件都是ByteArrayBody实例,ContentType必须为DEFAULT_BINARY,并且需要设置filename
InputStream inputStream0 = getClass().getClassLoader().getResourceAsStream("seal.png");
ByteArrayBody byteArrayBody0 = new ByteArrayBody(IOUtils.toByteArray(inputStream0), ContentType.DEFAULT_BINARY, "seal.png");
InputStream inputStream1 = getClass().getClassLoader().getResourceAsStream("seal.png");
ByteArrayBody byteArrayBody1 = new ByteArrayBody(IOUtils.toByteArray(inputStream1), ContentType.DEFAULT_BINARY, "seal.png");
InputStream inputStream2 = getClass().getClassLoader().getResourceAsStream("contract.pdf");
ByteArrayBody byteArrayBody2 = new ByteArrayBody(IOUtils.toByteArray(inputStream2), ContentType.DEFAULT_BINARY, "contract.pdf");
// 创建附件map,key为factoids中的角标,此处设置factoids中第1个factoid有1个附件,第2个factoid有2两个附件
Map<String, List<ByteArrayBody>> attachments = new HashMap<>();
attachments.put("0", Collections.singletonList(byteArrayBody0));
attachments.put("1", Arrays.asList(byteArrayBody1, byteArrayBody2));
// 此处省略payload的创建
try {
        CreateAttestationResponse response = client.createAttestation(payload, attachments);
        System.out.println(response.getData().getNo());
} catch (ServerException e) {
        System.out.println(e.getMessage());
}

追加陈述

AddFactoidsPayload addFactoidsPayload = new AddFactoidsPayload();
// 设置保全号
addFactoidsPayload.setAno("7F189BBB5FA1451EA8601D0693E36FE7");
// 添加陈述对象
factoids = new ArrayList<>();
factoid = new Factoid();
User user = new User();
user.setName("张三");
user.setRegistered_at("1466674609");
user.setUsername("tom");
user.setPhone_number("13452345987");
factoid.setUnique_id("5bf54bc4-ec69-4a5d-b6e4-a3f670f795f3");
factoid.setType("user");
factoid.setData(user);
factoids.add(factoid);
addFactoidsPayload.setFactoids(factoids);
// 调用追加陈述接口,如果成功则返回的success为true,如果失败则返回失败消息
try {
        AddFactoidsResponse response = client.addFactoids(addFactoidsPayload);
        System.out.println(response.getData().isSuccess());
} catch (ServerException e) {
        System.out.println(e.getMessage());
}

追加陈述的时候同样能为陈述上传附件,跟创建保全为陈述上传附件一样。

创建保全(sha256)

CreateAttestationPayload payload = new CreateAttestationPayload();
//模板必须为系统提供的文件HASH模板的子模板。
payload.setTemplateId("filehash");
payload.setUniqueId(randomUniqueId());
Map<IdentityType, String> identities = new HashMap<IdentityType, String>();
identities.put(IdentityType.MO, "15857110000");
payload.setIdentities(identities);
List<Factoid> factoids = new ArrayList<Factoid>();
Factoid factoid = new Factoid();
factoid.setUnique_id(randomUniqueId());
factoid.setType("file");
Map<String,String> map = new HashMap<String, String>();
factoid.setData(map);
map.put("owner_name","李三");
map.put("owner_id","330124199501017791");
factoids.add(factoid);
payload.setFactoids(factoids);
// 调用创建保全接口,如果成功则返回保全号,如果失败则返回失败消息
try {
        String sha256 = "654c71176b207401445fdd471f5e023f65af50d7361bf828e5b1c19c89b977b0";
        CreateAttestationResponse response = client.createAttestationWithSha256(payload,sha256);
        System.out.println(response.getData().getNo());
} catch (ServerException e) {
        System.out.println(e.getMessage());
}

网页取证

String url = "http://www.qq.com/";
CreateAttestationPayload payload = new CreateAttestationPayload();
// 设置保全唯一码
payload.setUniqueId(UUID.randomUUID().toString());
// 设置模板id
payload.setTemplateId("jcEGvWNn88XVzjdmGu5GDr");
// 设置陈述是否上传完成,如果设置成true,则后续不能继续追加陈述
payload.setCompleted(true);
// 设置保全所有者的身份标识,标识类型定义在IdentityType中

Map<IdentityType, String> identities = new HashMap<IdentityType, String>();
identities.put(IdentityType.ID, "429006198507104214");
identities.put(IdentityType.MO, "18767106890");
payload.setIdentities(identities);


List<Factoid> factoids = new ArrayList<Factoid>();
Factoid qqxxFactoid = new Factoid();
qqxxFactoid.setUnique_id(UUID.randomUUID().toString() + new Date().getTime());

qqxxFactoid.setType("qqxx");
payload.setUrl(url);
Map<String, String> loanDataMap = new HashMap<String, String>();
qqxxFactoid.setData(loanDataMap);
loanDataMap.put("url", url);
qqxxFactoid.setUnique_id(randomUniqueId());
qqxxFactoid.setType("website");
qqxxFactoid.setData(loanDataMap);
factoids.add(qqxxFactoid);
payload.setFactoids(factoids);
try {
        CreateAttestationResponse response = client.createAttestationWithUrl(payload, url);
    System.out.print(response.getData().getNo());
    System.out.println(response.getData().getNo());
 } catch (ServerException e) {
    System.out.println(e.getMessage());
 }

获取保全数据

try {
        GetAttestationResponse response = client.getAttestation("DB0C8DB14E3C44C7B9FBBE30EB179241", null);
        System.out.println(response.getData());
} catch (ServerException e) {
        System.out.println(e.getMessage());
}

getAttestation有两个参数,第1个参数ano是保全号,第二个参数fields是一个数组用于设置可选的返回字段

下载保全文件

try {
        DownloadFile downloadFile = client.downloadAttestation("7FF4E8F6A6764CD0895146581B2B28AA");

        FileOutputStream fileOutputStream = new FileOutputStream(downloadFile.getFileName());
        IOUtils.copy(downloadFile.getFile(), fileOutputStream);
        fileOutputStream.close();
} catch (ServerException e) {
        System.out.println(e.getMessage());
}

用户认证信息同步

try {
    UserKycResponse response = client.userKyc("15822222224", "用户一", "42012319800127691X");
} catch (ServerException e) {
    System.out.println(e.getMessage());
}

企业认证信息同步

try {
         KycEnterprisePayload payload = new KycEnterprisePayload();
payload.setAccountName("潇潇公司");
payload.setBank("中国银行");
payload.setBankAccount("111111111111");
payload.setName("这是我的公司");
payload.setOrgcode("123456");
payload.setPhone("17696526111");
InputStream businessInputStream = getClass().getClassLoader().getResourceAsStream("licence.jpg");
ByteArrayBody businessFile = new ByteArrayBody(IOUtils.toByteArray(businessInputStream), ContentType.DEFAULT_BINARY, "licence.jpg");
kycEnterpriseResponse response = client.kycEnterprise(payload, businessFile);
} catch (ServerException e) {
        System.out.println(e.getMessage());
}

上传签章图片

try {
     ContractPayload payload = new ContractPayload();
     InputStream inputStream = getClass().getClassLoader().getResourceAsStream("seal.png");
     ByteArrayBody byteArrayBody = new ByteArrayBody(IOUtils.toByteArray(inputStream), ContentType.DEFAULT_BINARY, "seal.png");
     Map<String, List<ByteArrayBody>> byteStreamBodyMap = new HashMap<String, List<ByteArrayBody>>();
     byteStreamBodyMap.put("0", Collections.singletonList(byteArrayBody));
     UploadSignatureResponse u=client.uploadSignature(payload, byteStreamBodyMap);
} catch (ServerException e) {
    System.out.println(e.getMessage());
}

设置默认签章图片

try {
     SignaturePayload payload = new SignaturePayload();
     payload.setSignature_id("cey4FBLpqbsUNaLp3SENdp");
     client.setSignatureDefaultId(payload);
} catch (ServerException e) {
    System.out.println(e.getMessage());
}

签章图片列表

try {
      client.listSignature();
} catch (ServerException e) {
    System.out.println(e.getMessage());
}

上传合同

try {
      ContractPayload payload = new ContractPayload();
      Calendar calendar = Calendar.getInstance();
      Date date = new Date(System.currentTimeMillis());
      calendar.setTime(date);
      calendar.add(Calendar.YEAR, +1);
      date = calendar.getTime();
      System.out.println(date);
      payload.setEnd_at(date);
      payload.setRemark("sas");
      payload.setTitle("ssss合同");
      InputStream inputStream = getClass().getClassLoader().getResourceAsStream("contract.pdf");
      ByteArrayBody byteArrayBody = new ByteArrayBody(IOUtils.toByteArray(inputStream), ContentType.DEFAULT_BINARY, "contract.pdf");
      Map<String, List<ByteArrayBody>> byteStreamBodyMap = new HashMap<String, List<ByteArrayBody>>();
      byteStreamBodyMap.put("0", Collections.singletonList(byteArrayBody));
      UploadContractResponse u = client.uploadContract(payload, byteStreamBodyMap);
      System.out.println(u.getContractId());
} catch (ServerException e) {
    System.out.println(e.getMessage());
}

发送验证码

try {
      client.sendVerifyCode("hspH56P7nZU4XSJRWWGvpy", "15811111111","personal");
} catch (ServerException e) {
    System.out.println(e.getMessage());
}

签署合同或设置合同状态

try {
    Map<String, String> identitiesMap = new HashMap<String, String>();
    List<PayloadFactoid> list = new ArrayList<PayloadFactoid>();
    PayloadFactoid payloadFactoid = new PayloadFactoid();
    LinkedHashMap<String , Object> linkedHashMap = new LinkedHashMap<String, Object>();
    linkedHashMap.put("userTruename","张三");
    linkedHashMap.put("address", "hangzhou");
    payloadFactoid.setType("product");
    payloadFactoid.setData(linkedHashMap);
    list.add(payloadFactoid);
    identitiesMap.put("MO", "15611111111");
    identitiesMap.put("ID", "430426198401361452");
    client.signContract("2B5KcmMKg195rHhLBuNbZB", "15611111111", "5755", "DONE", "4", "400", "550","_priv_template_2", identitiesMap, list,false,"","enterprise");
} catch (ServerException e) {
    System.out.println(e.getMessage());
}

合同列表

try {
   ContractListPayload payload = new ContractListPayload();
    payload.setStatus("DONE");
    client.queryList(payload);
} catch (ServerException e) {
    System.out.println(e.getMessage());
}

合同签署详情信息

try {
   client.getDetail("uqg9hB2JQg61g22ma2bFY2");
} catch (ServerException e) {
    System.out.println(e.getMessage());
}

签署合同下载

try {
        DownloadFile downloadFile = client.downloadContract("jVef7CWtiFTvGRZ9ZG6ndD");

        FileOutputStream fileOutputStream = new FileOutputStream(downloadFile.getFileName());
        IOUtils.copy(downloadFile.getFile(), fileOutputStream);
        fileOutputStream.close();
} catch (ServerException e) {
        System.out.println(e.getMessage());
}

证据固定保全存证

CreateAttestationPayload payload = new CreateAttestationPayload();
// 设置保全唯一码
payload.setUniqueId("e68eb8bc-3d7a-4e22-be47-d7999fb40c9a");
// 设置模板id
payload.setTemplateId("5Yhus2mVSMnQRXobRJCYgt");
// 设置陈述是否上传完成,如果设置成true,则后续不能继续追加陈述
payload.setCompleted(true);
// 设置保全所有者的身份标识,标识类型定义在IdentityType中
Map<IdentityType, String> identities = new HashMap<>();
identities.put(IdentityType.ID, "42012319800127691X");
identities.put(IdentityType.MO, "15857112383");
payload.setIdentities(identities);
// 添加证据固定陈述对象列表
List<Factoid> factoids = new ArrayList<>();
// 添加qqxx陈述
Factoid factoid = new Factoid();
factoid.setUnique_id("e13912e2-ccce-47df-997a-9f44eb2c7b6c");
factoid.setType("qqxx"); //这里type必须为"qqxx"
Map<String, String> qqxxDataMap = new HashMap<String, String>();
qqxxFactoid.setData(loanDataMap);
qqxxDataMap.put("platFormId", "1");
qqxxDataMap.put("nickname", "用户昵称");
qqxxDataMap.put("ywlj", "https://www.baoquan.com/");
qqxxDataMap.put("ywbt", "XX原文标题");
qqxxDataMap.put("originalType","1");
qqxxDataMap.put("url", "http://xx.com");
qqxxDataMap.put("qqbt", "XX侵权标题");
qqxxDataMap.put("qqwz", "XX网");
qqxxDataMap.put("bqgs", "数秦科技");
qqxxDataMap.put("cardNo", "342425199111103230");//证件号码(身份证或者统一社会代码)
qqxxDataMap.put("qqbh", "qq001");
qqxxDataMap.put("qqzt", "XX网");
qqxxDataMap.put("oriSubDate", "2018-01-01 06:20");//原文发布时间
qqxxDataMap.put("pirSubDate", "2018-01-02 06:20");//侵权文章发布时间
qqxxDataMap.put("qqzt", "XX网");
qqxxDataMap.put("matchNum", "0.99");
factoids.add(qqxxFactoid);
payload.setFactoids(factoids);
// 调用创建保全接口,如果成功则返回保全号,如果失败则返回失败消息
try {
        CreateAttestationResponse response = client.fixedEvidence(payload);
        System.out.println(response.getData().getNo());
} catch (ServerException e) {
        System.out.println(e.getMessage());
}

添加原创

OriginalArticlePayload payload = new OriginalArticlePayload();
// 设置原创认证唯一码
payload.setUniqueId(UUID.randomUUID().toString());
payload.setLinkUrl("http://www.baidu.com");
payload.setNickName("1111");
payload.setOriginalType("1,2");
payload.setPlatformCode("1");
payload.setSubDate("2018-06-27 15:22");
payload.setTitle("文章标题");
// 调用添加原创接口,如果成功则返回原创文章Id,如果失败则返回失败消息
try {
        OriginalArticleResponse response = client.createOriginalArticle(payload);
         System.out.print(response.getOriginalId());
} catch (ServerException e) {
        System.out.println(e.getMessage());
}

客户免验证码签约授权发送验证码

       public void testSendAuthorizationVerifyCode() throws ServerException {
    client.sendAuthorizationVerifyCode("15811111111", "persoanl");
}

客户免验证码签约授权确认

public void testauthorized() throws ServerException {
    client.authorized("15811111111", "7333", "personal");
}

PHP

如果使用composer,可以加入如下依赖:

{
  "require": {
    "baoquan/eagle-sdk": "1.0.12"
  }
}

初始化客户端

$client = new BaoquanClient();
// 设置api地址,比如保全网的测试环境地址
$client->setHost('https://baoquan.com');
// 设置access key
$client->setAccessKey('fsBswNzfECKZH9aWyh47fc');
// 设置rsa私钥文件的绝对路径
$client->setPemPath('path/to/rsa_private.pem');

rsa私钥文件应该以 -----BEGIN PRIVATE KEY----- 开头和 -----END PRIVATE KEY----- 结尾,比如:

-----BEGIN PRIVATE KEY-----
MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBALS8adG98pHSLEq6
kOT6PG25GMBzpiSs1oXwnPLTOVOYarffF0xSB7nk5yxbqx5BseJNz2NxyTpeJOk8
FXEI7qTbS6oYAgyH/2HMr5Az3pKGLRdIjJQrpu3qpJkzRw82qGP2MkmVkUYeOl9B
ZEUpk1GmziwrhbD0zcJITA0mnUqnAgMBAAECgYBnetUPjLTcvrwzURxyrb95hxff
4JdIuljdOUVzVnKlJUg83JOHVBQuYBvn7thLq4uAqdJK+rQfIhX6IDeaj2WqsO7Y
d4YoVxFAlfaHIICJKur15KOXuPMpdm3ilZ0c2yCTrJ0m3Xm6mpwd4blDDSupmlj4
HEXXiInGZgwfTqONAQJBAOlX3EyvE2NvzYMh39wz11fmOi0UiyIvz0immjed4dhV
0YvPjx8Gj7XGwCkzbuNwr7tlkMTaSiYR8cw1QzV4QoECQQDGSOlgAJC8oUP2+u4H
+A83jfSLlhQ8XKAJn5Din9kBvs4eKMSjTpJiDBgA7NUAhUfCqS2/m5TiTiS3X3Ij
ZKknAkEA2iaQCQks4SvnQI9s0FuPGdhdz0ODiCSWb9+CEjkCqdQhococje7+b/0u
Ldat9uilAlfD7qX96HWiTz4EZXrXAQJBAJ+CbgMl0Ul9bcBUsoHEovEtCEn2TIcW
eEPlkldNAfSuev+2CiHZhlbLpc+wtdU6YrUNBdl7HjVDabP+W0JvqscCQQDBoUR8
Y3NUOdGRcaSgwT56tP5J1cZxg1b4vCyr+YfvcEGSBrEaxEugDUjxbON4etMVflh/
H3QNSvRf4XQ44wQO
-----END PRIVATE KEY-----

或者以 -----BEGIN RSA PRIVATE KEY----- 开头和 -----END RSA PRIVATE KEY----- 结尾,比如:

-----BEGIN RSA PRIVATE KEY-----
MIICXgIBAAKBgQC0vGnRvfKR0ixKupDk+jxtuRjAc6YkrNaF8Jzy0zlTmGq33xdM
Uge55OcsW6seQbHiTc9jcck6XiTpPBVxCO6k20uqGAIMh/9hzK+QM96Shi0XSIyU
K6bt6qSZM0cPNqhj9jJJlZFGHjpfQWRFKZNRps4sK4Ww9M3CSEwNJp1KpwIDAQAB
AoGAZ3rVD4y03L68M1Eccq2/eYcX3+CXSLpY3TlFc1ZypSVIPNyTh1QULmAb5+7Y
S6uLgKnSSvq0HyIV+iA3mo9lqrDu2HeGKFcRQJX2hyCAiSrq9eSjl7jzKXZt4pWd
HNsgk6ydJt15upqcHeG5Qw0rqZpY+BxF14iJxmYMH06jjQECQQDpV9xMrxNjb82D
Id/cM9dX5jotFIsiL89Ippo3neHYVdGLz48fBo+1xsApM27jcK+7ZZDE2komEfHM
NUM1eEKBAkEAxkjpYACQvKFD9vruB/gPN430i5YUPFygCZ+Q4p/ZAb7OHijEo06S
YgwYAOzVAIVHwqktv5uU4k4kt19yI2SpJwJBANomkAkJLOEr50CPbNBbjxnYXc9D
g4gklm/fghI5AqnUIaHKHI3u/m/9Li3WrfbopQJXw+6l/eh1ok8+BGV61wECQQCf
gm4DJdFJfW3AVLKBxKLxLQhJ9kyHFnhD5ZJXTQH0rnr/tgoh2YZWy6XPsLXVOmK1
DQXZex41Q2mz/ltCb6rHAkEAwaFEfGNzVDnRkXGkoME+erT+SdXGcYNW+Lwsq/mH
73BBkgaxGsRLoA1I8WzjeHrTFX5Yfx90DUr0X+F0OOMEDg==
-----END RSA PRIVATE KEY-----
其它初始化设置

还有些其它可选的初始化设置,比如设置api版本,设置request id生成器,默认情况下你无需进行这些设置:

// 设置api版本
$client->setVersion('v2');
// 设置request id生成器,生成器需要实现RequestIdGenerator接口中的createRequestId方法
$client->setRequestIdGenerator(CustomRequestGenerator);

// sdk中默认的request id生成器
class DefaultRequestIdGenerator implements RequestIdGenerator
{
    /**
     * create request id
     * @return string
     */
    function createRequestId()
    {
        return md5(uniqid("", true));
    }
}

客户端初始化完成后即可调用客户端中的方法发送请求

创建保全

// 调用创建保全接口,如果成功则返回保全号,如果失败则返回失败消息
try {
        $response = $client->createAttestation([
                // 设置保全唯一码
                'unique_id'=>'5bf54bc4-ec69-4a5d-b6e4-a3f670f795f3',
                // 设置模板id
                'template_id'=>'5Yhus2mVSMnQRXobRJCYgt',
                // 设置保全所有者的身份标识
                'identities'=>[
                    'ID'=>'42012319800127691X',
                    'MO'=>'15857112383',
                ],
                // 陈述对象列表
                'factoids'=>[
                    // product陈述
                    [
                        'unique_id'=>'9826dc2a-f5af-4433-ab8d-f515630677c2',
                        'type'=>'product',
                        'data'=>[
                            'name'=>'浙金网',
                            'description'=>'p2g理财平台'
                        ]
                    ],
                    // user陈述
                    [
                        'unique_id'=>'c83d838e-3844-4689-addf-ca0f01171e7c',
                        'type'=>'user',
                        'data'=>[
                            'name'=>'张三',
                            'phone_number'=>'13234568732',
                            'registered_at'=>'1466674609',
                            'username'=>'tom'
                        ]
                    ]
                ],
                // 设置陈述是否上传完成,如果设置成true,则后续不能继续追加陈述
                'completed'=>true
                ]
        );
        echo $response['data']['no'];
} catch (ServerException $e) {
        echo $e->getMessage();
}

如果创建保全时需要给陈述上传对应的附件:

// 创建3个附件,其中product陈述有1个附件,user陈述有两个附件,附件列表的key对应陈述在陈述列表中的角标
// 每个附件由resource和resource_name组成,resource是一个php中的resource对象
$attachments = [
        0=>[
            [
                'resource'=>fopen(__DIR__.'/resources/seal.png', 'r'),
                'resource_name'=>'seal.png'
            ]
        ],
        1=>[
            [
                'resource'=>fopen(__DIR__.'/resources/seal.png', 'r'),
                'resource_name'=>'seal.png'
            ],
            [
                'resource'=>fopen(__DIR__.'/resources/contract.pdf', 'r'),
                'resource_name'=>'contract.pdf'
            ]
        ]
];

// 调用创建保全接口,如果成功则返回保全号,如果失败则返回失败消息
// 此处省略payload的创建
try {
        $response = $client->createAttestation($payload, $attachments);
        echo $response['data']['no'];
} catch (ServerException $e) {
        echo $e->getMessage();
}

追加陈述

try {
        $response = $client->addFactoids([
                // 设置保全号
                'ano'=>'7F189BBB5FA1451EA8601D0693E36FE7',
                // 陈述对象列表
                'factoids'=>[
                    [
                        'unique_id'=>'c83d838e-3844-4689-addf-ca0f01171e7c',
                        'type'=>'user',
                        'data'=>[
                            'name'=>'张三',
                            'phone_number'=>'13234568732',
                            'registered_at'=>'1466674609',
                            'username'=>'tom'
                        ]
                    ]
                ],
                'completed'=>true
                ]
        );
        echo $response['data']['success'];
} catch (ServerException $e) {
        echo $e->getMessage();
}

追加陈述的时候同样能为陈述上传附件,跟创建保全为陈述上传附件一样。

获取保全数据

try {
        $response = $client->getAttestation('DB0C8DB14E3C44C7B9FBBE30EB179241');
        var_dump($response['data']);
} catch (ServerException $e) {
        echo $e->getMessage();
}

getAttestation有两个参数,第1个参数ano是保全号,第二个参数fields是一个数组用于设置可选的返回字段

下载保全文件

try {
        $response = $client->downloadAttestation('DB0C8DB14E3C44C7B9FBBE30EB179241');
        $file = fopen($response['file_name'], 'w');
        fwrite($file, $response['file']->getContents());
        fclose($file);
} catch (ServerException $e) {
        echo $e->getMessage();
}

返回的response有两个字段,file_name表示文件名,file是一个\Psr\Http\Message\StreamInterface实例

申请ca证书

申请个人ca证书:

try {
        $response = $client->applyCa([
                'type'=>'PERSONAL',
                'link_name'=>'张三',
                'link_id_card'=>'330184198501184115',
                'link_phone'=>'13378784545',
                'link_email'=>'123@qq.com',
        ]);
        echo $response['data']['no'];
} catch (ServerException $e) {
        echo $e->getMessage();
}

三证合一情况,申请企业证书:

try {
        $response = $client->applyCa([
                'type'=>'ENTERPRISE',
                'name'=>'xxx有限公司',
                'ic_code'=>'91332406MA27XMXJ27',
                'link_name'=>'张三',
                'link_id_card'=>'330184198501184115',
                'link_phone'=>'13378784545',
                'link_email'=>'123@qq.com',
        ]);
        echo $response['data']['no'];
} catch (ServerException $e) {
        echo $e->getMessage();
}

非三证合一情况,申请企业证书:

try {
        $response = $client->applyCa([
                'type'=>'ENTERPRISE',
                'name'=>'xxx有限公司',
                'ic_code'=>'419001000033792',
                'org_code'=>'177470403',
                'tax_code'=>'419001177470403',
                'link_name'=>'张三',
                'link_id_card'=>'330184198501184115',
                'link_phone'=>'13378784545',
                'link_email'=>'123@qq.com',
        ]);
        echo $response['data']['no'];
} catch (ServerException $e) {
        echo $e->getMessage();
}

签章图片管理

上传签章图片:

try {
     $attachments = [
            0=>[
                [
                    'resource'=>fopen(__DIR__.'/resources/seal.png', 'r'),
                    'resource_name'=>'seal.png'
                ]
            ]
    ];

    $response = $client->uploadContractSignaturePng($attachments);
    print_r($response['signatureId']);
} catch (ServerException $e) {
    echo $e->getMessage();
}

列出签章图片:

try {
    $response = $client->listContractSignature();
    print_r($response);
} catch (ServerException $e) {
    echo $e->getMessage();
}

设置默认签章图片:

try {
    $response = $client->setDefaultContractSignatureId([
        'signature_id'=>"dtodydoVEtvCVY6ee2RNco"
        ]);
    print_r($response);
} catch (ServerException $e) {
    echo $e->getMessage();
}

删除签章图片:

try {
    $response = $client->deleteContractSignature([
        'signature_id'=>"nSysHgKX1Z1sHd9eQGRAe8"
        ]);

    print_r($response);
} catch (ServerException $e) {
    echo $e->getMessage();
}

合同管理

上传pdf合同文件:

try {
     $attachments = [
            0=>[
                [
                    'resource'=>fopen(__DIR__.'/resources/contract.pdf', 'r'),
                    'resource_name'=>'contract.pdf'
                ]
            ]
    ];

    $response = $client->uploadContractPdf($attachments);
    print_r($response);
} catch (ServerException $e) {
    echo $e->getMessage();
}

设置合同和内容,在上传合同之后请求:

try {
    $response = $client->setContractDetail([
        "contract_id"=>"qCWgbg26B63SJEio8Wr2rf",
        "title"=>"这是合同标题",
        "end_at"=>"2017-12-31",
        "userPhones"=>["13812345678","13712345678"],
        "remark"=>"这是备注信息",
        ]);
    print_r($response);
} catch (ServerException $e) {
    echo $e->getMessage();
}

请求短信验证码,在修改合同状态之前请求:

try {
    $response = $client->requireContractVerifyCode([
        "contract_id"=>"qCWgbg26B63SJEio8Wr2rf",
        "phone"=>"18167127094",
        ]);
    print_r($response);
} catch (ServerException $e) {
    echo $e->getMessage();
}

修改合同状态 (签署|取消|拒绝):

try {
    $response = $client->signContract([
        "contract_id"=>"qCWgbg26B63SJEio8Wr2rf",
        "phone"=>"13812345678",
        "verify_code"=>123456,
        "ecs_status"=>"DONE",
        "page"=>"1",
        "posX"=>"2",
        "posY"=>"3",
        ]);
    print_r($response);
} catch (ServerException $e) {
    echo $e->getMessage();
}

查询合同列表

try {
    $response = $client->contractList([
        'status'=>'DONE',
        'keyWord'=>'李四',
        'start'=>'2017-8-30',
        'end'=>'2017-9-1 12:00:00'
        ]);
    print_r($response);
} catch (ServerException $e) {
    echo $e->getMessage();
}

查询合同详情:

try {
    $response = $client->contractDetail([
        'contract_id'=>'uqg9hB2JQg61g22ma2bFY2'
        ]);
    print_r($response);
} catch (ServerException $e) {
    echo $e->getMessage();
}

Python

如果使用pip可以在requirements.txt中加入如下依赖:

eagle-sdk==1.0.8

注解

请在python 3环境下使用本sdk

初始化客户端

from baoquan import BaoquanClient

client = BaoquanClient()
// 设置api地址,比如保全网的测试环境地址
client.host = 'https://baoquan.com'
// 设置access key
client.access_key = 'fsBswNzfECKZH9aWyh47fc'
// 设置rsa私钥文件的绝对路径
client.pem_path = 'path/to/rsa_private.pem'

rsa私钥文件应该以 -----BEGIN RSA PRIVATE KEY----- 开头和 -----END RSA PRIVATE KEY----- 结尾,比如:

-----BEGIN RSA PRIVATE KEY-----
MIICXgIBAAKBgQC0vGnRvfKR0ixKupDk+jxtuRjAc6YkrNaF8Jzy0zlTmGq33xdM
Uge55OcsW6seQbHiTc9jcck6XiTpPBVxCO6k20uqGAIMh/9hzK+QM96Shi0XSIyU
K6bt6qSZM0cPNqhj9jJJlZFGHjpfQWRFKZNRps4sK4Ww9M3CSEwNJp1KpwIDAQAB
AoGAZ3rVD4y03L68M1Eccq2/eYcX3+CXSLpY3TlFc1ZypSVIPNyTh1QULmAb5+7Y
S6uLgKnSSvq0HyIV+iA3mo9lqrDu2HeGKFcRQJX2hyCAiSrq9eSjl7jzKXZt4pWd
HNsgk6ydJt15upqcHeG5Qw0rqZpY+BxF14iJxmYMH06jjQECQQDpV9xMrxNjb82D
Id/cM9dX5jotFIsiL89Ippo3neHYVdGLz48fBo+1xsApM27jcK+7ZZDE2komEfHM
NUM1eEKBAkEAxkjpYACQvKFD9vruB/gPN430i5YUPFygCZ+Q4p/ZAb7OHijEo06S
YgwYAOzVAIVHwqktv5uU4k4kt19yI2SpJwJBANomkAkJLOEr50CPbNBbjxnYXc9D
g4gklm/fghI5AqnUIaHKHI3u/m/9Li3WrfbopQJXw+6l/eh1ok8+BGV61wECQQCf
gm4DJdFJfW3AVLKBxKLxLQhJ9kyHFnhD5ZJXTQH0rnr/tgoh2YZWy6XPsLXVOmK1
DQXZex41Q2mz/ltCb6rHAkEAwaFEfGNzVDnRkXGkoME+erT+SdXGcYNW+Lwsq/mH
73BBkgaxGsRLoA1I8WzjeHrTFX5Yfx90DUr0X+F0OOMEDg==
-----END RSA PRIVATE KEY-----
其它初始化设置

还有些其它可选的初始化设置,比如设置api版本,设置request id生成器,默认情况下你无需进行这些设置:

// 设置api版本
client.version = 'v2'
// 设置request id生成器,生成器必须返回一个长度不超过256位的唯一字符串
// sdk中默认的request id生成器是uuid.uuid4
def custom_request_id_generator():
        pass
client.request_id_generator = custom_request_id_generator

客户端初始化完成后即可调用客户端中的方法发送请求

创建保全

// 调用创建保全接口,如果成功则返回保全号,如果失败则返回失败消息
try:
        response = client.create_attestation({
                // 设置保全唯一码
                'unique_id': 'd310a8f6-6af2-4dc9-baa0-1231cf910dbb',
                // 设置模板id
                'template_id': '5Yhus2mVSMnQRXobRJCYgt',
                // 设置保全所有者的身份标识
                'identities': {
                    'ID': '42012319800127691X',
                    'MO': '15857112383'
                },
                // 陈述对象列表
                'factoids': [
                    {
                        'unique_id': '72aa5bfc-0a62-4e09-9df0-fbf8a4fb7e8f',
                        'type': 'product',
                        'data': {
                            'name': '浙金网',
                            'description': 'p2g理财平台'
                        }
                    },
                    {
                        'unique_id': '4da45cbc-c234-4296-b566-35d03a092f5a',
                        'type': 'user',
                        'data': {
                            'name': '张三',
                            'phone_number': '13234568732',
                            'registered_at': '1466674609',
                            'username': 'tom'
                        }
                    }
                ],
                // 设置陈述是否上传完成,如果设置成true,则后续不能继续追加陈述
                'completed': true
        })
        print(response['data']['no'])
except ServerException as e:
        print(e.message)

如果创建保全时需要给陈述上传对应的附件:

// 创建3个附件,其中product陈述有1个附件,user陈述有两个附件,附件列表的key对应陈述在陈述列表中的角标
// 每个附件由resource、resource_name和resource_content_type组成,resource是字节数组
attachments = {
        0: [
                {
                    'resource': open(os.path.dirname(__file__) + '/resources/seal.png', 'rb').read(),
                    'resource_name': 'seal.png',
                    'resource_content_type': 'image/png'
                }
        ],
        1: [
                {
                    'resource': open(os.path.dirname(__file__) + '/resources/seal.png', 'rb').read(),
                    'resource_name': 'seal.png',
                    'resource_content_type': 'image/png'
                },
                {
                    'resource': open(os.path.dirname(__file__) + '/resources/contract.pdf', 'rb').read(),
                    'resource_name': 'contract.pdf',
                    'resource_content_type': 'application/pdf'
                }
        ]
}
// 调用创建保全接口,如果成功则返回保全号,如果失败则返回失败消息
// 此处省略payload的创建
try:
        response = client.create_attestation(payload, attachments)
        print(response['data']['no'])
except ServerException as e:
        print(e.message)

追加陈述

try:
        response = client.add_factoids({
                // 设置保全号
                'ano': '7F189BBB5FA1451EA8601D0693E36FE7',
                // 陈述对象列表
                'factoids': [
                    {
                        'unique_id': '4da45cbc-c234-4296-b566-35d03a092f5a',
                        'type': 'user',
                        'data': {
                            'name': '张三',
                            'phone_number': '13234568732',
                            'registered_at': '1466674609',
                            'username': 'tom'
                        }
                    }
                ]
                })
        print(response['data']['success'])
except ServerException as e:
        print(e.message)

追加陈述的时候同样能为陈述上传附件,跟创建保全为陈述上传附件一样。

获取保全数据

try:
        response = client.get_attestation('DB0C8DB14E3C44C7B9FBBE30EB179241')
        print(response['data'])
except ServerException as e:
        print(e.message)

get_attestation有两个参数,第1个参数ano是保全号,第二个参数fields是一个数组用于设置可选的返回字段

下载保全文件

try:
        response = client.download_attestation('DB0C8DB14E3C44C7B9FBBE30EB179241')
        with open(response['file_name'], 'wb') as f:
                f.write(response['file_content'])
except ServerException as e:
        print(e.message)

返回的response有两个字段,file_name表示文件名,file_content是以字节形式表示的文件内容

申请ca证书

申请个人ca证书:

try:
        response = client.apply_ca({
                'type': 'PERSONAL',
                'link_name': '张三',
                'link_id_card': '330184198501184115',
                'link_phone': '13378784545',
                'link_email': '123@qq.com',
        })
        print(response['data']['no'])
except ServerException as e:
        print(e.message)

三证合一情况,申请企业证书:

try:
        response = client.apply_ca({
                'type': 'ENTERPRISE',
                'name': 'xxx有限公司',
                'ic_code': '91332406MA27XMXJ27',
                'link_name': '张三',
                'link_id_card': '330184198501184115',
                'link_phone': '13378784545',
                'link_email': '123@qq.com',
        })
        print(response['data']['no'])
except ServerException as e:
        print(e.message)

非三证合一情况,申请企业证书:

try:
        response = client.apply_ca({
                'type': 'ENTERPRISE',
                'name': 'xxx有限公司',
                'ic_code': '419001000033792',
                'org_code': '177470403',
                'tax_code': '419001177470403',
                'link_name': '张三',
                'link_id_card': '330184198501184115',
                'link_phone': '13378784545',
                'link_email': '123@qq.com',
        })
        print(response['data']['no'])
except ServerException as e:
        print(e.message)