package cn.iocoder.yudao.module.bpm.framework.flowable.core.util; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.core.KeyValue; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import cn.iocoder.yudao.framework.common.util.spring.SpringUtils; import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder; import cn.iocoder.yudao.module.bpm.api.event.BpmProcessInstanceStatusEvent; import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO; import cn.iocoder.yudao.module.bpm.enums.definition.BpmHttpRequestParamTypeEnum; import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService; import tools.jackson.core.type.TypeReference; import lombok.extern.slf4j.Slf4j; import org.flowable.engine.runtime.ProcessInstance; import org.springframework.http.*; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.web.client.RestClientException; import org.springframework.web.client.RestTemplate; import java.util.HashMap; import java.util.List; import java.util.Map; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.HEADER_TENANT_ID; import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.PROCESS_INSTANCE_HTTP_CALL_ERROR; /** * 工作流发起 HTTP 请求工具类 * * @author 芋道源码 */ @Slf4j public class BpmHttpRequestUtils { public static void executeBpmHttpRequest(ProcessInstance processInstance, String url, List headerParams, List bodyParams, Boolean handleResponse, List> response) { BpmProcessInstanceService processInstanceService = SpringUtils.getBean(BpmProcessInstanceService.class); // 1.1 设置请求头 HttpHeaders headers = buildHttpHeaders(processInstance, headerParams); // 1.2 设置请求体 MultiValueMap body = buildHttpBody(processInstance, bodyParams); // 2. 发起请求 RestTemplate restTemplate = SpringUtils.getBean(RestTemplate.class); ResponseEntity responseEntity = sendHttpRequest(url, headers, body, restTemplate); // 3. 处理返回 if (Boolean.FALSE.equals(handleResponse)) { return; } // 3.1 判断是否需要解析返回值 if (responseEntity == null || StrUtil.isEmpty(responseEntity.getBody()) || !responseEntity.getStatusCode().is2xxSuccessful() || CollUtil.isEmpty(response)) { return; } // 3.2 解析返回值, 返回值必须符合 CommonResult 规范。 CommonResult> respResult = JsonUtils.parseObjectQuietly(responseEntity.getBody(), new TypeReference<>() {}); if (respResult == null || !respResult.isSuccess()) { return; } // 3.3 获取需要更新的流程变量 Map updateVariables = getNeedUpdatedVariablesFromResponse(respResult.getData(), response); // 3.4 更新流程变量 if (CollUtil.isNotEmpty(updateVariables)) { processInstanceService.updateProcessInstanceVariables(processInstance.getId(), updateVariables); } } public static void executeBpmHttpRequest(BpmProcessInstanceStatusEvent event, String url) { // 1.1 设置请求头 HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); if (TenantContextHolder.getTenantId() != null) { headers.add(HEADER_TENANT_ID, String.valueOf(TenantContextHolder.getTenantId())); } else { BpmProcessInstanceService processInstanceService = SpringUtils.getBean(BpmProcessInstanceService.class); ProcessInstance processInstance = processInstanceService.getProcessInstance(event.getId()); if (processInstance != null) { headers.add(HEADER_TENANT_ID, String.valueOf(TenantContextHolder.getTenantId())); } } // 1.2 设置请求体 // MultiValueMap body = new LinkedMultiValueMap<>(); // body.add("id", event.getId()); // body.add("processDefinitionKey", event.getProcessDefinitionKey()); // body.add("status", event.getStatus().toString()); // if (StrUtil.isNotEmpty(event.getBusinessKey())) { // body.add("businessKey", event.getBusinessKey()); // } // 2. 发起请求 RestTemplate restTemplate = SpringUtils.getBean(RestTemplate.class); sendHttpRequest(url, headers, event, restTemplate); } public static ResponseEntity sendHttpRequest(String url, HttpHeaders headers, Object body, RestTemplate restTemplate) { HttpEntity requestEntity = new HttpEntity<>(body, headers); ResponseEntity responseEntity; try { responseEntity = restTemplate.exchange(url, HttpMethod.POST, requestEntity, String.class); log.info("[sendHttpRequest][HTTP 请求,请求头:{},请求体:{},响应结果:{}]", headers, body, responseEntity); } catch (RestClientException e) { log.error("[sendHttpRequest][HTTP 请求,请求头:{},请求体:{},请求出错:{}]", headers, body, e.getMessage()); throw exception(PROCESS_INSTANCE_HTTP_CALL_ERROR); } return responseEntity; } public static HttpHeaders buildHttpHeaders(ProcessInstance processInstance, List headerSettings) { HttpHeaders headers = new HttpHeaders(); headers.add(HEADER_TENANT_ID, processInstance.getTenantId()); Map processVariables = processInstance.getProcessVariables(); addHttpRequestHeader(headers, headerSettings, processVariables); return headers; } public static MultiValueMap buildHttpBody(ProcessInstance processInstance, List bodySettings) { Map processVariables = processInstance.getProcessVariables(); MultiValueMap body = new LinkedMultiValueMap<>(); addHttpRequestParam(body, bodySettings, processVariables); if (!body.containsKey("processInstanceId")) { // 避免重复添加 body.add("processInstanceId", processInstance.getId()); } return body; } /** * 从请求返回值获取需要更新的流程变量 * * @param result 请求返回结果 * @param responseSettings 返回设置 * @return 需要更新的流程变量 */ public static Map getNeedUpdatedVariablesFromResponse(Map result, List> responseSettings) { Map updateVariables = new HashMap<>(); if (CollUtil.isEmpty(result)) { return updateVariables; } responseSettings.forEach(responseSetting -> { if (StrUtil.isNotEmpty(responseSetting.getKey()) && result.containsKey(responseSetting.getValue())) { updateVariables.put(responseSetting.getKey(), result.get(responseSetting.getValue())); } }); return updateVariables; } /** * 添加 HTTP 请求参数。请求头或者请求体 * * @param headers HTTP 请求头 * @param paramSettings HTTP 请求参数设置 * @param processVariables 流程变量 */ public static void addHttpRequestHeader(HttpHeaders headers, List paramSettings, Map processVariables) { if (CollUtil.isEmpty(paramSettings)) { return; } paramSettings.forEach(item -> { if (item.getType().equals(BpmHttpRequestParamTypeEnum.FIXED_VALUE.getType())) { headers.add(item.getKey(), item.getValue()); } else if (item.getType().equals(BpmHttpRequestParamTypeEnum.FROM_FORM.getType())) { headers.add(item.getKey(), processVariables.get(item.getValue()).toString()); } }); } public static void addHttpRequestParam(MultiValueMap params, List paramSettings, Map processVariables) { if (CollUtil.isEmpty(paramSettings)) { return; } paramSettings.forEach(item -> { if (item.getType().equals(BpmHttpRequestParamTypeEnum.FIXED_VALUE.getType())) { params.add(item.getKey(), item.getValue()); } else if (item.getType().equals(BpmHttpRequestParamTypeEnum.FROM_FORM.getType())) { params.add(item.getKey(), processVariables.get(item.getValue()).toString()); } }); } }