平台简介
新手指南
API协议
API文档
单点登录集成
小程序插件
常见问题
开放平台API接口调用常见报错以及解决方法汇总
帮助中心 / 开放平台帮助文档 / 发起合同
发起合同
调用此接口发起草稿状态的合同。支持在发起合同时指定签署位置。合同发起后,签署方将收到签署通知签署合同。

发起合同

描述

调用此接口发起草稿状态的合同。支持在发起合同时指定签署位置。合同发起后,签署方将收到签署通知签署合同。

请求地址

/v2/contract/send

请求方法

POST

请求格式

application/json;charset=UTF-8

请求参数

参数 类型 必须 描述
contractId String 合同ID,合同ID与业务ID二选一,不能同时为空
bizId String 业务ID,合同ID与业务ID二选一,不能同时为空
tenantName String 子公司名称,若使用业务ID发起合同,且合同是以子公司身份创建的,则需要传递该值,用于确定合同主体
stampers List<Stamper> 指定签署位置
stamperRule String 签署位置规则;MUST_FORBID(必须签署不可增加),MUST_ALLOW(必须签署可增加),OPTIONAL(非必须签署);默认取业务分类中配置的规则
locateAllStamperKeywords Boolean 是否必须找出全部签署位置传入的关键字,默认为true;传入false时,对于传入的关键字定位的签署位置,只需定位到任意一个签署位置的关键字即可

Stamper(签署位置):

