# 调用Rest接口

北京致远互联软件股份有限公司 2017年03月

# 适用范围

本文适用调用致远V5产品线已有的普通REST接口,按照本文操作,即可完成基础代码编写并运行。

A6产品线不支持Rest远程调用。如需定制化开发,需要使用A8版本。

# 特别注意

情况1:自V8.2SP1版本开始,为了提高接口安全性,部分涉及重要数据获取的接口无法使用本文档来调用。

如遇到低版本Rest接口可以调用,但升级到V8.2SP1及更高版本以后提示401无权限访问,请参考[Rest三方互信接口 (opens new window)]进行调整。

1718901410628.png

情况2:升级至V9.0SP1及更高版本后,REST账号如勾选了校验IP而没有配置绑定IP,会导致无法正确获取到TOKEN。处理策略:管理员后台点击取消校验IP的勾选或者配置上绑定IP

1723621793802.png

# 代码示例

# 基于POST的认证示例(推荐)

我们建议使用POST形式的请求获取Token,同时我们建议调用业务请求时将token放入header中,再配合HTTPS请求以保障更安全的数据传输。

try
{
	/** 第一步:访问/seeyon/rest/token获取Rest认证token **/
    String url = "https://xxx/seeyon/rest/token/";
    HttpHeaders headers = new HttpHeaders();
    // 必须:设置内容协商为JSON,接口最终会返回JSON对象
	headers.setAccept(MediaType.parseMediaTypes("application/json"));
    headers.setContentType(MediaType.APPLICATION_JSON);
	// 以POST形式发送,构建请求体
    Map<String,Object> body = new HashMap<>();
    body.put("userName","restName");
    body.put("password","restPassword");
    body.put("loginName","loginName");

    // 发送POST请求,并指定URL、请求实体和返回类型
    ResponseEntity<Map<String, Object>> response = restTemplate.exchange(
    	url,HttpMethod.POST,new HttpEntity<>(body,headers),new ParameterizedTypeReference<Map<String, Object>>() {});
    Map<String, Object> tokenInfo = response.getBody();
	String token = (String) tokenInfo.get("id");

	/** 第二步:访问V5的Rest开放接口,进行业务增删改查操作 **/
    String restUrl1 = "https://xxx/seeyon/rest/affair/pending/count";
	HttpHeaders headers1 = new HttpHeaders();
	// 必须:设置内容协商为JSON,接口最终会返回JSON对象
	headers1.setAccept(MediaType.parseMediaTypes("application/json"));
	headers1.setContentType(MediaType.APPLICATION_JSON);
	// 把token放到header中
	headers1.add("token", token);
	ResponseEntity<Map<String, Object>> response1 = restTemplate.exchange(restUrl1, HttpMethod.GET, new HttpEntity<>(headers1), new ParameterizedTypeReference<Map<String, Object>>(){});
   Map<String, Object> count = response1.getBody();
}
catch (RestClientException e)
{
	// 根据实际情况决定是否需要抛出异常或返回特定错误信息
    String error = "Rest认证不成功,可能是Rest帐号密码错误,可能是连接不上。" + e.getLocalizedMessage();
}

# 基于GET的认证示例

try
{
	/** 第一步:访问/seeyon/rest/token获取Rest认证token **/
    String url = String.format("http://127.0.0.1/seeyon/rest/token/%s/%s?loginName=%s", "restName", "restPassword", "loginName");
    HttpHeaders headers = new HttpHeaders();
    // 必须:设置内容协商为JSON,接口最终会返回JSON对象
    headers.setContentType(MediaType.APPLICATION_JSON);
    HttpEntity<String> entity = new HttpEntity<>(headers);
    ResponseEntity<Map<String, Object>> response = restTemplate.exchange(url, HttpMethod.GET, entity, new ParameterizedTypeReference<Map<String, Object>>(){});
    Map<String, Object> tokenInfo = response.getBody();
	String token = (String) tokenInfo.get("id");

	/** 第二步:访问V5的Rest开放接口,进行业务增删改查操作 **/
    String restUrl1 = "http://127.0.0.1/seeyon/rest/affair/pending/count?token=" + token;
    Map<String, Object> count = sendPostRequest(restUrl1);

	// token可以多次使用
	String restUrl2 = "http://127.0.0.1/seeyon/rest/affair/pending/code/002?token=" + token;
    Map<String, Object> count = sendGetRequest(restUrl2);
}
catch (RestClientException e)
{
	// 根据实际情况决定是否需要抛出异常或返回特定错误信息
    String error = "Rest认证不成功,可能是Rest帐号密码错误,可能是连接不上。" + e.getLocalizedMessage();
}

