发起合同
描述
调用此接口发起草稿状态的合同。支持在发起合同时指定签署位置。合同发起后,签署方将收到签署通知签署合同。
请求地址
/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)