一站式应用与数据集成平台(iPaaS) - 数环通

立即注冊

連接器配置

1. 連接器定義

1.1 授權定義

  • auth:連接器調用對應SaaS軟件的授權方式,授權的定義是一個對象,當沒有授權時可以為空

    • authType  授權類型,是第三方SaaS軟件驗證數環(huán)通權限的方式,目前主要有以下幾種類型

      • api_token 通過AppKey + AppSecret 直接訪問或者通過AppKey + AppSecret 換取AccessToken進行調用第三方SaaS的API接口,典型的SaaS有:自建釘釘,維格表等

      • oauth2 數環(huán)通作為第三方SaaS的平臺服務商申請AppKey+ AppSecret, 用戶通過授權數環(huán)通,由數環(huán)通獲取用戶的授權AccessToken調用第三方SaaS的API接口,典型的SaaS有:企業(yè)微信三方,釘釘三方

        • polling_oauth2 數環(huán)通作為第三方SaaS的平臺服務商申請AppKey+ AppSecret, 用戶通過授權數環(huán)通,由數環(huán)通獲取用戶的授權AccessToken調用第三方SaaS的API接口,但是與Oauth2 的區(qū)別在于,用戶的授權信息是通過后端服務接口進行推送的,典型的SaaS有:聚水潭

  • test 測試輸入賬號有效性的執(zhí)行方法,主要是在新增賬號時調用,用于驗證用戶輸入的數據是否有效,具體執(zhí)行方法的定義參考執(zhí)行方法定義

  • validate 驗證當前賬號的授權有效性的執(zhí)行方法,主要是在賬號新增賬號成功后調用,用于驗證當前授權信息如AccessToken等是否是有效狀態(tài),具體執(zhí)行方法的定義參考執(zhí)行方法定義

  • apiTokenConfig api_token類型的配置

    • autoRefresh 是否需要自動刷新,Boolean類型

      • true 需要刷新,需要配置refreshAccessToken

      • false 不需要自動刷新,AccessToken 是永久有效的

    • autoRefreshInterval 自動刷新的間隔,Integer類型 單位秒 例如3600 表示每小時刷新一次token

    • accessToken 獲取AccessToken的執(zhí)行方法

    • refreshAccessToken 刷新AccessToken的執(zhí)行方法

  • oauth2Config oauth2 和 polling_oauth2的授權配置

    • autoRefresh 是否需要自動刷新,Boolean類型

      • true 需要刷新,需要配置refreshAccessToken

      • false 不需要自動刷新,AccessToken 是永久有效的

    • autoRefreshInterval 自動刷新的間隔,Integer類型 單位秒 例如3600 表示每小時刷新一次token

    • preAuthorize 獲取授權鏈接前執(zhí)行方法列表,例如獲取預授權碼

    • authorizeUrl 獲取授權鏈接的執(zhí)行方法

    • accessToken 獲取AccessToken的執(zhí)行方法

    • refreshAccessToken 刷新AccessToken的執(zhí)行方法

  • thirdAuthConfig third_auth類型的配置

    • autoRefresh 是否需要自動刷新,Boolean類型

      • true 需要刷新,需要配置refreshAccessToken

      • false 不需要自動刷新,AccessToken 是永久有效的

    • autoRefreshInterval 自動刷新的間隔,Integer類型 單位秒 例如3600 表示每小時刷新一次token

    • accessToken 獲取AccessToken的執(zhí)行方法

    • refreshAccessToken 刷新AccessToken的執(zhí)行方法

  • helpFields 顯示提示幫助的字段列表,如提示用戶如何進行配置賬號和事件訂閱

  • inputFields 用戶需要輸入的參數字段列表,例如Appkey,AppSecret等,具體的字段配置參考字段定義

  • outputFields 保存到數據的參數列表,具體的字段配置參考字段定義

授權類型的說明:

api_token類型的授權流程:

oauth2 授權流程:

polling_oauth2 類型授權流程:

 

