A webhook is an HTTP-based callback function that allows lightweight, event-driven communication between 2 application programming interfaces (APIs). Webhooks are used by a wide variety of web apps to receive small amounts of data from other apps。

Response Data(That is the response data that webhookUrl in the request parameter needs to give us)

If success, http statusCode it must be 200

  • statusCode is the http status of response to your request . If success,it must be 200. If you do not return a status code value of 200, we will retry the response to your webhook address.

Response Data(The response result we give to the webhookUrl) Content-Type: application/json Response Attributes

ParameterTypeValueDescription
signatureStringmessage body signature: signature =sha1(sort(clientId、timestamp、nonce, dataEncrypt))
dataEncryptStringmessage body encryption, need decryption processing is required to obtain the real response data
timestampNumber
nonceString
{
  "signature": "04e30dd43d9d8f95dd7c127dad617f0929d61c1d",
  "dataEncrypt": "LuG1OVSVIwOO/xpW00eSYo77Ncxa9h4VKmOJRjwoyoAmCIS/8FdJRJ+BpZn90BVAAg8xpU1bMmcDlAYDT010Wa9tNi1jivX25Ld03iA4EKs=",
  "timestamp": 1710757981609,
  "nonce": "1529"
}

When we complete the signature checksum and dataEncrypt decryption, we can get the real response content. The decrypted content of dataEncrypt is:

ParameterTypeValueDescription
_idString_id: returned by each interface
statusNumber2 or 3 or 4status: the status of image or video or faceswap or background change or avatar or audio: 【1:queueing, 2:processing,3:completed, 4:failed】
typeStringfaceswap or image or audio or talking photo or video translate or background change or avatar or lipsyncDistinguish the type of each interface
urlStringwhen staus = 3, the url is the final result about audio, image, and video.

Next, we will introduce the process and methods of encryption and decryption.

Encryption and Decryption technology solution

The encryption and decryption technical solution is implemented based on the AES encryption and decryption algorithm, as follows:

  1. clientSecret: This is the message encryption and decryption Key. The length is fixed at 24 characters. ClientSecret is used as the encryption key.
  2. AES adopts CBC mode, the secret key length is 24 bytes (192 bits), and the data is filled with PKCS#7; PKCS#7: K is the number of bytes of the secret key (24 is used), Buf is the content to be encrypted, N is its number of bytes. Buf needs to be filled to an integer multiple of K. Fill (K - N%K) bytes at the end of Buf, and the content of each byte is (K - N%K).
  3. The IV length of AES is 16 bytes, and clientId is used as the IV.

Message body encryption dataEncrypt is the result of the platform encrypting the message as follows:

  • dataEncrypt = AES_Encrypt( data, clientId, clientSecret ) Among them, data is the body content we need to transmit, clientId is the initial vector, and clientSecret is the encryption key.

Message body signature In order to verify the legitimacy of the message body, developers can verify the authenticity of the message body and decrypt the message body that passes the verification. Specific method: dataSignature=sha1(sort(clientId、timestamp、nonce, dataEncrypt))

ParameterDescription
clientIdclientId of user key pair
timestamptimestamp in body
noncenonce in body
dataEncryptThe previous article describes the ciphertext message body

Message body verification and decryption The developer first verifies the correctness of the message body signature, and then decrypts the message body after passing the verification.

Ways of identifying:

  1. The developer calculates the signature,compareSignature=sha1(sort(clientId、timestamp、nonce, dataEncrypt))
  2. Compare compareSignature and the signature in the body to see if they are equal. If they are equal, the verification is passed.

The decryption method is as follows:

  • data = AES_Decrypt(dataEncrypt, clientSecret);

Example: Encryption and Decryption

  1. To use nodejs or python or java for encryption.
// To use nodejs for encryption, you need to install crypto-js. Use the command npm install crypto-js to install it.
const CryptoJS = require('crypto-js')
const crypto = require('crypto');


// Generate signature
function generateMsgSignature(clientId, timestamp, nonce, msgEncrypt){
    const sortedStr = [clientId, timestamp, nonce, msgEncrypt].sort().join('');
    const hash = crypto.createHash('sha1').update(sortedStr).digest('hex');
    return hash;
}


// decryption algorithm
function generateAesDecrypt(dataEncrypt,clientId,clientSecret){
    const aesKey = clientSecret
    const key = CryptoJS.enc.Utf8.parse(aesKey)
    const iv = CryptoJS.enc.Utf8.parse(clientId)
    const decrypted = CryptoJS.AES.decrypt(dataEncrypt, key, {
        iv: iv,
        mode: CryptoJS.mode.CBC,
        padding: CryptoJS.pad.Pkcs7
    })
    return decrypted.toString(CryptoJS.enc.Utf8)
}


// Encryption Algorithm
function generateAesEncrypt(data,clientId,clientSecret){
    const aesKey = clientSecret
    const key = CryptoJS.enc.Utf8.parse(aesKey)
    const iv = CryptoJS.enc.Utf8.parse(clientId)
    const srcs = CryptoJS.enc.Utf8.parse(data)
    // CBC encryption method, Pkcs7 padding method
    const encrypted = CryptoJS.AES.encrypt(srcs, key, {
            iv: iv,
            mode: CryptoJS.mode.CBC,
            padding: CryptoJS.pad.Pkcs7
    })
    return encrypted.toString()
}
  1. Assume that our webhookUrl has obtained the corresponding data, such as the following corresponding data
{
  "signature": "04e30dd43d9d8f95dd7c127dad617f0929d61c1d",
  "dataEncrypt": "LuG1OVSVIwOO/xpW00eSYo77Ncxa9h4VKmOJRjwoyoAmCIS/8FdJRJ+BpZn90BVAAg8xpU1bMmcDlAYDT010Wa9tNi1jivX25Ld03iA4EKs=",
  "timestamp": 1710757981609,
  "nonce": 1529
}
  1. To verify the correctness of the signature and decrypt the content, clientId and clientSecret are required.
// express example
const obj = {
  "signature": "04e30dd43d9d8f95dd7c127dad617f0929d61c1d",
  "dataEncrypt": "LuG1OVSVIwOO/xpW00eSYo77Ncxa9h4VKmOJRjwoyoAmCIS/8FdJRJ+BpZn90BVAAg8xpU1bMmcDlAYDT010Wa9tNi1jivX25Ld03iA4EKs=",
  "timestamp": 1710757981609,
  "nonce": 1529
}
 
 let clientId = "AKDt8rWEczpYPzCGur2xE="
 let clientSecret = "nmwUjMAK0PJpl0MOiXLOOOwZADm0gkLo"
 let signature = obj.signature
 let msg_encrypt = obj.dataEncrypt
 let timestamp = obj.timestamp
 let nonce = obj.nonce
 let newSignature = generateMsgSignature(clientId,timestamp,nonce,msg_encrypt)
 if (signature===newSignature) {
     let result = generateAesDecrypt(msg_encrypt,clientId,clientSecret)
     // Handle your own business logic
     response.status(200).json({})  // If the processing is successful,http statusCode:200 must be returned.
  }else {
     response.status(400).json({})
  }