参数 类型 必须 描述
actionId String 签署节点ID;公司的签署位置必须(创建合同草稿接口的返回值)
signatoryId String 签署方ID;个人的签署位置必传(创建合同草稿接口的返回值)
type String 签署类型:
COMPANY(公章),PERSONAL(个人签名),
LP(法人章),TIMESTAMP(时间戳),
ACROSS_PAGE(骑缝章), ACROSS_PAGE_ODD(奇数页骑缝章),ACROSS_PAGE_EVEN(偶数页骑缝章),ACROSS_PAGE_SCOPE(指定页面范围骑缝章)
acrossType String 骑缝章位置指定方式
【作用】
指定骑缝章位置时,可以通过此参数控制位置的指定方式
【传参】
取值范围:SINGLE_DOCUMENT(每份文档单独指定骑缝章位置),ALL_DOCUMENT(多份文档合并指定骑缝章位置);不传值默认为:SINGLE_DOCUMENT(每份文档单独指定骑缝章位置)。
sealPageConfig String 骑缝章自定义页面加盖
【传参】
1、可传入页码或页码范围,多组页码或页码范围之间用英文逗号(,)分隔,例如:2,4 ~ 7,8 ~ 11。
2、当rectType(签署位置类型)为ACROSS_PAGE_SCOPE(指定页面范围骑缝章)时,此参数必填。
documentId String 合同文档ID
documentIds String 签署文档id集合
【作用】
用于指定签署位置所在的签署文档,示例 2964011533600084814,2964011533611111111
keyword String 关键字
keywordIndex Integer 关键字索引:1代表第1个关键字,0代表所有关键字
,-1代表倒数第1个关键字;默认为1
page Integer 坐标页码,0代表所有 ,-1代表最后一页
offsetX Decimal 横坐标/关键字偏移量
offsetY Decimal 纵坐标/关键字偏移量
width Integer 签署位置宽度
【作用】
设置签署位置的宽度,防止用户在文件上添加的签名过大或过小
【传参方式】
1、取值范围10-120;
2、支持个人签名、时间戳位置,不支持签章位置;
3、仅传宽度时,高度按比例适配,两者均传参以宽度为准;
height Integer 签署位置高度
【作用】
设置签署位置的高度,防止用户在文件添加的签名过大或过小
【传参方式】
1、取值范围4-48;
2、支持个人签名、时间戳位置,不支持签章位置;
3、仅传宽度时。高度按比例适配。两者均传参以宽度为准;
rotationDegrees Double 签署位置旋转角度
【作用】
指定签署位置的旋转角度,当文件为横向或扫描件存在角度偏移时,可以指定签署位置的旋转角度
【传参方式】
1、取值范围0-360;
2.支持个人签名、时间戳、签章位置;
3、旋转中心为签署图片中心,方向为顺时针;
datePatterns List 时间戳格式:
HYPHEN(yyyy-mm-dd),Chinese(yyyy年mm月dd日(阿拉伯数字)
ALL_Chinese(yyyy年mm月dd日(中文)),ENGLISH(dd MMM yyyy(英文))
仅type为TIMESTAMP时生效,可指定多个格式

签署位置说明:

签署位置有以下两种表现方式:

1、用关键字确定坐标:
keyword:关键字。
offsetX:横坐标偏移量;默认合同页的宽为1,所以取值范围是(-1, 1)。
offsetY:纵坐标偏移量;默认合同页的高为1,所有取值范围是(-1, 1)。
找到keyword的坐标(x, y),再加上偏移量(offsetX, offsetY),最终得到的坐标是(x+offsetX, y+offsetY)。
坐标原点是合同页的左下角,坐标是指印章图片的左下角的坐标。

2、直接确定坐标:
page:印章所在页码;从1开始。
offsetX:横坐标;默认合同页的宽为1,所以取值范围是(0, 1)。
offsetY:纵坐标;默认合同页的高为1,所以取值范围是(0, 1)。
由page确定页码,由(offsetX, offsetY)确定坐标。
坐标原点是合同页的左下角,坐标是指印章图片的左下角的坐标。

返回参数

参数 类型 描述
responseCode String 响应码
message String 响应消息

响应码

(全局响应码请查看文档末“全局响应码”):

响应码 描述
11011101 无效的合同状态
11990005 无效的参数:参数格式错误,必传参数未传,参数超出取值范围,参数类型不正确;
11011109 签署页面超出限制
11011203 无效的印章状态
14990002 权限不匹配
21990001 内部错误:如果未找到对应的开放平台错误码,统一以此错误码返回;

请求示例

Http示例

POST /v2/contract/send HTTP/1.1
Host: [host]
x-qys-open-timestamp: [替换为请求头生成的Timestamp]
x-qys-open-signature: [替换为请求头生成的Signature]
x-qys-open-accesstoken: [替换为请求头生成的Token]
Content-Type: application/json
{
    "contractId": "2591540368898105360",
    "bizId": null,
    "stampers": [{
        "actionId": "2591541618892972178",
        "type": "COMPANY",
        "documentId": "2591542337725374704",
        "sealId": "2566229349702860958",
        "offsetX": "0.1",
        "offsetY": "-0.1",
        "keyword": "劳动",
        "keywordIndex": "2"
    }, {
        "actionId": "2591541618892972178",
        "type": "COMPANY",
        "documentId": "2591542337725374704",
        "sealId": "2566229349702860958",
        "offsetX": "0.5",
        "offsetY": "0.5",
        "page": "1"
    }, {
        "signatoryId": "2591541619077521559",
        "type": "PERSONAL",
        "documentId": "2591542337725374704",
        "offsetX": 0.9,
        "offsetY": 0.9,
        "page": 1
    }]
}
Java示例

// 初始化sdkClient
String serverUrl = "https://openapi.qiyuesuo.cn";
String accessKey = "替换为您申请的开放平台App Token";
String accessSecret = "替换为您申请的开放平台App Secret";
SdkClient sdkClient = new SdkClient(serverUrl, accessKey, accessSecret);
// 发起时可以设置签署位置
Stamper stamper = new Stamper();
stamper.setActionId(2589310177048080947L);
stamper.setDocumentId(2589310172379820580L);
stamper.setType("COMPANY");
stamper.setPage(1);
stamper.setOffsetX(0.1);
stamper.setOffsetY(0.1);
Stamper stamper2 = new Stamper();
stamper2.setActionId(2589310177048080947L);
stamper2.setDocumentId(2589310172379820580L);
stamper2.setType("COMPANY");
stamper2.setPage(1);
stamper2.setOffsetX(0.2);
stamper2.setOffsetY(0.1);
List<Stamper> stampers = new ArrayList<>();
stampers.add(stamper);
stampers.add(stamper2);
// 发起合同
ContractSendRequest request = new ContractSendRequest(2589310172899914283L, stampers);
String response = sdkClient.service(request);
SdkResponse<Object> responseObj = JSONUtils.toQysResponse(response);
if(responseObj.getResponseCode().equals("00000000")) {
    logger.info("合同发起成功");
} else {
    logger.info("请求失败,错误码:{},错误信息:{}", responseObj.getCode(), responseObj.getMessage());
}
C#示例

string serverUrl = "https://openapi.qiyuesuo.cn";
string accessKey = "替换为您申请的开放平台App Token";
string accessSecret = "替换为您申请的开放平台App Secret";
SDKClient client = new SDKClient(accessKey, accessSecret, serverUrl);
ContractSendRequest request = new ContractSendRequest();
//指定签署位置 
//发起方(公司):印章签署位置、法人章签署位置、时间戳位置
Stamper sealStamper = new Stamper();
sealStamper.DocumentId = documentId1;
sealStamper.ActionId = companyActionId;
sealStamper.Type = "COMPANY";
// 绝对位置定位:页数、X、Y定位
sealStamper.Page = 1;
sealStamper.OffsetX = 0.1;
sealStamper.OffsetY = 0.2;
// 关键字位置定位:keyword,keywordIndex,X,Y
//sealStamper.Keyword = "甲方签字"; //确保文件中包含该关键字
//sealStamper.KeywordIndex = 1;
//sealStamper.OffsetX = 0.0;
//sealStamper.OffsetY = 0.0;
Stamper lpStamper = new Stamper();
lpStamper.DocumentId = documentId1;
lpStamper.ActionId = lpActionId;
lpStamper.Type = "LP";
lpStamper.Page = 1;
lpStamper.OffsetX = 0.4;
lpStamper.OffsetY = 0.6;
Stamper timeStamper = new Stamper();
timeStamper.DocumentId = documentId1;
timeStamper.ActionId = companyActionId;
timeStamper.Type = "TIMESTAMP";
timeStamper.Page = 1;
timeStamper.OffsetX = 0.3;
timeStamper.OffsetY = 0.5;
//个人签署方 签署位置
Stamper personalStamper = new Stamper();
personalStamper.DocumentId = documentId1;
personalStamper.SignatoryId = personalSignatoryId;
personalStamper.Type = "PERSONAL";
personalStamper.Page = 1;
personalStamper.OffsetX = 0.7;
personalStamper.OffsetY = 0.5;
request.AddStamper(sealStamper);
request.AddStamper(lpStamper);
request.AddStamper(timeStamper);
request.AddStamper(personalStamper);
string response = null;
try
{
    response = client.Service(request);
}
catch (Exception e)
{
    throw new Exception("发起合同请求服务器失败,失败原因:" + e.Message);
}
SdkResponse<Object> sdkResponse = HttpJsonConvert.DeserializeResponse<Object>(response);
if (!sdkResponse.ResponseCode.Equals("00000000"))
{
    throw new Exception("发起合同失败,失败原因:" + sdkResponse.Message);
}
Console.WriteLine("合同发起成功");
PHP示例

// 初始化$sdkClient
class Util {
    const     url = "https://openapi.qiyuesuo.cn";
    const     accessKey = "替换为您申请的开放平台App Token";
    const     accessSecret = "替换为您申请的开放平台App Secret";
}
$sdkClient = Util::getSDk();
$contractSendRequest = new ContractSendRequest();
$contractSendRequest->setContractId('2590758386643734529');
$contractSendRequest->setBizId("1111111");
/\*\*个指定签署位置:关键字定位\*\*/
$stamper1 = new Stamper();
$stamper1->setType('COMPANY');
$stamper1->setActionId('2590758390800289796');
$stamper1->setDocumentId('2590764888637018192');
$stamper1->setSealId('2555244623418466517');
$stamper1->setKeyword('劳动');
$stamper1->setKeywordIndex('2');
$stamper1->setOffsetX('0.1');
$stamper1->setOffsetY('-0.1');
/\*\*个指定签署位置:坐标定位\*\*/
$stamper2 = new Stamper();
$stamper2->setType('COMPANY');
$stamper2->setActionId('2590758390800289796');
$stamper2->setDocumentId('2590762507098624044');
$stamper2->setSealId('2555244623418466517');
$stamper2->setPage('1');
$stamper2->setOffsetX('0.5');
$stamper2->setOffsetY('0.5');
$stampers = array();
array_push($stampers, $stamper1);
array_push($stampers, $stamper2);
$contractSendRequest->setStampers($stampers);
$result = $sdkClient->service($contractSendRequest);
print_r($result);
return $result;
Python示例

#初始化SdkClient
url = "https://openapi.qiyuesuo.cn"
accessToken = '替换为您申请的开放平台App Token'
accessSecret = '替换为您申请的开放平台App Secret'
sdkClient = SdkClient(url, accessToken, accessSecret)
# 设置签署位置 - 公章签署
seal_stamper = Stamper()
seal_stamper.set_actionId(company_actionId)
seal_stamper.set_documentId(file_documentId)
seal_stamper.set_type('COMPANY')
seal_stamper.set_offsetX(0.3)
seal_stamper.set_offsetY(0.5)
seal_stamper.set_page(1)
# 设置签署位置 - 法人章签署
lp_stamper = Stamper()
lp_stamper.set_actionId(lp_actionId)
lp_stamper.set_documentId(file_documentId)
lp_stamper.set_type('LP')
lp_stamper.set_offsetX(0.6)
lp_stamper.set_offsetY(0.4)
lp_stamper.set_page(1)
# 设置签署位置 - 时间戳签署
time_stamper = Stamper()
time_stamper.set_actionId(company_actionId)
time_stamper.set_documentId(file_documentId)
time_stamper.set_type('TIMESTAMP')
time_stamper.set_offsetX(0.9)
time_stamper.set_offsetY(0.5)
time_stamper.set_page(1)
# 设置签署位置 - 个人接收方 - 个人签名
personal_stamper = Stamper()
personal_stamper.set_signatoryId(personal_signatoryId)
personal_stamper.set_documentId(file_documentId)
personal_stamper.set_type('PERSONAL')
personal_stamper.set_offsetX(0.4)
personal_stamper.set_offsetY(0.7)
personal_stamper.set_page(1)
# 请求服务器
send_response = sdkClient.request(
    ContractSendRequest(draft_contractid, [seal_stamper, lp_stamper, time_stamper, personal_stamper]))
# 解析返回数据
send_mapper = json.loads(send_response)
if send_mapper['responseCode'] != '00000000':
    raise Exception('发起合同失败,失败原因:', send_mapper['message'])
print('合同发起成功')
Go示例

sdkClient := http.NewSdkClient("https://openapi.qiyuesuo.cn", "替换为您申请的开放平台App Token", "替换为您申请的开放平台App Secret")
req := request.ContractSendRequest{}
req.ContractId = "3121737020200780306"
response, err := sdkClient.Service(req)
if err != nil {
    fmt.Println("request failed,", err.Error())
    return
}
fmt.Println(response)