1.2 賬號定義

  • asset:連接器的賬號配置,主要是配置授權的哪些數據需要保存到賬號資產的數據庫中

    • autoRefresh 是否需要自動刷新,Boolean類型,需要與授權定義中保持一致

      • true 需要刷新,需要配置refreshAccessToken

      • false 不需要自動刷新,AccessToken 是永久有效的

    • autoRefreshInterval 自動刷新的間隔,Integer類型 單位秒 例如3600 表示每小時刷新一次token

    • assetTemplate 保存的字段列表,用于定義哪些字段需要存進賬號資產中

    • assetNameField 賬號名稱字段

    • assetUkField 賬號唯一性標識字段

 

1.3 模板配置

  • requestTemplate:連接器的請求模板配置,主要是配置當前連接器發(fā)起Http請求時的公共參數,如appKey,簽名配置等公共的配置,可以減少請求的配置

    • method 發(fā)起請求的方法,支持以下選項

      • GET

      • PUT

      • POST

      • PATCH

      • DELETE

      • HEAD

    • url 請求的完整地址

    • body 請求body配置

      • bodyType  請求體類型

        • NULL 為空

        • STRING 字符串

        • ARRAY 數組

        • OBJECT JSON對象類型

        • XML XML格式

      • bodyContent 請求體內容,根據bodyType傳入具體的值

    • queryParams 查詢請求參數,KV形式

    • formParams  表單請求參數,KV形式

    • headers 頭部請求參數

    • signConfig 簽名配置

      • signType 簽名類型,簽名的實現,目前可以使用簽名腳本類型

        • script 通過簽名腳本進行簽名

      • signOutField 簽名輸出字段

      • signInField 簽名字段參數,KV形式

      • signSetting 簽名配置,針對腳本簽名需要增加以下參數

        • connectorId 連接器ID

        • scriptType 腳本類型

        • sceneCode 場景編碼

        • version 腳本版本

    • responseType 請求返回值類型,默認按照STRING處理

      • BINARY 二進制

      • JSON JSON格式

      • STRING 純文本格式

    • beforeRequest 請求前執(zhí)行方法列表,一般用于對請求參數進行處理

    • afterResponse 請求后執(zhí)行方法列表,一般用于對于返回數據進行處理

  • triggerTemplate:消息通知和回調的配置。主要是配置當前連接器接收平臺Http請求時的參數,可用來做觸發(fā)器配置

    • pushUrl:消息推送回調地址。如:${eventDomainHost}/event/customPush/com.yuque.app/${assetId}/test

      • com.yuque.app 為連接器ID,用戶務必配置為當前連接器的ID

      • test 為用戶自定義參數

    • pushExecutor:推送數據的腳本配置

      • executeType:執(zhí)行類型。設置為script

      • connectorId:當前連接器的ID

      • connectorVersion:當前連接器的版本

      • sceneCode:場景碼。這里設置為dealPushEventContent

      • type:腳本類型。可選擇java,js,pythone

      • version:腳本的版本號。可設置為1~9

1.4 觸發(fā)器

  • triggers 觸發(fā)器列表,用于觸發(fā)器定義,觸發(fā)器列表是個KV列表,其中Key是觸發(fā)器的關鍵字定義,Value是一個觸發(fā)器定義

    • key 用于唯一標識觸發(fā)器

    • value 觸發(fā)器的具體定義

