產品介紹
什么是數環通
基礎概念講解
應用場景
多渠道數據融合
業務、財務、辦公自動化
產業鏈應用與數據集成
工業應用與設備互聯
智慧園區與未來社區
快速入門
創建LinkUp
應用授權
判斷用法
監控用法
分支用法
列表逐條處理
變量與表達式
流程管理
項目管理
流程創建
編輯器操作
單步測試與預覽
試運行
發布與版本管理
錯誤步驟重試
數據同步
JSON Path 使用
輸出處理
數據編排
1、功能使用手冊
2、腳本使用手冊
1 、簡單查詢
2、謂詞查詢
3、函數與表達式
4、構建結構結果
5、查詢組合
6、排序、分組和聚合
7、處理模型
8、函數式編程
9、正則表達式
10、日期、時間處理
11、路徑運算符
12、數字運算符
13、比較運算符
14、布爾運算符
15、其他運算符
16、字符串函數
17、數值函數
18、 數字聚合函數
19、布爾函數
20、數組函數
21、對象函數
22、日期/時間函數
23、高階函數
運行日志
運行記錄
開發工具
連接器工具
連接器源碼配置
控件類型配置
腳本配置說明
內置函數
應用講解
內置應用
瀏覽器插件
數據表
文本字符串
日期
數據篩選
數據處理
延時處理
數學計算器
定時觸發器
子流程調用
手動觸發器
物流地址解析
腳本執行器
自定義變量
文件讀取
Webhook
SMTP發送郵件
文件傳輸
JSON工具
網絡工具
消息處理
PDF水印工具
文件存儲
API服務
Http請求
循環控制
EDI 自定義標準數據轉換
對象類型判斷
瀏覽器操作
三方應用
簡道云
金山數據表
抖音
釘釘(自建應用)
語雀
金山表單
微信公眾號
企業微信群機器人
聚水潭
企業微信三方授權
MySQL
SqlServer
ChatGpt
快手
金山輕維表
抖店
維格表
巨量千川
飛書多維表
釘釘機器人
飛書(自建)
釘釘
百度網盤
QQ郵箱
金山工作表
易知微DTable
MQTT
Doirs
中通快遞
韻達速遞
企業微信(代開發)
知乎效果營銷平臺
飛書云文檔
騰訊企業郵箱
API管理
API管理概述
數據概覽
API服務
訪問憑證
API門戶
API安全密鑰簽名
API監控預警
擴展工具
代理網關
消息處理
管理中心
企業管理
操作日志
成員管理
開放平臺
開放平臺簡介
接入教程
常見問題
數環通ip白名單
最佳實踐
彥祖文化 |通過數環通實現全渠道數據融合打通
新石器|通過數環通實現跨系統、跨部門高效協同
幫助首頁
開發工具
連接器源碼配置
連接器源碼配置
# 1. 連接器定義 ## 1.1 授權定義 * auth:連接器調用對應 SaaS 軟件的授權方式,授權的定義是一個對象,當沒有授權時可以為空 * authType 授權類型,是第三方 SaaS 軟件驗證數環通權限的方式,目前主要有以下幾種類型 * api_token 通過 AppKey + AppSecret 直接訪問或者通過 AppKey + AppSecret 換取 AccessToken 進行調用第三方 SaaS 的 API 接口,典型的 SaaS 有:自建釘釘,維格表等 * oauth2 數環通作為第三方 SaaS 的平臺服務商申請 AppKey+ AppSecret, 用戶通過授權數環通,由數環通獲取用戶的授權 AccessToken 調用第三方 SaaS 的 API 接口,典型的 SaaS 有:企業微信三方,釘釘三方 * polling_oauth2 數環通作為第三方 SaaS 的平臺服務商申請 AppKey+ AppSecret, 用戶通過授權數環通,由數環通獲取用戶的授權 AccessToken 調用第三方 SaaS 的 API 接口,但是與 Oauth2 的區別在于,用戶的授權信息是通過后端服務接口進行推送的,典型的 SaaS 有:聚水潭  * test 測試輸入賬號有效性的執行方法,主要是在新增賬號時調用,用于驗證用戶輸入的數據是否有效,具體執行方法的定義參考執行方法定義 * validate 驗證當前賬號的授權有效性的執行方法,主要是在賬號新增賬號成功后調用,用于驗證當前授權信息如 AccessToken 等是否是有效狀態,具體執行方法的定義參考執行方法定義 * apiTokenConfig api_token 類型的配置 * autoRefresh 是否需要自動刷新,Boolean 類型 * true 需要刷新,需要配置 refreshAccessToken * false 不需要自動刷新,AccessToken 是永久有效的 * autoRefreshInterval 自動刷新的間隔,Integer 類型 單位秒 例如 3600 表示每小時刷新一次 token * accessToken 獲取 AccessToken 的執行方法 * refreshAccessToken 刷新 AccessToken 的執行方法 * oauth2Config oauth2 和 polling_oauth2 的授權配置 * autoRefresh 是否需要自動刷新,Boolean 類型 * true 需要刷新,需要配置 refreshAccessToken * false 不需要自動刷新,AccessToken 是永久有效的 * autoRefreshInterval 自動刷新的間隔,Integer 類型 單位秒 例如 3600 表示每小時刷新一次 token * preAuthorize 獲取授權鏈接前執行方法列表,例如獲取預授權碼 * authorizeUrl 獲取授權鏈接的執行方法 * accessToken 獲取 AccessToken 的執行方法 * refreshAccessToken 刷新 AccessToken 的執行方法 * thirdAuthConfig third_auth 類型的配置 * autoRefresh 是否需要自動刷新,Boolean 類型 * true 需要刷新,需要配置 refreshAccessToken * false 不需要自動刷新,AccessToken 是永久有效的 * autoRefreshInterval 自動刷新的間隔,Integer 類型 單位秒 例如 3600 表示每小時刷新一次 token * accessToken 獲取 AccessToken 的執行方法 * refreshAccessToken 刷新 AccessToken 的執行方法 * 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:連接器的請求模板配置,主要是配置當前連接器發起 Http 請求時的公共參數,如 appKey,簽名配置等公共的配置,可以減少請求的配置 * method 發起請求的方法,支持以下選項 * 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 請求前執行方法列表,一般用于對請求參數進行處理 * afterResponse 請求后執行方法列表,一般用于對于返回數據進行處理 * triggerTemplate:消息通知和回調的配置。主要是配置當前連接器接收平臺 Http 請求時的參數,可用來做觸發器配置 * pushUrl:消息推送回調地址。如:${eventDomainHost}/event/customPush/com.yuque.app/${assetId}/test * com.yuque.app 為連接器 ID,用戶務必配置為當前連接器的 ID * test 為用戶自定義參數 * pushExecutor:推送數據的腳本配置 * executeType:執行類型。設置為 script * connectorId:當前連接器的 ID * connectorVersion:當前連接器的版本 * sceneCode:場景碼。這里設置為 dealPushEventContent * type:腳本類型。可選擇 java,js,pythone * version:腳本的版本號。可設置為 1~9 ## 1.4 觸發器 * triggers 觸發器列表,用于觸發器定義,觸發器列表是個 KV 列表,其中 Key 是觸發器的關鍵字定義,Value 是一個觸發器定義 * key 用于唯一標識觸發器 * value 觸發器的具體定義 觸發器對象的定義: * key 觸發器的 key 和前文的 key 保持一致 * paramClass 參數對象類型,主要為了以后對參數映射進行擴展使用,當前暫時可以不配置 * resultClass 結果對象類型,主要為了以后對參數映射進行擴展使用,當前暫時可以不配置 * resultIsList 結果是否是一個數組列表,此處主要針對的是一級結果,默認為 false * true 表示結果是一個數組列表 * false 表示結果不是一個數組列表 * display 展示配置,用于前端頁面展示觸發器的名稱等信息 m * label 觸發器展示的名稱 * description 觸發器的描述信息 * directions 鏈接信息,可以設置為該觸發器的來源頁面地址 * important 是否置頂,默認為 false * true 表示需要置頂 * false 表示不需要置頂 * hidden 是否隱藏,當設置為 true 時前端不展示該觸發器,默認為 false * true 表示需要隱藏 * false 表示不需要隱藏 * triggerMode 觸發器的模式,主要是定義觸發器的數據來源,目前的選項有:輪詢和事件觸發 * polling 通過輪詢方式查詢數據,一般是通過時間來查詢某個列表 * pushing 事件或者消息來源,一般是第三方 SaaS 通過配置回調接口,進行事件推送 * triggerConfig 觸發器配置,主要是針對輪詢方式的觸發器的配置 * cron 輪詢的時間表達式, * outOfFrequencyControl 配置為 true cron 表達式才生效,否則會根據用戶版本設置輪訓周期 * startTime 開始觸發的時間 * ukFields 唯一標識記錄的字段列表,主要用于標識該條記錄有沒有觸發過 * supportPaging 是否支持分頁,支持分頁時需要 * true 支持 * false 不支持 * pageSize 分頁大小設置 * pageSizeField 分頁大小對應的字段名稱 * pageIndexField 分頁頁碼對應的字段名稱 * operation 獲取觸發數據的執行方法,對于輪詢的觸發器需要進行定義,事件觸發的無需定義,要求執行方法返回的數據是數組 * sample 獲取樣本數據的執行方法,對于輪詢的觸發器需要進行定義,事件觸發的無需定義,要求執行方法返回的數據是單個對象 * beforeTrigger 觸發器執行請求前執行方法列表,一般用于對請求參數進行處理,beforeTrigger 的執行時機是在獲取到觸發事件的數據之后,進行流程觸發之前,對于事件觸發的是在收到第三方的事件觸發之后,對于輪詢觸發的是在執行輪詢 operation,獲取到單個對象之后 * afterTrigger 觸發器后執行方法列表,一般用于對于返回數據進行處理,執行時機是在發出觸發事件之后 ## 1.5 執行器 * operations 執行器列表,用于執行器定義,執行器列表是個 KV 列表,其中 Key 是執行器的關鍵字定義,Value 是一個執行器定義 * key 用于唯一標識執行器 * value 執行器的具體定義 執行器對象的定義: * key 執行器的 key 和前文的 key 保持一致 * paramClass 參數對象類型,主要為了以后對參數映射進行擴展使用,當前暫時可以不配置 * resultClass 結果對象類型,主要為了以后對參數映射進行擴展使用,當前暫時可以不配置 * resultIsList 結果是否是一個數組列表,此處主要針對的是一級結果,默認為 false * true 表示結果是一個數組列表 * false 表示結果不是一個數組列表 * hidden 是否隱藏,當設置為 true 時前端不展示該執行器,默認為 false * true 表示需要隱藏 * false 表示不需要隱藏 * display 展示配置,用于前端頁面展示執行器的名稱等信息 * label 執行器展示的名稱 * description 執行器的描述信息 * directions 鏈接信息,可以設置為該執行器的來源頁面地址 * important 是否置頂,默認為 false * true 表示需要置頂 * false 表示不需要置頂 * categoryName 分類名,把同一類的放在一個組下,如 訂單、商品、 * operation 執行器的請求定義,在此定義執行器方法(具體定義看 3.8 執行方法定義) * inputFields 執行器輸入字段定義 * outputFields 執行器輸出字段定義 * tags 該執行器的備注信息 ## 1.6 執行方法定義 執行方法是引擎支持的某個具體的執行定義,當前支持 4 種類型,分別為: * request 請求類型 * function 函數類型 * dependency 依賴類型 * script 腳本類型 根據每個類型有具體的定義: ### 1.6.1 請求類型 請求類型是指主體功能是調用 HTTP API * executeType: request 請求類型 * method 發起請求的方法,支持以下選項 * GET * PUT * POST * PATCH * DELETE * HEAD * url 請求的完整地址 * body 請求 body 配置 * bodyType 請求體類型 * NULL 為空 * STRING 字符串 * ARRAY 數組 * OBJECT JSON 對象類型 * XML XML 格式 * bodyContent 請求體內容,根據 bodyType 傳入具體的值 * queryParams 查詢請求參數,KV 形式 * formParams 表單請求參數,KV 形式 * headers 頭部請求參數 (在此定義優先級高于 requestTemplate 中的定義) * signConfig 簽名配置 * signType 簽名類型,簽名的實現,目前可以使用簽名腳本類型 * script 通過簽名腳本進行簽名 * signOutField 簽名輸出字段 * signInField 簽名字段參數,KV 形式 * signSetting 簽名配置,針對腳本簽名需要增加以下參數 * connectorId 腳本連接器 ID * scriptType 腳本類型 * sceneCode 場景編碼 version 腳本版本 * beforeRequest 請求前執行方法列表,一般用于對請求參數進行處理 * afterResponse 請求后執行方法列表,一般用于對于返回數據進行處理 ### 1.6.2 函數類型 函數類型是指調用一個內置類的函數,或者內置表達式 * executeType function 函數類型 * isExpress 是否是表達式 * true 是 執行的是內置表達式 * false 否 執行的是類方法 * providerClass 執行類的全路徑,isExpress 為 false 時必填 示例: ? "providerClass":"com.shuhuan.ipaas.connector.spi.yunpian.InputAndOutputBuilder" * function 執行的具體方法,對于表達式來說是具體的表達式,對于執行類方法時是類的方法,對于是表達式時是具體的表達式 示例: ? "function":"generateTemplateContentInput" ? "function":"${assert:equals(0,object:eval(body, '/msg'))}" * paramsExpression 參數表達式,對于執行類方法時傳入 * returnType 返回值類型 * VOID 無返回值 * STRING 字符串 * BOOLEAN 布爾值 * NUM 數字 * INT 整形數字 * ARRAY 數組或者列表 * OBJECT 對象或者 Map 類型 * returnItemType 返回列表的數據類型,returnType 是 ARRAY 時需要 * VOID 無返回值 * STRING 字符串 * BOOLEAN 布爾值 * NUM 數字 * INT 整形數字 * ARRAY 數組或者列表 * OBJECT 對象或者 Map 類型 ### 1.6.3 依賴類型 依賴類型是指可以調用一組已經配置的執行動作,并做一些數據處理 * executeType dependency 依賴類型 * dependencyOperationKeys 依賴的執行動作的 Key 列表 示例: ? "dependencyOperationKeys": ["getUidByMobile", "getUserDetailByUserId"] * afterResponse 所有依賴的執行動作執行完成后執行方法列表,一般用于對于返回數據進行處理 ### 1.6.4 腳本類型 腳本類型是指執行一個腳本 * executeType script 腳本類型 * connectorId 腳本對應的連接器 ID * sceneCode 腳本場景碼,用來標識該腳本應用場景 * type 腳本類型 * java * js * python * version 腳本版本 * paramsExpression 執行的參數表達式,表達式為空時將會將整個參數上下文傳入,不為空時計算完成表達式后傳入 * returnType 返回值類型 * VOID 無返回值 * STRING 字符串 * BOOLEAN 布爾值 * NUM 數字 * INT 整形數字 * ARRAY 數組或者列表 * OBJECT 對象或者 Map 類型 * returnItemType 返回列表的數據類型,returnType 是 ARRAY 時需要 * VOID 無返回值 * STRING 字符串 * BOOLEAN 布爾值 * NUM 數字 * INT 整形數字 * ARRAY 數組或者列表 * OBJECT 對象或者 Map 類型 ## 1.7 字段定義 * key 用于該執行方法中唯一標識字段 * label 展示配置,用于前端頁面展示字段名稱 * helpText 幫助信息,作為輸入字段時需要,非必要不填寫 * placeholder 輸入框提示信息,作為輸入字段時需要 * type 字段類型 * widget 前端控件 [widgetConfig 配置說明文檔](http://www.sqtsgm.com/help/article/1970) * widgetConfig 前端組件的配置 KV 形式 * required 是否為必填選項,作為輸入字段時需要 * true 必填 * false 選填 * defaultValue 默認值 * supportMultiple 是否支持多選,默認 false(搭配選擇控件時使用) * true 支持 * false 不支持 * datasource 可選數據源,KV 形式 * label 展示鍵 * value 實際值 * dynamicDataSource 動態數據源 [動態數據路由](http://www.sqtsgm.com/help/article/1970) * routerType 動態類型 * beforeRequest 在請求之前 * afterRequest 在請求響應之后 * constant 常量 * condition 判斷是否符合路由條件 * params 執行動態數據源的參數列表 * selectCondition 判斷是否可選的條件表達式 * deepCondition 判斷是否可下拉的條件表達式 * refOperation 獲取動態數據源的執行動作 * refLabel 動態 label 的取值方式 * refValue 動態 value 的取值方式 * router 下級的路由規則 * datasource 靜態數據源,routerType 為 constant 時設置 * dynamicFields 動態字段 [dynamicFields](http://www.sqtsgm.com/help/article/1970) * routerType 動態類型 * beforeRequest 在請求之前 * afterRequest 在請求響應之后 * constant 常量 * condition 判斷是否符合路由條件 * params 參數列表 * refOperation 獲取動態字段的執行動作 * refInputFields 動態輸入字段的取值表達式 * refOutputFields 動態輸出字段的取值表達式 * inputFields 對于 routerType 是 constant 時設置 * outputFields 對于 routerType 是 constant 時設置 * childrenType 子節點類型 * children 子節點 # 2.簽名腳本開發 詳細參考:http://www.sqtsgm.com/doc/131/ 在應用 shuhuan-ipaas-app-libs 的 signer 目錄下開發簽名類,簽名算法改成通過 java 執行腳本的方案實現簽名算法,簽名類需要繼承 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.觸發器腳本開發 詳細參考:http://www.sqtsgm.com/doc/131/ 編寫事件回調數據處理腳本。例如 1. ```java 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.將事件標識轉換為觸發器的 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. 做觸發器的 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. 對應事件的輸出內容,與觸發器的輸出字段保持一致 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; } } ```
上一篇
連接器工具
下一篇
控件類型配置
手機掃碼
復制鏈接
手機掃一掃轉發分享
復制鏈接
Markdown文件
分享
鏈接
類型
密碼
更新密碼
主站蜘蛛池模板:
日韩天堂
|
国产欧美一区二区成人影院
|
伊人看片
|
97视频在线免费观看
|
五月天com
|
国产精品成人一区二区不卡
|
国产清纯白嫩大学生正在播放
|
欧美国产高清欧美
|
www.啪
|
久久久久久久久国产
|
国产美女久久久
|
男人天堂2018
|
国产图色
|
国产自在线
|
青草草产国视频
|
日本免费不卡
|
欧美69精品国产成人
|
久久青草免费视频
|
国产成人久久精品二区三区
|
日本羞羞动漫
|
日韩免费在线视频
|
久久99久久成人免费播放
|
99ri9
|
久久国产这里只有精品
|
国产精品久久久久久久久久98
|
九九精品免视频国产成人
|
奇米777在线
|
a一级免费
|
久久久久久青草大香综合精品
|
女大学生的沙龙室2中文版电影
|
美女视频大全网站免费
|
国产精品久久久久久久hd
|
国产精品无码久久久久
|
精品国产96亚洲一区二区三区
|
色五月激情五月
|
福利一区视频
|
男人天堂网av
|
亚洲精品性夜夜夜
|
视频在线播放免费
|
精品毛片免费看
|
亚洲综合色婷婷在线观看
|