mirror of
https://gitee.com/durcframework/SOP.git
synced 2025-08-11 21:57:56 +08:00
可自定义数据节点
This commit is contained in:
@@ -1,23 +1,25 @@
|
|||||||
* [首页](/?t=1556455222293)
|
* [首页](/?t=1556955558296)
|
||||||
* 开发文档
|
* 开发文档
|
||||||
* [快速体验](files/10010_快速体验.md?t=1556455222295)
|
* [快速体验](files/10010_快速体验.md?t=1556955558299)
|
||||||
* [项目接入到SOP](files/10011_项目接入到SOP.md?t=1556455222316)
|
* [项目接入到SOP](files/10011_项目接入到SOP.md?t=1556955558316)
|
||||||
* [新增接口](files/10020_新增接口.md?t=1556455222316)
|
* [新增接口](files/10020_新增接口.md?t=1556955558316)
|
||||||
* [业务参数校验](files/10030_业务参数校验.md?t=1556455222316)
|
* [业务参数校验](files/10030_业务参数校验.md?t=1556955558316)
|
||||||
* [错误处理](files/10040_错误处理.md?t=1556455222317)
|
* [错误处理](files/10040_错误处理.md?t=1556955558316)
|
||||||
* [编写文档](files/10041_编写文档.md?t=1556455222317)
|
* [编写文档](files/10041_编写文档.md?t=1556955558316)
|
||||||
* [接口交互详解](files/10050_接口交互详解.md?t=1556455222317)
|
* [接口交互详解](files/10050_接口交互详解.md?t=1556955558317)
|
||||||
* [easyopen支持](files/10070_easyopen支持.md?t=1556455222317)
|
* [easyopen支持](files/10070_easyopen支持.md?t=1556955558317)
|
||||||
* [使用签名校验工具](files/10080_使用签名校验工具.md?t=1556455222317)
|
* [使用签名校验工具](files/10080_使用签名校验工具.md?t=1556955558317)
|
||||||
* [ISV管理](files/10085_ISV管理.md?t=1556455222317)
|
* [ISV管理](files/10085_ISV管理.md?t=1556955558317)
|
||||||
* [路由授权](files/10090_路由授权.md?t=1556455222317)
|
* [路由授权](files/10090_路由授权.md?t=1556955558317)
|
||||||
* [接口限流](files/10092_接口限流.md?t=1556455222317)
|
* [接口限流](files/10092_接口限流.md?t=1556955558317)
|
||||||
* [SDK开发](files/10095_SDK开发.md?t=1556455222317)
|
* [SDK开发](files/10095_SDK开发.md?t=1556955558317)
|
||||||
* [使用SpringCloudGateway](files/10096_使用SpringCloudGateway.md?t=1556455222318)
|
* [使用SpringCloudGateway](files/10096_使用SpringCloudGateway.md?t=1556955558317)
|
||||||
* [应用授权](files/10097_应用授权.md?t=1556455222318)
|
* [应用授权](files/10097_应用授权.md?t=1556955558317)
|
||||||
|
* [更改数据节点名称](files/10099_更改数据节点名称.md?t=1556955558318)
|
||||||
|
* [对接前端](files/10100_对接前端.md?t=1556955558318)
|
||||||
* 原理分析
|
* 原理分析
|
||||||
* [原理分析之@ApiMapping](files/90010_原理分析之@ApiMapping.md?t=1556455222318)
|
* [原理分析之@ApiMapping](files/90010_原理分析之@ApiMapping.md?t=1556955558318)
|
||||||
* [原理分析之路由存储](files/90011_原理分析之路由存储.md?t=1556455222318)
|
* [原理分析之路由存储](files/90011_原理分析之路由存储.md?t=1556955558318)
|
||||||
* [原理分析之如何路由](files/90012_原理分析之如何路由.md?t=1556455222318)
|
* [原理分析之如何路由](files/90012_原理分析之如何路由.md?t=1556955558318)
|
||||||
* [原理分析之文档归纳](files/90013_原理分析之文档归纳.md?t=1556455222318)
|
* [原理分析之文档归纳](files/90013_原理分析之文档归纳.md?t=1556955558318)
|
||||||
* [常见问题](files/90100_常见问题.md?t=1556455222318)
|
* [常见问题](files/90100_常见问题.md?t=1556955558318)
|
||||||
|
@@ -21,7 +21,7 @@ SDK依赖了三个jar包
|
|||||||
- 参数:name 故事名称
|
- 参数:name 故事名称
|
||||||
- 返回信息
|
- 返回信息
|
||||||
|
|
||||||
```
|
```json
|
||||||
{
|
{
|
||||||
"alipay_story_find_response": {
|
"alipay_story_find_response": {
|
||||||
"msg": "Success",
|
"msg": "Success",
|
||||||
|
69
doc/docs/files/10099_更改数据节点名称.md
Normal file
69
doc/docs/files/10099_更改数据节点名称.md
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
# 更改数据节点名称
|
||||||
|
|
||||||
|
针对`alipay.story.find`接口,它的返回结果如下:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"alipay_story_find_response": {
|
||||||
|
"msg": "Success",
|
||||||
|
"code": "10000",
|
||||||
|
"name": "白雪公主",
|
||||||
|
"id": 1,
|
||||||
|
"gmtCreate": 1554193987378
|
||||||
|
},
|
||||||
|
"sign": "xxxxx"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
其中`alipay_story_find_response`是它的数据节点。规则是:
|
||||||
|
|
||||||
|
> 将接口名中的"."转换成"_",后面加上"_response"。
|
||||||
|
|
||||||
|
代码实现如下:
|
||||||
|
|
||||||
|
```java
|
||||||
|
String method = "alipay.story.find";
|
||||||
|
return method.replace('.', '_') + "_response";
|
||||||
|
```
|
||||||
|
|
||||||
|
详见`DefaultDataNameBuilder.java`
|
||||||
|
|
||||||
|
如果要更改数据节点,比如`result`,可使用`CustomDataNameBuilder.java`。
|
||||||
|
|
||||||
|
```java
|
||||||
|
@Configuration
|
||||||
|
public class ZuulConfig extends AlipayZuulConfiguration {
|
||||||
|
|
||||||
|
static {
|
||||||
|
...
|
||||||
|
ApiConfig.getInstance().setDataNameBuilder(new CustomDataNameBuilder());
|
||||||
|
...
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
设置后,网关统一的返回结果如下:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"result": {
|
||||||
|
...
|
||||||
|
},
|
||||||
|
"sign": "xxxxx"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
此外,构造方法可指定自定义字段名称:`new CustomDataNameBuilder("data");`。
|
||||||
|
设置后,数据节点将变成`data`
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
...
|
||||||
|
},
|
||||||
|
"sign": "xxxxx"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**注**:网关设置了CustomDataNameBuilder后,SDK也要做相应的更改:`SdkConfig.dataNameBuilder = new CustomDataNameBuilder();`
|
145
doc/docs/files/10100_对接前端.md
Normal file
145
doc/docs/files/10100_对接前端.md
Normal file
@@ -0,0 +1,145 @@
|
|||||||
|
# 对接前端
|
||||||
|
|
||||||
|
开放平台一般对接服务端应用,开发者使用SDK来调用接口。
|
||||||
|
理论上来说,只要是客户端程序,都可以调用网关接口。因此,同样可以对接前端应用(H5、小程序、App)。
|
||||||
|
|
||||||
|
针对H5页面,配置方式如下:
|
||||||
|
|
||||||
|
- 网关关闭签名校验。`ApiConfig.getInstance().setIgnoreValidate(true);`
|
||||||
|
|
||||||
|
由于是网页调用接口,把秘钥放在前端意义不大,干脆直接关闭签名校验。
|
||||||
|
|
||||||
|
- 设置统一的数据节点
|
||||||
|
|
||||||
|
```java
|
||||||
|
@Configuration
|
||||||
|
public class ZuulConfig extends AlipayZuulConfiguration {
|
||||||
|
|
||||||
|
static {
|
||||||
|
...
|
||||||
|
ApiConfig.getInstance().setIgnoreValidate(true);
|
||||||
|
ApiConfig.getInstance().setDataNameBuilder(new CustomDataNameBuilder());
|
||||||
|
...
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
设置后,网关统一的返回结果如下:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"result": {
|
||||||
|
...
|
||||||
|
},
|
||||||
|
"sign": "xxxxx"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
- 封装请求工具【可选】
|
||||||
|
|
||||||
|
封装请求,方便调用,针对vue的封装如下:
|
||||||
|
|
||||||
|
```js
|
||||||
|
// 创建axios实例
|
||||||
|
const client = axios.create({
|
||||||
|
baseURL: process.env.BASE_API, // api 的 base_url
|
||||||
|
timeout: 5000, // 请求超时时间
|
||||||
|
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
|
||||||
|
})
|
||||||
|
|
||||||
|
const RequestUtil = {
|
||||||
|
/**
|
||||||
|
* 请求接口
|
||||||
|
* @param method 接口名,如:goods.get,goods.get
|
||||||
|
* @param version 版本号,如:1.0
|
||||||
|
* @param data 请求数据,json格式
|
||||||
|
* @param callback 成功回调
|
||||||
|
* @param errorCallback 失败回调
|
||||||
|
*/
|
||||||
|
post: function(method, version, data, callback, errorCallback) {
|
||||||
|
client.request({
|
||||||
|
method: method,
|
||||||
|
version: version,
|
||||||
|
biz_content: JSON.stringify(data)
|
||||||
|
}).then(function(response) {
|
||||||
|
const resp = response.result
|
||||||
|
const code = resp.code
|
||||||
|
// 成功,网关正常且业务正常
|
||||||
|
if (code === '10000' && !resp.sub_code) {
|
||||||
|
callback(resp)
|
||||||
|
} else {
|
||||||
|
// 报错
|
||||||
|
Message({
|
||||||
|
message: resp.msg,
|
||||||
|
type: 'error',
|
||||||
|
duration: 5 * 1000
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(function(error) {
|
||||||
|
console.log('err' + error) // for debug
|
||||||
|
errorCallback && errorCallback(error)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default RequestUtil
|
||||||
|
```
|
||||||
|
|
||||||
|
jQuery版本如下:
|
||||||
|
|
||||||
|
```js
|
||||||
|
var RequestUtil = {
|
||||||
|
/**
|
||||||
|
* 请求接口
|
||||||
|
* @param method 接口名,如:goods.get,goods.get
|
||||||
|
* @param version 版本号,如:1.0
|
||||||
|
* @param data 请求数据,json格式
|
||||||
|
* @param callback 成功回调
|
||||||
|
* @param errorCallback 失败回调
|
||||||
|
*/
|
||||||
|
post: function(method, version, data, callback, errorCallback) {
|
||||||
|
$.ajax({
|
||||||
|
url: 'http://localhost:8081/api' // 网关url
|
||||||
|
, type: 'post'
|
||||||
|
, headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
|
||||||
|
, data: {
|
||||||
|
method: method,
|
||||||
|
version: version,
|
||||||
|
biz_content: JSON.stringify(data)
|
||||||
|
}
|
||||||
|
,success:function(response){
|
||||||
|
var resp = response.result
|
||||||
|
var code = resp.code
|
||||||
|
// 成功,网关正常且业务正常
|
||||||
|
if (code === '10000' && !resp.sub_code) {
|
||||||
|
callback(resp)
|
||||||
|
} else {
|
||||||
|
// 报错
|
||||||
|
alert(resp.msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
, error: function(error) {
|
||||||
|
errorCallback && errorCallback(error)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
jQuery调用示例:
|
||||||
|
|
||||||
|
```js
|
||||||
|
$(function () {
|
||||||
|
var data = {
|
||||||
|
id: 1
|
||||||
|
,name: '葫芦娃'
|
||||||
|
}
|
||||||
|
RequestUtil.post('alipay.story.get', '1.0', data, function (result) {
|
||||||
|
console.log(result)
|
||||||
|
});
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
|
@@ -10,6 +10,8 @@ import com.gitee.sop.gatewaycommon.manager.DefaultRouteConfigManager;
|
|||||||
import com.gitee.sop.gatewaycommon.manager.IsvRoutePermissionManager;
|
import com.gitee.sop.gatewaycommon.manager.IsvRoutePermissionManager;
|
||||||
import com.gitee.sop.gatewaycommon.manager.RouteConfigManager;
|
import com.gitee.sop.gatewaycommon.manager.RouteConfigManager;
|
||||||
import com.gitee.sop.gatewaycommon.param.ParamBuilder;
|
import com.gitee.sop.gatewaycommon.param.ParamBuilder;
|
||||||
|
import com.gitee.sop.gatewaycommon.result.DataNameBuilder;
|
||||||
|
import com.gitee.sop.gatewaycommon.result.DefaultDataNameBuilder;
|
||||||
import com.gitee.sop.gatewaycommon.result.ResultExecutor;
|
import com.gitee.sop.gatewaycommon.result.ResultExecutor;
|
||||||
import com.gitee.sop.gatewaycommon.secret.CacheIsvManager;
|
import com.gitee.sop.gatewaycommon.secret.CacheIsvManager;
|
||||||
import com.gitee.sop.gatewaycommon.secret.IsvManager;
|
import com.gitee.sop.gatewaycommon.secret.IsvManager;
|
||||||
@@ -108,6 +110,11 @@ public class ApiConfig {
|
|||||||
*/
|
*/
|
||||||
private LimitManager limitManager = new DefaultLimitManager();
|
private LimitManager limitManager = new DefaultLimitManager();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构建数据节点名称
|
||||||
|
*/
|
||||||
|
private DataNameBuilder dataNameBuilder = new DefaultDataNameBuilder();
|
||||||
|
|
||||||
// -------- fields ---------
|
// -------- fields ---------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -7,7 +7,11 @@ import org.springframework.beans.BeansException;
|
|||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.context.ApplicationContext;
|
import org.springframework.context.ApplicationContext;
|
||||||
import org.springframework.context.ApplicationContextAware;
|
import org.springframework.context.ApplicationContextAware;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.core.env.Environment;
|
import org.springframework.core.env.Environment;
|
||||||
|
import org.springframework.web.cors.CorsConfiguration;
|
||||||
|
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
|
||||||
|
import org.springframework.web.filter.CorsFilter;
|
||||||
|
|
||||||
import javax.annotation.PostConstruct;
|
import javax.annotation.PostConstruct;
|
||||||
|
|
||||||
@@ -28,6 +32,36 @@ public class AbstractConfiguration implements ApplicationContextAware {
|
|||||||
applicationContext = ctx;
|
applicationContext = ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 跨域过滤器
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public CorsFilter corsFilter() {
|
||||||
|
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
|
||||||
|
source.registerCorsConfiguration("/**", corsConfiguration());
|
||||||
|
return new CorsFilter(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected CorsFilter createCorsFilter() {
|
||||||
|
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
|
||||||
|
this.registerCorsConfiguration(source);
|
||||||
|
return new CorsFilter(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void registerCorsConfiguration(UrlBasedCorsConfigurationSource source) {
|
||||||
|
source.registerCorsConfiguration("/**", corsConfiguration());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected CorsConfiguration corsConfiguration() {
|
||||||
|
CorsConfiguration corsConfiguration = new CorsConfiguration();
|
||||||
|
corsConfiguration.addAllowedOrigin("*");
|
||||||
|
corsConfiguration.addAllowedHeader("*");
|
||||||
|
corsConfiguration.addAllowedMethod("*");
|
||||||
|
return corsConfiguration;
|
||||||
|
}
|
||||||
|
|
||||||
@PostConstruct
|
@PostConstruct
|
||||||
public final void after() {
|
public final void after() {
|
||||||
if (RouteRepositoryContext.getRouteRepository() == null) {
|
if (RouteRepositoryContext.getRouteRepository() == null) {
|
||||||
|
@@ -2,6 +2,7 @@ package com.gitee.sop.gatewaycommon.result;
|
|||||||
|
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import com.gitee.sop.gatewaycommon.bean.ApiConfig;
|
||||||
import com.gitee.sop.gatewaycommon.bean.ApiContext;
|
import com.gitee.sop.gatewaycommon.bean.ApiContext;
|
||||||
import com.gitee.sop.gatewaycommon.bean.SopConstants;
|
import com.gitee.sop.gatewaycommon.bean.SopConstants;
|
||||||
import com.gitee.sop.gatewaycommon.bean.TargetRoute;
|
import com.gitee.sop.gatewaycommon.bean.TargetRoute;
|
||||||
@@ -23,11 +24,8 @@ public abstract class BaseExecutorAdapter<T, R> implements ResultExecutor<T, R>
|
|||||||
private static final ErrorMeta ISP_UNKNOW_ERROR_META = ErrorEnum.ISP_UNKNOW_ERROR.getErrorMeta();
|
private static final ErrorMeta ISP_UNKNOW_ERROR_META = ErrorEnum.ISP_UNKNOW_ERROR.getErrorMeta();
|
||||||
private static final ErrorMeta ISP_BIZ_ERROR = ErrorEnum.BIZ_ERROR.getErrorMeta();
|
private static final ErrorMeta ISP_BIZ_ERROR = ErrorEnum.BIZ_ERROR.getErrorMeta();
|
||||||
|
|
||||||
private static final char DOT = '.';
|
|
||||||
private static final char UNDERLINE = '_';
|
|
||||||
public static final String GATEWAY_CODE_NAME = "code";
|
public static final String GATEWAY_CODE_NAME = "code";
|
||||||
public static final String GATEWAY_MSG_NAME = "msg";
|
public static final String GATEWAY_MSG_NAME = "msg";
|
||||||
public static final String DATA_SUFFIX = "_response";
|
|
||||||
public static final String ARRAY_START = "[";
|
public static final String ARRAY_START = "[";
|
||||||
public static final String ARRAY_END = "]";
|
public static final String ARRAY_END = "]";
|
||||||
public static final String ROOT_JSON = "{'items':%s}".replace("'", "\"");
|
public static final String ROOT_JSON = "{'items':%s}".replace("'", "\"");
|
||||||
@@ -137,8 +135,9 @@ public abstract class BaseExecutorAdapter<T, R> implements ResultExecutor<T, R>
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 点换成下划线
|
// 点换成下划线
|
||||||
String method = name.replace(DOT, UNDERLINE);
|
DataNameBuilder dataNameBuilder = ApiConfig.getInstance().getDataNameBuilder();
|
||||||
ret.put(method + DATA_SUFFIX, jsonObjectService);
|
String method = dataNameBuilder.build(name);
|
||||||
|
ret.put(method, jsonObjectService);
|
||||||
ret.put(ParamNames.SIGN_NAME, sign);
|
ret.put(ParamNames.SIGN_NAME, sign);
|
||||||
return ret.toJSONString();
|
return ret.toJSONString();
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,30 @@
|
|||||||
|
package com.gitee.sop.gatewaycommon.result;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回固定的
|
||||||
|
* {
|
||||||
|
* "result": {
|
||||||
|
* "code": "20000",
|
||||||
|
* "msg": "Service Currently Unavailable",
|
||||||
|
* "sub_code": "isp.unknow-error",
|
||||||
|
* "sub_msg": "系统繁忙"
|
||||||
|
* },
|
||||||
|
* "sign": "ERITJKEIJKJHKKKKKKKHJEREEEEEEEEEEE"
|
||||||
|
* }
|
||||||
|
* @author tanghc
|
||||||
|
*/
|
||||||
|
public class CustomDataNameBuilder implements DataNameBuilder {
|
||||||
|
private String dataName = "result";
|
||||||
|
|
||||||
|
public CustomDataNameBuilder() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public CustomDataNameBuilder(String dataName) {
|
||||||
|
this.dataName = dataName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String build(String method) {
|
||||||
|
return dataName;
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,13 @@
|
|||||||
|
package com.gitee.sop.gatewaycommon.result;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author tanghc
|
||||||
|
*/
|
||||||
|
public interface DataNameBuilder {
|
||||||
|
/**
|
||||||
|
* 构建数据节点名称
|
||||||
|
* @param method
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
String build(String method);
|
||||||
|
}
|
@@ -0,0 +1,28 @@
|
|||||||
|
package com.gitee.sop.gatewaycommon.result;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将方法名中的"."转成"_"并在后面追加"_response"<br>
|
||||||
|
* 如:alipay.trade.order.settle --> alipay_trade_order_settle_response<br>
|
||||||
|
* <pre>
|
||||||
|
* {
|
||||||
|
* "alipay_trade_order_settle_response": {
|
||||||
|
* "code": "20000",
|
||||||
|
* "msg": "Service Currently Unavailable",
|
||||||
|
* "sub_code": "isp.unknow-error",
|
||||||
|
* "sub_msg": "系统繁忙"
|
||||||
|
* },
|
||||||
|
* "sign": "ERITJKEIJKJHKKKKKKKHJEREEEEEEEEEEE"
|
||||||
|
* }
|
||||||
|
* </pre>
|
||||||
|
* @author tanghc
|
||||||
|
*/
|
||||||
|
public class DefaultDataNameBuilder implements DataNameBuilder {
|
||||||
|
private static final char DOT = '.';
|
||||||
|
private static final char UNDERLINE = '_';
|
||||||
|
private static final String DATA_SUFFIX = "_response";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String build(String method) {
|
||||||
|
return method.replace(DOT, UNDERLINE) + DATA_SUFFIX;
|
||||||
|
}
|
||||||
|
}
|
@@ -22,10 +22,6 @@ namespace SDKCSharp.Client
|
|||||||
|
|
||||||
private static OpenConfig DEFAULT_CONFIG = new OpenConfig();
|
private static OpenConfig DEFAULT_CONFIG = new OpenConfig();
|
||||||
|
|
||||||
private static char DOT = '.';
|
|
||||||
private static char UNDERLINE = '_';
|
|
||||||
public static string DATA_SUFFIX = "_response";
|
|
||||||
|
|
||||||
private Dictionary<string, string> header = new Dictionary<string, string>();
|
private Dictionary<string, string> header = new Dictionary<string, string>();
|
||||||
|
|
||||||
|
|
||||||
@@ -35,6 +31,7 @@ namespace SDKCSharp.Client
|
|||||||
|
|
||||||
private OpenConfig openConfig;
|
private OpenConfig openConfig;
|
||||||
private OpenRequest openRequest;
|
private OpenRequest openRequest;
|
||||||
|
private DataNameBuilder dataNameBuilder;
|
||||||
|
|
||||||
|
|
||||||
public OpenClient(string url, string appId, string privateKey) : this(url, appId, privateKey,false, DEFAULT_CONFIG)
|
public OpenClient(string url, string appId, string privateKey) : this(url, appId, privateKey,false, DEFAULT_CONFIG)
|
||||||
@@ -59,6 +56,7 @@ namespace SDKCSharp.Client
|
|||||||
{
|
{
|
||||||
this.privateKey = LoadCertificateFile(privateKey);
|
this.privateKey = LoadCertificateFile(privateKey);
|
||||||
}
|
}
|
||||||
|
this.dataNameBuilder = openConfig.DataNameBuilder;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -111,9 +109,9 @@ namespace SDKCSharp.Client
|
|||||||
string sign = SignUtil.CreateSign(form, privateKey, request.Charset, request.SignType);
|
string sign = SignUtil.CreateSign(form, privateKey, request.Charset, request.SignType);
|
||||||
form[this.openConfig.SignName] = sign;
|
form[this.openConfig.SignName] = sign;
|
||||||
|
|
||||||
string resp = this.doExecute(url, requestForm, header);
|
string resp = this.DoExecute(url, requestForm, header);
|
||||||
|
|
||||||
return this.parseResponse<T>(resp, request);
|
return this.ParseResponse<T>(resp, request);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -123,7 +121,7 @@ namespace SDKCSharp.Client
|
|||||||
/// <param name="requestForm">请求内容</param>
|
/// <param name="requestForm">请求内容</param>
|
||||||
/// <param name="header">请求header</param>
|
/// <param name="header">请求header</param>
|
||||||
/// <returns>返回服务器响应内容</returns>
|
/// <returns>返回服务器响应内容</returns>
|
||||||
protected virtual String doExecute(String url, RequestForm requestForm, Dictionary<string, string> header)
|
protected virtual String DoExecute(String url, RequestForm requestForm, Dictionary<string, string> header)
|
||||||
{
|
{
|
||||||
return openRequest.Request(this.url, requestForm, header);
|
return openRequest.Request(this.url, requestForm, header);
|
||||||
}
|
}
|
||||||
@@ -135,9 +133,9 @@ namespace SDKCSharp.Client
|
|||||||
/// <param name="resp">服务器响应内容</param>
|
/// <param name="resp">服务器响应内容</param>
|
||||||
/// <param name="request">请求Request</param>
|
/// <param name="request">请求Request</param>
|
||||||
/// <returns>返回Response</returns>
|
/// <returns>返回Response</returns>
|
||||||
protected virtual T parseResponse<T>(string resp, BaseRequest<T> request) where T: BaseResponse {
|
protected virtual T ParseResponse<T>(string resp, BaseRequest<T> request) where T: BaseResponse {
|
||||||
string method = request.Method;
|
string method = request.Method;
|
||||||
string dataName = method.Replace(DOT, UNDERLINE) + DATA_SUFFIX;
|
string dataName = this.dataNameBuilder.Build(method);
|
||||||
Dictionary<string, object> jsonObject = JsonUtil.ParseToDictionary(resp);
|
Dictionary<string, object> jsonObject = JsonUtil.ParseToDictionary(resp);
|
||||||
object data = jsonObject[dataName];
|
object data = jsonObject[dataName];
|
||||||
string jsonData = data == null ? "{}" : data.ToString();
|
string jsonData = data == null ? "{}" : data.ToString();
|
||||||
|
27
sop-sdk/sdk-csharp/SDKCSharp/Common/CustomDataNameBuilder.cs
Normal file
27
sop-sdk/sdk-csharp/SDKCSharp/Common/CustomDataNameBuilder.cs
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
using System;
|
||||||
|
namespace SDKCSharp.Common
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 返回固定的dataName
|
||||||
|
/// </summary>
|
||||||
|
public class CustomDataNameBuilder: DataNameBuilder
|
||||||
|
{
|
||||||
|
|
||||||
|
private string dataName = "result";
|
||||||
|
|
||||||
|
public CustomDataNameBuilder()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public CustomDataNameBuilder(string dataName)
|
||||||
|
{
|
||||||
|
this.dataName = dataName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Build(string method)
|
||||||
|
{
|
||||||
|
return dataName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
13
sop-sdk/sdk-csharp/SDKCSharp/Common/DataNameBuilder.cs
Normal file
13
sop-sdk/sdk-csharp/SDKCSharp/Common/DataNameBuilder.cs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
using System;
|
||||||
|
namespace SDKCSharp.Common
|
||||||
|
{
|
||||||
|
public interface DataNameBuilder
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 构建数据节点名称
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>返回数据节点名称.</returns>
|
||||||
|
/// <param name="method">方法名.</param>
|
||||||
|
string Build(string method);
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,20 @@
|
|||||||
|
using System;
|
||||||
|
namespace SDKCSharp.Common
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 将方法名中的"."转成"_"并在后面追加"_response"。
|
||||||
|
/// 如:alipay.trade.order.settle --> alipay_trade_order_settle_response。
|
||||||
|
/// </summary>
|
||||||
|
public class DefaultDataNameBuilder : DataNameBuilder
|
||||||
|
{
|
||||||
|
|
||||||
|
private const char DOT = '.';
|
||||||
|
private const char UNDERLINE = '_';
|
||||||
|
private const string DATA_SUFFIX = "_response";
|
||||||
|
|
||||||
|
public string Build(string method)
|
||||||
|
{
|
||||||
|
return method.Replace(DOT, UNDERLINE) + DATA_SUFFIX;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -186,6 +186,11 @@ namespace SDKCSharp.Common
|
|||||||
public string SignTypeName { get => signTypeName; set => signTypeName = value; }
|
public string SignTypeName { get => signTypeName; set => signTypeName = value; }
|
||||||
|
|
||||||
|
|
||||||
|
private DataNameBuilder dataNameBuilder = SdkConfig.dataNameBuilder;
|
||||||
|
/// <summary>
|
||||||
|
/// 节点名称构造器
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The data name builder.</value>
|
||||||
|
public DataNameBuilder DataNameBuilder { get => dataNameBuilder; set => dataNameBuilder = value; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -20,5 +20,7 @@ namespace SDKCSharp.Common
|
|||||||
public static Encoding CHARSET = Encoding.UTF8;
|
public static Encoding CHARSET = Encoding.UTF8;
|
||||||
|
|
||||||
public static SignType SIGN_TYPE = SignType.RSA2;
|
public static SignType SIGN_TYPE = SignType.RSA2;
|
||||||
|
|
||||||
|
public static DataNameBuilder dataNameBuilder = new DefaultDataNameBuilder();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -2,6 +2,7 @@
|
|||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using SDKCSharp.Client;
|
using SDKCSharp.Client;
|
||||||
|
using SDKCSharp.Common;
|
||||||
using SDKCSharp.Model;
|
using SDKCSharp.Model;
|
||||||
using SDKCSharp.Request;
|
using SDKCSharp.Request;
|
||||||
using SDKCSharp.Response;
|
using SDKCSharp.Response;
|
||||||
|
@@ -2,12 +2,13 @@ package com.gitee.sop.sdk.client;
|
|||||||
|
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import com.gitee.sop.sdk.common.DataNameBuilder;
|
||||||
import com.gitee.sop.sdk.common.OpenConfig;
|
import com.gitee.sop.sdk.common.OpenConfig;
|
||||||
import com.gitee.sop.sdk.common.RequestForm;
|
import com.gitee.sop.sdk.common.RequestForm;
|
||||||
import com.gitee.sop.sdk.sign.SopSignException;
|
import com.gitee.sop.sdk.exception.SdkException;
|
||||||
import com.gitee.sop.sdk.request.BaseRequest;
|
import com.gitee.sop.sdk.request.BaseRequest;
|
||||||
import com.gitee.sop.sdk.response.BaseResponse;
|
import com.gitee.sop.sdk.response.BaseResponse;
|
||||||
import com.gitee.sop.sdk.exception.SdkException;
|
import com.gitee.sop.sdk.sign.SopSignException;
|
||||||
import com.gitee.sop.sdk.sign.SopSignature;
|
import com.gitee.sop.sdk.sign.SopSignature;
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
@@ -25,16 +26,13 @@ public class OpenClient {
|
|||||||
|
|
||||||
private static final OpenConfig DEFAULT_CONFIG = new OpenConfig();
|
private static final OpenConfig DEFAULT_CONFIG = new OpenConfig();
|
||||||
|
|
||||||
private static final char DOT = '.';
|
|
||||||
private static final char UNDERLINE = '_';
|
|
||||||
public static final String DATA_SUFFIX = "_response";
|
|
||||||
|
|
||||||
private String url;
|
private String url;
|
||||||
private String appId;
|
private String appId;
|
||||||
private String privateKey;
|
private String privateKey;
|
||||||
|
|
||||||
private OpenConfig openConfig;
|
private OpenConfig openConfig;
|
||||||
private OpenRequest openRequest;
|
private OpenRequest openRequest;
|
||||||
|
private DataNameBuilder dataNameBuilder;
|
||||||
|
|
||||||
public OpenClient(String url, String appId, String privateKey) {
|
public OpenClient(String url, String appId, String privateKey) {
|
||||||
this(url, appId, privateKey, DEFAULT_CONFIG);
|
this(url, appId, privateKey, DEFAULT_CONFIG);
|
||||||
@@ -50,6 +48,7 @@ public class OpenClient {
|
|||||||
this.openConfig = openConfig;
|
this.openConfig = openConfig;
|
||||||
|
|
||||||
this.openRequest = new OpenRequest(openConfig);
|
this.openRequest = new OpenRequest(openConfig);
|
||||||
|
this.dataNameBuilder = openConfig.getDataNameBuilder();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -109,7 +108,7 @@ public class OpenClient {
|
|||||||
|
|
||||||
protected <T extends BaseResponse> T parseResponse(String resp, BaseRequest<T> request) {
|
protected <T extends BaseResponse> T parseResponse(String resp, BaseRequest<T> request) {
|
||||||
String method = request.getMethod();
|
String method = request.getMethod();
|
||||||
String dataName = method.replace(DOT, UNDERLINE) + DATA_SUFFIX;
|
String dataName = dataNameBuilder.build(method);
|
||||||
JSONObject jsonObject = JSON.parseObject(resp);
|
JSONObject jsonObject = JSON.parseObject(resp);
|
||||||
JSONObject data = jsonObject.getJSONObject(dataName);
|
JSONObject data = jsonObject.getJSONObject(dataName);
|
||||||
T t = data.toJavaObject(request.getResponseClass());
|
T t = data.toJavaObject(request.getResponseClass());
|
||||||
|
@@ -0,0 +1,30 @@
|
|||||||
|
package com.gitee.sop.sdk.common;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回固定的
|
||||||
|
* {
|
||||||
|
* "result": {
|
||||||
|
* "code": "20000",
|
||||||
|
* "msg": "Service Currently Unavailable",
|
||||||
|
* "sub_code": "isp.unknow-error",
|
||||||
|
* "sub_msg": "系统繁忙"
|
||||||
|
* },
|
||||||
|
* "sign": "ERITJKEIJKJHKKKKKKKHJEREEEEEEEEEEE"
|
||||||
|
* }
|
||||||
|
* @author tanghc
|
||||||
|
*/
|
||||||
|
public class CustomDataNameBuilder implements DataNameBuilder {
|
||||||
|
private String dataName = "result";
|
||||||
|
|
||||||
|
public CustomDataNameBuilder() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public CustomDataNameBuilder(String dataName) {
|
||||||
|
this.dataName = dataName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String build(String method) {
|
||||||
|
return dataName;
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,13 @@
|
|||||||
|
package com.gitee.sop.sdk.common;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author tanghc
|
||||||
|
*/
|
||||||
|
public interface DataNameBuilder {
|
||||||
|
/**
|
||||||
|
* 构建数据节点名称
|
||||||
|
* @param method 方法名
|
||||||
|
* @return 返回数据节点名称
|
||||||
|
*/
|
||||||
|
String build(String method);
|
||||||
|
}
|
@@ -0,0 +1,28 @@
|
|||||||
|
package com.gitee.sop.sdk.common;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将方法名中的"."转成"_"并在后面追加"_response"<br>
|
||||||
|
* 如:alipay.trade.order.settle --> alipay_trade_order_settle_response<br>
|
||||||
|
* <pre>
|
||||||
|
* {
|
||||||
|
* "alipay_trade_order_settle_response": {
|
||||||
|
* "code": "20000",
|
||||||
|
* "msg": "Service Currently Unavailable",
|
||||||
|
* "sub_code": "isp.unknow-error",
|
||||||
|
* "sub_msg": "系统繁忙"
|
||||||
|
* },
|
||||||
|
* "sign": "ERITJKEIJKJHKKKKKKKHJEREEEEEEEEEEE"
|
||||||
|
* }
|
||||||
|
* </pre>
|
||||||
|
* @author tanghc
|
||||||
|
*/
|
||||||
|
public class DefaultDataNameBuilder implements DataNameBuilder {
|
||||||
|
private static final char DOT = '.';
|
||||||
|
private static final char UNDERLINE = '_';
|
||||||
|
private static final String DATA_SUFFIX = "_response";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String build(String method) {
|
||||||
|
return method.replace(DOT, UNDERLINE) + DATA_SUFFIX;
|
||||||
|
}
|
||||||
|
}
|
@@ -45,4 +45,9 @@ public class OpenConfig {
|
|||||||
private int readTimeoutSeconds = 10;
|
private int readTimeoutSeconds = 10;
|
||||||
/** http写超时时间 */
|
/** http写超时时间 */
|
||||||
private int writeTimeoutSeconds = 10;
|
private int writeTimeoutSeconds = 10;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构建数据节点名称
|
||||||
|
*/
|
||||||
|
private DataNameBuilder dataNameBuilder = SdkConfig.dataNameBuilder;
|
||||||
}
|
}
|
||||||
|
@@ -13,4 +13,6 @@ public class SdkConfig {
|
|||||||
public static String CHARSET = "UTF-8";
|
public static String CHARSET = "UTF-8";
|
||||||
|
|
||||||
public static String SIGN_TYPE = "RSA2";
|
public static String SIGN_TYPE = "RSA2";
|
||||||
|
|
||||||
|
public static volatile DataNameBuilder dataNameBuilder = new DefaultDataNameBuilder();
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user