templete.md 10.5 KB

${事件名称}

1.概述

${事件说明}

2.请求地址

请求方法 协议 地址
post HTTP/REST http://${ESB服务地址}/api/esb/execute
execute SOAP/WebService http://${ESB服务地址}/services/ESBServiceV2?wsdl

3.请求参数

名称 类型 必须 描述
appkey string ESB 分配给产品的 AppKey ,进入 ESB 中心"产品管理-安全设置"可查看该产品的公共参数信息。
timestamp long 时间戳,精确到毫秒,时区需与 ESB 中心所在服务器的一致,ESB API 允许客户端最大时间误差为 15 分钟
username string 认证用户名,ESB 中心“产品管理-安全设置”中认证开启时必填
指定加密方式后,值为加密(username+timestamp)
password string 认证密码,ESB 中心“产品管理-安全设置”中认证开启时必填
指定加密方式后,值为加密(password+timestamp)
sign string API 输入参数签名结果,签名算法参照下面的介绍
format string 响应格式(${数据格式})
eventkey string 事件标识(${事件标识})
params ${数据格式} 请求数据

${请求参数}

4.响应参数

名称 类型 描述
code string 请求返回的状态码
msg string 请求返回的状态说明
partialFailure boolean 是否存在接口执行失败跳过的情况发生(true:存在)
data ${数据格式} 响应数据

${响应参数}

5.请求示例

5.1 SDK 请求示例

外部系统可以通过引入SDK的方式,调用SDK中提供的方法,触发ESB中的事件。 注: 1.SDK在"ESB中心-业务系统集成ESB导航-业务系统集成"中下载。 2.SDK中已对timestamp、sign、format等参数进行了处理,外部系统调用时,只需按照以下示例,传递参数即可。 3.requestConfig中设置的参数,可参考第3节中的请求参数说明。 4.事件返回结果,可参考第6节中的响应示例。

RequestConfig requestConfig = new RequestConfig();
requestConfig.setAppKey(appKey);            //应用标识
requestConfig.setServerUrl(serverUrl);//ESB 服务所在地址
requestConfig.setSign(Boolean.True);    //启用签名
requestConfig.setSercetKey(sercetKey);//签名密钥
requestConfig.setUserName(userName);    //认证用户名,通过 SDK 调用无需加密,SDK 将根据加密方式自动加密
requestConfig.setPassword(password);    //认证密码,通过 SDK 调用无需加密,SDK 将根据加密方式自动加密
requestConfig.setEncryption(encryption); //加密方式 MD5、SHA1

String eventkey = "${事件标识}";    //事件标识
String params = "${请求数据}"; //事件请求数据

EsbService service = EsbManager.getService("http", requestConfig); //获取 ESB 服务
String response = service.execute(eventkey, params);    //触发 ESB 事件

5.2 OA 请求示例

OA系统已经集成了ESB相关的SDK,可参考以下方式触发ESB事件。 注: 1.请求参数,可参考第3节中的请求参数说明。 2.事件返回结果,可参考第6节中的响应示例。

String eventKey = "${事件标识}"; //事件标识
String params = "${请求数据}"; //事件请求参数

//EsbService其他方法及说明见ESB API接口说明文档
EsbService service = EsbClient.getService(); //获取 ESB 服务
String result = service.execute(eventkey, params);

5.3 HTTP 请求示例

HTTP请求包含2种方式,使用加密传输传输时,请求参数中需要对用户名、密码进行加密。

#用户名密码非加密传输
POST /api/esb/execute?appkey=应用标识&username=用户名&password=密码&timestamp=时间戳format=${数据格式}&eventkey=${事件标识}&params=${请求数据} HTTP/1.1
Cache-Control: no-cache
Host: ${ESB服务地址}

#用户名密码加密传输
POST /api/esb/execute?appkey=应用标识&username=加密方法(用户名+时间戳)&password=加密方法(密码+时间戳)&timestamp=时间戳format=${数据格式}&eventkey=${事件标识}&params=${请求数据} HTTP/1.1
Cache-Control: no-cache
Host: ${ESB服务地址}

6. 响应示例

${响应数据}

7. 错误码解释