觸發(fā)器對象的定義:

  • key 觸發(fā)器的key 和前文的key 保持一致

  • paramClass 參數對象類型,主要為了以后對參數映射進行擴展使用,當前暫時可以不配置

  • resultClass 結果對象類型,主要為了以后對參數映射進行擴展使用,當前暫時可以不配置

  • resultIsList 結果是否是一個數組列表,此處主要針對的是一級結果,默認為false

    • true 表示結果是一個數組列表

    • false 表示結果不是一個數組列表

  • display 展示配置,用于前端頁面展示觸發(fā)器的名稱等信息m

    • label 觸發(fā)器展示的名稱

    • description 觸發(fā)器的描述信息

    • directions 鏈接信息,可以設置為該觸發(fā)器的來源頁面地址

    • important 是否置頂,默認為false

      • true 表示需要置頂

      • false 表示不需要置頂

    • hidden 是否隱藏,當設置為true時前端不展示該觸發(fā)器,默認為false

      • true 表示需要隱藏

      • false 表示不需要隱藏

  • triggerMode 觸發(fā)器的模式,主要是定義觸發(fā)器的數據來源,目前的選項有:輪詢和事件觸發(fā)

    • polling 通過輪詢方式查詢數據,一般是通過時間來查詢某個列表

    • pushing 事件或者消息來源,一般是第三方SaaS通過配置回調接口,進行事件推送

  • triggerConfig 觸發(fā)器配置,主要是針對輪詢方式的觸發(fā)器的配置

    • cron 輪詢的時間表達式,

    • outOfFrequencyControl 配置為true cron表達式才生效,否則會根據用戶版本設置輪訓周期

    • startTime 開始觸發(fā)的時間

    • ukFields 唯一標識記錄的字段列表,主要用于標識該條記錄有沒有觸發(fā)過

    • supportPaging 是否支持分頁,支持分頁時需要

      • true 支持

      • false 不支持

    • pageSize 分頁大小設置

    • pageSizeField 分頁大小對應的字段名稱

    • pageIndexField 分頁頁碼對應的字段名稱

  • operation 獲取觸發(fā)數據的執(zhí)行方法,對于輪詢的觸發(fā)器需要進行定義,事件觸發(fā)的無需定義,要求執(zhí)行方法返回的數據是數組

  • sample 獲取樣本數據的執(zhí)行方法,對于輪詢的觸發(fā)器需要進行定義,事件觸發(fā)的無需定義,要求執(zhí)行方法返回的數據是單個對象

  • beforeTrigger 觸發(fā)器執(zhí)行請求前執(zhí)行方法列表,一般用于對請求參數進行處理,beforeTrigger的執(zhí)行時機是在獲取到觸發(fā)事件的數據之后,進行流程觸發(fā)之前,對于事件觸發(fā)的是在收到第三方的事件觸發(fā)之后,對于輪詢觸發(fā)的是在執(zhí)行輪詢operation,獲取到單個對象之后

  • afterTrigger 觸發(fā)器后執(zhí)行方法列表,一般用于對于返回數據進行處理,執(zhí)行時機是在發(fā)出觸發(fā)事件之后

1.5 執(zhí)行器

  • operations 執(zhí)行器列表,用于執(zhí)行器定義,執(zhí)行器列表是個KV列表,其中Key是執(zhí)行器的關鍵字定義,Value是一個執(zhí)行器定義

  • key 用于唯一標識執(zhí)行器

  • value 執(zhí)行器的具體定義

執(zhí)行器對象的定義:

  • key 執(zhí)行器的key 和前文的key 保持一致

  • paramClass 參數對象類型,主要為了以后對參數映射進行擴展使用,當前暫時可以不配置

  • resultClass 結果對象類型,主要為了以后對參數映射進行擴展使用,當前暫時可以不配置

  • resultIsList 結果是否是一個數組列表,此處主要針對的是一級結果,默認為false

    • true 表示結果是一個數組列表

    • false 表示結果不是一個數組列表

  • hidden 是否隱藏,當設置為true時前端不展示該執(zhí)行器,默認為false

    • true 表示需要隱藏

    • false 表示不需要隱藏

  • display 展示配置,用于前端頁面展示執(zhí)行器的名稱等信息

    • label 執(zhí)行器展示的名稱

    • description 執(zhí)行器的描述信息

    • directions 鏈接信息,可以設置為該執(zhí)行器的來源頁面地址

    • important 是否置頂,默認為false

      • true 表示需要置頂

      • false 表示不需要置頂

  • categoryName 分類名,把同一類的放在一個組下,如 訂單、商品、

  • operation 執(zhí)行器的請求定義,在此定義執(zhí)行器方法(具體定義看 3.8 執(zhí)行方法定義)

  • inputFields 執(zhí)行器輸入字段定義

  • outputFields 執(zhí)行器輸出字段定義

  • tags 該執(zhí)行器的備注信息

1.6 執(zhí)行方法定義

執(zhí)行方法是引擎支持的某個具體的執(zhí)行定義,當前支持4種類型,分別為:

  • request 請求類型

  • function 函數類型

  • dependency 依賴類型

  • script 腳本類型

根據每個類型有具體的定義:

1.6.1 請求類型

