当前位置: 首页 > article >正文

Java系统对接企业微信审批项目流程

若依做的一个系统需求需要对接企业微信的人员去审核订单 回款之类,以下是详细步骤.

1.首先登入企业微信管理后台:

企业微信

2.找到应用管理

3.自建一个应用

4.这些数据都可以拿到

5.配置可信Ip

6.进入有两种方法让你去配置 ,第一种用公司的域名,然后下面有个文件需要导入,必须导入,不然不会成功的。导入之后配置自己电脑的IP公网地址。

7.配置回调的url接口

踩雷:::框架用的若依,这个接口必须开放,返回的也是字符串格式不能是json格式。

这里需要写两个接口 一个是get  一个是post。

8.创建自己的模板

9.模板显示范围和自建的应用必须关联

10.开发前必读 - 文档 - 企业微信开发者中心进入这个里面查看具体的教程

11.附所有的代码

wechat:
  # 企业ID
  corpId: wwd
  # 审批应用ID
  agentId: 100
  # 审批应用Secret
  corpSecret: 5vE
  # 回调校验的Token
  sToken: 2a
  # 回调校验的Key
  encodingAesKey: 5JH4nvyvb1
  # tokenURL
  tokenUrl: https://qyapi.weixin.qq.com/cgi-bin/gettoken
  # 审核申请URL
  approvalUrl: https://qyapi.weixin.qq.com/cgi-bin/oa/applyevent
  # 获取模板详情URL
  templateUrl: https://qyapi.weixin.qq.com/cgi-bin/oa/gettemplatedetail
  # 上传文件到企业微信URL
  uploadFileUrl: https://qyapi.weixin.qq.com/cgi-bin/media/upload
  # 获取用户信息url
  getUserUrl: https://qyapi.weixin.qq.com/cgi-bin/user/get
  # 添加实验区审批流模版ID
  areaTemplateId: 3WMV
package com.ruoyi.bingo.config.wechat;

import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

/**
 * @author yj
 */
@Data
@Component
public class WeChatConfig {
    @Value("${wechat.corpId}")
    private String corpId;
    @Value("${wechat.agentId}")
    private String agentId;
    @Value("${wechat.corpSecret}")
    private String corpSecret;
    @Value("${wechat.sToken}")
    private String sToken;
    @Value("${wechat.encodingAesKey}")
    private String encodingAesKey;
    @Value("${wechat.tokenUrl}")
    private String tokenUrl;
    @Value("${wechat.templateUrl}")
    private String templateUrl;
    @Value("${wechat.approvalUrl}")
    private String approvalUrl;
    @Value("${wechat.uploadFileUrl}")
    private String uploadFileUrl;
    @Value("${wechat.getUserUrl}")
    private String getUserUrl;
    @Value("${wechat.areaTemplateId}")
    private String areaTemplateId;
    @Value("${wechat.schoolTemplateId}")
    private String schoolTemplateId;
    @Value("${wechat.clientTemplateId}")
    private String clientTemplateId;
    @Value("${wechat.createOrderTemplateId}")
    private String createOrderTemplateId;
    @Value("${wechat.costTemplateId}")
    private String costTemplateId;
    @Value("${wechat.returnedTemplateId}")
    private String returnedTemplateId;
    @Value("${wechat.contractTemplateId}")
    private String contractTemplateId;
    @Value("${wechat.finishOrderTemplateId}")
    private String finishOrderTemplateId;
    // 提供公开的 Getter 方法
    public String getCorpId() {
        return corpId;
    }

    public String getAgentId() {
        return agentId;
    }

    public String getCorpSecret() {
        return corpSecret;
    }

    public String getSToken() {
        return sToken;
    }

    public String getEncodingAesKey() {
        return encodingAesKey;
    }

    public String getTokenUrl() {
        return tokenUrl;
    }

    public String getTemplateUrl() {
        return templateUrl;
    }

    public String getApprovalUrl() {
        return approvalUrl;
    }