错误码 错误消息 解决方案
100 执行成功
101 无有效应用 查看对应事件是否已发布应用
102 无同步应用 查看对应事件已发布的应用是否有同步类别的应用
201 无效的Appkey 检查 appkey与 ESB 中心-产品管理-安全设置中的 appkey 是否一致
202 请求超时 检查传递的时间戳是否精确到毫秒
检查调用方的服务器时间与 ESB 中心的服务时间是否一致
203 签名错误 根据文档中的签名算法进行签名计算
关闭 ESB 中心-产品管理-安全设置中的签名校验开关
204 IP 地址不在可访问名单 检查调用方的 IP 是否在ESB 中心-产品管理-安全设置-IP 白名单中
检查调用方的 IP 是否在ESB 中心-产品管理-安全设置-IP 黑名单中
关闭ESB 中心-产品管理-安全设置中的IP 限制开关
205 用户名、密码不正确 检查调用方传递的用户名、密码与 ESB 中心-产品管理-安全设置中的用户名、密码是否一致
关闭 ESB 中心-产品管理-安全设置中的认证开关
301 系统错误 检查系统日志
302 无有效事件 检查调用方传递的事件标识是否存在,且状态是否正确
303 执行失败 检查系统日志,查看应用对应接口是否可访问
查看对应接口配置的成功标识是否正确
304 模块标识格式错误 标识只能由字符、数字、下划线组成
305 事件标识格式错误 标识只能由字符、数字、下划线组成
306 模块标识已存在 更换模块标识(新建编辑事件时)
307 事件标识已存在 更换事件标识(新建编辑事件时)
308 模块所属产品AppKey不一致 更换模板标识
309 参数格式不正确 检查事件发送的数据是否正确
检查事件发送的数据,与 ESB 中心事件定义的数据格式是否一致
404 未找到对应数据 检查请求数据

8. 签名算法

为了防止API调用过程中被黑客恶意篡改,可在 ESB 中心"产品管理-安全设置"中开启签名,开启签名后调用任何 API需要携带签名,ESB 中心根据请求参数,对签名进行验证,签名不合法的请求将会被拒绝。

签名大体过程如下:

  1. 对所有API(除去sign参数),根据参数名称的ASCII码表的顺序排序。如:

foo:1, bar:2, foo_bar:3, foobar:4

排序后的顺序是:

bar:2, foo:1, foo_bar:3, foobar:4

  1. 将排序好的参数名和参数值拼装在一起,根据上面的示例得到的结果为:

3. 用app的secret初始化HMAC_MD5算法后,再进行摘要,如:

   ```java 
   SecretKey secretKey = new SecretKeySpec(secret.getBytes(), "HmacMD5");
   Mac mac = Mac.getInstance(secretKey.getAlgorithm());
   mac.init(secretKey);
   bytes = mac.doFinal(“bar2foo1foo_bar3foobar4”.getBytes());
  1. 将摘要得到的字节流结果使用十六进制表示,如:

hex(“helloworld”.getBytes(“utf-8”)) = “68656C6C6F776F726C64”

8.1 JAVA 签名算法示例

public static String sign( Map<String,String> params, String secret){

    // 第一步:检查参数是否已经排序
    String[] keys = params.keySet().toArray(new String[0]);
    Arrays.sort(keys);

    // 第二步:把所有参数名和参数值串在一起
    StringBuilder query = new StringBuilder();

    for (String key : keys) {
        if(key != null && !key.isEmpty()) {
            String value = params.get(key);
            if (value != null && !value.isEmpty()) {
                query.append(key).append(value);
            }
        }
    }
    // 第三步:使用HMAC加密
    byte[] bytes = encryptHMAC(query.toString(), secret);

    // 第四步:把二进制转化为大写的十六进制(正确签名应该为32大写字符串,此方法需要时使用)
    return byte2hex(bytes);
}

/**
 * 使用HMAC加密
 * @param data
 * @param secret
 * @return
 */
private static byte[] encryptHMAC(String data, String secret) {
    byte[] bytes = null;
    try {
        SecretKey secretKey = new SecretKeySpec(secret.getBytes(), "HmacMD5");
        Mac mac = Mac.getInstance(secretKey.getAlgorithm());
        mac.init(secretKey);
        bytes = mac.doFinal(data.getBytes());
    } catch (Exception e) {
    }
    return bytes;
}

/**
 * 二进制转化为大写的十六进制
 * @param bytes
 * @return
 */
private static String byte2hex(byte[] bytes) {
    StringBuilder sign = new StringBuilder();
    for (int i = 0; i < bytes.length; i++) {
        String hex = Integer.toHexString(bytes[i] & 0xFF);
        if (hex.length() == 1) {
            sign.append("0");
        }
        sign.append(hex.toUpperCase());
    }
    return sign.toString();
}