請求類型是指主體功能是調用HTTP API

 

  • executeType: request  請求類型

  • method 發(fā)起請求的方法,支持以下選項

    • GET

    • PUT

    • POST

    • PATCH

    • DELETE

    • HEAD

  • url 請求的完整地址

  • body 請求body配置

    • bodyType  請求體類型

      • NULL 為空

      • STRING 字符串

      • ARRAY 數組

      • OBJECT JSON對象類型

      • XML XML格式

    • bodyContent 請求體內容,根據bodyType傳入具體的值

  • queryParams 查詢請求參數,KV形式

  • formParams  表單請求參數,KV形式

  • headers 頭部請求參數 (在此定義優(yōu)先級高于requestTemplate中的定義)

  • signConfig 簽名配置

    • signType 簽名類型,簽名的實現,目前可以使用簽名腳本類型

      • script 通過簽名腳本進行簽名

    • signOutField 簽名輸出字段

    • signInField 簽名字段參數,KV形式

    • signSetting 簽名配置,針對腳本簽名需要增加以下參數

      • connectorId 腳本連接器ID

      • scriptType 腳本類型

      • sceneCode 場景編碼version 腳本版本

  • beforeRequest 請求前執(zhí)行方法列表,一般用于對請求參數進行處理

  • afterResponse 請求后執(zhí)行方法列表,一般用于對于返回數據進行處理

 

1.6.2 函數類型

函數類型是指調用一個內置類的函數,或者內置表達式

  • executeType  function  函數類型

  • isExpress 是否是表達式

    • true 是 執(zhí)行的是內置表達式

    • false 否 執(zhí)行的是類方法

  • providerClass 執(zhí)行類的全路徑,isExpress 為false時必填

示例:

? "providerClass":"com.shuhuan.ipaas.connector.spi.yunpian.InputAndOutputBuilder"

  • function 執(zhí)行的具體方法,對于表達式來說是具體的表達式,對于執(zhí)行類方法時是類的方法,對于是表達式時是具體的表達式

示例:

? "function":"generateTemplateContentInput"

? "function":"${assert:equals(0,object:eval(body, '/msg'))}"

  • paramsExpression 參數表達式,對于執(zhí)行類方法時傳入

  • returnType 返回值類型

    • VOID 無返回值

    • STRING 字符串

    • BOOLEAN 布爾值

    • NUM 數字

    • INT 整形數字

    • ARRAY 數組或者列表

    • OBJECT 對象或者Map類型

  • returnItemType 返回列表的數據類型,returnType是ARRAY時需要

    • VOID 無返回值

    • STRING 字符串

    • BOOLEAN 布爾值

    • NUM 數字

    • INT 整形數字

    • ARRAY 數組或者列表

    • OBJECT 對象或者Map類型

1.6.3 依賴類型

依賴類型是指可以調用一組已經配置的執(zhí)行動作,并做一些數據處理

  • executeType  dependency  依賴類型

  • dependencyOperationKeys 依賴的執(zhí)行動作的Key列表

示例:

? "dependencyOperationKeys": ["getUidByMobile", "getUserDetailByUserId"]

  • afterResponse 所有依賴的執(zhí)行動作執(zhí)行完成后執(zhí)行方法列表,一般用于對于返回數據進行處理

 

1.6.4 腳本類型

腳本類型是指執(zhí)行一個腳本

  • executeType  script  腳本類型

  • connectorId 腳本對應的連接器ID

  • sceneCode 腳本場景碼,用來標識該腳本應用場景

  • type 腳本類型

    • java

    • js

    • python

  • version 腳本版本

  • paramsExpression 執(zhí)行的參數表達式,表達式為空時將會將整個參數上下文傳入,不為空時計算完成表達式后傳入

  • returnType 返回值類型

    • VOID 無返回值

    • STRING 字符串

    • BOOLEAN 布爾值

    • NUM 數字

    • INT 整形數字

    • ARRAY 數組或者列表

    • OBJECT 對象或者Map類型

  • returnItemType 返回列表的數據類型,returnType是ARRAY時需要

    • VOID 無返回值

    • STRING 字符串

    • BOOLEAN 布爾值

    • NUM 數字

    • INT 整形數字

    • ARRAY 數組或者列表

    • OBJECT 對象或者Map類型

