关键词:OpenAPI、附件面板


一、需求

苍穹平台内有一业务单据,其中存在多个附件面板控件。现有第三方系统,需将其内的业务单据数据及其多个附件文件远程上传至苍穹平台内的该单据上,且附件文件分别显示在不同的附件面板上。


二、思路与方案

2.1 分析思路

第三方系统远程上传业务单据数据至苍穹平台内,平台本身可开放单据保存的OpenAPI接口(操作服务)供其调用,但该接口不能同步上传与该业务单据相关的附件文件,故在实现过程中可通过平台对外提供的attachment/uploadFile.do请求先完成文件上传,然后对外开放一个自定义服务接口来完成业务单据数据的保存、附件文件持久化,并建立两者之间的关联关系,最后第三方系统通过调用此自定义服务接口来完成实际业务功能。


2.2 实现方案

先通过苍穹平台的标准接口(attachment/uploadFile.do)上传附件,然后开发自定义服务实现业务单据数据的保存、附件持久化、并建立两者之间的关联关系,最后在第三方系统中通过调用该接口实现功能。


三、实现过程

1. 获取accessToken。

	public static void main(String[] args) {
		ThirdSysRemoteOperateAttachmentWithCosmic remoteOperateAtta = new ThirdSysRemoteOperateAttachmentWithCosmic();
		// 获取appToken,需在方法体内修改配置信息
		String appToken = AppLoginService.getService().getAppToken(URL_COSMICHOST);
		// 获取accessToken,需在方法体内修改配置信息
		String accessToken = UserLoginService.getService().getAccessToken(URL_COSMICHOST, appToken);
		try {
			// 远程上传单据&附件
			remoteOperateAtta.remoteSaveAttasToCosmic(accessToken);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}


2. 调用苍穹的文件上传请求(uploadFile.do)将文件发送至苍穹系统缓存中,并返回临时附件的url。

	/**
	 * 将文件发送到苍穹中
	 * @param file
	 * @param accessToken
	 * @return
	 * @throws Exception
	 */
	private String postFileToCosmic(File file, String accessToken) throws Exception {
		// 第三方系统上传附件到苍穹的请求接口
        StringBuffer url = new StringBuffer();
        url.append(URL_COSMICHOST).append("attachment/uploadFile.do");
        // 上传可能需要传的参数
        Map<String, Object> param = new HashMap<String, Object>();
		// 上传附件,返回该附件在苍穹缓存中的临时存储路径
        return FileUploadService.getService().postFile(url.toString(), param, file, accessToken);
	}


3. 封装单据&附件数据。

	/**
	 * 封装单据数据  & 所有附件数据
	 * @param allFiles		所有待上传到苍穹的附件
	 * @param accessToken
	 * @return
	 * @throws Exception
	 */
	private Map<String, Object> generateBizData(Map<String, List<File>> allFiles, String accessToken) throws Exception {
		Map<String, Object> allBizBillData = new HashMap<String, Object>();
		// 生成单据数据
		Map<String, Object> billData = new HashMap<String, Object>();
		billData.put("billno", billno);
		billData.put("billstatus", "A");
		allBizBillData.put("billData", billData);
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("appId", KEY_APPNUMBER);
		params.put("entityName", KEY_BILL);
		allBizBillData.put("params", params);
		// 生成单据上所有的附件数据
		Map<String, Object> allAttachmentsData = new HashMap<String, Object>();
		// 单个附件面板中所有附件的信息
		List<Map<String, Object>> attachments = null;
		// 单个附件的信息
		Map<String, Object> attachmentInfo = null;
		StringBuffer uid = new StringBuffer();
		uid.append("rc-upload-").append(new Date().getTime()).append("-");
		int index = (int) (1 + Math.random()*10);
		for (String tempAttaKey : allFiles.keySet()) {
			List<File> files = allFiles.get(tempAttaKey);
			attachments = new ArrayList<Map<String, Object>>();
			for (File tempFile : files) {
				String tempAttaUrl = this.postFileToCosmic(tempFile, accessToken);
				attachmentInfo = new HashMap<String, Object>();
				attachmentInfo.put("entityNum", KEY_BILL);
				attachmentInfo.put("name", tempFile.getName());
				attachmentInfo.put("url", tempAttaUrl);
				attachmentInfo.put("size", tempFile.length());
				attachmentInfo.put("status", "success");
				attachmentInfo.put("uid", uid.toString() + index++);
				attachments.add(attachmentInfo);
			}
			allAttachmentsData.put(tempAttaKey, attachments);
		}
		allBizBillData.put("allAttachmentsData", allAttachmentsData);
		return allBizBillData;
	}


4. 开发自定义服务,插件中实现单据数据保存,并同步持久化缓存中附件到附件服务器上。

	@SuppressWarnings("unchecked")
	@Override
	public ApiResult doCustomService(Map<String, Object> params) {
		Map<String, Object> resultInfo = new HashMap<String, Object>();
		// 单据数据
		Map<String, Object> bizObject = (Map<String, Object>) params.get("billData");
		logger.info("单据数据: " + bizObject);
		// 附件信息
		Map<String, Object> attachmentInfo = (Map<String, Object>) params.get("allAttachmentsData");
		// 参数信息
		Map<String, Object> paramMap = (Map<String, Object>) params.get("params");
		String entityNumber = paramMap.get("entityName").toString();
		logger.info(">>> 上传附件 <<<");
		// 保存单据数据
		DynamicObject dynamicObject = BusinessDataServiceHelper.newDynamicObject(entityNumber);
		dynamicObject.set("billno", bizObject.get("billno"));
		dynamicObject.set("billstatus", bizObject.get("billstatus"));
		dynamicObject.set("createtime", new Date());
		dynamicObject.set("modifytime", new Date());
		OperationResult result = SaveServiceHelper.saveOperate(entityNumber, new DynamicObject [] {dynamicObject}, OperateOption.create());
		if (!result.isSuccess()) {
			List<IOperateInfo> operateInfo = result.getAllErrorOrValidateInfo();
			for (IOperateInfo tempOperateInfo : operateInfo) {
				logger.error(tempOperateInfo.getMessage());
			}
			return ApiResult.fail("单据保存失败!");
		}
		// 上传附件
		String appId = paramMap.get("appId").toString();
		Object pkId = result.getSuccessPkIds().get(0);
		DynamicObjectCollection collection = AttachmentServiceHelper.saveTempAttachments(entityNumber, pkId, appId, attachmentInfo);
		if (null == collection || collection.size() == 0) {
			return ApiResult.fail(collection.toString());
		} else {
			resultInfo.put("message", collection);
		}
		return ApiResult.success(resultInfo);
	}


5. 第三方系统中调用苍穹对外开放的自定义服务接口完成单据数据保存和附件持久化。

	/**
	 * 第三方系统远程上传单据&附件到苍穹系统
	 * 参考资料:https://www.cnblogs.com/zwqh/p/9635176.html
	 *        https://blog.csdn.net/zzq900503/article/details/72920914/
	 * 
	 * @throws Exception
	 */
	private void remoteSaveAttasToCosmic(String accessToken) throws Exception {
		// 第三方系统中待上传到苍穹系统的文件
		File file1 = new File("E:\\test1.txt");
		List<File> fileList1 = new ArrayList<>();
		fileList1.add(file1);
		File file2 = new File("E:\\test2.txt");
		List<File> fileList2 = new ArrayList<>();
		fileList2.add(file2);
		Map<String, List<File>> files = new HashMap<String, List<File>>();
		// 将各文件放入苍穹单据上指定的附件面板中
		files.put(KEY_BILL_ATTACHMENTPANELS[0], fileList1);
		files.put(KEY_BILL_ATTACHMENTPANELS[1], fileList2);
		// 封装数据, 并文件发送至苍穹系统中
		Map<String, Object> allBizBillData = this.generateBizData(files, accessToken);
		// 上传数据
		String responseStr = BizOperateService.getService().bizSave(URL_COSMICHOST, accessToken, allBizBillData);
		JSONObject responseJson = JSONObject.parseObject(responseStr);
		Boolean success = Boolean.valueOf(responseJson.getString("success"));
		if (success) {
			System.out.println("文件已成功上传至苍穹系统!");
		} else {
			String message = responseJson.getJSONObject("data").getString("message");
			throw new Exception(message);
		}
	}


四、效果图

第三方系统远程上传单据&附件--效果图.png

图1


五、开发环境版本

V2.0.036(含)以上


六、注意事项

1. 如需复现样例效果,请注意按实际系统配置信息修改代码中相关变量参数。

2. 文章附件包含案例元数据补丁包、Java代码源码。解压之后请在MC中以更新补丁的形式将元数据压缩包导入平台里,Java代码放到本地开发工具(Eclipse/Idea)中,重启服务,运行代码即可查看效果,实际操作请查阅附件内的文档《操作步骤.doc》。


七、参考资料

开发平台

学习成长中心

开放平台(视频)

开放平台(文档)

插件开发—开放API

附件面板控件

第三方系统远程查询苍穹系统内指定单据的附件信息

第三方系统远程下载苍穹系统内指定单据的所有附件

复制合同模板(基础资料)上的附件并填充数据后重新绑定到业务单据上