    public String getUploadFileUrl() {
        return uploadFileUrl;
    }

    public String getGetUserUrl() {
        return getUserUrl;
    }

    public String getAreaTemplateId() {
        return areaTemplateId;
    }

    public String getSchoolTemplateId() {
        return schoolTemplateId;
    }

    public String getClientTemplateId() {
        return clientTemplateId;
    }

    public String getCreateOrderTemplateId() {
        return createOrderTemplateId;
    }

    public String getCostTemplateId() {
        return costTemplateId;
    }

    public String getReturnedTemplateId() {
        return returnedTemplateId;
    }

    public String getContractTemplateId() {
        return contractTemplateId;
    }

    public String getFinishOrderTemplateId() {
        return finishOrderTemplateId;
    }
}

12.加密解密XML工具栏

package com.ruoyi.bingo.config.wechat.xml;

import com.ruoyi.common.utils.bean.BeanUtils;
import org.springframework.stereotype.Component;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.InputSource;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.util.ArrayList;
import java.util.List;

/**
 * Description :
 *
 * @author YJ
 * date 2024-12-15
 * time 20:28
 */
@Component
public class XmlUtils {
    /**
     * 解析xmL
     *
     * @param xmlData
     */
    public ApprovalBack analysis(String xmlData) {
        try {
            // 调用 fromXml 方法解析 XML 数据
            ApprovalCallback callback = ApprovalCallback.fromXml(xmlData);
            // 输出解析结果
            System.out.println("ToUserName: " + callback.toUserName);
            System.out.println("FromUserName: " + callback.fromUserName);
            System.out.println("CreateTime: " + callback.createTime);
            System.out.println("MsgType: " + callback.msgType);
            System.out.println("Event: " + callback.event);
            System.out.println("AgentID: " + callback.agentID);
            System.out.println("SpNo: " + callback.spNo);
            System.out.println("SpName: " + callback.spName);
            System.out.println("SpStatus: " + callback.spStatus);
            System.out.println("TemplateId: " + callback.templateId);
            System.out.println("ApplyTime: " + callback.applyTime);
            //System.out.println("Applyer UserId: " + callback.applyer.userId);
            //System.out.println("Applyer Party: " + callback.applyer.party);
            //System.out.println("SpRecord SpStatus: " + callback.spRecord.spStatus);
            //System.out.println("StatuChangeEvent: " + callback.statuChangeEvent);
            //
             输出 ProcessList 中的 SubNodeList 信息
            //if (callback.processList != null && callback.processList.nodeList != null) {
            //    for (ApprovalCallback.UserInfo userInfo : callback.processList.nodeList.subNodeList) {
            //        System.out.println("SubNode UserId: " + userInfo.userId);
            //    }
            //}
            System.out.println("解密内容call: " + callback);
            ApprovalBack approvalBack = new ApprovalBack();
            approvalBack.setSpNo(callback.spNo);
            approvalBack.setSpStatus(callback.spStatus);
            return approvalBack;
        } catch (
                Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}

class ApprovalCallback {
    String toUserName;
    String fromUserName;
    String createTime;
    String msgType;
    String event;
    String agentID;
    String spNo;
    String spName;
    String spStatus;
    String templateId;
    String applyTime;
    Applyer applyer;
    SpRecord spRecord;
    String statuChangeEvent;
    ProcessList processList;

    public static ApprovalCallback fromXml(String xmlContent) throws Exception {
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = factory.newDocumentBuilder();
        InputSource inputSource = new InputSource(new java.io.StringReader(xmlContent));
        Document doc = builder.parse(inputSource);

        ApprovalCallback callback = new ApprovalCallback();

        callback.toUserName = doc.getElementsByTagName("ToUserName").item(0).getTextContent();
        callback.fromUserName = doc.getElementsByTagName("FromUserName").item(0).getTextContent();
        callback.createTime = doc.getElementsByTagName("CreateTime").item(0).getTextContent();
        callback.msgType = doc.getElementsByTagName("MsgType").item(0).getTextContent();
        callback.event = doc.getElementsByTagName("Event").item(0).getTextContent();
        callback.agentID = doc.getElementsByTagName("AgentID").item(0).getTextContent();
        // 解析 ApprovalInfo
        org.w3c.dom.NodeList approvalInfo = doc.getElementsByTagName("ApprovalInfo");
        if (approvalInfo.getLength() > 0) {
            Element approvalInfoElement = (Element) approvalInfo.item(0);
            callback.spNo = approvalInfoElement.getElementsByTagName("SpNo").item(0).getTextContent();
            callback.spName = approvalInfoElement.getElementsByTagName("SpName").item(0).getTextContent();
            callback.spStatus = approvalInfoElement.getElementsByTagName("SpStatus").item(0).getTextContent();
            callback.templateId = approvalInfoElement.getElementsByTagName("TemplateId").item(0).getTextContent();
            callback.applyTime = approvalInfoElement.getElementsByTagName("ApplyTime").item(0).getTextContent();

            // Applyer info
            Element applyerElement = (Element) approvalInfoElement.getElementsByTagName("Applyer").item(0);
            callback.applyer = new Applyer();
            callback.applyer.userId = applyerElement.getElementsByTagName("UserId").item(0).getTextContent();
            callback.applyer.party = applyerElement.getElementsByTagName("Party").item(0).getTextContent();

            // SpRecord info
            org.w3c.dom.NodeList spRecordList = approvalInfoElement.getElementsByTagName("SpRecord");
            if (spRecordList.getLength() > 0) {
                Element spRecordElement = (Element) spRecordList.item(0);
                callback.spRecord = new SpRecord();
                callback.spRecord.spStatus = spRecordElement.getElementsByTagName("SpStatus").item(0).getTextContent();
                callback.spRecord.approverAttr = spRecordElement.getElementsByTagName("ApproverAttr").item(0).getTextContent();

                // Details info
                org.w3c.dom.NodeList detailsList = spRecordElement.getElementsByTagName("Details");
                if (detailsList.getLength() > 0) {
                    Element detailsElement = (Element) detailsList.item(0);
                    callback.spRecord.details = new Details();
                    callback.spRecord.details.userId = detailsElement.getElementsByTagName("UserId").item(0).getTextContent();
                    callback.spRecord.details.speech = detailsElement.getElementsByTagName("Speech").item(0).getTextContent();
                    callback.spRecord.details.spStatus = detailsElement.getElementsByTagName("SpStatus").item(0).getTextContent();
                }
            }

            callback.statuChangeEvent = approvalInfoElement.getElementsByTagName("StatuChangeEvent").item(0).getTextContent();

            // ProcessList info
            org.w3c.dom.NodeList processList = approvalInfoElement.getElementsByTagName("ProcessList");
            if (processList.getLength() > 0) {
                Element processListElement = (Element) processList.item(0);
                callback.processList = new ProcessList();
                org.w3c.dom.NodeList nodeList = processListElement.getElementsByTagName("NodeList");
                if (nodeList.getLength() > 0) {
                    Element nodeListElement = (Element) nodeList.item(0);
                    org.w3c.dom.NodeList subNodeList = nodeListElement.getElementsByTagName("SubNodeList");
                    callback.processList.nodeList = new ApprovalCallback.NodeList();
                    callback.processList.nodeList.subNodeList = new ArrayList<>();

                    for (int i = 0; i < subNodeList.getLength(); i++) {
                        Element subNodeElement = (Element) subNodeList.item(i);
                        UserInfo userInfo = new UserInfo();
                        userInfo.userId = subNodeElement.getElementsByTagName("UserId").item(0).getTextContent();
                        callback.processList.nodeList.subNodeList.add(userInfo);
                    }
                }
            }
        }

        return callback;
    }

    public static class Applyer {
        private String userId;
        private String party;
    }

    public static class SpRecord {
        private String spStatus;
        private String approverAttr;
        private ApprovalCallback.Details details;
    }

    public static class Details {
        private String userId;
        private String speech;
        private String spStatus;
    }

    public static class ProcessList {
        private NodeList nodeList;
    }

    public static class NodeList {
        private List<UserInfo> subNodeList;
    }

    public static class UserInfo {
        private String userId;
    }
}
package com.ruoyi.bingo.config.wechat.xml;

import lombok.Data;

/**
 * Description :
 *
 * @author YJ
 * date 2024-12-15
 * time 20:40
 */
@Data
public class ApprovalBack {
    private String toUserName;
    private String createTime;
    private String msgType;
    private String event;
    private String agentID;
    //审批编号
    private String spNo;
    private String spName;
    private String spStatus;
    private String templateId;
    private String applyTime;
    private ApprovalCallback.Applyer applyer;
    private ApprovalCallback.SpRecord spRecord;
    private String statuChangeEvent;
    private ApprovalCallback.ProcessList processList;
}

13.controller层

@Anonymous
@Api(description = "对接企业微信")
@RestController
@RequestMapping("/enterprise/wechat")
public class EnterpriseWeChatController extends BaseController {
    @Autowired
    private EnterpriseWeChatService weChatService;

    /**
     * 获取Access Token
     *
     * @return
     */
    @ApiOperation("获取Access Token")
    @PreAuthorize("@ss.hasPermi('bingo:wechat:accessToken')")
    @PostMapping("/accessToken")
    public String getAccessToken() {
        return weChatService.getAccessToken();
    }

    /**
     * 验证回调 URL 的有效性
     *
     * @return
     */
    @ApiOperation("验证回调 URL 的有效性")
    @GetMapping("/approval/back")
    public String approvalBack(@RequestParam("msg_signature") String msgSignature,
                               @RequestParam("timestamp") String timestamp,
                               @RequestParam("nonce") String nonce,
                               @RequestParam("echostr") String ech,
                               HttpServletResponse response) {

        return weChatService.approvalBack(msgSignature, timestamp, nonce, ech, response);
    }

    /**
     * 处理审批回调事件
     */
    @PostMapping("/approval/back")
    public void handleApprovalCallback(
            @RequestParam("msg_signature") String msgSignature,
            @RequestParam("timestamp") String timestamp,
            @RequestParam("nonce") String nonce,
            HttpServletRequest request,
            HttpServletResponse response) {
        weChatService.handleApprovalCallback(msgSignature, timestamp, nonce, request, response);
    }

    /**
     * 获取企业微信用户信息
     *
     * @return
     */
    @ApiOperation("获取企业微信用户信息")
    @PreAuthorize("@ss.hasPermi('bingo:wechat:getUser')")
    @PostMapping("/getUser")
    public AjaxResult getUser(@RequestBody WechatUserDTO wechatUserDTO) {
        return success(weChatService.getUser(wechatUserDTO));
    }

    /**
     * 上传文件到企业微信
     *
     * @return
     */
    @ApiOperation("上传文件到企业微信")
    @PreAuthorize("@ss.hasPermi('bingo:wechat:upload')")
    @PostMapping("/upload")
    public AjaxResult upload(MultipartFile file) {
        return success(weChatService.uploadWeChat(file));
    }
}

14.server层

 /**
     * 验证回调 URL 的有效性
     *
     * @param msgSignature
     * @param timestamp
     * @param nonce
     * @param echostr
     * @param response
     * @return
     */
    @Override
    public String approvalBack(String msgSignature, String timestamp, String nonce, String
            echostr, HttpServletResponse response) {
        try {
            log.info("验证回调 URL 的有效性");
            return wxBizMsgCrypt.VerifyURL(msgSignature, timestamp, nonce, echostr);
        } catch (Exception e) {
            e.printStackTrace();
            log.error("验证回调 URL 的有效性");
        }
        return null;
    }
 /**
     * 处理审批回调事件
     *
     * @param msgSignature
     * @param timestamp
     * @param nonce
     * @param request
     * @param response
     */
    @Override
    public void handleApprovalCallback(String msgSignature, String timestamp, String nonce, HttpServletRequest
            request, HttpServletResponse response) {
        log.info("处理审批回调事件----------");
        try {
            // 读取回调数据
            StringBuilder sb = new StringBuilder();
            BufferedReader reader = new BufferedReader(new InputStreamReader(request.getInputStream()));
            String line;
            while ((line = reader.readLine()) != null) {
                sb.append(line);
            }
            String callbackXml = sb.toString();
            String decryptedMessage = wxBizMsgCrypt.DecryptMsg(msgSignature, timestamp, nonce, callbackXml);
            ApprovalBack analysis = xmlUtils.analysis(decryptedMessage);
            System.out.println("解密内容analysis: " + analysis);
            auditInfoMapper.updateAuditStatus(analysis);
            AuditInfo audit = auditInfoMapper.selectApprovalInfo(analysis.getSpNo());
            //实验区
            if (audit.getAuditType().equals(FileTypeConstants.FILE_AREA_TYPE)) {
                ExperimentArea experimentArea = new ExperimentArea();
                experimentArea.setId(audit.getId());
                experimentArea.setApprovalStatus(Integer.valueOf(analysis.getSpStatus()));
                areaMapper.updateById(experimentArea);
            }
            //实验校
            if (audit.getAuditType().equals(FileTypeConstants.FILE_SCHOOL_TYPE)) {
                ExperimentSchool experimentSchool = new ExperimentSchool();
                experimentSchool.setId(audit.getId());
                experimentSchool.setApprovalStatus(Integer.valueOf(analysis.getSpStatus()));
                schoolMapper.updateById(experimentSchool);
            }
            //客户
            if (audit.getAuditType().equals(FileTypeConstants.FILE_CLIENT_TYPE)) {
                Client client = new Client();
                client.setId(audit.getId());
                client.setApprovalStatus(Integer.valueOf(analysis.getSpStatus()));
                clientMapper.updateById(client);
            }
            //创建订单
            if (audit.getAuditType().equals(FileTypeConstants.FILE_CREATE_ORDER_TYPE)) {
                Orders orders = new Orders();
                orders.setId(audit.getId());
                orders.setApprovalCreateStatus(Integer.valueOf(analysis.getSpStatus()));
                ordersMapper.updateById(orders);
            }
            //费用
            if (audit.getAuditType().equals(FileTypeConstants.FILE_COST_TYPE)) {
                Cost cost = new Cost();
                cost.setId(audit.getId());
                cost.setApprovalStatus(Integer.valueOf(analysis.getSpStatus()));
                costMapper.updateById(cost);
            }
            //合同
            if (audit.getAuditType().equals(FileTypeConstants.FILE_CONTRACT_TYPE)) {
                Contract contract = new Contract();
                contract.setId(audit.getId());
                contract.setApprovalStatus(Integer.valueOf(analysis.getSpStatus()));
                contractMapper.updateById(contract);
            }
            //完成订单
            if (audit.getAuditType().equals(FileTypeConstants.FILE_FINISH_ORDER_TYPE)) {
                Orders orders = new Orders();
                orders.setId(audit.getId());
                orders.setApprovalFinishStatus(Integer.valueOf(analysis.getSpStatus()));
                ordersMapper.updateById(orders);
            }
            //回款
            if (audit.getAuditType().equals(FileTypeConstants.FILE_RETURNED_TYPE)) {
                Returned returned = new Returned();
                returned.setId(audit.getId());
                returned.setApprovalStatus(Integer.valueOf(analysis.getSpStatus()));
                returnedMapper.updateById(returned);
            }
            // 返回成功响应
        } catch (
                Exception e) {
            // 处理异常,例如返回错误信息
            throw new ServiceException(e.getMessage());
        }
callbackXml就是回调的xml,然后进行解密解析。
analysis 属于明文
 ApprovalCallback callback = ApprovalCallback.fromXml(xmlData);

这个属于解密后所有的明文数据

15.提交审批的代码

 /**
     * 创建订单申请
     *
     * @param approvalOrderDTO
     * @return
     */
    @Override
    public String approvalOrder(ApprovalOrderDTO approvalOrderDTO) {
        ApprovalTemplateDTO approvalTemplateDTO = new ApprovalTemplateDTO();
        approvalTemplateDTO.setTemplate_id(weChatConfig.getCreateOrderTemplateId());
        try {
            String url = weChatConfig.getTemplateUrl() + "?access_token=" + getAccessToken();
            // 获取模板信息
            String jsonBody = new ObjectMapper().writeValueAsString(approvalTemplateDTO);
            String response = HttpUtils.sendPost(url, jsonBody);
            System.out.println("获取创建订单模板:" + response);
            JSONObject jsonResponse = new JSONObject(response);
            if (jsonResponse.getInt("errcode") != 0) {
                return null;
            }
            // 获取模板控件内容
            JSONObject templateContent = jsonResponse.getJSONObject("template_content");
            JSONArray controls = templateContent.getJSONArray("controls");
            // 构造字段内容
            JSONArray formArray = new JSONArray();
            //构造内容
            setArrayOrder(approvalOrderDTO, controls, formArray);
            String businessName = ordersMapper.selectOrderBusinessName(approvalOrderDTO.getBusinessType());
            approvalOrderDTO.setBusinessName(businessName);
            JSONObject applyData = new JSONObject();
            for (int i = 0; i < controls.length(); i++) {
                JSONObject control = controls.getJSONObject(i).getJSONObject("property");
                String controlType = control.getString("control");
                String controlId = control.getString("id");
                String title = control.getJSONArray("title").getJSONObject(0).getString("text");
                JSONObject field = new JSONObject();
                field.put("id", controlId);
                field.put("control", controlType);
                JSONObject fieldValue = new JSONObject();

                if ("Text".equals(controlType)) {
                    switch (title) {
                        case "客户名称":
                            fieldValue.put("text", approvalOrderDTO.getClientName());
                            break;
                        case "业务类型":
                            fieldValue.put("text", approvalOrderDTO.getBusinessName());
                            break;
                        case "合同总额":
                            fieldValue.put("text", approvalOrderDTO.getOrderMoney());
                            break;
                        default:
                            fieldValue.put("text", "无");
                            break;
                    }
                } else if ("File".equals(controlType)) {
                    if (approvalOrderDTO.getMediaIdList() != null) {
                             JSONArray filesArray = new JSONArray();
                    for (String mediaId : approvalAreaDTO.getMediaIdList()) {
                        JSONObject fileObject = new JSONObject();
                        fileObject.put("file_id", mediaId);
                        filesArray.put(fileObject);
                    }
                    fieldValue.put("files", filesArray);
                    }
                } else if ("Textarea".equals(controlType)) {
                    if (!StringUtils.isNull(approvalOrderDTO.getRemark())) {
                        fieldValue.put("text", approvalOrderDTO.getRemark());
                    }
                }
                field.put("value", fieldValue);
                formArray.put(field);
            }
            //处理子控件
            for (int i = 0; i < controls.length(); i++) {
                JSONObject control = controls.getJSONObject(i).getJSONObject("property");
                String controlType = control.getString("control");
                String controlId = control.getString("id");
                JSONObject resultObject = new JSONObject();
                resultObject.put("id", controlId);
                resultObject.put("control", controlType);
                if ("Table".equals(controlType)) {
                    // 获取表格控件的配置信息
                    JSONObject config = controls.getJSONObject(i).getJSONObject("config");
                    JSONArray children = config.getJSONObject("table").getJSONArray("children");
                    // 获取订单项目列表
                    List<OrdersProjectListDTO> orderDetails = approvalOrderDTO.getOrdersProjectList();
                    JSONArray jsonArray = new JSONArray(); // 用于存放所有表格行数据
                    if (orderDetails != null && !orderDetails.isEmpty()) {
                        for (OrdersProjectListDTO detail : orderDetails) {
                            // 用于存放当前行的所有列数据
                            JSONArray rowArray = new JSONArray();
                            // 遍历表格模板的 children 数组,按模板字段顺序填充数据
                            for (int n = 0; n < children.length(); n++) {
                                JSONObject property = children.getJSONObject(n).getJSONObject("property");
                                // 提取控件 ID、类型和标题
                                String id = property.getString("id");
                                String controlTypeInTable = property.getString("control");
                                String tit = property.getJSONArray("title").getJSONObject(0).getString("text");
                                // 填充对应字段值
                                JSONObject value = new JSONObject();
                                switch (tit) {
                                    case "合作项目":
                                        value.put("text", detail.getProjectName()); // 填充项目名称
                                        break;
                                    case "单价":
                                        value.put("text", detail.getUnitPrice()); // 填充单价
                                        break;
                                    case "数量":
                                        value.put("text", detail.getQuantity()); // 填充数量
                                        break;
                                    case "小计":
                                        value.put("text", detail.getSubtotal()); // 填充小计
                                        break;
                                    default:
                                        value.put("text", "未知字段"); // 其他字段使用默认值
                                        break;
                                }
                                // 构造当前列的数据结构
                                JSONObject columnData = new JSONObject();
                                columnData.put("id", id);
                                columnData.put("control", controlTypeInTable);
                                columnData.put("title", new JSONArray().put(new JSONObject().put("text", tit))); // 包含字段标题
                                columnData.put("value", value);
                                rowArray.put(columnData);
                            }

                            // 构造当前行数据
                            JSONObject rowData = new JSONObject();
                            rowData.put("list", rowArray);
                            jsonArray.put(rowData); // 添加当前行到表格数据
                        }
                        // 遍历 JSON 数组
                        for (int j = 0; j < formArray.length(); j++) {
                            JSONObject obj = formArray.getJSONObject(j);
                            // 判断是否是 Table 控件
                            if ("Table".equals(obj.getString("control"))) {
                                JSONObject value = obj.getJSONObject("value");
                                value.put("children", jsonArray);
                            }
                        }
                    }
                }
            }
            // 构造最终的审批请求
            applyData.put("contents", formArray);
            JSONObject auditRequest = new JSONObject();
            auditRequest.put("template_id", approvalTemplateDTO.getTemplate_id());
            auditRequest.put("creator_userid", approvalOrderDTO.getWechatUser());
            auditRequest.put("use_template_approver", 1);
            auditRequest.put("apply_data", applyData);
            System.out.println("构造最终的审批请求:" + auditRequest);
            // 调用企业微信审核接口
            String auditApiUrl = weChatConfig.getApprovalUrl() + "?access_token=" + getAccessToken();
            String res = HttpUtils.sendPost(auditApiUrl, auditRequest.toString());
            System.out.println("return:" + res);
            JSONObject jsonObject = new JSONObject(res);
            return jsonObject.getString("sp_no");
        } catch (Exception e) {
            e.printStackTrace();
            throw new ServiceException(ServiceConstants.USER_APPROVAL);
        }
    }

控件不一样,类型不一样 具体参照文档

给的例子全是value里面的参数

附带订单上传的json 格式

{
    "template_id": "C4ZULJy5ZkE7UuXWFu5rBfe1Xt7d91wbgpL2Rwrj1",
    "creator_userid": "laoyou",
    "use_template_approver": 1,
    "apply_data": {
        "contents": [
            {
                "id": "Text-1734055236654",
                "control": "Text",
                "value": {
                    "text": "老友测试客户"
                }
            },
            {
                "id": "Text-1734055244339",
                "control": "Text",
                "value": {
                    "text": "产品销售类"
                }
            },
            {
                "id": "Table-1734417961974",
                "control": "Table",
                "value": {
                    "children": [
                        {
                            "list": [
                                {
                                    "id": "Text-1734417976091",
                                    "control": "Text",
                                    "title": [
                                        {
                                            "text": "合作项目"
                                        }
                                    ],
                                    "value": {
                                        "text": "A项目"
                                    }
                                },
                                {
                                    "id": "Text-1734417982652",
                                    "control": "Text",
                                    "title": [
                                        {
                                            "text": "单价"
                                        }
                                    ],
                                    "value": {
                                        "text": 1
                                    }
                                },
                                {
                                    "id": "Text-1734417988404",
                                    "control": "Text",
                                    "title": [
                                        {
                                            "text": "数量"
                                        }
                                    ],
                                    "value": {
                                        "text": 1
                                    }
                                },
                                {
                                    "id": "Text-1734417994187",
                                    "control": "Text",
                                    "title": [
                                        {
                                            "text": "小计"
                                        }
                                    ],
                                    "value": {
                                        "text": 1
                                    }
                                }
                            ]
                        },
                        {
                            "list": [
                                {
                                    "id": "Text-1734417976091",
                                    "control": "Text",
                                    "title": [
                                        {
                                            "text": "合作项目"
                                        }
                                    ],
                                    "value": {
                                        "text": "B项目"
                                    }
                                },
                                {
                                    "id": "Text-1734417982652",
                                    "control": "Text",
                                    "title": [
                                        {
                                            "text": "单价"
                                        }
                                    ],
                                    "value": {
                                        "text": 2
                                    }
                                },
                                {
                                    "id": "Text-1734417988404",
                                    "control": "Text",
                                    "title": [
                                        {
                                            "text": "数量"
                                        }
                                    ],
                                    "value": {
                                        "text": 2
                                    }
                                },
                                {
                                    "id": "Text-1734417994187",
                                    "control": "Text",
                                    "title": [
                                        {
                                            "text": "小计"
                                        }
                                    ],
                                    "value": {
                                        "text": 4
                                    }
                                }
                            ]
                        }
                    ]
                }
            },
            {
                "id": "Text-1734055362163",
                "control": "Text",
                "value": {
                    "text": 5
                }
            },
            {
                "id": "Textarea-1734055383107",
                "control": "Textarea",
                "value": {
                    "text": "这是一个订单"
                }
            },
            {
                "id": "File-1734055390371",
                "control": "File",
                "value": {
                    "files": [
                        {
                            "file_id": "39EZFpTASgYAlxDf2S09ClA0TKaQcGPyQZPEQ9HbEwQN0AWwl4BLXy8MHyB5CG6yG"
                        }
                    ]
                }
            }
        ]
    }
}

加密解密下载链接

登录 - 企业微信开发者中心


http://www.kler.cn/a/443087.html

相关文章:

  • python学opencv|读取图像(三十一)缩放图像的三种方法
  • Kotlin学习(一)
  • c++入门之 命名空间与输入输出
  • SQL中的公用表表达式
  • [大模型]本地离线运行openwebui+ollama容器化部署
  • AI的主流数据库介绍及其功能对比
  • jmeter连接mysql
  • fastAPI接口的请求与响应——基础
  • ArkTs组件的学习
  • Vue 2 中页面跳转方式的详细介绍
  • 如何在 Ubuntu 22.04 上使用 vnStat 监控网络流量
  • java 通过jdbc连接sql2000方法
  • JS 生成防篡改水印
  • OCR多模态大模型:视觉模型与LLM的结合之路
  • PDFMathTranslate 一个基于AI优秀的PDF论文翻译工具
  • 知识库管理系统可扩展性深度测评
  • 【论文笔记】Visual Prompt Tuning
  • 《自制编译器》--青木峰郎 -读书笔记 编译hello
  • 三维测量与建模笔记 - 7.2 点云滤波
  • mapper.xml传入参数为Map的正确做法
  • springboot使用scoket
  • C#速成(文件读、写操作)
  • Vite打包后动态路由加载失败的问题
  • springboot集成h2数据库并使用多数据源
  • AG32 IDE 开发环境搭建
  • 大模型微调---Prompt-tuning微调