This topic outlines how to integrate third-party approval processes with Dataphin BPMS, detailing the open interface capabilities, integration steps, and example use cases.
Prerequisites
Ensure the Approval Settings are configured within the Dataphin system. For configuration details, see approval settings. For tenant operations, refer to the Approval Settings under Select Approval System and the Other configuration items.
Approval interfaces
{url}: The integration address for third-party approval flows. The URL for submitting approval requests is http(s)://{url}.
-
Connection test.
Request Method: Use POST.
Request URL: http(s)://{url}/dataphin/bpms/check/connect.
Request Time Series Chart

Query Parameters
Parameter Name
Parameter Type
Description
accessToken
String
Credential used to call the server-side API.
Generated automatically on the Dataphin page or manually by the user and entered into Dataphin. For instance: 6d1b2n1c.
timestamp
String
The time when the information was sent, expressed in milliseconds. For example: 1654156836531.
Request Body Parameters
checkEvent (String): This parameter represents a connection test, such as checking for connectivity.
Returned Parameters
checkResult (String): Indicates the outcome of the check; a return value of 'success' denotes a successful connection test. Any other values indicate a failure in the connection test. For instance, 'success'.
-
Submit approval.
Request Method: POST
Request Address: http(s)://{url}/dataphin/bpms/processinstance/create
Submit Approval Time Series Chart

