ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
## 一、概述 提供外部自建系统的代理商,可以通过接口服务,实现对方系统与我方系统之间的技术衔接; ![](https://img.kancloud.cn/d1/f7/d1f765bbc1d73f1b7fe491041d3fa223_620x254.png) ## 二、参考 >[danger] > 1、在本系统里面,无需独立的去开放平台开户,创建顶级代理商的时候,就自动开户了,也就可以获得相关参数了; > 2、需要注意,需要在开放服务模块,针对当前代理商的客户端,设置允许访问的IP白名单; > 3、调用的api,需要对客户端做授权; ## 三、整体流程 创建接口开放服务账号->获取接口开放服务参数->第三方编写程序->测试->上线; ![](https://img.kancloud.cn/e8/f4/e8f4ede4edf86d551ce2552963863458_1173x168.png) ### **客户端请求实例代码** ``` public class ClientSample { public static void main(String[] args) { Log4jV2Util.initLog4jV2TestEnv(); String hostUrl = "http://{hosturl}/api/rayoauth"; String apiUrl = "/query/card"; String appId = "ray40c9903c1"; String appSecret = "46bacebf-f63c-41cc-b29c-5812994a5e83"; Map<String, String> paramap = new HashMap(); paramap.put("userCode", "13313312"); String result = OauthCaller.call(hostUrl, apiUrl, appId, appSecret, paramap); Logger logger = LoggerFactory.getLogger(OauthClientTest.class); logger.debug(result); } } ``` OauthCaller: ``` public class OauthCaller { public static String call(String oauthHostUrl, String servceUrl, String appId, String appSecret, Map<String, String> businessParaMap) { Map<String, String> allParaMap = new HashMap(); Map<String, String> headmap = new HashMap(); headmap.put(RayOauthServerConstants.rayOauthHeadAppId, appId); headmap.put(RayOauthServerConstants.rayOauthHeadTimeStamp, String.valueOf(new Date().getTime())); allParaMap.putAll(businessParaMap); allParaMap.putAll(headmap); headmap.put(RayOauthServerConstants.rayOauthHeadSignature, Sign.generateSign(allParaMap, appSecret)); String result = null; try { result = HttpPostUtil.executeActionWithHead(oauthHostUrl + servceUrl, businessParaMap, headmap, "", false); } catch (Exception e) { e.printStackTrace(); } return result; } } ``` HttpPostUtil.executeActionWithHead: ``` public static String executeActionWithHead(String postUrl, Map<String, String> postParaMap, Map<String, String> headParaMap, String paraContentType, boolean trace) throws Exception { BasicCookieStore cookieStore = new BasicCookieStore(); try (final CloseableHttpClient httpclient = HttpClients.custom().setConnectionManager(connectionConfig()).setDefaultCookieStore(cookieStore).setDefaultRequestConfig(requestConfig()).build();) { String result = null; try { ClassicRequestBuilder requestBuilder = ClassicRequestBuilder.post().setUri(postUrl); if (postParaMap != null) { Iterator paramIterator = postParaMap.entrySet().iterator(); while (paramIterator.hasNext()) { Map.Entry entry = (Map.Entry) paramIterator.next(); requestBuilder.addParameter(new BasicNameValuePair((String) entry.getKey(), (String) entry.getValue())); } } if (headParaMap != null) { Iterator headIterator = headParaMap.entrySet().iterator(); while (headIterator.hasNext()) { Map.Entry<String, String> entry = (Map.Entry) headIterator.next(); requestBuilder.addHeader(entry.getKey(), entry.getValue()); } } if (!StringUtils.isEmpty(paraContentType)) { requestBuilder.setHeader("Content-type", paraContentType); } ClassicHttpRequest request = requestBuilder.build(); try (final CloseableHttpResponse response = httpclient.execute(request)) { result = EntityUtils.toString(response.getEntity()); } } catch (Exception ex) { logger.error("executeAction执行中发生了异常,堆栈如下:", ex); } return result; } } ``` ## 四、技术要求 1.所有接口的请求,采用httpPost方式提交,发出http请求的时候,请求content-type需设定为:application/x-www-form-urlencoded;charset=UTF-8 ,参数按照普通表单参数传值,不必包裹成一个json字符串; 2.所有接口的响应,采用json格式,编码为UTF-8,响应的content-type为:application/json;charset=UTF-8); 3.提供ip白名单功能,仅供授权的ip调用; 4.每个对外提供服务的api,都必须在请求头部包含参数rayOauthServerAppId及rayOauthServerTimeStamp,为了确保不被外部不法分子恶意篡改请求,请求参数中绝对不能包含appSecret; 5.每个对外提供服务的api,都必须在请求头部包含一个rayOauthServerSignature参数,该参数是通过算法计算出来的值,具体算法参考后续签名算法章节; 6.考虑服务器承载量,目前限制每个ip访问接口频率不得超过1秒10次,超过这个次数,该ip将会被禁止调用,程序中不得做高频率轮询; ## 五、时间戳格式 1.获取从1970, 00:00:00开始到当前的毫秒数(13位) ; 2.每个api请求的有效时间为3分钟,所以,务必确保当前服务请求的时间是准确的; ## 六、rayOauthServerSignature签名算法 假设:rayOauthServerSignature= 当前api的所有参数(除rayOauthServerSignature外),根据 **参数名升序** 排序,以“**`参数名=值&`**”的方式连接起来,最后一个参数不需要&符号,以值结尾; 结果:rayOauthServerSignature= md5(md5(paramstrings)+appSecret) > 注意: > 1、是双层md5(32位小写)加密,中间那个"+"仅表示两段字符相连,并不包括该符号本身; > 2、参数包括了请求头和请求体里面的所有参数; ## 七、测试案例 ![](https://img.kancloud.cn/16/73/1673519b3f79c1ba8adb9b48b25c4dcc_1323x692.png)![](https://img.kancloud.cn/1c/8d/1c8d82217a7b0a8694b480acaf6296ad_1371x703.png)