1.7 字段定義

  • key 用于該執(zhí)行方法中唯一標識字段

  • label 展示配置,用于前端頁面展示字段名稱

  • helpText 幫助信息,作為輸入字段時需要,非必要不填寫

  • placeholder 輸入框提示信息,作為輸入字段時需要

  • type 字段類型

  • widget 前端控件widgetConfig 配置說明文檔

  • widgetConfig 前端組件的配置 KV形式

  • required 是否為必填選項,作為輸入字段時需要

    • true 必填

    • false 選填

  • defaultValue 默認值

  • supportMultiple 是否支持多選,默認false(搭配選擇控件時使用)

    • true 支持

    • false 不支持

  • datasource 可選數據源,KV形式

    • label 展示鍵

    • value 實際值

  • dynamicDataSource 動態(tài)數據源 動態(tài)數據路由

    • routerType 動態(tài)類型

      • beforeRequest 在請求之前

      • afterRequest 在請求響應之后

      • constant 常量

    • condition 判斷是否符合路由條件

    • params  執(zhí)行動態(tài)數據源的參數列表

    • selectCondition 判斷是否可選的條件表達式

    • deepCondition 判斷是否可下拉的條件表達式

    • refOperation 獲取動態(tài)數據源的執(zhí)行動作 

    • refLabel 動態(tài)label的取值方式

    • refValue  動態(tài)value的取值方式

    • router 下級的路由規(guī)則

    • datasource 靜態(tài)數據源,routerType 為constant時設置

  • dynamicFields 動態(tài)字段 dynamicFields

    • routerType 動態(tài)類型

      • beforeRequest 在請求之前

      • afterRequest 在請求響應之后

      • constant 常量

    • condition 判斷是否符合路由條件

    • params 參數列表

    • refOperation 獲取動態(tài)字段的執(zhí)行動作 

    • refInputFields 動態(tài)輸入字段的取值表達式

    • refOutputFields 動態(tài)輸出字段的取值表達式

    • inputFields 對于routerType 是constant時設置

    • outputFields 對于routerType 是constant時設置

  • childrenType 子節(jié)點類型

  • children 子節(jié)點

2.簽名腳本開發(fā)

在應用shuhuan-ipaas-app-libs的signer目錄下開發(fā)簽名類,簽名算法改成通過java執(zhí)行腳本的方案實現簽名算法,簽名類需要繼承JavaScriptRunner類重寫execute方法    

/**
 * @author yunmu
 * @date 2022-03-04 6:44 下午
 */
public abstract class JavaScriptRunner {

    public abstract <T> T execute(Object params);
}

params 是一個Map對象,Map中會包含以下數據:

  • 上下文參數數據

  • signRequest 待簽名的http請求獲取方式:

HttpApiRequest apiRequest = (HttpApiRequest) paramsMap.get(SignConfigConstant.SIGN_REQUEST);
  • 簽名配置中的signInField 中的信息

  • signOutField 簽名的輸出字段

簽名腳本示例:

package com.shuhuan.ipaas.applibs.signer;

import com.aliyun.unicorn.http.MultipartFormData;
import com.aliyun.unicorn.http.MultipartFormValue;
import com.aliyun.unicorn.http.QueryString;
import com.aliyun.unicorn.sdk.HttpApiRequest;
import com.aliyun.unicorn.type.Consumer;
import com.aliyun.unicorn.type.Parameter;
import com.shuhuan.ipaas.common.ResultCode;
import com.shuhuan.ipaas.core.encryption.Md5Util;
import com.shuhuan.ipaas.exception.IpaasException;
import com.shuhuan.ipaas.meta.constants.SignConfigConstant;
import com.shuhuan.ipaas.script.java.JavaScriptRunner;
import org.apache.commons.lang3.StringUtils;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;

/**
 * @author yunmu
 * @date 2022-03-05 4:22 下午
 */
public class BanniuScriptSigner extends JavaScriptRunner {

    private static final String METHOD = "method";
    private static final String ACCESS_TOKEN = "access_token";
    public static final String TIMESTAMP = "timestamp";
    private static final String SIGN = "sign";

    @Override
    public <T> T execute(Object params) {
        if (!(params instanceof Map)){
            throw new IpaasException(ResultCode.PARAM_ERROR, "params is not map");
        }
        Map<String,Object> paramsMap = (Map<String, Object>) params;
        HttpApiRequest apiRequest = (HttpApiRequest) paramsMap.get(SignConfigConstant.SIGN_REQUEST);
        String appKey = (String) paramsMap.get(SignConfigConstant.APP_KEY);
        String appSecret = (String) paramsMap.get(SignConfigConstant.APP_SECRET);

        QueryString queryString = apiRequest.getQueryString();

        TreeMap<String, String> pmap = new TreeMap<>();
        queryString.foreachValues((paramKey, value) -> {
            pmap.put(paramKey, value);
        });

        MultipartFormData formData = apiRequest.getForm();
        if (formData != null && !formData.isMultipart()) {
            apiRequest.getForm().foreach(new Consumer<Parameter<MultipartFormValue>>() {
                @Override
                public void accept(Parameter<MultipartFormValue> a) {
                    String v = a.getFirstValue() != null ? a.getFirstValue().getValue() : null;
                    if (METHOD.equals(a.getName())) {
                        pmap.put(METHOD, v);
                    }
                    if (ACCESS_TOKEN.equals(a.getName())) {
                        pmap.put(ACCESS_TOKEN, v);
                    }
                    if (TIMESTAMP.equals(a.getName())) {
                        pmap.put(METHOD, v);
                    }
                    if (ACCESS_TOKEN.equals(a.getName())) {
                        pmap.put(ACCESS_TOKEN, v);
                    }
                }
            });
        }

        String stringToSign = sign(pmap, appSecret);
        String signature = Md5Util.md5(stringToSign, "utf-8").toUpperCase();
        queryString.add(SIGN, signature);
        Map<String, String> resultMap = new HashMap<>();
        resultMap.put(SignConfigConstant.SIGNATURE, signature);
        resultMap.put(SignConfigConstant.STRING_TO_SIGN, stringToSign);
        return (T) resultMap;
    }

    // 代碼一, 簽名排序代碼.
    // pmap 為所有參數, TreeMap 表示為樹形結構的哈希容器
    // appSecret 班牛分配給您的密鑰
    private String sign(TreeMap<String, String> pmap, String appSecret) {
        StringBuilder sb = new StringBuilder(appSecret);
        Iterator i$ = pmap.entrySet().iterator();
        while (i$.hasNext()) {
            Map.Entry<String, String> entry = (Map.Entry) i$.next();
            String name = entry.getKey();
            String value = entry.getValue();
            if (StringUtils.isNoneEmpty(new String[]{name, value})) {
                sb.append(name).append(value);
            }
        }
        sb.append(appSecret);

        return sb.toString();
    }
}

 

3.觸發(fā)器腳本開發(fā)

