1.1. 简介
在与企企系统对接中,企企提供异步接口。草稿态新增时,可使用异步接口进行单据提交。异步接口支持单据的提交,撤回,弃审,同意。本教程将介绍如果通过开放平台openApi实现企企异步接口的调用。
1.1.1. 操作流程
本教程通过 API 实现企企与第三方系统的对接,操作时序图如下所示:
1.1.2. 使用到的 OpenAPI
本教程将调用以下 OpenApi 接口
方法(API) | 操作 | 访问凭证 |
---|---|---|
POST /v1/list
|
查询对象列表 |
openid(v1 版本) |
PUT /v1/update
|
更新对象(单据状态为:草稿、已退回、已撤回 时支持更新) | openid(v1 版本) |
POST /v1/delete
|
删除对象 | openid(v1 版本) |
POST /v1/batchDo
|
同步步任务接口,用于单据状态变更(支持状态:提交,撤回,弃审,同意状态) | openid(v1 版本) |
GET /v1/code
|
根据code获取openid | 无需openid |
1.2. 案例实现
1.2.1. 新增报销单
草稿态新增报销单:
a. 使用接口,POST https://api2.77hub.com/v1/add 新增接口。
b. 使用sdk,新增时自动提交付款单示例如下, Save-As-Draft 设置为 true
public void testAdd() {
PostAddRequest request = new PostAddRequest();
ApiParams apiParams = new ApiParams();
apiParams.setJson("{\"objectType\":\"Reimburse\",\"data\":{\"billType.name\":\"差旅报销单\",\"webEditTemplate.name\":\"差旅报销单\",\"businessType.name\":\"日常报销\",\"businessDate\":\"2023-08-02\",\"code\":\"122kEX0120220800001\",\"applyDepartment.name\":\"总部\",\"applyUser.name\":\"qianqian-1127\",\"department.name\":\"总部\",\"isEntrust\":false,\"description\":\"出差报销\",\"project.name\":\"预算项目\",\"originActualAmount\":6000,\"reimburseTaxis\":[{\"cost.name\":\"广告费\",\"activityDate\":\"1659283200000\",\"originAmount\":500,\"originDeductedAmount\":500,\"description\":\"出差打车\",\"fromPlace\":\"北京\",\"toPlace\":\"大兴机场\",\"reimburseVoucher.name\":\"增值税普通发票\",\"isDeduction\":false,\"project.name\":\"预算项目\",\"originActualAmount\":500,\"budgetAccount.name\":\"费用预算001\"}],\"reimburseTransports\":[{\"cost.name\":\"营业外支出\",\"activityDate\":\"1659283200000\",\"originAmount\":1000,\"originDeductedAmount\":921.56,\"description\":\"长途\",\"fromDistrict.code\":\"01\",\"fromDistrict.name\":\"北京\",\"toDistrict.code\":\"09\",\"toDistrict.name\":\"上海市\",\"transport.name\":\"飞机\",\"transportClass.name\":\"经济舱\",\"discount\":0,\"reimburseVoucher.name\":\"行程单\",\"isDeduction\":true,\"originDeductibleTaxAmount\":78.44,\"deductionTaxRate\":0.09,\"originActualAmount\":1000,\"project.name\":\"预算项目\",\"budgetAccount.name\":\"费用预算001\"}],\"reimburseAllowances\":[{\"cost.name\":\"财务费\",\"startDate\":\"1659283200000\",\"endDate\":\"1661875200000\",\"originAmount\":3000,\"originDeductedAmount\":3000,\"days\":30,\"originActualAmount\":3000,\"city.name\":\"上海市\",\"project.name\":\"预算项目\",\"budgetAccount.name\":\"费用预算001\"}],\"reimburseHotels\":[{\"cost.name\":\"财务费\",\"startDate\":\"2022-08-01\",\"endDate\":\"2022-08-31\",\"days\":30,\"originAmount\":3000,\"city.code\":\"09\",\"city.name\":\"上海市\",\"description\":\"住宿\",\"isDeduction\":true,\"originDeductibleTaxAmount\":66,\"deductionTaxRate\":0,\"project.name\":\"预算项目\",\"originActualAmount\":3000}],\"externalObjectId\":\"2100000028\",\"externalObjectType\":\"Reimburse\",\"externalSystemCode\":\"210028\"}}";
request.sdkRequestConfig(getSdkRequestConfig(request, true, true));
request.setApiParams(apiParams);
PostAddResult postAddResult = openapi().postAdd(request);
ApiResponse apiResponse = postAddResult.getApiResponse();
System.out.println(apiResponse);
}
c. 返回结果:
{"json":"{\"id\":\"RMUEHSDv87000S\"}"}
1.2.2. 提交报销单
提交新增的报销单,提交后,如果有审批流程,会直接进入单据的审批流程
a. 使用接口,POST https://api2.77hub.com/v1/asyncBatchDo 提交报销单。
b. 在请求体(Body)中,以 JSON 格式填写请求参数。
{
"objectType":"Reimburse", // 对象名称,从数据字典中查看对象名称,必填
"objectId":"RMUEHSDv87000S", // 对象id ,必填
"action":"manualSubmit", // 执行动作,必填
"reason":"原因" // 执行原因
}
c. 提交报销单返回:
{
"json":"{\"runningIds\":[\"RMUEHSDv87000S\"],\"successIds\":[],\"failIds\":{},\"warningIds\":{},\"userTaskActionValue\":\"manualSubmit\",\"objectType\":\"Reimburse\",\"failedCount\":0,\"runningCount\":1,\"successCount\":0,\"warningCount\":0,\"totalCount\":1,\"taskId\":\"L3QAT462XQU009G\",\"isCompleted\":false,\"requestId\":\"time-65a78588-dbe7-4b02-aabc-f789d5cb8494\"}"
}
参数说明:
- runningIds: 执行的单据id
- requestId: 查询一步任务执行结果的id
1.2.3. 查询提交的结果
根据提交返回的requestId查询提交的结果
a. 使用接口,POST https://api2.77hub.com/v1/v1/asynctask 提交报销单。
b. 在请求体(Body)中,以 JSON 格式填写请求参数。
{
"requestId":"time-65a78588-dbe7-4b02-aabc-f789d5cb8494" // 提交返回的requestId
}
c.使用sdk,修改付款单示例如下
public void testAsyncTask() {
PostAsynctaskRequest request = new PostAsynctaskRequest();
request.sdkRequestConfig(getSdkRequestConfig(request));
AsyncTaskParams params = new AsyncTaskParams();
params.setRequestId("time-d5b4e7a2-d593-4b5e-afd4-c42f2418aee1");
request.setAsyncTaskParams(params);
PostAsynctaskResult result = openapi().postAsynctask(request);
System.out.println(result.getAsyncTask());
}
d.返回结果:
- 提交成功返回结果
{AsyncTaskItems: [{AsyncTaskItemStatusObject: {Id: AsyncTaskItemStatus.succeeded,Title: 成功},BillStatusObject: {Id: BillStatus.restarted,Title: 已退回},LastErrorMsg: ,ObjectId: L3QAT462XQU0009,ObjectType: Reimburse}],IsCompleted: true}
- AsyncTaskItemStatusObject; 异步任务状态
- id: AsyncTaskItemStatus.succeeded 异步任务成功
- IsCompleted:true 是否完成
- AsyncTaskItemStatusObject; 异步任务状态
- 提交报错返回结果
{AsyncTaskItems: [{AsyncTaskItemStatusObject: {Id: AsyncTaskItemStatus.failed,Title: 失败},BillStatusObject: {Id: BillStatus.draft,Title: 未提交},LastErrorMsg: {"type":"error","code":"0010","message":"提交的数据存在问题","description":"Object validation failed","args":{"problems":{"default":{"ERROR":[{"fieldPath":"reimburseTaxis[0].budgetAccount","type":"error","code":"0011","message":"字段必填","args":{"objectType":"ReimburseTaxi"}},{"fieldPath":"reimburseAllowances[0].budgetAccount","type":"error","code":"0011","message":"字段必填","args":{"objectType":"ReimburseAllowance"}},{"fieldPath":"reimburseTransports[0].budgetAccount","type":"error","code":"0011","message":"字段必填","args":{"objectType":"ReimburseTransport"}}]}}}},ObjectId: L3QAT462XQU0009,ObjectType: Reimburse}],IsCompleted: true}
- AsyncTaskItemStatusObject; 异步任务状态
- id: AsyncTaskItemStatus.failed 异步任务失败
- LastErrorMsg: 错误信息
- IsCompleted:true 是否完成
- AsyncTaskItemStatusObject; 异步任务状态
e. 如果返回错误信息,需要先处理错误信息,针对错误信息更新数据:
- 使用接口,POST https://api2.77hub.com/v1/update 更新报销单。
在请求体(Body)中,以 JSON 格式填写请求参数。
{ "json":"{\"objectType\":\"Reimburse\",\"data\":{\"id\":\"L3QAT462XQU0009\",\"reimburseTaxis\":[{\"id\":\"L3QAT462XQU0008\",\"budgetAccount\":\"4000\",\"budgetAccount.name\":\"费用预算001\",\"editFlag\":\"update\"}],\"reimburseAllowances\":[{\"id\":\"L3QAT462XQU0005\",\"budgetAccount\":\"11\",\"budgetAccount.name\":\"费用预算001\",\"editFlag\":\"update\"}],\"reimburseTransports\":[{\"id\":\"L3QAT462XQU0006\",\"budgetAccount\":\"22\",\"budgetAccount.name\":\"费用预算001\",\"editFlag\":\"update\"}]}}" }
json 的value 值如下:
{ "objectType":"Reimburse", "data":{ "id":"L3QAT462XQU0009", // 报销单单据id "reimburseTaxis":[ { "id":"L3QAT462XQU0008", //出差打车明细id,更新明细,需要加上明细ID "budgetAccount":"4000", "budgetAccount.name":"费用预算001", "editFlag":"update" } ], "reimburseAllowances":[ { "id":"L3QAT462XQU0005", //出差打车明细id "budgetAccount":"11", "budgetAccount.name":"费用预算001", "editFlag":"update" } ], "reimburseTransports":[ { "id":"L3QAT462XQU0006", //出差打车明细id "budgetAccount":"22", "budgetAccount.name":"费用预算001", "editFlag":"update" } ] } }
使用sdk,新增时自动提交付款单示例如下
public void testUpdate() { PutUpdateRequest request = new PutUpdateRequest(); ApiParams apiParams = new ApiParams(); apiParams.setJson("{\"objectType\":\"Reimburse\",\"data\":{\"id\":\"L3QAT462XQU0009\",\"reimburseTaxis\":[{\"id\":\"L3QAT462XQU0008\",\"budgetAccount\":\"4000\",\"budgetAccount.name\":\"费用预算001\",\"editFlag\":\"update\"}],\"reimburseAllowances\":[{\"id\":\"L3QAT462XQU0005\",\"budgetAccount\":\"11\",\"budgetAccount.name\":\"费用预算001\",\"editFlag\":\"update\"}],\"reimburseTransports\":[{\"id\":\"L3QAT462XQU0006\",\"budgetAccount\":\"22\",\"budgetAccount.name\":\"费用预算001\",\"editFlag\":\"update\"}]}}"); request.sdkRequestConfig(getSdkRequestConfig(request)); request.setApiParams(apiParams); PutUpdateResult result = openapi().putUpdate(request); ApiResponse apiResponse = result.getApiResponse(); System.out.println(apiResponse); }
更新返回结果
{"json":"{\"success\":true}"}
数据更新后异步提交:
{ "json":"{\"runningIds\":[\"L3QAT462XQU0009\"],\"successIds\":[],\"failIds\":{},\"warningIds\":{},\"userTaskActionValue\":\"manualSubmit\",\"objectType\":\"Reimburse\",\"failedCount\":0,\"runningCount\":1,\"successCount\":0,\"warningCount\":0,\"totalCount\":1,\"taskId\":\"L3QAT462XQU00D9\",\"isCompleted\":false,\"requestId\":\"time-3720ce9e-178a-46f9-9025-e4810516ef1a\"}" }
异步提交口查询提交结果:
{AsyncTaskItems: [{AsyncTaskItemStatusObject: {Id: AsyncTaskItemStatus.succeeded,Title: 成功},BillStatusObject: {Id: BillStatus.restarted,Title: 已退回},LastErrorMsg: ,ObjectId: L3QAT462XQU0009,ObjectType: Reimburse}],IsCompleted: true}