Query Parameters
Parameter Name
Parameter Type
Description
accessToken
String
Credential used to call the server-side API.
Generated automatically on the Dataphin page or manually by the user and entered into Dataphin. For instance: 6d1b2n1c.
timestamp
String
The time when the information was sent, expressed in milliseconds. For example: 1654156836531.
Body Parameters
Parameter Name
Parameter Type
Description
applyId
String
The Dataphin approval order ID. For example: 1223.
title
String
The title of the Dataphin approval order. For example: dataphin bpms.
content
String
The content of the Dataphin approval order. For example: bpms content. Refer to approval message content metadata description.
type
String
Approval order type: APPROVAL_DOC_TYPE.
Code review: CODE_REVIEW.
Publish control: PUBLISH.
Business planning: BIZ_PLANNING.
Authorization approval: AUTH.
Default: DEFAULT.
templateCode
String
The code for the approval template, which can be left empty and is related to page configuration.
Approval Message Content Metadata Description
Parameter Name
Parameter Type
Description
resourceType
String
The type of the approval task, which is an enumeration value that includes the following types:
PhysicalTable: Physical table.
LogicTable: Logical table.
MetaTable: Real-time meta table.
MirrorTable: Mirror table.
Fun: Function.
DataSource: Data source.
FeatureConfig: Feature permission configuration.
OSAPP: Data service APP.
OSAPI: Data service API.
OSLogicUnit: Data service unit.
OSDS: Data service data source.
SECRET_KEY:_KEY: Key.
GLOBAL_PARAM: Global variable.
grantToUsers
List<GrantToUser>
A list of authorized users. Refer to GrantToUser.
bpmsEnvironment
BpmsEnvironment
Information about the approval system environment. See BpmsEnvironment.
operates
List<String>
The types of permissions requested, which include:
SYNC_READ: Data source read-through.
SYNC_WRITE: Data source write-through.
SQL_QUERY: SQL query for physical and logical tables.
SQL_WRITE: SQL write for physical tables.
SQL_ALTER: SQL modification for physical tables.
SQL_DROP: SQL deletion for physical and logical tables.
SELECT: Query for data service API.
WRITE: Write permission.
DEV: Development permission.
USE: Usage permission.
UPDATE: Modify table data.
PIPELINE_ENCRY: Integration encryption.
PIPELINE_DECRY: Integration decryption.
levels
List<String>
Permission levels, including HIGH, MIDDLE, and LOW.
operations
List<String>
Permission types, including:
SELECT-Query.
DESCRIBE- Describe table structure.
UPDATE- Modify table data.
ALTER- Modify table structure.
DELETE-Delete table.
COPY_TASK- Copy.
resources
List<BpmsResource>
Resource content. See BpmsResource.
applyObject
ApplyObject
Application object information. Refer to ApplyObject.
reason
String
The reason for the application.
GrantToUser
Parameter Name
Parameter Type
Description
account
Account
The list of authorized accounts. See Account.
period
Period
The validity period. See Period.
Account
Parameter Name
Parameter Type
Description
accountType
String
Authorization types include personal account, tenant account, and application account.
PERSONAL: Personal account.
TENANT: Tenant account.
APPLICATION: Application account.
userName
String
The username associated with the account. The format is yyyy-mm-dd. For example: 2022-09-11.
Period
Parameter Name
Parameter Type
Description
periodType
String
The validity period type includes support for long-term (LONG_TERM) options.
periodEnd
String
The expiration time of the permission, formatted as yyyy-mm-dd. For example: 2022-09-11.
BpmsEnvironment
Parameter Name
Parameter Type
Description
projectName
String
The name of the project.
bizUnitName
String
The name of the business unit.
resourceEnv
String
The environment, categorized into production and development environments.
PROD: Production.
DEV: Development.
BpmsResource
Parameter Name
Parameter Type
Description
resourceType
String
Refer to the approval message content metadata description.
resourceName
String
The name of the resource.
children
List<Children>
A list of fields. See Children.
operations
List<String>
Refer to the operates in the approval message content metadata description.
authTypes
String
The type of application permission.
Children
Parameter Name
Parameter Type
Description
resourceName
String
The name of the field.
resourceProperties
String
The properties of the field.
ResourceProperties
Parameter Name
Parameter Type
Description
columnType
String
The data type of the field.
columnIsPartition
String
Indicates whether the field is a partition field.
columnIsPk
String
Specifies whether the field is a primary key.
ApplyObject
Parameter Name
Parameter Type
Description
objectName
String
The name of the object involved in the application.
codeContent
String
The content of the code associated with the application.
name
String
The English name of the business activity.
bizObjectType
String
The type of the business object.
bizObjectChangeType
String
The type of change to the business object.
bizObjectPkField
String
The primary key field of the business object.
bizObjectParent
String
The parent object to which the business object belongs.
bizObjectChildren
String
Downstream child objects related to the business object.
bizProcessCn
String
The Chinese name of the business activity.
bizProcessType
String
The type of the business activity.
bizProcessChangeType
String
The type of change to the business process.
bizProcessNodes
String
The nodes within the business process flow.
atomicIndexCn
String
The Chinese name of the index.
dataType
String
The data type of the index.
unit
String
The unit of measurement for the index.
bizProcess
String
The name of the business process.
des
String
The description or caliber of the business process.
derivedLogic
String
The logic derived from the business process.
protoLogics
String
The underlying logic for the business process.
Return Parameters
processInstanceId (String): The ID of the third-party approval instance. For example: 6d1b2n1c.
Revoke approval.
NoteIf the content of the application does not meet expectations after submission, the approval can be revoked.
Request Method: POST
Request Address: http(s)://{url}/dataphin/bpms/processinstance/revoke
Query Parameters
Parameter Name
Parameter Type
Description
accessToken
String
Credential used to call the server-side API.
Generated automatically on the Dataphin page or manually by the user and entered into Dataphin. For instance: 6d1b2n1c.
timestamp
String
The time when the information was sent, expressed in milliseconds. For example: 1654156836531.
Body Parameters
Parameter Name
Parameter Type
Description
applyId
String
Dataphin approval order ID, such as 1223.
processInstanceId
String
The ID of a third-party approval instance, such as 6d1b2a3c.
operatingUserId
String
Operator ID, such as 6d1bx1d2.
Return Parameters
result (String): Information indicating the outcome of the revocation. The operation is deemed successful if the return value is 'success'.
-
Query approval instance URL.
Request Method: GET
Request URL: http(s)://{url}/dataphin/bpms/processinstance/apply.
Query Parameters
Parameter Name
Parameter Type
Description
accessToken
String
Credential used to call the server-side API.
Generated automatically on the Dataphin page or manually by the user and entered into Dataphin. For instance: 6d1b2n1c.
timestamp
String
The time when the information was sent, expressed in milliseconds. For example: 1654156836531.
Callback interfaces
-
The Callback URL, https://{callbackUrl}, is configured in the approval settings within the Other section.
-
accessToken: The credential for invoking the server-side API. Automatically generated by the Dataphin page, or generated by the user and filled in Dataphin.
-
callBackAesKey: Callback authentication credential. Automatically generated by the Dataphin page, or generated by the user and filled in Dataphin.
-
Callback method.
Request Method: Use POST.
Request URL: http://{callbackUrl}.
Query Parameters
Parameter Name
Parameter Type
Description
signature
String
The signature is the message authentication code. For encryption and decryption methods, refer to the relevant documentation.
timestamp
String
The timestamp represents the time the information was sent, expressed in milliseconds. For instance: 1654156836531.
nonce
String
A nonce is a random number used once. For encryption and decryption methods, see the corresponding documentation.
Request Body Parameters
encrypt (String): The encrypted information, such as ajls384k.
Return Parameters
encrypt (String): The encrypted information representing the callback status, such as ajls384k.
-
Callback encrypted content.
Callback connectivity verification.
-
Enter encrypted parameters:
applyStatus (String): This parameter is used to check connectivity. For example, use "CHECK" to verify connection parameters.
-
Return encrypted parameters:
success: The successful callback return value.
Callback return bpms instance approval result.
-
Input encrypted parameters:
Parameter Name
Parameter Type
Description
applyId
String
Dataphin approval order ID, such as 1223.
processInstanceId
String
The ID of a third-party approval instance, such as 6d1b2a3c.
comment
String
Information on approval instance comments.
applyStatus
String
accept: To accept.
reject: Rejection of the application.
revoke: Revocation of the application.
-
Return encrypted parameters:
success: The successful callback return value.
-
-
Encryption and decryption methods.
Encryption Example:
Map<String, String> callBackJson = Maps.newHashMap(); callBackJson.put("applyId", "1"); callBackJson.put("applyStatus", "accept"); callBackJson.put("processInstanceId", "2"); callBackJson.put("comment", "test"); 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);Decryption Example:
String encryptMsg = JSONObject.parseObject(encrypt); String decryptMsg = callbackCrypto.getDecryptMsg(signature, timestamp, nonce, encryptMsg); if ("success".equalsIgnoreCase(decryptMsg)) { log.error("call back success"); }Encryption and Decryption Tools
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 open platform encryption and decryption methods */ 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 fixed length **/ private static final Integer AES_ENCODE_KEY_LENGTH = 43; /** * Encryption random string byte length **/ private static final Integer RANDOM_LENGTH = 16; /** * Constructor * * @param token Developer set token * @param encodingAesKey Developer set EncodingAESKey * * @throws ThirdPartyEncryptException Execution failed. Please check the error code and specific error message of this exception */ 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)); } /** * Encrypt the message body synchronized with Dataphin and return the encrypted Map * * @param plaintext The plaintext of the message body to be transmitted * @param timeStamp Timestamp * @param nonce Random string * @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); } // Encrypt 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; } /** * Decrypt the ciphertext * * @param msgSignature Signature string * @param timeStamp Timestamp * @param nonce Random string * @param encryptMsg Ciphertext * @return Decrypted original text * @throws ThirdPartyEncryptException */ public String getDecryptMsg(String msgSignature, String timeStamp, String nonce, String encryptMsg) throws ThirdPartyEncryptException { // Verify signature String signature = getSignature(TOKEN, timeStamp, nonce, encryptMsg); if (!signature.equals(msgSignature)) { throw new ThirdPartyEncryptException(ThirdPartyEncryptException.COMPUTE_SIGNATURE_ERROR); } // Decrypt return decrypt(encryptMsg); } /** * Encrypt plaintext * @param plaintext Plaintext to be encrypted * @return Encrypted base64 encoded string */ 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); } } /** * Decrypt ciphertext * @param text Ciphertext to be decrypted * @return Decrypted plaintext */ private String decrypt(String text) throws ThirdPartyEncryptException { byte[] originalArr; try { // Set decryption mode to AES CBC mode 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); // Decode ciphertext using BASE64 byte[] encrypted = Base64.decodeBase64(text); // Decrypt originalArr = cipher.doFinal(encrypted); } catch (Exception e) { throw new ThirdPartyEncryptException(ThirdPartyEncryptException.COMPUTE_DECRYPT_TEXT_ERROR); } String plainText; try { // Remove padding characters byte[] bytes = PKCS7Padding.removePaddingBytes(originalArr); // Separate 16-bit random string, network byte order, and 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; } /** * Digital signature * * @param token isv token * @param timestamp Timestamp * @param nonce Random string * @param encrypt Encrypted text * @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, "Success"); msgMap.put(900001, "Encryption plaintext illegal"); msgMap.put(900002, "Encryption timestamp parameter illegal"); msgMap.put(900003, "Encryption random string parameter illegal"); msgMap.put(900005, "Signature does not match"); msgMap.put(900006, "Signature calculation failed"); msgMap.put(900004, "Illegal aes key"); msgMap.put(900007, "Encryption text calculation error"); msgMap.put(900008, "Decryption text calculation error"); msgMap.put(900009, "Decryption text length does not match"); msgMap.put(900010, "Decryption text corpId does not match"); } 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)); } }