全部产品
Search
文档中心

智能数据建设与治理 Dataphin:自定义审批系统对接接口

更新时间:May 29, 2026

本文为您介绍Dataphin BPMS支持对接第三方审批流,包括开放了哪些接口能力,如何接入审批能力以及审批案例等内容。

前提条件

已在Dataphin系统配置审批设置,如何配置,详情请参见审批设置。运维租户参见审批设置选择审批系统其他配置项。

审批接口

重要
  • {url}:为第三方审批流对接地址,http(s)://{url}为提交审批申请URL。

  • accessToken:调用服务端API的凭证。Dataphin页面自动生成,或用户生成填入Dataphin。

  • 连接测试

    请求方式:POST。

    请求地址:http(s)://{url}/dataphin/bpms/check/connect。

    请求时序图

    image

    Query参数

    参数名称

    参数类型

    描述

    accessToken

    String

    调用服务端API的凭证。

    Dataphin页面自动生成,或用户生成填入Dataphin。如:6d1bxxxx。

    timestamp

    String

    单位毫秒,信息发送时间戳。如:1654156836531。

    Body参数

    checkEvent(String):检查事件为连接测试。如:connectivity。

    返回参数

    checkResult(String):检查结果:成功,仅当返回值为success时,认定为成功。其他值均被认为测试连接失败。如:success。

  • 提交审批

    请求方式:POST。

    请求地址:http(s)://{url}/dataphin/bpms/processinstance/create。

    提交审批的时序图

    image

    Query参数

    参数名称

    参数类型

    描述

    accessToken

    String

    调用服务端API的凭证。

    Dataphin页面自动生成,或用户生成填入Dataphin。如:6d1bxxxx。

    timestamp

    String

    单位毫秒,信息发送时间戳。如:1654156836531。

    Body参数

    参数名称

    参数类型

    描述

    applyId

    String

    Dataphin审批单Id。如:1223。

    title

    String

    Dataphin审批单标题。如:dataphin bpms。

    content

    String

    Dataphin审批单内容。如:bpms content。请参见审批消息内容元数据描述

    type

    String

    • 审批单类型:APPROVAL_DOC_TYPE。

    • 代码审核:CODE_REVIEW。

    • 发布管控:PUBLISH。

    • 业务规划:BIZ_PLANNING。

    • 权限审批:AUTH。

    • 默认:DEFAULT。

    templateCode

    String

    审批模板code,可为空,与页面配置有关。

    审批消息内容元数据描述

    参数名称

    参数类型

    描述

    resourceType

    String

    审批任务类型,为枚举值,包含以下的类型:

    • PhysicalTable:物理表。

    • LogicTable:逻辑表。

    • MetaTable:实时元表。

    • MirrorTable:镜像表。

    • Fun:函数。

    • DataSource:数据源。

    • FeatureConfig:功能权限配置。

    • OSAPP:数据服务APP。

    • OSAPI:数据服务API 。

    • OSLogicUnit:数据服务单元。

    • OSDS:数据服务数据源。

    • SECRET_KEY:密钥。

    • GLOBAL_PARAM:全局变量。

    grantToUsers

    List<GrantToUser>

    授权用户列表。请参见GrantToUser

    bpmsEnvironment

    BpmsEnvironment

    审批系统环境信息。请参见BpmsEnvironment

    operates

    List<String>

    申请的权限类型,包含以下类型:

    • SYNC_READ:数据源同步读。

    • SYNC_WRITE:数据源同步写。

    • SQL_QUERY:物理表及逻辑表的SQL查询。

    • SQL_WRITE:物理表的SQL写入。

    • SQL_ALTER:物理表的SQL修改。

    • SQL_DROP:物理表及逻辑表的SQL删除。

    • SELECT:数据服务API的查询。

    • WRITE:写入权限。

    • DEV:开发权限。

    • USE:使用权限。

    • UPDATE:改表数据。

    • PIPELINE_ENCRY:集成加密。

    • PIPELINE_DECRY:集成解密。

    levels

    List<String>

    权限等级,包含三个等级:HIGH、MIDDLE、LOW。

    operations

    List<String>

    权限类型,包含以下类型:

    • SELECT-查询。

    • DESCRIBE-查表结构。

    • UPDATE-改表数据。

    • ALTER-改表结构。

    • DELETE-删除表。

    • COPY_TASK-复制。

    resources

    List<BpmsResource>

    资源内容,请参见BpmsResource

    applyObject

    ApplyObject

    申请对象信息,请参见ApplyObject

    reason

    String

    申请原因。

    GrantToUser

    参数名称

    参数类型

    描述

    account

    Account

    授权账户列表,请参见Account

    period

    Period

    有效期,请参见Period

    Account

    参数名称

    参数类型

    描述

    accountType

    String

    授权类型,包括个人账号生产账号应用账号三种。

    • PERSONAL:个人账号。

    • PRODUCE:生产账号。

    • APPLICATION:应用账号。

    userName

    String

    结束时间格式为yyyy-mm-dd。如:2022-09-11。

    Period

    参数名称

    参数类型

    描述

    periodType

    String

    有效期类型支持长期(LONG_TERM

    periodEnd

    String

    权限到期时间格式为yyyy-mm-dd。如:2022-09-11。

    BpmsEnvironment

    参数名称

    参数类型

    描述

    projectName

    String

    项目名称。

    bizUnitName

    String

    业务板块名称。

    resourceEnv

    String

    环境分为生产环境和开发环境两种环境。

    • PROD:生产。

    • DEV:开发。

    BpmsResource

    参数名称

    参数类型

    描述

    resourceType

    String

    请参见审批消息内容元数据描述

    resourceName

    String

    资源名称。

    children

    List<Children>

    字段列表,请参见Children

    operations

    List<String>

    请参见审批消息内容元数据描述的operates。

    authTypes

    String

    申请权限类型。

    Children

    参数名称

    参数类型

    描述

    resourceName

    String

    字段名称。

    resourceProperties

    String

    字段属性。

    ResourceProperties

    参数名称

    参数类型

    描述

    columnType

    String

    字段类型。

    columnIsPartition

    String

    是否为分区字段。

    columnIsPk

    String

    是否为主键。

    ApplyObject

    参数名称

    参数类型

    描述

    objectName

    String

    对象名称。

    codeContent

    String

    代码内容。

    name

    String

    业务活动英文名称。

    bizObjectType

    String

    对象类型。

    bizObjectChangeType

    String

    变更类型。

    bizObjectPkField

    String

    组件字段。

    bizObjectParent

    String

    所属父对象。

    bizObjectChildren

    String

    下游子对象。

    bizProcessCn

    String

    活动名称。

    bizProcessType

    String

    活动类型。

    bizProcessChangeType

    String

    变更类型。

    bizProcessNodes

    String

    流程节点。

    atomicIndexCn

    String

    指标名称。

    dataType

    String

    数据类型。

    unit

    String

    计量单位。

    bizProcess

    String

    活动名称。

    des

    String

    活动口径。

    derivedLogic

    String

    衍生公司。

    protoLogics

    String

    计算逻辑。

    返回参数

    processInstanceId(String):第三方审批实例ID。如:6d1bxxxx。

  • 撤销审批

    说明

    提交审批后,若申请内容不符合预期,可撤销审批。

    请求方式:POST。

    请求地址:http(s)://{url}/dataphin/bpms/processinstance/revoke。

    Query参数

    参数名称

    参数类型

    描述

    accessToken

    String

    调用服务端API的凭证。

    Dataphin页面自动生成,或用户生成填入Dataphin。如:6d1bxxxx。

    timestamp

    String

    单位毫秒,信息发送时间戳。如:1654156836531。

    Body参数

    参数名称

    参数类型

    描述

    applyId

    String

    Dataphin审批单Id。如:1223。

    processInstanceId

    String

    第三方审批实例Id。如:6d1bxxxx。

    operatingUserId

    String

    操作人工号。如:6d1bxxxx。

    返回参数

    result(String):撤回结果信息。仅当返回值为success时被认定为成功。

  • 查询审批实例URL

    请求方式:GET。

    请求地址:http(s)://{url}/dataphin/bpms/processinstance/apply。

    Query参数

    参数名称

    参数类型

    描述

    accessToken

    String

    调用服务端API的凭证。

    Dataphin页面自动生成,或用户生成填入Dataphin。如:6d1bxxxx。

    timestamp

    String

    单位毫秒,信息发送时间戳。如:1654156836531。

回调接口

重要
  • https://{callbackUrl}即为审批设置其他配置的Callback URL。

  • accessToken:调用服务端API的凭证。Dataphin页面自动生成,或用户生成填入Dataphin。

  • callBackAesKey:回调认证凭证。Dataphin页面自动生成,或用户生成填入Dataphin。

  • 回调方法

    请求方式:POST。

    请求地址:http://{callbackUrl}/api/oa/bpms/integration/thirdparty/callback。

    Query参数

    参数名称

    参数类型

    描述

    signature

    String

    消息认证信息,请参见加解密方法。

    timestamp

    String

    单位毫秒,信息发送时间戳。如:1654156836531。

    nonce

    String

    随机数,请参见加解密方法。

    Body参数

    encrypt(String):加密信息。如:ajls384k。

    返回参数

    encrypt(String):回调状态加密信息。如:ajls384k。

  • 回调加密内容

    回调连通性校验

    • 传入加密参数:

      applyStatus(String):检查连通性参数。如:CHECK。

    • 返回加密参数:

      success:成功回调返回值。

    回调返回bpms实例审批结果

    • 传入加密参数:

      参数名称

      参数类型

      描述

      applyId

      String

      Dataphin审批单Id。如:1223。

      processInstanceId

      String

      第三方审批实例Id。如:6d1bxxxx。

      comment

      String

      审批实例评论信息。

      applyStatus

      String

      • accept:接受。

      • reject:拒绝。

      • revoke:撤销。

      nodes

      List<ApplyCallBackNode>

      第三方审批系统侧的审批节点列表,非必填,当对接方式选择为显示三方审批的所有节点时填入。

    • ApplyCallBackNode

      参数名称

      参数类型

      描述

      nodeId

      String

      节点ID,从1到n进行排序。

      nodeStatus

      String

      节点状态(ApproveNodeStatusEnum)。

      • APPROVING:审批中。

      • ACCEPTED:已通过。

      • REJECTED:已驳回。

      • REVOKED:已撤回。

      nodeName

      String

      节点名称。

      approverRelation

      String

      审批关系(ApproveOperatorEnum)。

      • AND:多人均要审批方可通过。

      • OR:任何一人审批通过即可。

      pendingApprovers

      List<ExternalApproverInfo>

      当前待审批人列表,如果相关审批人已审批,则该字段为空。

      records

      List<OperationRecord>

      当审批人员执行操作时填入,按照时间先后顺序排序。

    • ExternalApproverInfo

      参数名称

      参数类型

      描述

      userId

      String

      第三方审批系统侧的用户ID。如:1223。

      userName

      String

      第三方审批系统侧的用户名。如:张三。

    • OperationRecord

      参数名称

      参数类型

      描述

      operateUser

      ExternalApproverInfo

      操作人信息。如:{"userId":"1111", "userName":"张三"}。

      action

      String

      操作类型(ApproveNodeActionType)。

      • ASSIGN_APPROVE:转交权限申请。

      • COUNTER_SIGN_APPROVE:加签权限申请。

      • REVOKE_APPLY:撤回权限申请。

      • APPROVE:审批权限。

      comment

      String

      操作评论。

      operatedTime

      String

      操作时间。

      transferApprovers

      List<ExternalApproverInfo>

      转移目标人列表,非必填,当执行加签或者转交操作时填写。如:[{"userId":"2222", "userName":"李四"}]。

    • 返回加密参数

      success:成功回调返回值。

  • 回调返回bpms实例审批结果样例

    当前第三方审批系统支持仅显示最终审批结果显示三方审批的所有节点两种对接方式。不同对接方式下,第三方审批系统返回的审批信息内容各不相同。

    • 仅显示最终审批结果

      该对接方式仅需返回审批系统的最终结果,系统中仅展示开始节点和结束节点。仅当第三方审批系统侧的整体审批流程结束后,调用该回调接口即可。回传内容结构体样例如下:

      {
         "applyId": "123456",
         "applyStatus": "accept",
         "comment": "同意审批",
         "processInstanceId": "qwqwqqq"
      }
      说明
      • nodes字段在该对接方式下无需填写。

      • applyStatus字段可填写acceptrejectrevokeapproving表示审批中,为中间态,仅供显示三方审批的所有节点对接方式下使用。

    • 显示三方审批的所有节点

      该对接方式需返回审批系统每个节点的详情,系统中将同步展示所有审批节点。当某一审批人员执行审批操作时,即可通过该回调接口将当前的审批节点信息通知至Dataphin系统。

      涉及字段的解释说明
      • 该对接方法下需要传入applyIdapplyStatusprocessInstanceIdnodes字段。

      • 整体审批单状态applyStatus,可选值:approving、accept、reject、revoke。

        • 当存在某一审批节点流程尚未结束时,applyStatus设置为approving。

        • 当所有审批节点均审批通过时,applyStatus设置为accept。

        • 当存在某一审批节点被审批拒绝时,applyStatus设置为reject。

        • 当存在某一审批节点被审批撤回时,applyStatus设置为revoke。

      • 审批节点列表根据内部的nodeId进行排序,nodeId格式为1,2,3。

      • 审批节点状态nodeStatus,可选值:APPROVING、ACCEPTED、REJECTED和REVOKED。

        • 如果当前审批节点流程未结束,nodeStatus设置为APPROVING。

        • 如果当前审批节点审批通过,nodeStatus设置为ACCEPTED。

        • 如果当前审批节点审批拒绝,nodeStatus设置为REJECTED。

        • 如果当前审批节点审批撤回,nodeStatus设置为REVOKED。

      • 审批节点展示名称nodeName。

      • 节点审批关系approverRelation,可选值:OR和AND。

        • OR:任一审批人审批处理即可通过。

        • AND:所有人审批处理方可通过。

      • 待审批人列表pendingApprovers。

        • 未执行审批处理的审批人列表。

        • 当有相关人员执行审批操作时,下次传输时,需要从待审批列表中移除,然后写入到操作记录列表中。

      • 操作记录列表records。

        • 执行操作的操作人信息operateUser。

        • 操作评论comment。

        • 操作时间operatedTime,操作记录列表按照操作时间升序排列。

        • 操作类型action,可选值:ASSIGN_APPROVE、COUNTER_SIGN_APPROVE、REVOKE_APPLY、APPROVE。

          • 当节点审批关系为OR,待审批人中某一审批人通过,action设置为APPROVE,同时审批节点状态nodeStatus设置为ACCEPTED。

          • 当节点审批关系为OR,待审批人中某一审批人拒绝,action设置为APPROVE,同时审批节点状态nodeStatus设置为REJECTED。

          • 当节点审批关系为OR,待审批人中某一审批人撤回,action设置为REVOKE_APPLY,同时审批节点状态nodeStatus设置为REVOKED。

          • 当待审批人中某一审批人执行转交操作,action设置为ASSIGN_APPROVE,同时审批节点状态nodeStatus设置为ACCEPTED。

          • 当待审批人中某一审批人执行加签操作,action设置为COUNTER_SIGN_APPROVE,同时审批节点状态nodeStatus设置为ACCEPTED。

          • 当节点审批关系为AND,某一审批人通过,action设置为APPROVE。如果剩余人未执行审批,审批节点状态仍为APPROVING;当所有人审批通过时,审批节点状态nodeStatus设置为ACCEPTED。

          • 当节点审批关系为AND,某一审批人拒绝,action设置为APPROVE,审批节点状态nodeStatus设置为ACCEPTED。

          • 当节点审批关系为AND,某一审批人撤回,action设置为REVOKE_APPLY,审批节点状态nodeStatus设置为ACCEPTED。

        • 转移目标人列表transferApprovers,记录被加签或者转交的人员信息。

      不同审批场景下审批内容的结构体
      • 多个审批节点,审批关系为或关系,每个审批节点均未进行审批。

        样例如下:

        某审批单在第三方审批系统侧存在两个审批节点,节点间通过nodeId排序。

        第一个审批节点,待审批人张三和李四均未进行审批,待审批人列表pendingApprovers中记录张三和李四的相关信息,节点审批状态nodeStatus为APPROVING,因两位待审批人均未执行操作,所以records字段为空。

        第二个审批节点,待审批人王五未进行审批,待审批人列表pendingApprovers中记录王五的相关信息,且因王五还未进行审批,所以records字段为空。

        两个审批节点均不是终态,整体审批单状态为approving。

        {
           "applyId": "123456",
           "processInstanceId": "qwqwqeqe",
           "applyStatus": "approving",
           "nodes": [
              {
                 "nodeId": "1",
                 "nodeStatus": "APPROVING",
                 "nodeName": "审批测试节点1",
                 "approverRelation": "OR",
                 "pendingApprovers": [
                    {
                       "userId": "1111",
                       "userName": "张三"
                    },
                    {
                       "userId": "2222",
                       "userName": "李四"
                    }
                 ],
                 "records": []
              },
              {
                 "nodeId": "2",
                 "nodeStatus": "APPROVING",
                 "nodeName": "审批测试节点2",
                 "approverRelation": "OR",
                 "pendingApprovers": [
                    {
                       "userId": "33333",
                       "userName": "王五"
                    }
                 ],
                 "records": []
              }
           ]
        }
      • 多个审批节点,审批关系为或关系,第一个审批节点中部分审批人审批通过,部分审批人未进行审批,第二个审批节点中所有审批人均未进行审批操作。

        样例如下:

        某审批单在第三方审批系统侧存在两个审批节点,节点间通过nodeId排序。

        第一个审批节点中,张三同意了审批,李四未执行审批相关操作。待审批人列表pendingApprovers中仅记录李四的信息。审批节点审批关系为OR,因张三同意了审批,所以节点审批状态nodeStatus为ACCEPTED。操作记录列表records中记录张三的操作信息,张三执行了同意审批,action字段为APPROVE,comment字段填写操作评论信息。

        第二个审批节点,所有审批人未执行审批操作。节点审批状态nodeStatus为APPROVING,待审批人列表pendingApprovers中记录待审批人王五的信息。

        该审批单总共存在两个审批节点,因第二个审批节点没有人执行审批操作,所以整体审批单状态applyStatus为approving。

        {
           "applyId": "123456",
           "processInstanceId": "qwqwqeqe",
           "applyStatus": "approving",
           "nodes": [
              {
                 "nodeId": "1",
                 "nodeStatus": "ACCEPTED",
                 "nodeName": "审批测试节点1",
                 "approverRelation": "OR",
                 "pendingApprovers": [
                    {
                       "userId": "2222",
                       "userName": "李四"
                    }
                 ],
                 "records": [
                    {
                       "operateUser": {
                          "userId": "1111",
                          "userName": "张三"
                       },
                       "action": "APPROVE",
                       "comment": "同意该表权限审批",
                       "operatedTime": "2026-03-19 19:01:23"
                    }
                 ]
              },
              {
                 "nodeId": "2",
                 "nodeStatus": "APPROVING",
                 "nodeName": "审批测试节点2",
                 "approverRelation": "OR",
                 "pendingApprovers": [
                    {
                       "userId": "33333",
                       "userName": "王五"
                    }
                 ],
                 "records": []
              }
           ]
        }
      • 多个审批节点,审批关系为或关系,第一个审批节点中部分审批人审批通过,部分审批人未执行审批操作,第二个审批节点所有审批人审批通过。

        样例如下:

        某审批单在第三方审批系统侧存在两个审批节点,节点间通过nodeId排序。

        第一个审批节点中,张三同意了审批,李四未执行审批相关操作。待审批人列表pendingApprovers中仅记录李四的信息。审批节点审批关系为OR,因张三同意了审批,所以节点审批状态nodeStatus为ACCEPTED。操作记录列表records中记录张三的操作信息,张三执行了同意审批,action字段为APPROVE,comment字段填写操作评论信息。

        第二个审批节点,待审批人只有王五, 且同意了审批。节点审批状态nodeStatus为 ACCEPTED,待审批人列表pendingApprovers为空。操作记录列表records中记录王五的操作信息,王五执行了同意审批,action字段为APPROVE,comment字段填写操作评论信息。

        该审批单总共存在两个审批节点,并且每个审批节点均已达到终态,审批通过,所以整体审批单状态applyStatus为accept。

        {
           "applyId": "123456",
           "processInstanceId": "qwqwqeqe",
           "applyStatus": "accept",
           "nodes": [
              {
                 "nodeId": "1",
                 "nodeStatus": "ACCEPTED",
                 "nodeName": "审批测试节点1",
                 "approverRelation": "OR",
                 "pendingApprovers": [
                    {
                       "userId": "2222",
                       "userName": "李四"
                    }
                 ],
                 "records": [
                    {
                       "operateUser": {
                          "userId": "1111",
                          "userName": "张三"
                       },
                       "action": "APPROVE",
                       "comment": "同意该表权限审批",
                       "operatedTime": "2026-03-19 19:01:23"
                    }
                 ]
              },
              {
                 "nodeId": "2",
                 "nodeStatus": "ACCEPTED",
                 "nodeName": "审批测试节点2",
                 "approverRelation": "OR",
                 "pendingApprovers": [],
                 "records": [
                    {
                       "operateUser": {
                          "userId": "33333",
                          "userName": "王五"
                       },
                       "action": "APPROVE",
                       "comment": "王五同意权限审批",
                       "operatedTime": "2026-03-19 19:07:21"
                    }
                 ]
              }
           ]
        }
      • 多个审批节点,审批关系为或关系,第一个审批节点中部分审批人审批通过,部分审批人未执行审批操作,第二个审批节点中所有审批人审批拒绝。

        样例如下:

        某审批单在第三方审批系统侧存在两个审批节点,节点间通过nodeId排序。

        第一个审批节点中,张三同意了审批,李四未执行审批相关操作。待审批人列表pendingApprovers中仅记录李四的信息。审批节点审批关系为OR,因张三同意了审批,所以节点审批状态nodeStatus为ACCEPTED。操作记录列表records中记录张三的操作信息,张三执行了同意审批,action字段设置为APPROVE,comment字段填写操作评论信息。

        第二个审批节点,待审批人只有王五, 且拒绝了审批。节点审批状态nodeStatus为REJECTED,待审批人列表pendingApprovers为空。操作记录列表records中记录王五的操作信息,王五执行了拒绝操作,action字段为APPROVE,comment 字段填写操作评论信息。

        该审批单总共存在两个审批节点,每个审批节点均已达到终态,其中第二个审批节点审批拒绝,所以整体审批单状态applyStatus为reject。

        {
           "applyId": "123456",
           "processInstanceId": "qwqwqeqe",
           "applyStatus": "reject",
           "nodes": [
              {
                 "nodeId": "1",
                 "nodeStatus": "ACCEPTED",
                 "nodeName": "审批测试节点1",
                 "approverRelation": "OR",
                 "pendingApprovers": [
                    {
                       "userId": "2222",
                       "userName": "李四"
                    }
                 ],
                 "records": [
                    {
                       "operateUser": {
                          "userId": "1111",
                          "userName": "张三"
                       },
                       "action": "APPROVE",
                       "comment": "同意该表权限审批",
                       "operatedTime": "2026-03-19 19:01:23"
                    }
                 ]
              },
              {
                 "nodeId": "2",
                 "nodeStatus": "REJECTED",
                 "nodeName": "审批测试节点2",
                 "approverRelation": "OR",
                 "pendingApprovers": [],
                 "records": [
                    {
                       "operateUser": {
                          "userId": "33333",
                          "userName": "王五"
                       },
                       "action": "APPROVE",
                       "comment": "王五拒绝了权限审批",
                       "operatedTime": "2026-03-19 19:07:21"
                    }
                 ]
              }
           ]
        }
      • 多个审批节点,审批关系为或关系,第一个审批节点中部分审批人审批通过,部分审批人未执行审批操作,第二个审批节点中审批人审批撤回。

        样例介绍:

        某审批单在第三方审批系统侧存在两个审批节点,节点间通过nodeId排序。

        第一个审批节点中,张三同意了审批,李四未执行审批相关操作。待审批人列表pendingApprovers中仅记录李四的信息。审批节点审批关系为OR,因张三同意了审批,所以节点审批状态nodeStatus为ACCEPTED。操作记录列表records记录张三的操作信息,张三执行了同意审批,action字段为APPROVE,comment字段填写操作评论信息。

        第二个审批节点,待审批人只有王五, 且执行了审批撤回。节点审批状态nodeStatus为REVOKED,待审批人列表pendingApprovers 为空。操作记录列表 records记录王五的操作信息,王五执行了审批撤回操作,action字段为REVOKE_APPLY,comment字段填写操作评论信息。

        该审批单总共存在两个审批节点,每个审批节点均已达到终态,其中第二个审批节点审批撤回 ,所以整体审批单状态applyStatus为revoke。

        {
           "applyId": "123456",
           "processInstanceId": "qwqwqeqe",
           "applyStatus": "revoke",
           "nodes": [
              {
                 "nodeId": "1",
                 "nodeStatus": "ACCEPTED",
                 "nodeName": "审批测试节点1",
                 "approverRelation": "OR",
                 "pendingApprovers": [
                    {
                       "userId": "2222",
                       "userName": "李四"
                    }
                 ],
                 "records": [
                    {
                       "operateUser": {
                          "userId": "1111",
                          "userName": "张三"
                       },
                       "action": "APPROVE",
                       "comment": "同意该表权限审批",
                       "operatedTime": "2026-03-19 19:01:23"
                    }
                 ]
              },
              {
                 "nodeId": "2",
                 "nodeStatus": "REVOKED",
                 "nodeName": "审批测试节点2",
                 "approverRelation": "OR",
                 "pendingApprovers": [],
                 "records": [
                    {
                       "operateUser": {
                          "userId": "33333",
                          "userName": "王五"
                       },
                       "action": "REVOKE_APPLY",
                       "comment": "王五撤回该权限审批",
                       "operatedTime": "2026-03-19 19:07:21"
                    }
                 ]
              }
           ]
        }
      • 多个审批节点,审批关系为且关系,第一个审批节点部分审批人审批通过,部分审批人未执行审批操作,第二个审批节点所有审批人未执行审批操作。

        样例如下:

        某审批单在第三方审批系统侧存在两个审批节点,节点间通过nodeId排序。

        第一个审批节点中,张三同意了审批,李四未执行审批相关操作。待审批人列表pendingApprovers中仅记录李四的信息。审批节点审批关系为AND,张三同意了审批,李四未进行审批,节点审批状态为APPROVING。操作记录列表records记录张三的操作信息,张三执行了同意审批,action字段设置为APPROVE,comment字段填写操作评论信息。

        第二个审批节点,所有审批人未执行审批操作。节点审批状态nodeStatus为 APPROVING,待审批人列表pendingApprovers记录待审批人王五的信息。

        该审批单总共存在两个审批节点,每个审批节点均未达到终态,所以整体审批单状态applyStatus为approving。

        {
           "applyId": "123456",
           "processInstanceId": "qwqwqeqe",
           "applyStatus": "approving",
           "nodes": [
              {
                 "nodeId": "1",
                 "nodeStatus": "APPROVING",
                 "nodeName": "审批测试节点1",
                 "approverRelation": "AND",
                 "pendingApprovers": [
                    {
                       "userId": "2222",
                       "userName": "李四"
                    }
                 ],
                 "records": [
                    {
                       "operateUser": {
                          "userId": "1111",
                          "userName": "张三"
                       },
                       "action": "APPROVE",
                       "comment": "同意该表权限审批",
                       "operatedTime": "2026-03-19 19:01:23"
                    }
                 ]
              },
              {
                 "nodeId": "2",
                 "nodeStatus": "APPROVING",
                 "nodeName": "审批测试节点2",
                 "approverRelation": "AND",
                 "pendingApprovers": [
                    {
                       "userId": "33333",
                       "userName": "王五"
                    }
                 ],
                 "records": []
              }
           ]
        }
      • 多个审批节点,审批关系为且关系,第一个审批节点所有人审批通过,第二个审批节点所有审批人未执行审批操作。

        样例如下:

        某审批单在第三方审批系统侧存在两个审批节点,节点间通过nodeId排序。

        第一个审批节点中,张三和李四均同意了审批。待审批人列表pendingApprovers为空。审批节点审批关系为AND,张三和李四均同意了审批,所以节点审批状态为ACCEPTED。操作记录列表records中记录张三和李四的操作信息,张三执行了同意审批,action字段为APPROVE,comment字段填写操作评论信息;李四执行了同意审批,action字段设置为APPROVE。

        第二个审批节点,所有审批人未执行审批操作。节点审批状态nodeStatus设置为APPROVING。待审批人列表pendingApprovers记录待审批人王五的信息。

        该审批单总共存在两个审批节点,第一个审批节点到达终态,第二个节点没有达到终态,所以整体审批单状态applyStatus设置为approving。

        {
           "applyId": "123456",
           "processInstanceId": "qwqwqeqe",
           "applyStatus": "approving",
           "nodes": [
              {
                 "nodeId": "1",
                 "nodeStatus": "ACCEPTED",
                 "nodeName": "审批测试节点1",
                 "approverRelation": "AND",
                 "pendingApprovers": [],
                 "records": [
                    {
                       "operateUser": {
                          "userId": "1111",
                          "userName": "张三"
                       },
                       "action": "APPROVE",
                       "comment": "同意该表权限审批",
                       "operatedTime": "2026-03-19 19:01:23"
                    },
                    {
                       "operateUser": {
                          "userId": "2222",
                          "userName": "李四"
                       },
                       "action": "APPROVE",
                       "comment": "同意该表权限审批",
                       "operatedTime": "2026-03-19 19:02:23"
                    }
                 ]
              },
              {
                 "nodeId": "2",
                 "nodeStatus": "APPROVING",
                 "nodeName": "审批测试节点2",
                 "approverRelation": "AND",
                 "pendingApprovers": [
                    {
                       "userId": "33333",
                       "userName": "王五"
                    }
                 ],
                 "records": []
              }
           ]
        }
      • 多个审批节点,审批关系为且关系,第一个审批节点部分审批人执行拒绝操作,第二个审批节点所有审批人未执行审批操作。

        样例如下:

        某审批单在第三方审批系统侧存在两个审批节点,节点间通过nodeId排序。

        第一个审批节点中,存在两个审批人,张三同意了审批,李四拒绝了审批。两个审批人均执行了操作,所以待审批人列表pendingApprovers为空。审批节点审批关系为AND, 因李四拒绝了审批,所以节点审批状态设置为REJECTED。操作记录列表records记录张三和李四的操作信息,张三执行了同意审批,action字段为APPROVE,comment字段填写操作评论信息;李四执行了拒绝审批,action字段为 APPROVE。

        第二个审批节点,所有审批人未执行审批操作。节点审批状态nodeStatus为APPROVING。待审批人列表pendingApprovers记录待审批人王五的信息。

        该审批单总共存在两个审批节点,第一个审批节点中审批人执行了拒绝操作,终止了审批流程,所以整体审批单状态applyStatus为reject。

        {
           "applyId": "123456",
           "processInstanceId": "qwqwqeqe",
           "applyStatus": "reject",
           "nodes": [
              {
                 "nodeId": "1",
                 "nodeStatus": "REJECTED",
                 "nodeName": "审批测试节点1",
                 "approverRelation": "AND",
                 "pendingApprovers": [],
                 "records": [
                    {
                       "operateUser": {
                          "userId": "1111",
                          "userName": "张三"
                       },
                       "action": "APPROVE",
                       "comment": "同意该表权限审批",
                       "operatedTime": "2026-03-19 19:01:23"
                    },
                    {
                       "operateUser": {
                          "userId": "2222",
                          "userName": "李四"
                       },
                       "action": "APPROVE",
                       "comment": "拒绝该表权限审批",
                       "operatedTime": "2026-03-19 19:02:23"
                    }
                 ]
              },
              {
                 "nodeId": "2",
                 "nodeStatus": "APPROVING",
                 "nodeName": "审批测试节点2",
                 "approverRelation": "AND",
                 "pendingApprovers": [
                    {
                       "userId": "33333",
                       "userName": "王五"
                    }
                 ],
                 "records": []
              }
           ]
        }
      • 多个审批节点,审批关系为且关系,第一个审批节点部分审批人执行撤回操作,第二个审批节点所有审批人未执行审批操作。

        样例如下:

        某审批单在第三方审批系统侧存在两个审批节点,节点间通过nodeId排序。

        第一个审批节点中,存在两个审批人,张三同意了审批,李四执行了撤回审批。两个审批人均执行了操作,所以待审批人列表pendingApprovers为空。审批节点审批关系为AND, 因李四执行了撤回审批,所以节点审批状态设置为REVOKED。操作记录列表records中记录张三和李四的操作信息,张三执行了同意审批,action字段为APPROVE,comment字段填写操作评论信息;李四执行了撤回审批,action字段为REVOKE_APPLY。

        第二个审批节点,所有审批人均未执行审批操作。节点审批状态nodeStatus设置为 APPROVING。待审批人列表pendingApprovers记录待审批人王五的信息。

        该审批单总共存在两个审批节点,第一个审批节点中审批人执行了撤回操作,终止了审批流程,所以整体审批单状态applyStatus设置为revoke。

        {
           "applyId": "123456",
           "processInstanceId": "qwqwqeqe",
           "applyStatus": "revoke",
           "nodes": [
              {
                 "nodeId": "1",
                 "nodeStatus": "REVOKED",
                 "nodeName": "审批测试节点1",
                 "approverRelation": "AND",
                 "pendingApprovers": [],
                 "records": [
                    {
                       "operateUser": {
                          "userId": "1111",
                          "userName": "张三"
                       },
                       "action": "APPROVE",
                       "comment": "同意该表权限审批",
                       "operatedTime": "2026-03-19 19:01:23"
                    },
                    {
                       "operateUser": {
                          "userId": "2222",
                          "userName": "李四"
                       },
                       "action": "REVOKE_APPLY",
                       "comment": "撤回该表权限审批",
                       "operatedTime": "2026-03-19 19:02:23"
                    }
                 ]
              },
              {
                 "nodeId": "2",
                 "nodeStatus": "APPROVING",
                 "nodeName": "审批测试节点2",
                 "approverRelation": "AND",
                 "pendingApprovers": [
                    {
                       "userId": "33333",
                       "userName": "王五"
                    }
                 ],
                 "records": []
              }
           ]
        }
      • 多个审批节点,审批关系为且关系,第一个审批节点审批人执行了转交操作,第二个审批节点所有审批人均未执行审批操作。

        样例如下:

        某审批单起初存在两个审批节点,第一个审批节点存在审批人张三和李四,第二个审批节点存在审批人王五,两个节点均处于待审批的状态。

        {
           "applyId": "123456",
           "processInstanceId": "qwqwqeqe",
           "applyStatus": "approving",
           "nodes": [
              {
                 "nodeId": "1",
                 "nodeStatus": "APPROVING",
                 "nodeName": "审批测试节点1",
                 "approverRelation": "AND",
                 "pendingApprovers": [
                    {
                       "userId": "1111",
                       "userName": "张三"
                    },
                    {
                       "userId": "2222",
                       "userName": "李四"
                    }
                 ],
                 "records": []
              },
              {
                 "nodeId": "2",
                 "nodeStatus": "APPROVING",
                 "nodeName": "审批测试节点2",
                 "approverRelation": "AND",
                 "pendingApprovers": [
                    {
                       "userId": "33333",
                       "userName": "王五"
                    }
                 ],
                 "records": []
              }
           ]
        }

        随后,第一个审批节点中审批人张三执行了转交操作,转交给小七进行审批。 此时将新增一个审批节点,代表转交的流程。待审批人列表pendingApprovers为空。操作记录列表records记录张三转交至小七的操作,action为ASSIGN_APPROVE,代表转交操作。comment填写评论信息,operateUser填写操作人张三的信息,transferApprovers填写被转交人小七的信息。新增审批节点的节点状态nodeStatus为ACCEPTED。

        张三将审批转交至小七后,待审批人已更新为李四和小七,李四和小七未进行审批,pendingApprovers中记录两者信息。操作记录列表records记录为空,节点审批状态为APPROVING。因为上述新增了一个审批节点,代表转交流程,则起初的两个审批节点进行顺延,nodeId变为2和3。

        第二个审批节点,所有审批人未执行审批操作。节点审批状态nodeStatus设置为 APPROVING。待审批人列表pendingApprovers记录待审批人王五的信息。

        第二个和第三个审批节点状态未到达终态,整体节点审批状态设置为approving。

        {
           "applyId": "123456",
           "processInstanceId": "qwqwqeqe",
           "applyStatus": "approving",
           "nodes": [
              {
                 "nodeId": "1",
                 "nodeStatus": "ACCEPTED",
                 "nodeName": "转交节点测试1",
                 "approverRelation": "AND",
                 "pendingApprovers": [],
                 "records": [
                    {
                       "operateUser": {
                          "userId": "1111",
                          "userName": "张三"
                       },
                       "action": "ASSIGN_APPROVE",
                       "comment": "转交至七仔审批",
                       "transferApprovers": {
                          "userId": "7777",
                          "userName": "七仔"
                       },
                       "operatedTime": "2026-03-19 19:01:23"
                    }
                 ]
              },
              {
                 "nodeId": "2",
                 "nodeStatus": "APPROVING",
                 "nodeName": "审批测试节点1",
                 "approverRelation": "AND",
                 "pendingApprovers": [
                    {
                       "userId": "7777",
                       "userName": "七仔"
                    },
                    {
                       "userId": "2222",
                       "userName": "李四"
                    }
                 ],
                 "records": []
              },
              {
                 "nodeId": "3",
                 "nodeStatus": "APPROVING",
                 "nodeName": "审批测试节点2",
                 "approverRelation": "AND",
                 "pendingApprovers": [
                    {
                       "userId": "33333",
                       "userName": "王五"
                    }
                 ],
                 "records": []
              }
           ]
        }
      • 多个审批节点,审批关系为且关系,第一个审批节点审批人执行了加签操作,第二个审批节点所有审批人未执行审批操作。

        样例如下:

        某审批单起初存在两个审批节点,第一个审批节点存在审批人张三和李四,第二个审批节点存在审批人王五,两个节点均处于待审批的状态。

        {
           "applyId": "123456",
           "processInstanceId": "qwqwqeqe",
           "applyStatus": "approving",
           "nodes": [
              {
                 "nodeId": "1",
                 "nodeStatus": "APPROVING",
                 "nodeName": "审批测试节点1",
                 "approverRelation": "AND",
                 "pendingApprovers": [
                    {
                       "userId": "1111",
                       "userName": "张三"
                    },
                    {
                       "userId": "2222",
                       "userName": "李四"
                    }
                 ],
                 "records": []
              },
              {
                 "nodeId": "2",
                 "nodeStatus": "APPROVING",
                 "nodeName": "审批测试节点2",
                 "approverRelation": "AND",
                 "pendingApprovers": [
                    {
                       "userId": "33333",
                       "userName": "王五"
                    }
                 ],
                 "records": []
              }
           ]
        }

        随后,第一个审批节点中审批人张三执行了加签操作,先让小七进行审批。操作记录列表records记录张三转交至小七的操作。action为ASSIGN_APPROVE, 表示转交操作。comment填写评论信息,operateUser填写操作人张三的信息。transferApprovers填写被转交人小七的信息。新增审批节点的节点状态nodeStatus为ACCEPTED。

        新增两个审批节点,代表张三加签和小七审批的流程。

        其中新增的第一个审批节点,代表张三加签小七,待审批人列表pendingApprovers设置为空,节点审批状nodeStatus为ACCEPTED,操作记录列表records记录张三加签至小七的操作,action为COUNTER_SIGN_APPROVE,表示加签操作。comment填写评论信息,operateUser填写操作人张三的相关信息,transferApprovers填写被加签人小七的相关信息。

        新增的第二个审批节点,代表被加签人小七待审批,待审批人列表pendingApprovers记录待审批人小七的相关信息。操作记录列表records记录为空,节点审批状态nodeStatus为APPROVING。

        因为上述新增了两个审批节点代表加签流程,起初的两个审批节点进行顺延,nodeId变为3和4。

        第三个审批节点,待审批人张三和李四均未进行审批,待审批人列表pendingApprovers记录张三和李四的相关信息。节点审批状态nodeStatus为 APPROVING。两位待审批人均未执行操作,records字段为空。

        第四个审批节点,所有审批人未执行审批操作。节点审批状态nodeStatus为APPROVING。待审批人列表pendingApprovers记录待审批人王五的信息。

        因为第二个、第三个和第四个审批节点状态均未达到终态,整体节点审批状态为approving。

        {
           "applyId": "123456",
           "processInstanceId": "qwqwqeqe",
           "applyStatus": "approving",
           "nodes": [
              {
                 "nodeId": "1",
                 "nodeStatus": "ACCEPTED",
                 "nodeName": "加签节点测试1",
                 "approverRelation": "AND",
                 "pendingApprovers": [],
                 "records": [
                    {
                       "operateUser": {
                          "userId": "1111",
                          "userName": "张三"
                       },
                       "action": "COUNTER_SIGN_APPROVE",
                       "comment": "加签至七仔审批",
                       "transferApprovers": {
                          "userId": "7777",
                          "userName": "七仔"
                       },
                       "operatedTime": "2026-03-19 19:01:23"
                    }
                 ]
              },
              {
                 "nodeId": "2",
                 "nodeStatus": "APPROVING",
                 "nodeName": "加签节点七仔审批",
                 "approverRelation": "AND",
                 "pendingApprovers": [
                    {
                       "userId": "7777",
                       "userName": "七仔"
                    }
                 ],
                 "records": []
              },
              {
                 "nodeId": "3",
                 "nodeStatus": "APPROVING",
                 "nodeName": "",
                 "approverRelation": "AND",
                 "pendingApprovers": [
                    {
                       "userId": "1111",
                       "userName": "张三"
                    },
                    {
                       "userId": "2222",
                       "userName": "李四"
                    }
                 ],
                 "records": []
              },
              {
                 "nodeId": "4",
                 "nodeStatus": "APPROVING",
                 "nodeName": "审批测试节点2",
                 "approverRelation": "AND",
                 "pendingApprovers": [
                    {
                       "userId": "33333",
                       "userName": "王五"
                    }
                 ],
                 "records": []
              }
           ]
        }
  • 加解密方法

    加密(以bpms接收回调为例):

    Map<String, String> callBackJson = Maps.newHashMap();
    callBackJson.put("applyId", "1");
    callBackJson.put("applyStatus", "accept");
    callBackJson.put("processInstanceId", "2");
    callBackJson.put("comment", "test");
    // 如果对接方式选择 “显示三方审批的所有节点”,需要填充 nodes 字段信息
    String nodesJson = "[{"approverRelation":"OR","nodeId":"1","nodeName":"执行通过节点测试","nodeStatus":"ACCEPTED","pendingApprovers":[],"records":[{"action":"APPROVE","comment":"同意审批","operateUser":{"userId":"22222","userName":"张三"},"operatedTime":"2026-03-18 15:14:23"}]}]";
    callBackJson.put("nodes", nodesJson)
    String callBackResult = JSON.toJSONString(callBackJson);
    
    ThirdPartyCrypto callbackCrypto = new ThirdPartyCrypto(token, aesKey);
    
    String timestamp = String.valueOf(System.currentTimeMillis());
    String nonce = ThirdPartyCrypto.Utils.getRandomStr(16);
    String encrypt = callbackCrypto.encrypt(nonce, callBackResult);
    String signature = callbackCrypto.getSignature(token, timestamp, nonce, encrypt);

    解密(以bpms返回成功信息为例):

    String encryptMsg = JSONObject.parseObject(encrypt);
    String decryptMsg = callbackCrypto.getDecryptMsg(signature, timestamp, nonce, encryptMsg);
    if ("success".equalsIgnoreCase(decryptMsg)) {
     log.error("call back success");
    }

    加解密工具

    import com.alibaba.fastjson.JSON;
    import org.apache.commons.codec.binary.Base64;
    
    import javax.crypto.Cipher;
    import javax.crypto.spec.IvParameterSpec;
    import javax.crypto.spec.SecretKeySpec;
    import java.io.ByteArrayOutputStream;
    import java.lang.reflect.Field;
    import java.nio.charset.Charset;
    import java.nio.charset.StandardCharsets;
    import java.security.MessageDigest;
    import java.security.Permission;
    import java.security.PermissionCollection;
    import java.security.Security;
    import java.util.Arrays;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.Random;
    
    /**
     * Dataphin开放平台加解密方法
     */
    public class ThirdPartyCrypto {
    
     private static final Charset CHARSET = StandardCharsets.UTF_8;
     private static final Base64 BASE_64 = new Base64();
     private final byte[] AES_KEY;
     private final String TOKEN;
    
     /**
     * ask getPaddingBytes key固定长度
     **/
     private static final Integer AES_ENCODE_KEY_LENGTH = 43;
     /**
     * 加密随机字符串字节长度
     **/
     private static final Integer RANDOM_LENGTH = 16;
    
     /**
     * 构造函数
     *
     * @param token 开发者设置的token
     * @param encodingAesKey 开发者设置的EncodingAESKey
     *
     * @throws ThirdPartyEncryptException 执行失败,请查看该异常的错误码和具体的错误信息
     */
     public ThirdPartyCrypto(String token, String encodingAesKey) throws ThirdPartyEncryptException {
     if (null == encodingAesKey || encodingAesKey.length() != AES_ENCODE_KEY_LENGTH) {
     throw new ThirdPartyEncryptException(ThirdPartyEncryptException.AES_KEY_ILLEGAL);
     }
     this.TOKEN = token;
     AES_KEY = Base64.decodeBase64(encodingAesKey + "=");
     }
    
     public Map<String, String> getEncryptedMap(String plaintext) throws ThirdPartyEncryptException {
     return getEncryptedMap(plaintext, System.currentTimeMillis(), Utils.getRandomStr(16));
     }
    
     /**
     * 将和Dataphin同步的消息体加密,返回加密Map
     *
     * @param plaintext 传递的消息体明文
     * @param timeStamp 时间戳
     * @param nonce 随机字符串
     * @return
     * @throws ThirdPartyEncryptException
     */
     public Map<String, String> getEncryptedMap(String plaintext, Long timeStamp, String nonce)
     throws ThirdPartyEncryptException {
     if (null == plaintext) {
     throw new ThirdPartyEncryptException(ThirdPartyEncryptException.ENCRYPTION_PLAINTEXT_ILLEGAL);
     }
     if (null == timeStamp) {
     throw new ThirdPartyEncryptException(ThirdPartyEncryptException.ENCRYPTION_TIMESTAMP_ILLEGAL);
     }
     if (null == nonce) {
     throw new ThirdPartyEncryptException(ThirdPartyEncryptException.ENCRYPTION_NONCE_ILLEGAL);
     }
     // 加密
     String encrypt = encrypt(Utils.getRandomStr(RANDOM_LENGTH), plaintext);
     String signature = getSignature(TOKEN, String.valueOf(timeStamp), nonce, encrypt);
     Map<String, String> resultMap = new HashMap<String, String>();
     resultMap.put("msg_signature", signature);
     resultMap.put("encrypt", encrypt);
     resultMap.put("timeStamp", String.valueOf(timeStamp));
     resultMap.put("nonce", nonce);
     return resultMap;
     }
    
     /**
     * 密文解密
     *
     * @param msgSignature 签名串
     * @param timeStamp 时间戳
     * @param nonce 随机串
     * @param encryptMsg 密文
     * @return 解密后的原文
     * @throws ThirdPartyEncryptException
     */
     public String getDecryptMsg(String msgSignature, String timeStamp, String nonce, String encryptMsg)
     throws ThirdPartyEncryptException {
     //校验签名
     String signature = getSignature(TOKEN, timeStamp, nonce, encryptMsg);
     if (!signature.equals(msgSignature)) {
     throw new ThirdPartyEncryptException(ThirdPartyEncryptException.COMPUTE_SIGNATURE_ERROR);
     }
     // 解密
     return decrypt(encryptMsg);
     }
    
     /**
     * 对明文加密.
     * @param plaintext 需要加密的明文
     * @return 加密后base64编码的字符串
     */
     public String encrypt(String random, String plaintext) throws ThirdPartyEncryptException {
     try {
     byte[] randomBytes = random.getBytes(CHARSET);
     byte[] plainTextBytes = plaintext.getBytes(CHARSET);
     byte[] lengthByte = Utils.int2Bytes(plainTextBytes.length);
     ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
     byteStream.write(randomBytes);
     byteStream.write(lengthByte);
     byteStream.write(plainTextBytes);
     byte[] padBytes = PKCS7Padding.getPaddingBytes(byteStream.size());
     byteStream.write(padBytes);
     byte[] unencrypted = byteStream.toByteArray();
     byteStream.close();
     Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
     SecretKeySpec keySpec = new SecretKeySpec(AES_KEY, "AES");
     IvParameterSpec iv = new IvParameterSpec(AES_KEY, 0, 16);
     cipher.init(Cipher.ENCRYPT_MODE, keySpec, iv);
     byte[] encrypted = cipher.doFinal(unencrypted);
     String result = BASE_64.encodeToString(encrypted);
     return result;
     } catch (Exception e) {
     throw new ThirdPartyEncryptException(ThirdPartyEncryptException.COMPUTE_ENCRYPT_TEXT_ERROR);
     }
     }
    
     /**
     * 对密文进行解密.
     * @param text 需要解密的密文
     * @return 解密得到的明文
     */
     private String decrypt(String text) throws ThirdPartyEncryptException {
     byte[] originalArr;
     try {
     // 设置解密模式为AES的CBC模式
     Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
     SecretKeySpec keySpec = new SecretKeySpec(AES_KEY, "AES");
     IvParameterSpec iv = new IvParameterSpec(Arrays.copyOfRange(AES_KEY, 0, 16));
     cipher.init(Cipher.DECRYPT_MODE, keySpec, iv);
     // 使用BASE64对密文进行解码
     byte[] encrypted = Base64.decodeBase64(text);
     // 解密
     originalArr = cipher.doFinal(encrypted);
     } catch (Exception e) {
     throw new ThirdPartyEncryptException(ThirdPartyEncryptException.COMPUTE_DECRYPT_TEXT_ERROR);
     }
    
     String plainText;
     try {
     // 去除补位字符
     byte[] bytes = PKCS7Padding.removePaddingBytes(originalArr);
     // 分离16位随机字符串,网络字节序和corpId
     byte[] networkOrder = Arrays.copyOfRange(bytes, 16, 20);
     int plainTextLegth = Utils.bytes2int(networkOrder);
     plainText = new String(Arrays.copyOfRange(bytes, 20, 20 + plainTextLegth), CHARSET);
     } catch (Exception e) {
     throw new ThirdPartyEncryptException(ThirdPartyEncryptException.COMPUTE_DECRYPT_TEXT_LENGTH_ERROR);
     }
    
     return plainText;
     }
    
     /**
     * 数字签名
     *
     * @param token isv token
     * @param timestamp 时间戳
     * @param nonce 随机串
     * @param encrypt 加密文本
     * @return
     * @throws ThirdPartyEncryptException
     */
     public String getSignature(String token, String timestamp, String nonce, String encrypt)
     throws ThirdPartyEncryptException {
     try {
     String[] array = new String[] {token, timestamp, nonce, encrypt};
     Arrays.sort(array);
     System.out.println(JSON.toJSONString(array));
     StringBuffer sb = new StringBuffer();
     for (int i = 0; i < 4; i++) {
     sb.append(array[i]);
     }
     String str = sb.toString();
     System.out.println(str);
     MessageDigest md = MessageDigest.getInstance("SHA-1");
     md.update(str.getBytes());
     byte[] digest = md.digest();
    
     StringBuffer hexstr = new StringBuffer();
     String shaHex = "";
     for (int i = 0; i < digest.length; i++) {
     shaHex = Integer.toHexString(digest[i] & 0xFF);
     if (shaHex.length() < 2) {
     hexstr.append(0);
     }
     hexstr.append(shaHex);
     }
     return hexstr.toString();
     } catch (Exception e) {
     throw new ThirdPartyEncryptException(ThirdPartyEncryptException.COMPUTE_SIGNATURE_ERROR);
     }
     }
    
     public static class Utils {
     public Utils() {
     }
    
     public static String getRandomStr(int count) {
     String base = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
     Random random = new Random();
     StringBuffer sb = new StringBuffer();
    
     for (int i = 0; i < count; ++i) {
     int number = random.nextInt(base.length());
     sb.append(base.charAt(number));
     }
    
     return sb.toString();
     }
    
     public static byte[] int2Bytes(int count) {
     byte[] byteArr = new byte[] {(byte)(count >> 24 & 255), (byte)(count >> 16 & 255), (byte)(count >> 8 & 255),
     (byte)(count & 255)};
     return byteArr;
     }
    
     public static int bytes2int(byte[] byteArr) {
     int count = 0;
    
     for (int i = 0; i < 4; ++i) {
     count <<= 8;
     count |= byteArr[i] & 255;
     }
    
     return count;
     }
     }
    
     public static class PKCS7Padding {
     private static final Charset CHARSET = StandardCharsets.UTF_8;
     private static final int BLOCK_SIZE = 32;
    
     public PKCS7Padding() {
     }
    
     public static byte[] getPaddingBytes(int count) {
     int amountToPad = 32 - count % 32;
     if (amountToPad == 0) {
     amountToPad = 32;
     }
    
     char padChr = chr(amountToPad);
     String tmp = new String();
    
     for (int index = 0; index < amountToPad; ++index) {
     tmp = tmp + padChr;
     }
    
     return tmp.getBytes(CHARSET);
     }
    
     public static byte[] removePaddingBytes(byte[] decrypted) {
     int pad = decrypted[decrypted.length - 1];
     if (pad < 1 || pad > 32) {
     pad = 0;
     }
    
     return Arrays.copyOfRange(decrypted, 0, decrypted.length - pad);
     }
    
     private static char chr(int a) {
     byte target = (byte)(a & 255);
     return (char)target;
     }
     }
    
     public static class ThirdPartyEncryptException extends Exception {
     public static final int SUCCESS = 0;
     public static final int ENCRYPTION_PLAINTEXT_ILLEGAL = 900001;
     public static final int ENCRYPTION_TIMESTAMP_ILLEGAL = 900002;
     public static final int ENCRYPTION_NONCE_ILLEGAL = 900003;
     public static final int AES_KEY_ILLEGAL = 900004;
     public static final int SIGNATURE_NOT_MATCH = 900005;
     public static final int COMPUTE_SIGNATURE_ERROR = 900006;
     public static final int COMPUTE_ENCRYPT_TEXT_ERROR = 900007;
     public static final int COMPUTE_DECRYPT_TEXT_ERROR = 900008;
     public static final int COMPUTE_DECRYPT_TEXT_LENGTH_ERROR = 900009;
     public static final int COMPUTE_DECRYPT_TEXT_CORPID_ERROR = 900010;
     private static Map<Integer, String> msgMap = new HashMap();
     private Integer code;
    
     static {
     msgMap.put(0, "成功");
     msgMap.put(900001, "加密明文文本非法");
     msgMap.put(900002, "加密时间戳参数非法");
     msgMap.put(900003, "加密随机字符串参数非法");
     msgMap.put(900005, "签名不匹配");
     msgMap.put(900006, "签名计算失败");
     msgMap.put(900004, "不合法的aes key");
     msgMap.put(900007, "计算加密文字错误");
     msgMap.put(900008, "计算解密文字错误");
     msgMap.put(900009, "计算解密文字长度不匹配");
     msgMap.put(900010, "计算解密文字corpid不匹配");
     }
    
     public Integer getCode() {
     return this.code;
     }
    
     public ThirdPartyEncryptException(Integer exceptionCode) {
     super((String)msgMap.get(exceptionCode));
     this.code = exceptionCode;
     }
     }
     static {
     try {
     Security.setProperty("crypto.policy", "limited");
     RemoveCryptographyRestrictions();
     } catch (Exception var1) {
     }
    
     }
     private static void RemoveCryptographyRestrictions() throws Exception {
     Class<?> jceSecurity = getClazz("javax.crypto.JceSecurity");
     Class<?> cryptoPermissions = getClazz("javax.crypto.CryptoPermissions");
     Class<?> cryptoAllPermission = getClazz("javax.crypto.CryptoAllPermission");
     if (jceSecurity != null) {
     setFinalStaticValue(jceSecurity, "isRestricted", false);
     PermissionCollection defaultPolicy = (PermissionCollection)getFieldValue(jceSecurity, "defaultPolicy", (Object)null, PermissionCollection.class);
     if (cryptoPermissions != null) {
     Map<?, ?> map = (Map)getFieldValue(cryptoPermissions, "perms", defaultPolicy, Map.class);
     map.clear();
     }
    
     if (cryptoAllPermission != null) {
     Permission permission = (Permission)getFieldValue(cryptoAllPermission, "INSTANCE", (Object)null, Permission.class);
     defaultPolicy.add(permission);
     }
     }
    
     }
     private static Class<?> getClazz(String className) {
     Class clazz = null;
    
     try {
     clazz = Class.forName(className);
     } catch (Exception var3) {
     }
    
     return clazz;
     }
     private static void setFinalStaticValue(Class<?> srcClazz, String fieldName, Object newValue) throws Exception {
     Field field = srcClazz.getDeclaredField(fieldName);
     field.setAccessible(true);
     Field modifiersField = Field.class.getDeclaredField("modifiers");
     modifiersField.setAccessible(true);
     modifiersField.setInt(field, field.getModifiers() & -17);
     field.set((Object)null, newValue);
     }
     private static <T> T getFieldValue(Class<?> srcClazz, String fieldName, Object owner, Class<T> dstClazz) throws Exception {
     Field field = srcClazz.getDeclaredField(fieldName);
     field.setAccessible(true);
     return dstClazz.cast(field.get(owner));
     }
    
    }