編寫事件回調數據處理腳本。例如

  1. package com.shuhuan.ipaas.applibs.dealPushEventContent.caoliao;
    
    import com.alibaba.fastjson.JSON;
    import com.alibaba.fastjson.JSONObject;
    import com.google.common.collect.Lists;
    import com.shuhuan.ipaas.script.java.JavaScriptRunner;
    import lombok.extern.slf4j.Slf4j;
    
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    /**
     * 推送事件  數據處理
     * 文檔地址: https://cli.im/help/65847
     */
    @Slf4j
    public class caoliaoDemo extends JavaScriptRunner {
    
        private static final String EVENT_TYPE = "eventType";
    
        private static final String BODY = "body";
    
        private static final String EVENT_CONTENTS = "eventContents";
    
        private static final String EVENT_CONTENT = "eventContent";
    
        private static final String ASSET = "asset";
    
        private static final String RESULT = "result";
    
    
        @Override
        public <T> T execute(Object params) {
            return (T) buildPushEventOutput(params);
        }
    
        /**
         * @param params
    
         *
         * {
         *     "asset": {
         *     },
         *  "body": {
         *     "time": "2022-06-30 17:06:39",
         *     "event": "FORM_DATA_SUBMIT",
         *     "data": {
         *         "ref_data": {
         *             "created_at": "2022-06-30 17:06:39",
         *             "serial_number": "L1000001",
         *             "form": {
         *                 "number": "D20",
         *                 "name": "會議簽到"
         *             },
         *             "fields": {
         *                 "姓名": "草料",
         *                 "手機": "18888648888",
         *                 "微信名": "CHEN",
         *                 "身份證號": "330200000000000000",
         *                 "工號": "FBI100",
         *                 "單選項": "是"
         *             }
         *         }
         *     }
         * }
         *
         *
         * @return
         * {
         *     "result": {
         *         "code": 200,
         *         "message": "success"
         *     },
         *     "eventContents": [
         *         {
         *             "eventType": "FORM_DATA_SUBMIT",
         *             "eventContent": {
         *                 "ref_data": {
         *                     "created_at": "2022-06-30 17:06:39",
         *                     "serial_number": "L1000001",
         *                     "form": {
         *                         "number": "D20",
         *                         "name": "會議簽到"
         *                     },
         *                     "fields": {
         *                         "姓名": "草料",
         *                         "手機": "18888648888",
         *                         "微信名": "CHEN",
         *                         "身份證號": "330200000000000000",
         *                         "工號": "FBI100",
         *                         "單選項": "是"
         *                     }
         *                 }
         *             }
         *         }
         *     ]
         * }
         */
        public static JSONObject buildPushEventOutput(Object params) {
            JSONObject output = new JSONObject();
            if (!(params instanceof Map)) {
                log.error("當前腳本入參類型錯誤!期望是Map,但是實際為{},具體值為{}", params.getClass().getName(), JSON.toJSONString(params));
                return output;
            }
            JSONObject input = (JSONObject) params;
    
            /**
             * 這里的事件內容的數據類型,有可能是數組,也可能是對象,具體按照推送方格式為準,作匹配的處理:
             * 1.解密(不是所有的消息都需要做)
             * 2.獲取事件的標識
             * 3.將事件標識轉換為觸發(fā)器的key
             * 4.構造接口返回,務必與推送方要求保持一致
             */
    
            List<JSONObject> eventContents = Lists.newArrayList();
            JSONObject data = (JSONObject) input.get(BODY);
            JSONObject item = new JSONObject();
            //2. 獲取對應事件的key。
            String event = (String) data.get("event");
            //3. 做觸發(fā)器的key與事件的key映射
            if ("FORM_DATA_SUBMIT".equals(event)) {
                item.put(EVENT_TYPE, "FORM_DATA_SUBMIT");
            } else if ("FORM_DATA_EDITED".equals(event)) {
                item.put(EVENT_TYPE, "FORM_DATA_EDITED");
            } else if ("FORM_DATA_REVIEW".equals(event)) {
                item.put(EVENT_TYPE, "FORM_DATA_REVIEW");
            }
            //4. 對應事件的輸出內容,與觸發(fā)器的輸出字段保持一致
            item.put(EVENT_CONTENT, JSON.parseObject(data.getString("data")));
            eventContents.add(item);
    
            output.put(EVENT_CONTENTS, eventContents);
    
    
            //推送事件后的響應結果,必須和推送方要求的返回結果一致
            Map<String, Object> result = new HashMap<>(16);
            result.put("code", 0);
            result.put("message", "success");
    
            output.put(RESULT, result);
            return output;
        }
    
    
    }
    

     

 

 

本篇目錄

{{item.innerText}}

