parent
3bfc5f7cc8
commit
99d90d60cc
@ -0,0 +1,27 @@ |
|||||||
|
package com.gitee.sop.gatewaycommon.easyopen; |
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSON; |
||||||
|
import com.gitee.sop.gatewaycommon.message.Error; |
||||||
|
import com.gitee.sop.gatewaycommon.result.ApiResult; |
||||||
|
import com.gitee.sop.gatewaycommon.result.ResultExecutor; |
||||||
|
import com.gitee.sop.gatewaycommon.zuul.result.ZuulResultExecutor; |
||||||
|
import com.netflix.zuul.context.RequestContext; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author tanghc |
||||||
|
*/ |
||||||
|
public class EasyopenResultExecutor implements ResultExecutor<RequestContext, String> { |
||||||
|
@Override |
||||||
|
public String mergeResult(RequestContext request, String serviceResult) { |
||||||
|
return serviceResult; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String buildErrorResult(RequestContext request, Throwable ex) { |
||||||
|
ApiResult apiResult = new ApiResult(); |
||||||
|
Error error = ZuulResultExecutor.getError(ex); |
||||||
|
apiResult.setCode(error.getSub_code()); |
||||||
|
apiResult.setMsg(error.getSub_msg()); |
||||||
|
return JSON.toJSONString(apiResult); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,34 @@ |
|||||||
|
package com.gitee.sop.gatewaycommon.easyopen; |
||||||
|
|
||||||
|
import com.gitee.sop.gatewaycommon.param.ApiParam; |
||||||
|
import com.gitee.sop.gatewaycommon.validate.AbstractSigner; |
||||||
|
import com.gitee.sop.gatewaycommon.validate.taobao.TaobaoSigner; |
||||||
|
import org.apache.commons.codec.digest.DigestUtils; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.Collections; |
||||||
|
import java.util.List; |
||||||
|
import java.util.Set; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author tanghc |
||||||
|
*/ |
||||||
|
public class EasyopenSigner extends AbstractSigner { |
||||||
|
@Override |
||||||
|
protected String buildServerSign(ApiParam params, String secret) { |
||||||
|
Set<String> keySet = params.keySet(); |
||||||
|
List<String> paramNames = new ArrayList<String>(keySet); |
||||||
|
|
||||||
|
Collections.sort(paramNames); |
||||||
|
|
||||||
|
StringBuilder paramNameValue = new StringBuilder(); |
||||||
|
|
||||||
|
for (String paramName : paramNames) { |
||||||
|
paramNameValue.append(paramName).append(params.get(paramName)); |
||||||
|
} |
||||||
|
|
||||||
|
String source = secret + paramNameValue.toString() + secret; |
||||||
|
|
||||||
|
return DigestUtils.md5Hex(source).toUpperCase(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,26 @@ |
|||||||
|
package com.gitee.sop.gatewaycommon.easyopen; |
||||||
|
|
||||||
|
import com.gitee.sop.gatewaycommon.bean.ApiConfig; |
||||||
|
import com.gitee.sop.gatewaycommon.bean.ApiContext; |
||||||
|
import com.gitee.sop.gatewaycommon.gateway.configuration.BaseGatewayConfiguration; |
||||||
|
import com.gitee.sop.gatewaycommon.param.ParamNames; |
||||||
|
import com.gitee.sop.gatewaycommon.validate.taobao.TaobaoSigner; |
||||||
|
import com.gitee.sop.gatewaycommon.zuul.configuration.BaseZuulConfiguration; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author tanghc |
||||||
|
*/ |
||||||
|
public class EasyopenZuulConfiguration extends BaseZuulConfiguration { |
||||||
|
|
||||||
|
static { |
||||||
|
ParamNames.APP_KEY_NAME = "app_key"; |
||||||
|
ParamNames.API_NAME = "name"; |
||||||
|
ParamNames.SIGN_TYPE_NAME = "sign_type"; |
||||||
|
ParamNames.APP_AUTH_TOKEN_NAME = "access_token"; |
||||||
|
ApiConfig apiConfig = ApiContext.getApiConfig(); |
||||||
|
apiConfig.setSigner(new EasyopenSigner()); |
||||||
|
apiConfig.setZuulResultExecutor(new EasyopenResultExecutor()); |
||||||
|
apiConfig.setMergeResult(false); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,27 @@ |
|||||||
|
package com.gitee.sop.gatewaycommon.manager; |
||||||
|
|
||||||
|
import com.gitee.sop.gatewaycommon.bean.BaseRouteDefinition; |
||||||
|
|
||||||
|
import java.util.HashMap; |
||||||
|
import java.util.Map; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author tanghc |
||||||
|
*/ |
||||||
|
public class RouteDefinitionItemContext { |
||||||
|
// key:id
|
||||||
|
private static Map<String, BaseRouteDefinition> routeDefinitionMap = new HashMap<>(64); |
||||||
|
|
||||||
|
public static void add(BaseRouteDefinition routeDefinition) { |
||||||
|
routeDefinitionMap.put(routeDefinition.getId(), routeDefinition); |
||||||
|
} |
||||||
|
|
||||||
|
public static BaseRouteDefinition getRouteDefinition(String id) { |
||||||
|
return routeDefinitionMap.get(id); |
||||||
|
} |
||||||
|
|
||||||
|
public static void delete(BaseRouteDefinition routeDefinition) { |
||||||
|
routeDefinitionMap.remove(routeDefinition.getId()); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,25 @@ |
|||||||
|
package com.gitee.sop.gatewaycommon.param; |
||||||
|
|
||||||
|
import com.gitee.sop.gatewaycommon.bean.BaseRouteDefinition; |
||||||
|
import com.gitee.sop.gatewaycommon.manager.RouteDefinitionItemContext; |
||||||
|
import com.gitee.sop.gatewaycommon.message.ErrorEnum; |
||||||
|
|
||||||
|
import java.util.Map; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author tanghc |
||||||
|
*/ |
||||||
|
public class ApiParamFactory { |
||||||
|
public static ApiParam build(Map<String, ?> params) { |
||||||
|
ApiParam apiParam = new ApiParam(); |
||||||
|
for (Map.Entry<String, ?> entry : params.entrySet()) { |
||||||
|
apiParam.put(entry.getKey(), entry.getValue()); |
||||||
|
} |
||||||
|
BaseRouteDefinition routeDefinition = RouteDefinitionItemContext.getRouteDefinition(apiParam.fetchNameVersion()); |
||||||
|
if (routeDefinition == null) { |
||||||
|
throw ErrorEnum.ISV_INVALID_METHOD.getErrorMeta().getException(); |
||||||
|
} |
||||||
|
apiParam.setIgnoreValidate(routeDefinition.isIgnoreValidate()); |
||||||
|
return apiParam; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,102 @@ |
|||||||
|
package com.gitee.sop.servercommon.configuration; |
||||||
|
|
||||||
|
import com.gitee.easyopen.ApiContext; |
||||||
|
import com.gitee.easyopen.annotation.Api; |
||||||
|
import com.gitee.easyopen.annotation.ApiService; |
||||||
|
import com.gitee.easyopen.util.ReflectionUtil; |
||||||
|
import com.gitee.sop.servercommon.bean.ServiceApiInfo; |
||||||
|
import com.gitee.sop.servercommon.manager.ApiMetaManager; |
||||||
|
import com.gitee.sop.servercommon.manager.DefaultRequestMappingEvent; |
||||||
|
import com.gitee.sop.servercommon.manager.RequestMappingEvent; |
||||||
|
import com.gitee.sop.servercommon.mapping.ApiMappingHandlerMapping; |
||||||
|
import org.springframework.context.ApplicationContext; |
||||||
|
import org.springframework.core.annotation.AnnotationUtils; |
||||||
|
import org.springframework.core.env.Environment; |
||||||
|
import org.springframework.util.ReflectionUtils; |
||||||
|
import org.springframework.util.StringUtils; |
||||||
|
import org.springframework.web.method.HandlerMethod; |
||||||
|
import org.springframework.web.servlet.mvc.method.RequestMappingInfo; |
||||||
|
|
||||||
|
import java.lang.reflect.Method; |
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.List; |
||||||
|
import java.util.Map; |
||||||
|
import java.util.function.Consumer; |
||||||
|
|
||||||
|
/** |
||||||
|
* 提供给easyopen项目使用 |
||||||
|
* @author tanghc |
||||||
|
*/ |
||||||
|
public class EasyopenServiceConfiguration extends BaseServiceConfiguration { |
||||||
|
|
||||||
|
@Override |
||||||
|
protected RequestMappingEvent getRequestMappingEvent(ApiMetaManager apiMetaManager, Environment environment) { |
||||||
|
return new EasyopenRequestMappingEvent(apiMetaManager, environment); |
||||||
|
} |
||||||
|
|
||||||
|
class EasyopenRequestMappingEvent extends DefaultRequestMappingEvent { |
||||||
|
String prefixPath; |
||||||
|
|
||||||
|
public EasyopenRequestMappingEvent(ApiMetaManager apiMetaManager, Environment environment) { |
||||||
|
super(apiMetaManager, environment); |
||||||
|
|
||||||
|
String prefixPath = getEnvironment().getProperty("easyopen.prefix-path"); |
||||||
|
if (prefixPath == null) { |
||||||
|
throw new IllegalArgumentException("请在application.propertis中设置easyopen.prefix-path属性,填IndexController上面的@RequestMapping()中的值"); |
||||||
|
} |
||||||
|
this.prefixPath = prefixPath; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected List<ServiceApiInfo.ApiMeta> buildApiMetaList(ApiMappingHandlerMapping apiMappingHandlerMapping) { |
||||||
|
ApplicationContext ctx = getApplicationContext(); |
||||||
|
String[] apiServiceNames = ReflectionUtil.findApiServiceNames(ctx); |
||||||
|
List<ServiceApiInfo.ApiMeta> apiMetaList = new ArrayList<>(); |
||||||
|
for (String apiServiceName : apiServiceNames) { |
||||||
|
Object bean = ctx.getBean(apiServiceName); |
||||||
|
doWithMethods(bean.getClass(), method -> { |
||||||
|
Api api = AnnotationUtils.findAnnotation(method, Api.class); |
||||||
|
ServiceApiInfo.ApiMeta apiMeta = new ServiceApiInfo.ApiMeta(); |
||||||
|
apiMeta.setName(api.name()); |
||||||
|
apiMeta.setVersion(api.version()); |
||||||
|
apiMeta.setIgnoreValidate(api.ignoreValidate()); |
||||||
|
// /api/goods.get/
|
||||||
|
String servletPath = this.buildPath(api); |
||||||
|
apiMeta.setPath(servletPath); |
||||||
|
apiMetaList.add(apiMeta); |
||||||
|
}); |
||||||
|
} |
||||||
|
return apiMetaList; |
||||||
|
} |
||||||
|
|
||||||
|
protected void doWithMethods(Class<?> clazz, Consumer<Method> consumer) { |
||||||
|
// Keep backing up the inheritance hierarchy.
|
||||||
|
Method[] methods = clazz.getDeclaredMethods(); |
||||||
|
for (Method method : methods) { |
||||||
|
boolean match = !method.isSynthetic() && AnnotationUtils.findAnnotation(method, Api.class) != null; |
||||||
|
if (match) { |
||||||
|
consumer.accept(method); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
protected String buildPath(Api api) { |
||||||
|
// /api/goods.get/
|
||||||
|
String servletPath = prefixPath + "/" + api.name() + "/"; |
||||||
|
String version = api.version(); |
||||||
|
if (StringUtils.hasLength(version)) { |
||||||
|
// /api/goods.get/1.0/
|
||||||
|
servletPath = servletPath + version + "/"; |
||||||
|
} |
||||||
|
return servletPath; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void after() { |
||||||
|
super.after(); |
||||||
|
// 取消验证
|
||||||
|
// todo:需要在easyopen端修改
|
||||||
|
//ApiContext.getApiConfig().setIgnoreValidate(true);
|
||||||
|
} |
||||||
|
} |
@ -0,0 +1,93 @@ |
|||||||
|
package com.gitee.sop; |
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSON; |
||||||
|
import junit.framework.TestCase; |
||||||
|
import org.apache.commons.codec.digest.DigestUtils; |
||||||
|
import org.junit.Test; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
import java.net.URLEncoder; |
||||||
|
import java.text.SimpleDateFormat; |
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.Collections; |
||||||
|
import java.util.Date; |
||||||
|
import java.util.HashMap; |
||||||
|
import java.util.List; |
||||||
|
import java.util.Map; |
||||||
|
import java.util.Set; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author tanghc |
||||||
|
*/ |
||||||
|
public class EasyopenClientPostTest extends TestBase { |
||||||
|
|
||||||
|
String url = "http://localhost:8081/api"; |
||||||
|
String appKey = "easyopen_test"; |
||||||
|
String secret = "G9w0BAQEFAAOCAQ8AMIIBCgKCA"; |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testPost() throws IOException { |
||||||
|
// 业务参数
|
||||||
|
Map<String, String> bizParams = new HashMap<String, String>(); |
||||||
|
bizParams.put("goods_name", "iphoneX"); |
||||||
|
|
||||||
|
String json = JSON.toJSONString(bizParams); |
||||||
|
json = URLEncoder.encode(json, "utf-8"); |
||||||
|
|
||||||
|
// 系统参数
|
||||||
|
Map<String, String> params = new HashMap<>(); |
||||||
|
params.put("name", "goods.get"); |
||||||
|
params.put("app_key", appKey); |
||||||
|
params.put("data", json); |
||||||
|
params.put("timestamp", getTime()); |
||||||
|
params.put("version", ""); |
||||||
|
|
||||||
|
String sign = buildSign(params, secret); |
||||||
|
|
||||||
|
params.put("sign", sign); |
||||||
|
|
||||||
|
System.out.println("=====请求数据====="); |
||||||
|
System.out.println(JSON.toJSONString(params)); |
||||||
|
System.out.println("=====返回结果====="); |
||||||
|
String resp = post(url, params); |
||||||
|
System.out.println(resp); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 构建签名串 |
||||||
|
* @param paramsMap 请求参数 |
||||||
|
* @param secret 秘钥 |
||||||
|
* @return |
||||||
|
* @throws IOException |
||||||
|
*/ |
||||||
|
public String buildSign(Map<String, ?> paramsMap, String secret) throws IOException { |
||||||
|
Set<String> keySet = paramsMap.keySet(); |
||||||
|
List<String> paramNames = new ArrayList<String>(keySet); |
||||||
|
|
||||||
|
Collections.sort(paramNames); |
||||||
|
|
||||||
|
StringBuilder paramNameValue = new StringBuilder(); |
||||||
|
|
||||||
|
for (String paramName : paramNames) { |
||||||
|
paramNameValue.append(paramName).append(paramsMap.get(paramName)); |
||||||
|
} |
||||||
|
|
||||||
|
String source = secret + paramNameValue.toString() + secret; |
||||||
|
|
||||||
|
return md5(source); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 生成md5,全部大写。 |
||||||
|
* |
||||||
|
* @param source |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public static String md5(String source) { |
||||||
|
return DigestUtils.md5Hex(source).toUpperCase(); |
||||||
|
} |
||||||
|
|
||||||
|
public String getTime() { |
||||||
|
return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()); |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue