全部產品
Search
文件中心

Quick Audience:自訂群組件UDF接入管理

更新時間:Jan 16, 2026

一、自訂群組件UDF說明

自訂群組件簡稱 UDF(User-Defined Functions),取名於常用的資料開發平台所使用的使用者自訂函數。以下均以 UDF 代替自訂群組件。

UDF 接入分為配置和執行兩部分,配置用於介面管理、畫布配置組件,執行用於旅程執行過程中的回調(執行部分和 WebHook 相似)。

二、UDF配置接入文檔

為了與Quick Audience對接,您需要開發一個HTTP Server。注意是Post請求,請求逾時時間為10秒。Quick Audience發起的HTTP請求和接入方回執請求約定如下通用參數,為必傳項。

2.1 系統間的流轉介面圖

image.png

① 為“開發線下提供配置資訊”如下所示

② 為iframe頁面跳轉,跳轉到外部系統中

③ API 介面:通過令牌擷取使用者資訊;同時需要將結果返回給iframe頁面。

④ API 介面:通過令牌擷取標籤資訊;同時需要將結果返回給iframe頁面。

⑤ 前端提交資料到iframe嵌入頁面中的 API,由外部系統後台通過 ⑥ 提交資料到 QA

⑥ API 介面:將配置資訊提交到 QA,QA 根據選擇的標籤資訊進行流程執行

2.1.1 產品介面配置 UDF 組件資訊

image.png

欄位填寫限制:

欄位

限制

嵌入頁面地址

組件內需要iframe嵌入的連結地址,必須是合法的完整地址,包含使用的協議(如HTTP或HTTPS),建議使用HTTPS,提高資訊傳輸的安全性。

icon URL

組件顯示icon,建議尺寸21 * 21px

請求地址

要接受訊息推送的介面地址,必須是合法的完整地址,包含使用的協議(如HTTP或HTTPS),建議使用HTTPS,提高資訊傳輸的安全性。

回執設定

回執設定將以介面形式將營銷結果返回到QA,需要配置回執結果欄位,將在自動化營銷中可通過結果判斷基於回執結果分流。

AES密鑰

AES密鑰長度可以為128、192或256位,對應字元為16、24、32位。

是否公開

是否公開開啟後,則當前組織下所有的空間都可以使用UDF組件;

是否公開關閉,則只能當前空間下可以使用UDF組件。

2.1.1.1 配置的原始 JSON 資訊
{
    "name":"自訂群組件名稱",
    "type":"marketing", //自訂群組件類別:當前只支援 marketing -> 營銷組件
    "version":"版本號碼", // 預設 1.0
    "endpoint":"自訂群組件目標網域名稱 以http或https開頭,如:http://demo.com/二級路徑 跳轉至 $endpoint/index.html",
    "iconUrl":"icon地址",
    "enable": true // true or false是否啟用
    "accessKey":"組件鑒權accessKey",
    "accessSecret":"組件鑒權accessSecret",
    "metaData":{ // 中繼資料資訊,不通類型組件 metaData 格式不同
        "allowIDType":"該組件支援使用者ID類型,如 mobile | email | idfa | imei等",
        "encryptionMethod":"推送營銷訊息 密碼編譯演算法  null | encryptionMethod",
        "sendParam":{
            "batchSendUrl":"營銷任務推送地址 以http或httpss開頭,如 http://demo.com/send",
            "batchLimit":100, //批量推送條數限制 1~1000, 預設100
            "timeout": 10, //請求逾時時間(單位秒) 0 ~ 60, 預設10
            "retryTimes":0, //失敗重試次數  0 ~ 3, 預設0
            "retryPeriod":0, //重試時間間隔(單位秒) 0 ~ 3600, 預設 0
        },
        "callbackParam":{//營銷組件回執參數
            "usableInHours": 3 * 24, //1 ~ 30 * 24,預設3 推送結果回執資料在多少天的時間內返回算有效,超過則丟棄 
            "clearInHours": 7 * 24, //1 ~ 365 * 24,預設 7 * 24 推送結果回執資料超過多少天后將被回收
            "resultEnumList":[ //推送結果回執枚舉列表, 預設 success & fail 
                {
                    "code":"success",
                    "name":"成功"
                },
                {
                    "code":"fail",
                    "name":"失敗"
                }
            ],
            "extParams": {
              "extParam1": "拓展參數列頭001", //在效果分析中展示的列名,拓展欄位01
              "extParam2": "拓展參數列頭002", //在效果分析中展示的列名,拓展欄位02
              "extParam3": "拓展參數列頭003" //在效果分析中展示的列名,拓展欄位03
            }
        }
    }
}

2.1.2 iframe 跳轉

需要外部系統提供一個 iframe 頁面,頁面連結在上一步配置的endpoint中填寫。

注意:會存在跨域問題,需要增加跨域支援,X-Frame-Options: allow-from https://example.com/

跳轉 URL

/endPoint?comeFrom=xxx&qaEndpoint=xxx&token=xxx

返回結果

{
  "success":true,
  "errorDesc":"錯誤資訊,可以為空白"
}

2.1.3 API 介面:通過令牌擷取使用者資訊

API:/openapi/v3/account/query?token=xxx

傳回值:

{
  "success": false,
  "errorDesc": "",
  "data": {
    "organizationId":"組織 ID",
    "organizationName":"組織名稱",
    "userId":"使用者識別碼",
    "nickName":"使用者暱稱",
  },
  "@comment": {
    "success": "/**\n     * 枚舉值:true | false\n     */",
    "errorDesc": "/**\n     * 錯誤資訊描述\n     */",
    "data": "/**\n     * 使用者資訊\n     */"
  }
}

只有成功擷取到使用者資訊,才說明正常可用,如果未擷取到使用者資訊,渲染頁面時應該返回 token 失效錯誤資訊。

2.1.4 API 介面:儲存UDF選擇的人群、事件 id 等

API:/restapi/marketing/udf_component/genUdfComponentNode

入參

{
    "componentId": "1001",
    "sourceId": "c1f5691dd5864479820c10c0089bece9 (這裡傳人群 id,事件 id)",
    "sourceNodeId": "",
    "nodeId": "83a2d328-030d-436a-b607-21da8ee2e34b",
    "sourceType": 1  // 這裡傳類型,1是人群 2是事件
}

傳回值

{
    "data": {
        "nodeId": "83a2d328-030d-436a-b607-21da8ee2e34b",
        "token": "zKBfv7flRQmhd+XP1l1uuKCjE6seEOq8l02cBFWWRr5xQoOUPxb3+tj+ZPctWDG4rM5vC2PMQLxG0Xw7Qw6TpsDfXSYFwD8kmTjpUOV4AjxQfZPfC5q0wPrEFhvgfjz9X1OKDu4V4p1oJnJcbt5nELidsVk6jxkbVwHEL8ezXcyXFRKbC+jVYxOwG5ElUhS0+hraAK5IiwR1XgZCarFgOGf5ZZo/Nacjrp5AP8HbF3tl4+thAjp8ZuMWTYXsBJbe"
    },
    "errorCode": null,
    "errorDesc": null,
    "exStack": null,
    "opers": [],
    "solution": null,
    "success": true,
    "traceId": "48d6e570-1918-47a4-83ee-27c3f32d3a99"
}

2.1.5 API 介面:通過令牌擷取人群標籤列表/事件屬性列表 (依賴2.1.4)

API:/openapi/v3/udf_component/marketing/getNodeUsableLabels?token=xxx&nodeId=xxx&version=VERSION_2

傳回值:

[
    {
        "id": "標籤ID/屬性ID",
        "name": "標籤名稱/屬性名稱"
    }
]

選擇的標籤/屬性會在最終外調三方系統的時候作為參數傳入。

2.1.6 前端提交資料到iframe嵌入頁面中的 API

該頁面參數由三方自行定義,最終執行時,由 QA 調用到三方後,三方自行執行。但需要將選中的 QA 標籤通過⑥的介面回傳給 QA。

2.1.7 提交 UDF 配置資訊(依賴2.1.5)

API:/openapi/v3/udf_component/marketing/saveOrUpdateNodeConfig?token=xxx

請求體:

{
  "nodeId": "節點ID",
  "nodeName": "節點名稱",
  "labelIdList": [
    "標籤ID.[name]",
    "標籤ID.[name]"
  ]
}

傳回值:無傳回值,判斷 HTTP 狀態200即可

三、UDF執行接入文檔

系統流轉圖如下所示

image.png

3.1 節點執行請求

為了與Quick Audience對接,您需要開發一個HTTP Server。注意是Post請求,請求逾時時間為10秒。Quick Audience發起的請求和接入方回執請求約定如下通用參數,為必傳項。

請求URL:{UDF配置的 sendParam.batchSendUrl }

請求Header資訊

Header資訊讀取後需要通過java.net.URLDecoder#decode(java.lang.String, java.lang.String),編碼為UTF-8。

v=4 // 固定參數,用於區分新老版本,新版本為4,老版本沒有這個欄位

請求體

請求入參

備忘

參數

參數

類型

是否必須

請求時間戳記

time

Long

請求ID

requstId

String

組件ID

componentId

String

組件accessKey

accessKey

String

AES密鑰長度可以為128、192或256位,對應字元為16、24、32位。

訊息體密碼編譯演算法

encryptionMethod

String

預設不加密 null

目前僅支援AES 加密,加密和填充方式為:AES/ECB/PKCS5Padding

簽名

signature

String

time +

componentId +

accessKey + accessSecret 經過hmac 加密後

註:簽名演算法和 WebHook 一樣。

訊息體

data

String

經過encryptionMethod加密後訊息體:

  • processId=旅程ID

  • processName=旅程名稱

  • processSchedulerId=旅程每次周期調度的ID

  • processSchedulerName=旅程每次周期調度的名稱:旅程ID+周期的時間拼接字串

  • processSchedulerStartTime=旅程周期開始時間,時間戳記格式

  • processNodeId=旅程節點ID(每個周期的節點ID都是一樣的)

  • processNodeName=旅程節點名稱(每個周期的節點ID都是一樣的)

  • batchId=批次號,每批次調用的時候唯一ID,可做批次等冪ID(2022年07月07日增加)

  • activityId=營銷日曆活動ID

  • activityName=營銷日曆活動名稱

  • subActivityId=營銷日曆子活動ID

  • subActivityName=營銷日曆子活動名稱

  • v=4 // 固定參數,用於區分新老版本,新版本為4,老版本沒有這個欄位

  • jobId=廢棄:等於processId,推薦用processId

  • jobName=廢棄:等於processName,推薦用processName

  • nodeId=廢棄:等於processNodeId,推薦用processNodeId

  • nodeName=廢棄:等於processNodeName,推薦用processNodeName

  • taskStartTimestamp=廢棄:等於processSchedulerStartTime,是時間戳記格式,推薦用processSchedulerStartTime

  • processInstanceId=廢棄:相容老版本:等於processSchedulerId

  • processInstanceName=廢棄:相容老版本:等於processSchedulerName

  • processInstanceStartTime=廢棄:相容老版本:等於processSchedulerStartTime

  • taskId=無此欄位,等於processNodeInstanceId,無法相容

  • processNodeInstanceId=無此欄位,無法相容

  • processNodeInstanceStartTime=無此欄位,無法相容

  • nodeStartTimestamp=無此欄位,等於processNodeInstanceStartTime,無法相容

  • data

  • messageId 訊息id

  • customerList 數組

    • customerId使用者id

    • labels => {"$labelId":"$labelValue"} 標籤列表,map格式

    • featureMap => [{"key","value"},{"key","value"}] //featureMap在回執時必須帶回,作為回執參數

    • processInfo => 如下描述

  • idMappings

    QA會將目前使用者的ID都放到該欄位中下發,JSON格式。

請求體樣本:

{
  "time": 0,
  "requestId": "111",
  "componentId": "111",
  "accessKey": "111",
  "signature": "111",
  "encryptionMethod": [
    "AES"
  ],
  "data": "字串格式,詳細格式如下"
}

// data 的格式
{
    "jobId": "",
    "jobName": "",
    "nodeId": "",
    "nodeName": "",
    "componentName": "",
    "taskId": "",
    "taskStartTimestamp": 0,
    "nodeStartTimestamp": 0,
    "data": {
      "messageId": "",
      "customerList": [
        {
          "customerId": "",
          "featureMap": {
            "回執欄位":"原樣帶回"
          },
          "idMappings": {
                    "mobile": "手機號碼",//舉例的ID類型,如果有其他類型也會一起下發
                    "qaid": "QA產生的QAID"
                },
                "labels": {},
          "processInfo": {
            "processInstanceId": "新版:旅程周期中,每個使用者的旅程執行個體ID",
            "processInstanceStartTime": "新版:旅程周期中,每個使用者的旅程執行個體開始時間,時間戳記格式",
            "processNodeInstanceId": "新版:旅程節點執行個體ID(每次不同)",
            "processNodeInstanceStartTime": "新版:旅程周期中,每個使用者的旅程的節點執行個體開始時間,時間戳記格式",
            "groupName":"nodeId:nodeName:groupResult(node.result),groupName(node.resultExt);nodeId:nodeName:groupResult(node.result),groupName(node.resultExt)",
            "@comment":{
              "groupName" : "節點id:節點名稱(介面配置的):分組結果(隨機分組的百分比數字,兩位小數):分組名稱(介面配置的);多個用分號隔開"
            }
        	}
          "@comment": {
            "featureMap": "/**\n         * 拓展欄位,非同步回執時下遊必須帶回\n         */"
          }
        }
      ]
    },
    "activityId": "",
    "activityName": "",
    "subActivityId": "",
    "subActivityName": "",
    "processId": "",
    "processName": "",
    "processInstanceId": "",
    "processInstanceName": "",
    "processInstanceStartTime": "",
    "processNodeId": "",
    "processNodeName": "",
    "processNodeInstanceId": "",
    "processNodeInstanceStartTime": "",
    "groupId": "",
    "groupName": "",
    "@comment": {
      "activityId": "/**\n     * 活動ID\n     */",
      "activityName": "/**\n     * 活動名稱\n     */",
      "subActivityId": "/**\n     * 子活動ID\n     */",
      "subActivityName": "/**\n     * 子活動名稱\n     */",
      "processId": "/**\n     * 旅程ID(自動化ID);活動ID\n     */",
      "processName": "/**\n     * 旅程名稱(自動化名稱);活動名稱\n     */",
      "processInstanceId": "/**\n     * 旅程執行個體ID;活動執行個體ID\n     */",
      "processInstanceName": "/**\n     * 活動執行個體名稱(有執行個體的時間)\n     */",
      "processInstanceStartTime": "/**\n     * 活動執行個體開始時間\n     */",
      "processNodeId": "/**\n     * 活動節點ID\n     */",
      "processNodeName": "/**\n     * 活動節點名稱\n     */",
      "processNodeInstanceId": "/**\n     * 活動節點執行個體ID\n     */",
      "processNodeInstanceStartTime": "/**\n     * 活動節點執行個體開始時間\n     */",
      "groupId": "/**\n     * ABTest分組ID(暫未實現,為空白)\n     */",
      "groupName": "/**\n     * ABTest分組名稱(暫未實現,為空白)\n     */"
    }
  }

傳回值

{
  "success": true,
  "errorDesc": "錯誤資訊",
  "customerList": [
    {
      "messageId": "訊息 ID",
      "customerId": "客戶 ID",
      "returnType": "回執結果,該結果和回執結果一樣,如果有則直接當做回執結果,如果不希望直接填寫回執結果,不要傳遞",
      "returnMessage": "回執訊息,長度限制255,超過會自動截取掉"
    }
  ]
}

3.1.1 鑒權方式

簽名演算法

long sendTime = System.currentTimeMillis();
// 組件id
// 組件ak
// 組件sk

String sign = getSignatureByHmacSHA1(sendTime, componentModel.getComponentId(), componentModel.getAccessKey(), componentModel.getAccessSecret());

public static String getSignatureByHmacSHA1(long time, String prametersString, String accessKey, String accessSecret) {
    String str = time + prametersString + accessKey;
    return HmacUtils.hmacSha256Hex(accessSecret, str.replaceAll("\\s+", ""));
}

3.2回執上報

接入方執行營銷任務後,向Quick Audience上報回執,反饋營銷訊息的發送結果。

HTTP請求URL

API:/restapi/marketing2/udfComponent/receiveCallback?

請求體

{
  "time": 0,
  "componentId": "UDF組件ID",
  "signature": "簽名",
  "data": "加密後回執資訊,字串",
  "@comment":{
    "time":"回執時間戳記,毫秒"
  }
}

// data的原始格式
{
  "nodeId": "節點ID",
  "taskId": "任務ID",
  "customerList": [
    {
      "messageId": "訊息 ID",
      "customerId": "客戶 ID",
      "returnType": "回執結果",
      "sendTimestamp": 0,
      "featureMap": {
        "請求參數": "原樣回傳回來"
      }
      "@comment": {
        "messageId": "/**\n         * 訊息ID,QA推送的時候  會帶上這個ID\n         */",
        "customerId": "/**\n         * 使用者ID\n         */",
        "returnType": "/**\n         * 回執結果\n         */",
        "sendTimestamp": "/**\n         * 訊息推送時間\n         */",
        "featureMap": "發送請求時的參數,需要在回執時原樣帶回來"
      },
      "extParam1": "拓展參數001-自訂傳回值",
      "extParam2": "拓展參數002-自訂傳回值",
      "extParam3": "拓展參數003-自訂傳回值"
    }
  ],
  "@comment": {
    "nodeId": "/**\n     * 節點ID\n     */",
    "taskId": "/**\n     * 任務ID\n     */",
    "customerList": "/**\n     * 回執使用者/粉絲列表\n     */"
  }
}

傳回值:

{
  "success": true,
  "errorDesc": "",
  "@comment": {
    "success": "/**\n     * 枚舉值:true | false\n     */",
    "errorDesc": "/**\n     * 錯誤資訊描述\n     */",
    "data": "/**\n     * 使用者資訊\n     */"
  }
}