{{item.categoryName}}
主站蜘蛛池模板: 無谷轻食官网_沙拉轻食加盟_轻食加盟总部_轻食加盟费用 | 长型材数控钻孔攻牙机-自动数控热熔钻孔机-东莞市利速数控机械有限公司 | 山东金起起重机械有限公司[官网]-金桥银路悬臂吊,金起龙门吊,山东金起起重行吊,单梁起重机 | 木材粉碎机,木头木材破碎机,大型木材粉碎机多少钱一台-晨红木材粉碎机厂家-巩义市晨红机械厂 | 无负压供水设备-杭州勤铭机电有限公司| 合肥食品检测-安徽卫生检测-水质检测机构-安徽金标准检测研究院有限公司 | 液压升降货梯_导轨式升降机_往复式提升机_济南宇轩机械厂家 | 泊头市天一泵业有限公司_齿轮泵,高粘度齿轮泵,螺杆泵,三螺杆泵 | 振动给料机_电磁振动给料机_振动给料机厂家-新乡市大汉振动机械有限公司 | 铸铁平台-铸铁平板平台厂家-加工优质高精度检验划线装配T型槽平台-尺寸规格全供应-建新铸造 | 梦想加空间 - 一个程序猿的个人博客网站 | 猪粪烘干机|小型鸡粪烘干机|猪粪烘干机价格|小型鸡粪烘干机价格 - 河南宏科重工干燥机设备生产厂家 | 橡塑保温材料_防火保温材料_保温棉_东莞康成保温材料有限公司 | 塑料检查井_双扣聚氯乙烯增强管_双壁波纹管-河南中盈塑料制品有限公司 | 面粉加工成套设备|面粉加工设备|面粉加工机械|面粉机组设备-河南成立粮油机械有限公司 | 无线对讲机系统-中继台-山区隧道信号覆盖-贝亚特 | 矿用精确定位系统,井下4G无线通讯系统,工作面集控系统,皮带保护系统-山东新云鹏电气有限公司 | 通用变频器|国产变频器|深圳变频器厂家-深圳市英捷思技术有限公司 | 美国Riverhawk轴承,Riverhawk十字弹簧轴承,Riverhawk联轴器,Riverhawk液压工具 | 中国建材信息总网-中国建材行业权威的信息资讯平台 | 廊坊金星化工有限公司-钢套钢保温管厂家,玻璃钢缠绕保温管,镀锌铁皮保温管厂家,廊坊金星化工有限公司 | 锯骨机-砍排机-全自动锯骨机-商用砍排机-切丁机 - 广州市九盈机械设备有限公司 | 湖州搬家公司_档案搬迁_货物运输_钟点搬运价格「湖州蓝天家政综合服务有限公司」 | 西安防静电地板_防静电地板厂家_防静电地板价格_OA网络地板_写字楼架空地板_机房墙板安装-红梅防静电地板厂家直销 | 形创(CREAFORM)3D扫描仪|三维检测|三维数字化处理|3D设备租赁|3D打印|——北京中显恒业仪器仪表有限公司 | 汽车衡,进口地磅,地磅厂家,无人值守称重系统丨青岛维特沃斯 | 新中式家具,广东新中式家具,广州新中式家具,佛山新中式家具,顺德新中式家具,乐从新中式家具,新中式家具厂家直销--唐明雅居 | 陕西筱润智能科技有限公司 干部人事智能档案柜 智能密集架 智能档案柜 部队选层文件智能柜 智能枪弹柜 财务智能档案柜 边防武警智能密集架 医院智能档案柜 部队选层文件智能柜智能枪弹柜 学校医院文件柜 企事业单位公检法智能文件柜 生产厂家-筱润智能科技有限公司 RFID射频智能密集架 全自动智能选层档案柜 智能密保柜 枪柜部队营房营具床桌椅办公家具 办公用品档案盒设备货架 全自动智能选层柜生产厂家-筱润智能科技有限公司 | 监控工程,安防监控公司,北京监控安装,北京安装监控,安装摄像头,北京监控维保,监控施工,北京监控维修,监控弱电工程,监控器安装,监控维护保养,监控工程设计,北京监控设备维修,监控报警安装,北京北方合力科技有限公司 | 清河县隆鑫密封件有限公司,汽车用密封条,配电箱柜、集装箱密封胶条,建筑门窗、家具用密封条,无毒环保医用密封条,船舶、农机用密封条,异型产品 | 开拓者喷雾设备有限公司专业生产喷嘴,喷雾设备,清洗,喷涂,降温,除尘,润滑等喷雾系统的方案解决商 | 企业微信注册_CRM客户管理系统_SCRM解决方案_私域流量运营_腾讯企点服务_企业QQ-腾辉网络 | 上海vi设计公司_logo设计_包装设计_品牌定位策划公司-焕识品牌设计 - | 金华美凡文化传媒有限公司| 胶球清洗-射水抽气器-磷酸盐加药装置-连云港振辉机械设备有限公司 | 限矩型液力偶合器_调速型液力偶合器_摩擦型耦合器生产厂家-河南省华升矿机有限公司 | 衡水物流网,衡水物流信息网,衡水物流公司,衡水货运专线,衡水专线运输车辆 | 山东日兴新材料股份有限公司| 清河县隆鑫密封件有限公司,汽车用密封条,配电箱柜、集装箱密封胶条,建筑门窗、家具用密封条,无毒环保医用密封条,船舶、农机用密封条,异型产品 | 陕西散花照明-西安太阳能路灯,陕西太阳能路灯,西安太阳能路灯厂家,陕西太阳能路灯厂家 | 浙江云野科技有限公司_智慧旅游规划_智慧景区管理系统_全域旅游解决方案-云野科技旅游大数据管理平台 |