# 实现步骤

# 1. 注册Rest帐号

外部系统要调用V5系统Rest接口,一定需要有身份凭证(而且不能是V5的普通登录帐号),故V5设定了Rest帐号管理,第三方调用Rest都需要先注册帐号。

1)在V5系统侧,登录系统管理员界面,在左侧导航栏选择 “信息集成配置”,进入“REST用户管理”界面。

2)新建REST用户(保存用户名和密码!!!密码随机生成且只显示一次,忘记密码时只能通过密码重置找回!)

1714466006255.png

3)新建REST用户后,通过顶部“授权”菜单,给对应REST账号勾选允许调用的接口模块。

1714626940388.png

# 2. 通过Rest帐号获取token

完成上一步Rest帐号注册后,通过调用V5系统seeyon/rest/token/{userName}/{password}接口获取token,随后所有Rest接口带上token即可被正常使用。

平台提供了GET和POST两种请求方式获取认证,这个由开发自行决定采用哪种方案认证。

基于POST的认证:

POST http://127.0.0.1/seeyon/rest/token HTTP/1.1
Host: 127.0.0.1
Accept: application/json
Content-Type: application/json
请求消息体:{"userName":"rest","password":"123456"}

基于GET的认证: 注意:get请求若想返回Json格式需带上返回类型参数Content-Type: application/json,否则可能随机返回string格式的token

GET请求:http://IP:port/seeyon/rest/token/{userName}/{password}
GET http://127.0.0.1/seeyon/rest/token/rest/123456 HTTP/1.1
Host: 127.0.0.1
Accept: application/json
Content-Type: application/json

以上认证的返回结果应该如下:

成功:{"id": "013a2a1e-a0b0-4f66-b533-da0563f89c6c"}
失败:{"id": "-1"} 如果密码错误,可能返回404信号码

如获取token返回值有时字符串,有时json格式,则需要在发送请求前设置“内容协商”,比如需要json格式,则发送请求时设置Accept: application/json。

GET http://127.0.0.1/seeyon/rest/token/rest/123456 HTTP/1.1
Accept: application/json
Host: 127.0.0.1

返回

{
  "bindingUser" : null,
  "id" : "a5ad648c-0a40-49b0-bedd-9fd7025313b5"
}

请求

GET http://127.0.0.1/seeyon/rest/token/rest/123456 HTTP/1.1
Accept: text/plain
Host: 127.0.0.1

返回

d72640bd-48b0-46cd-87a1-ca9a449da185

# 3. 获取token并模拟人员登录

按照上一步获取授权之后,只能访问有限的公共Rest,当调用涉及身份验证的接口时就会报错。

我们还有模拟指定用户进行相关Rest调用场景,平台提供了能力:验证服务接口可以绑定一个OA真实用户登录。

模拟登录的方式同样沿用上面的请求,只是增加了loginName参数,同样支持POST和GET:

Accept: application/json
Content-Type: application/json

POST http://127.0.0.1/seeyon/rest/token
{
"userName":"REST帐号",
"password":"REST密码",
"memberId":"用户的ID",
"loginName":"用户的登录名",
"code":"用户的人员编码",
"userAgentFrom":"如pc、weixin、iphone"
}

GET http://127.0.0.1/seeyon/rest/token/{userName}/{password}?loginName=zhangsan

POST和GET允许的参数如下(其中memberId、loginName、memberCode三个参数任选一个即可):

参数 是否必填 说明
userName REST帐号
password REST密码
memberId 用户的ID
loginName 用户的登录名
memberCode 用户的人员编码
userAgentFrom 如pc、weixin、iphone

以上认证的返回结果应该如下:

成功:
{"bindingUser":"..."
"id": "013a2a1e-a0b0-4f66-b533-da0563f89c6c"}
失败:
{"id": "-1"}
如果密码错误,可能返回404信号码

# 4. 设置模拟哪个端登录

请求参数userAgentFrom用于标识当前Rest请求来源,不传递此参数时,默认userAgentFrom=rest

当你是通过移动端H5做Rest接口认证,建议设置userAgentFrom=mobile,请求格式如下:

GET http://127.0.0.1/seeyon/rest/token/{userName}/{password}?loginName={loginName}&userAgentFrom=mobile

截止V9.0版本,userAgentFrom变量包含如下枚举:

        pc, // 15普通电脑,包括台式机、笔记本,一般只通过IE等浏览器登录的
        mobile, //20 手机终端,一般只通过wap登录的
        email, //12 通过email过来的
        other, //16 其它终端
        iphone, //21 M
        ipad, //22 M
        androidphone, //23 M
        androidpad, //24 M
		wechat, //80 来自微信     
        share, //13 分享到外部
        ucpc, //40 致信PC客户端
        vjoin, //11 致信PC客户端
		rest, //14 rest
		h5, // 160 h5
		zhifei,//320 致飞
		WeChat, //微信公众号,不影响之前的逻辑新增     
		 Lark,// 飞书
		DingTalk ,//钉钉
		wxwork,// 企业微信
		welink, // welink

# 5. 获取Token是否校验绑定IP(Since:V5.6)

新建REST帐号时,通过是否勾选【获取Token是否校验IP】来设置在获取Token时,是否对当前请求的IP做校验。

参数说明

参数 是否勾选 说明
获取token是否校验绑定IP 勾选 获取token时校验IP,如果与【绑定IP】设置不同,无法获取token
获取token是否校验绑定IP 不勾选 不对请求IP做校验

# 6. 执行具体Rest接口调用

前面小节都在介绍获取Token的方法,之所以要这么做是因为:所有的REST调用时必须传递Token,如果不传递Token或传递错误的Token,将返回HttpStatus.SC_UNAUTHORIZED401错误及错误信息。

Token的生命周期为15分钟,如果15分钟无调用,Token将失效,失效以后调用返回401,提示“Invalid token,please authenticate again”。

第三方系统调用系统内的任意Rest接口,都必须有token身份才行!传递Token身份有两种方式:

第一种:在HTTP请求的header中使用token属性

GET http://127.0.0.1/seeyon/rest/xxx HTTP/1.1
Host: 127.0.0.1
Accept: application/json
Content-Type: application/json;charset=UTF-8
User-Agent: Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.76 Safari/537.36
Cookie: JSESSIONID=5079B8DC8A4BD52E48FBA4DE78C2A43C
token:013a2a1e-a0b0-4f66-b533-da0563f89c6c

第二种:在请求参数中传递,URL请求后面跟上token参数即可

http://127.0.0.1/seeyon/rest/orgMember/123?token=013a2a1e-a0b0-4f66-b533-da0563f89c6c

# 7 注意事项

开发执行远程调用一定要根据接口API文档中的说明进行相关参数匹配方可调用Rest成功。

要实现多语言国际化,则需要在head中增加Accept-Language属性,详见[编写Rest接口 - 国际化]章节。

返回结果要XML、JSON还是普通Text文本,需要在head中增加Accept属性,详见本文[编写Rest接口 - 内容协商]章节。

PS:不是所有接口都开通了三种返回格式,我们一般都是基于application/json传输。

启动服务后,可以查看RESTFull web service服务的WADL:

http://ip:port/seeyon/rest/application.wadl
例如:http://127.0.0.1:8080/seeyon/rest/application.wadl

如果您使用的是我们的客户端,调用client.authenticate(userName, password);即可。

# 8 token失效时长

不同版本可能存在差异,以v8.2sp1 20221013版本为例,时长为20分钟

编撰人:lichaoj、admin、het