本文为您介绍Dataphin BPMS支持对接第三方审批流,包括开放了哪些接口能力,如何接入审批能力以及审批案例等内容。
前提条件
已在Dataphin系统配置审批设置,如何配置,详情请参见审批设置。运维租户参见审批设置中选择审批系统的其他配置项。
审批接口
{url}:为第三方审批流对接地址,http(s)://{url}为提交审批申请URL。
accessToken:调用服务端API的凭证。Dataphin页面自动生成,或用户生成填入Dataphin。
连接测试
请求方式:POST。
请求地址:http(s)://{url}/dataphin/bpms/check/connect。
请求时序图

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。
提交审批的时序图

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字段可填写
accept、reject或revoke。approving表示审批中,为中间态,仅供显示三方审批的所有节点对接方式下使用。
显示三方审批的所有节点
该对接方式需返回审批系统每个节点的详情,系统中将同步展示所有审批节点。当某一审批人员执行审批操作时,即可通过该回调接口将当前的审批节点信息通知至Dataphin系统。
涉及字段的解释说明
该对接方法下需要传入
applyId、applyStatus、processInstanceId和nodes字段。整体审批单状态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,记录被加签或者转交的人员信息。
不同审批场景下审批内容的结构体
加解密方法
加密(以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)); } }