WebAPI登记典型场景
1 业务背景
当金蝶云星瀚希望通过WebAPI登记与其他外部系统集成的时候,可使用集成服务云的WebAPI登记将外部系统暴露的API登记到集成云中以供调用。该文章主要针对登记过程中的各种常见问题进行讲解,具体登记过程详见文末参考资料。
2 典型场景
2.1 需要对URLEncode
参数编码通常用于确保传输的数据在HTTP传输过程中格式正确,比如使用Base64编码或者URL编码,以下图GET请求为例。
同样开启脚本模式以后,编辑脚本内容如下,直接使用MapToURLEncodeString函数将map转换为url参数字符串,并使用urlencode对其进行编码。
假如请求体是{'b':1,'a':2},排序以后的新map是{'a':2,'b':1},变成url参数格式以后再使用urlencode得到结果a=2&b=1。
注:生成新的url需要使用$$(),从而自动替换字符串中的#{},比如$$("#{$website}#{$connection.web_app}/kapi")将自动将对应连接配置上的协议、ip、端口、web_app替换#{$website}和#{$connection.web_app}。
// 调用转换函数,格式化url参数 var urlParams = MapToURLEncodeString($urlParam); var new_url=$$("#{$website}#{$connection.web_app}/kapi/v2/basedata/bd_customer/query?"+urlParams); //head 请求头变量 var head = { "Content-Type":"application/json", "accesstoken":$session.access_token }; var dataStr = null; //调用并返回结果body字符串 return HttpAccess(new_url, "GET", dataStr, "UTF-8", null, head, 0).result;
2.2 严格控制过期时间(过期的话重新获取token)
很多WebAPI都会通过过期时间来控制访问的安全性,比如一个API使用JWT(JSON Web Tokens)来控制访问。JWT中包含了过期时间(exp字段),如果当前时间超过了这个时间戳,那么请求将被拒绝。以下图API为例。
开启脚本模式以后,编辑脚本,使用$session.expire_time可以获取上次登录会话拿到的过期时间,对其进行判断以后可以使用Relogin()函数重新进行登录。
注:此处直接使用了Relogin()函数重新调用登录脚本获取新token,如果有对应刷新token的脚本也可直接走刷新逻辑。
var url = "https://open.feishu.cn:443/open-apis/contact/v3/users?department_id_type=department_id&user_id_type=user_id"; //如果过期时间小于当前时间的话,重新调用登录脚本获取tenant_access_token if($session.expire_time<NOW){ var head = { "Content-Type":"application/json", "Authorization":Relogin().tenant_access_token }; }else{ var head = { "Content-Type":"application/json", "Authorization":$session.tenant_access_token }; } //将请求体数据转换为JSON串 var dataStr = String.FormatJson($body); //调用并返回结果body字符串 return HttpAccess(url, "POST", dataStr, "UTF-8", null, head, 0).result;
2.3 请求数据需要排序生成签名
在这种方式中,请求的参数按照一定的规则(如字典顺序)进行排序,并可能结合其他信息(如密钥)生成签名。这样做可以防止请求参数被篡改。以下图中的请求为例,假设我们需要根据原始请求参数排序以后转为字符串用MD5生成签名作为请求的参数。
开启脚本模式以后修改脚本如下,先使用sort函数对请求体的参数进行排序,然后生成新的Map,使用MapToURLEncodeString函数将map转换为url参数格式并进行URLEncode。将生成请求参数的字符串使用MD5加密,将得到的签名作为请求体的一个参数。
假如请求体是{'b':1,'a':2},排序以后的新map是{'a':2,'b':1},变成url参数格式以后再使用URLEncode得到结果a=2&b=1,最后使用MD5对该字符串进行加密以后的到签名b33b063ed6ac78b448048a5a3b1e1db1。
var url = $$("#{$website}#{$connection.web_app}/kapi/v2/haos/openapi/adminorgoperate/enable"); //head 请求头变量 var head = { "Content-Type":"application/json", "accesstoken":$session.access_token }; //对请求体按参数排序 var sorted_body=$body.sort(this.key); //将排序后的list转换为map var new_body=sorted_body.mapping($.key, $.value); // 调用函数将map转换为urlencode字符串 var newDataStr = MapToURLEncodeString(new_body); //获得签名串 var signature=Hash.MD5(newDataStr); dataStr.signature=signature; //调用并返回结果body字符串 return HttpAccess(url, "POST", dataStr, "UTF-8", null, head, 0).result;
2.4 请求数据需要加密
在WebAPI调用的时候,请求的数据会使用一定的加密算法进行加密。这保证了数据在传输过程中的安全性,防止中间人攻击。以AES加密为例,需要在创建连接类型的时候将AES的加密密钥作为该连接类型的动态参数,如下图。
使用此连接类型登记WebAPI的时候需要保存以后开启脚本模式。
并修改脚本内容如下,先使用MapToURLEncodeString将请求体的map转换为url参数格式的字符串并进行url编码得到请求体的字符串,然后通过$connection获取连接配置上的aes_key,以此作为AES加密的秘钥,再使用函数AES.encrypt对请求体进行加密。
注:在脚本中可以$connection访问连接配置上的信息。
var url = $$("#{$website}/baseline_a/kapi/v2/iscb/route/meta_yjh_pbc_test"); //head 请求头变量 var head = { "Content-Type":"text/plain", "accesstoken":$session.access_token }; //将请求体转换为编码以后的字符串 var body=MapToURLEncodeString($body); //对密钥进行处理 var aesKey=$connection.aes_key; var aesKeyDecode = Base64Decode(aesKey); var iv = Array.sub(aesKeyDecode,0,16); //对请求体进行加密 var dataStr = AES.encrypt("CBC","PKCS5Padding",aesKeyDecode,body,iv); //调用并返回结果body字符串 return HttpAccess(url, "POST", dataStr, "UTF-8", null, head, 0).result;
3 适用版本
金蝶云·星瀚V5.0.017及以上。
4 参考资料
WebAPI登记典型场景
本文2024-09-23 00:49:56发表“云苍穹知识”栏目。
本文链接:https://wenku.my7c.com/article/kingdee-cangqiong-142023.html