Merge branch 'develop'

1.x
tanghc 6 years ago
commit 16d7d77083
  1. 10
      changelog.md
  2. 63
      doc/docs/_sidebar.md
  3. 2
      doc/docs/files/10010_快速体验.md
  4. 33
      doc/docs/files/10111_动态修改请求参数.md
  5. 2
      sop-admin/sop-admin-server/pom.xml
  6. 2
      sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/ZookeeperContext.java
  7. 2
      sop-admin/sop-admin-server/src/main/resources/public/index.html
  8. 1
      sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-9f479afe.2db777db.js
  9. 1
      sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-9f479afe.53fe8d4e.js
  10. 23
      sop-admin/sop-admin-vue/src/views/service/serviceList.vue
  11. 2
      sop-common/pom.xml
  12. 4
      sop-common/sop-gateway-common/pom.xml
  13. 7
      sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/ApiConfig.java
  14. 2
      sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/DefaultEnvGrayManager.java
  15. 18
      sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/ParameterFormatter.java
  16. 8
      sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/validate/ApiValidator.java
  17. 16
      sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/configuration/BaseZuulConfiguration.java
  18. 7
      sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/filter/BaseZuulFilter.java
  19. 42
      sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/filter/PreParameterFormatterFilter.java
  20. 10
      sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/param/ZuulParameterFormatter.java
  21. 183
      sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/param/ZuulParameterUtil.java
  22. 2
      sop-common/sop-registry-api/pom.xml
  23. 14
      sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/bean/ServiceInfo.java
  24. 7
      sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/service/impl/RegistryServiceNacos.java
  25. 4
      sop-common/sop-service-common/pom.xml
  26. 5
      sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/bean/ServiceConstants.java
  27. 18
      sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/bean/ZookeeperTool.java
  28. 10
      sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/configuration/BaseServiceConfiguration.java
  29. 9
      sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/manager/ServiceZookeeperApiMetaManager.java
  30. 3
      sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/param/ServiceParamValidator.java
  31. 19
      sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/route/ServiceRouteInfo.java
  32. 4
      sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/swagger/SwaggerSupport.java
  33. 6
      sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/util/OpenUtil.java
  34. 2
      sop-example/sop-auth/pom.xml
  35. 2
      sop-example/sop-book/sop-book-web/pom.xml
  36. 2
      sop-example/sop-easyopen/pom.xml
  37. 2
      sop-example/sop-springmvc/pom.xml
  38. 19
      sop-example/sop-story/sop-story-web/pom.xml
  39. 14
      sop-example/sop-story/sop-story-web/src/main/java/com/gitee/sop/storyweb/config/OpenServiceConfig.java
  40. 44
      sop-example/sop-story/sop-story-web/src/main/java/com/gitee/sop/storyweb/controller/AlipayController.java
  41. 2
      sop-gateway/pom.xml
  42. 11
      sop-gateway/src/main/java/com/gitee/sop/gateway/controller/RedirectController.java
  43. 18
      sop-gateway/src/test/java/com/gitee/sop/gateway/CuratorTest.java
  44. 23
      sop-sdk/sdk-java/src/main/java/com/gitee/sop/sdk/client/OpenHttp.java
  45. 6
      sop-sdk/sdk-java/src/test/java/com/gitee/sop/sdk/SdkTest.java
  46. 280
      sop-test/src/main/java/com/gitee/sop/test/Client.java
  47. 219
      sop-test/src/test/java/com/gitee/sop/test/AllInOneTest.java
  48. 2
      sop-website/website-server/pom.xml
  49. 3
      sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/bean/DocInfo.java
  50. 5
      sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/bean/WebsiteConstants.java
  51. 103
      sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/bean/ZookeeperContext.java
  52. 6
      sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/controller/DocController.java
  53. 3
      sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/manager/DocManager.java
  54. 101
      sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/manager/DocManagerImpl.java
  55. 213
      sop.sql

@ -1,5 +1,15 @@
# changelog
## 1.15.0
- 优化预发布、灰度
- 网关动态修改请求参数
- 支持swagger-bootstrap插件
- admin服务列表在线/离线筛选(在线靠前)
- 文档刷新逻辑
- 测试all in one
- 修复中文乱码问题
## 1.14.0
- 支持预发布、灰度发布环境

@ -1,33 +1,34 @@
* [首页](/?t=1565165921486)
* [首页](/?t=1565681110217)
* 开发文档
* [快速体验](files/10010_快速体验.md?t=1565165921490)
* [项目接入到SOP](files/10011_项目接入到SOP.md?t=1565165921508)
* [新增接口](files/10020_新增接口.md?t=1565165921508)
* [业务参数校验](files/10030_业务参数校验.md?t=1565165921509)
* [错误处理](files/10040_错误处理.md?t=1565165921509)
* [编写文档](files/10041_编写文档.md?t=1565165921509)
* [接口交互详解](files/10050_接口交互详解.md?t=1565165921509)
* [easyopen支持](files/10070_easyopen支持.md?t=1565165921509)
* [使用签名校验工具](files/10080_使用签名校验工具.md?t=1565165921509)
* [ISV管理](files/10085_ISV管理.md?t=1565165921509)
* [自定义路由](files/10086_自定义路由.md?t=1565165921509)
* [自定义返回结果](files/10087_自定义返回结果.md?t=1565165921510)
* [自定义过滤器](files/10088_自定义过滤器.md?t=1565165921510)
* [路由授权](files/10090_路由授权.md?t=1565165921510)
* [接口限流](files/10092_接口限流.md?t=1565165921510)
* [监控日志](files/10093_监控日志.md?t=1565165921510)
* [SDK开发](files/10095_SDK开发.md?t=1565165921510)
* [使用SpringCloudGateway](files/10096_使用SpringCloudGateway.md?t=1565165921510)
* [应用授权](files/10097_应用授权.md?t=1565165921510)
* [传统web开发](files/10100_传统web开发.md?t=1565165921510)
* [文件上传](files/10104_文件上传.md?t=1565165921510)
* [nacos注册中心](files/10106_nacos注册中心.md?t=1565165921510)
* [扩展其它注册中心](files/10107_扩展其它注册中心.md?t=1565165921511)
* [配置Sleuth链路追踪](files/10109_配置Sleuth链路追踪.md?t=1565165921511)
* [预发布灰度发布](files/10110_预发布灰度发布.md?t=1565165921511)
* [快速体验](files/10010_快速体验.md?t=1565681110219)
* [项目接入到SOP](files/10011_项目接入到SOP.md?t=1565681110236)
* [新增接口](files/10020_新增接口.md?t=1565681110236)
* [业务参数校验](files/10030_业务参数校验.md?t=1565681110236)
* [错误处理](files/10040_错误处理.md?t=1565681110236)
* [编写文档](files/10041_编写文档.md?t=1565681110236)
* [接口交互详解](files/10050_接口交互详解.md?t=1565681110236)
* [easyopen支持](files/10070_easyopen支持.md?t=1565681110236)
* [使用签名校验工具](files/10080_使用签名校验工具.md?t=1565681110237)
* [ISV管理](files/10085_ISV管理.md?t=1565681110237)
* [自定义路由](files/10086_自定义路由.md?t=1565681110237)
* [自定义返回结果](files/10087_自定义返回结果.md?t=1565681110237)
* [自定义过滤器](files/10088_自定义过滤器.md?t=1565681110237)
* [路由授权](files/10090_路由授权.md?t=1565681110237)
* [接口限流](files/10092_接口限流.md?t=1565681110237)
* [监控日志](files/10093_监控日志.md?t=1565681110237)
* [SDK开发](files/10095_SDK开发.md?t=1565681110237)
* [使用SpringCloudGateway](files/10096_使用SpringCloudGateway.md?t=1565681110237)
* [应用授权](files/10097_应用授权.md?t=1565681110238)
* [传统web开发](files/10100_传统web开发.md?t=1565681110238)
* [文件上传](files/10104_文件上传.md?t=1565681110238)
* [nacos注册中心](files/10106_nacos注册中心.md?t=1565681110238)
* [扩展其它注册中心](files/10107_扩展其它注册中心.md?t=1565681110238)
* [配置Sleuth链路追踪](files/10109_配置Sleuth链路追踪.md?t=1565681110238)
* [预发布灰度发布](files/10110_预发布灰度发布.md?t=1565681110238)
* [动态修改请求参数](files/10111_动态修改请求参数.md?t=1565681110238)
* 原理分析
* [原理分析之@ApiMapping](files/90010_原理分析之@ApiMapping.md?t=1565165921511)
* [原理分析之路由存储](files/90011_原理分析之路由存储.md?t=1565165921511)
* [原理分析之如何路由](files/90012_原理分析之如何路由.md?t=1565165921511)
* [原理分析之文档归纳](files/90013_原理分析之文档归纳.md?t=1565165921511)
* [常见问题](files/90100_常见问题.md?t=1565165921511)
* [原理分析之@ApiMapping](files/90010_原理分析之@ApiMapping.md?t=1565681110238)
* [原理分析之路由存储](files/90011_原理分析之路由存储.md?t=1565681110238)
* [原理分析之如何路由](files/90012_原理分析之如何路由.md?t=1565681110238)
* [原理分析之文档归纳](files/90013_原理分析之文档归纳.md?t=1565681110239)
* [常见问题](files/90100_常见问题.md?t=1565681110239)

@ -13,7 +13,7 @@
- 启动微服务:打开sop-story-web下的`application-dev.properties`文件
1. 指定zookeeper地址,如果zookeeper安装在本机则不用改
2. 运行`SopStoryApplication.java`
- 找到sop-test,打开测试用例,进行接口调用测试,运行com.gitee.sop.AlipayClientPostTest.testPost()
- 找到sop-test,打开`AllInOneTest.java`进行接口调用测试
确保注册中心先启动

@ -0,0 +1,33 @@
# 动态修改请求参数
自1.14.0开始,zuul网关支持动态修改请求参数。即在网关修改客户端传递过来的参数,然后发送到微服务端。
```
客户端参数{"name": "jim"} --> zuul中修改为{"name": "Lucy"} --> 微服务端将收到{"name": "Lucy"}
```
使用场景:客户端请求参数经过加密,在网关解密后,再次发送明文参数给微服务端
- 如何使用
在网关springboot启动函数中添加如下代码
```java
public static void main(String[] args) {
ApiConfig.getInstance().setZuulParameterFormatter(requestParams -> {
// 获取biz_content
JSONObject jsonObject = requestParams.getJSONObject(ParamNames.BIZ_CONTENT_NAME);
// 修改biz_content中的值
jsonObject.put("name", "name修改了111");
jsonObject.put("remark", "remark修改了222");
// 重新设置biz_content
requestParams.put(ParamNames.BIZ_CONTENT_NAME, jsonObject);
});
SpringApplication.run(SopGatewayApplication.class, args);
}
```
其中requestParams是客户端传递过来的参数,直接修改其中的值即可。
更多参考:com.gitee.sop.gatewaycommon.zuul.filter.PreParameterFormatterFilter.java

@ -30,7 +30,7 @@
<dependency>
<groupId>com.gitee.sop</groupId>
<artifactId>sop-registry-api</artifactId>
<version>1.14.0-SNAPSHOT</version>
<version>1.15.0-SNAPSHOT</version>
</dependency>
<!-- easyopen starter -->

@ -288,7 +288,7 @@ public class ZookeeperContext {
}
/**
* 监听一个节点
* 监听一个临时节点
*
* @param path
* @param listenCallback 回调

@ -1 +1 @@
<!DOCTYPE html><html><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge,chrome=1"><meta name=viewport content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no"><link rel=icon href=favicon.ico><title>SOP Admin</title><link href=static/css/chunk-elementUI.81cf475c.css rel=stylesheet><link href=static/css/chunk-libs.3dfb7769.css rel=stylesheet><link href=static/css/app.4f0872ef.css rel=stylesheet></head><body><noscript><strong>We're sorry but SOP Admin doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id=app></div><script>(function(e){function n(n){for(var r,c,a=n[0],f=n[1],i=n[2],l=0,d=[];l<a.length;l++)c=a[l],u[c]&&d.push(u[c][0]),u[c]=0;for(r in f)Object.prototype.hasOwnProperty.call(f,r)&&(e[r]=f[r]);h&&h(n);while(d.length)d.shift()();return o.push.apply(o,i||[]),t()}function t(){for(var e,n=0;n<o.length;n++){for(var t=o[n],r=!0,c=1;c<t.length;c++){var a=t[c];0!==u[a]&&(r=!1)}r&&(o.splice(n--,1),e=f(f.s=t[0]))}return e}var r={},c={runtime:0},u={runtime:0},o=[];function a(e){return f.p+"static/js/"+({}[e]||e)+"."+{"chunk-238a81e9":"5955f13d","chunk-25908fca":"ca176fa6","chunk-2d2085ef":"7c741493","chunk-2d221c34":"c8ef105a","chunk-34c76be7":"98e1e7e5","chunk-37401378":"4e39ec9b","chunk-6f78c9fe":"f1ed64fa","chunk-73b2dcec":"14f248eb","chunk-9b31c83a":"2758df30","chunk-9f479afe":"2db777db","chunk-ea2e58a4":"f3f85b0e"}[e]+".js"}function f(n){if(r[n])return r[n].exports;var t=r[n]={i:n,l:!1,exports:{}};return e[n].call(t.exports,t,t.exports,f),t.l=!0,t.exports}f.e=function(e){var n=[],t={"chunk-238a81e9":1,"chunk-25908fca":1,"chunk-34c76be7":1,"chunk-37401378":1,"chunk-73b2dcec":1,"chunk-9b31c83a":1,"chunk-ea2e58a4":1};c[e]?n.push(c[e]):0!==c[e]&&t[e]&&n.push(c[e]=new Promise(function(n,t){for(var r="static/css/"+({}[e]||e)+"."+{"chunk-238a81e9":"e8e2beee","chunk-25908fca":"89ab33e8","chunk-2d2085ef":"31d6cfe0","chunk-2d221c34":"31d6cfe0","chunk-34c76be7":"f531fb07","chunk-37401378":"a43114f3","chunk-6f78c9fe":"31d6cfe0","chunk-73b2dcec":"99cf6327","chunk-9b31c83a":"3b12267b","chunk-9f479afe":"31d6cfe0","chunk-ea2e58a4":"d10599db"}[e]+".css",u=f.p+r,o=document.getElementsByTagName("link"),a=0;a<o.length;a++){var i=o[a],l=i.getAttribute("data-href")||i.getAttribute("href");if("stylesheet"===i.rel&&(l===r||l===u))return n()}var d=document.getElementsByTagName("style");for(a=0;a<d.length;a++){i=d[a],l=i.getAttribute("data-href");if(l===r||l===u)return n()}var h=document.createElement("link");h.rel="stylesheet",h.type="text/css",h.onload=n,h.onerror=function(n){var r=n&&n.target&&n.target.src||u,o=new Error("Loading CSS chunk "+e+" failed.\n("+r+")");o.code="CSS_CHUNK_LOAD_FAILED",o.request=r,delete c[e],h.parentNode.removeChild(h),t(o)},h.href=u;var s=document.getElementsByTagName("head")[0];s.appendChild(h)}).then(function(){c[e]=0}));var r=u[e];if(0!==r)if(r)n.push(r[2]);else{var o=new Promise(function(n,t){r=u[e]=[n,t]});n.push(r[2]=o);var i,l=document.createElement("script");l.charset="utf-8",l.timeout=120,f.nc&&l.setAttribute("nonce",f.nc),l.src=a(e),i=function(n){l.onerror=l.onload=null,clearTimeout(d);var t=u[e];if(0!==t){if(t){var r=n&&("load"===n.type?"missing":n.type),c=n&&n.target&&n.target.src,o=new Error("Loading chunk "+e+" failed.\n("+r+": "+c+")");o.type=r,o.request=c,t[1](o)}u[e]=void 0}};var d=setTimeout(function(){i({type:"timeout",target:l})},12e4);l.onerror=l.onload=i,document.head.appendChild(l)}return Promise.all(n)},f.m=e,f.c=r,f.d=function(e,n,t){f.o(e,n)||Object.defineProperty(e,n,{enumerable:!0,get:t})},f.r=function(e){"undefined"!==typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},f.t=function(e,n){if(1&n&&(e=f(e)),8&n)return e;if(4&n&&"object"===typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(f.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&n&&"string"!=typeof e)for(var r in e)f.d(t,r,function(n){return e[n]}.bind(null,r));return t},f.n=function(e){var n=e&&e.__esModule?function(){return e["default"]}:function(){return e};return f.d(n,"a",n),n},f.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},f.p="",f.oe=function(e){throw console.error(e),e};var i=window["webpackJsonp"]=window["webpackJsonp"]||[],l=i.push.bind(i);i.push=n,i=i.slice();for(var d=0;d<i.length;d++)n(i[d]);var h=l;t()})([]);</script><script src=static/js/chunk-elementUI.8ebdfbab.js></script><script src=static/js/chunk-libs.9cf9cc40.js></script><script src=static/js/app.8145abe4.js></script></body></html>
<!DOCTYPE html><html><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge,chrome=1"><meta name=viewport content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no"><link rel=icon href=favicon.ico><title>SOP Admin</title><link href=static/css/chunk-elementUI.81cf475c.css rel=stylesheet><link href=static/css/chunk-libs.3dfb7769.css rel=stylesheet><link href=static/css/app.4f0872ef.css rel=stylesheet></head><body><noscript><strong>We're sorry but SOP Admin doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id=app></div><script>(function(e){function n(n){for(var r,c,a=n[0],f=n[1],i=n[2],l=0,h=[];l<a.length;l++)c=a[l],u[c]&&h.push(u[c][0]),u[c]=0;for(r in f)Object.prototype.hasOwnProperty.call(f,r)&&(e[r]=f[r]);d&&d(n);while(h.length)h.shift()();return o.push.apply(o,i||[]),t()}function t(){for(var e,n=0;n<o.length;n++){for(var t=o[n],r=!0,c=1;c<t.length;c++){var a=t[c];0!==u[a]&&(r=!1)}r&&(o.splice(n--,1),e=f(f.s=t[0]))}return e}var r={},c={runtime:0},u={runtime:0},o=[];function a(e){return f.p+"static/js/"+({}[e]||e)+"."+{"chunk-238a81e9":"5955f13d","chunk-25908fca":"ca176fa6","chunk-2d2085ef":"7c741493","chunk-2d221c34":"c8ef105a","chunk-34c76be7":"98e1e7e5","chunk-37401378":"4e39ec9b","chunk-6f78c9fe":"f1ed64fa","chunk-73b2dcec":"14f248eb","chunk-9b31c83a":"2758df30","chunk-9f479afe":"53fe8d4e","chunk-ea2e58a4":"f3f85b0e"}[e]+".js"}function f(n){if(r[n])return r[n].exports;var t=r[n]={i:n,l:!1,exports:{}};return e[n].call(t.exports,t,t.exports,f),t.l=!0,t.exports}f.e=function(e){var n=[],t={"chunk-238a81e9":1,"chunk-25908fca":1,"chunk-34c76be7":1,"chunk-37401378":1,"chunk-73b2dcec":1,"chunk-9b31c83a":1,"chunk-ea2e58a4":1};c[e]?n.push(c[e]):0!==c[e]&&t[e]&&n.push(c[e]=new Promise(function(n,t){for(var r="static/css/"+({}[e]||e)+"."+{"chunk-238a81e9":"e8e2beee","chunk-25908fca":"89ab33e8","chunk-2d2085ef":"31d6cfe0","chunk-2d221c34":"31d6cfe0","chunk-34c76be7":"f531fb07","chunk-37401378":"a43114f3","chunk-6f78c9fe":"31d6cfe0","chunk-73b2dcec":"99cf6327","chunk-9b31c83a":"3b12267b","chunk-9f479afe":"31d6cfe0","chunk-ea2e58a4":"d10599db"}[e]+".css",u=f.p+r,o=document.getElementsByTagName("link"),a=0;a<o.length;a++){var i=o[a],l=i.getAttribute("data-href")||i.getAttribute("href");if("stylesheet"===i.rel&&(l===r||l===u))return n()}var h=document.getElementsByTagName("style");for(a=0;a<h.length;a++){i=h[a],l=i.getAttribute("data-href");if(l===r||l===u)return n()}var d=document.createElement("link");d.rel="stylesheet",d.type="text/css",d.onload=n,d.onerror=function(n){var r=n&&n.target&&n.target.src||u,o=new Error("Loading CSS chunk "+e+" failed.\n("+r+")");o.code="CSS_CHUNK_LOAD_FAILED",o.request=r,delete c[e],d.parentNode.removeChild(d),t(o)},d.href=u;var s=document.getElementsByTagName("head")[0];s.appendChild(d)}).then(function(){c[e]=0}));var r=u[e];if(0!==r)if(r)n.push(r[2]);else{var o=new Promise(function(n,t){r=u[e]=[n,t]});n.push(r[2]=o);var i,l=document.createElement("script");l.charset="utf-8",l.timeout=120,f.nc&&l.setAttribute("nonce",f.nc),l.src=a(e),i=function(n){l.onerror=l.onload=null,clearTimeout(h);var t=u[e];if(0!==t){if(t){var r=n&&("load"===n.type?"missing":n.type),c=n&&n.target&&n.target.src,o=new Error("Loading chunk "+e+" failed.\n("+r+": "+c+")");o.type=r,o.request=c,t[1](o)}u[e]=void 0}};var h=setTimeout(function(){i({type:"timeout",target:l})},12e4);l.onerror=l.onload=i,document.head.appendChild(l)}return Promise.all(n)},f.m=e,f.c=r,f.d=function(e,n,t){f.o(e,n)||Object.defineProperty(e,n,{enumerable:!0,get:t})},f.r=function(e){"undefined"!==typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},f.t=function(e,n){if(1&n&&(e=f(e)),8&n)return e;if(4&n&&"object"===typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(f.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&n&&"string"!=typeof e)for(var r in e)f.d(t,r,function(n){return e[n]}.bind(null,r));return t},f.n=function(e){var n=e&&e.__esModule?function(){return e["default"]}:function(){return e};return f.d(n,"a",n),n},f.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},f.p="",f.oe=function(e){throw console.error(e),e};var i=window["webpackJsonp"]=window["webpackJsonp"]||[],l=i.push.bind(i);i.push=n,i=i.slice();for(var h=0;h<i.length;h++)n(i[h]);var d=l;t()})([]);</script><script src=static/js/chunk-elementUI.8ebdfbab.js></script><script src=static/js/chunk-libs.9cf9cc40.js></script><script src=static/js/app.8145abe4.js></script></body></html>

@ -82,8 +82,10 @@
<el-button v-if="!scope.row.metadata.env" type="text" size="mini" @click="onEnvPreOpen(scope.row)">开启预发布</el-button>
<el-button v-if="!scope.row.metadata.env" type="text" size="mini" @click="onEnvGrayOpen(scope.row)">开启灰度</el-button>
</span>
<el-button v-if="scope.row.status === 'UP'" type="text" size="mini" @click="onDisable(scope.row)">禁用</el-button>
<el-button v-if="scope.row.status === 'OUT_OF_SERVICE'" type="text" size="mini" @click="onEnable(scope.row)">启用</el-button>
<span style="margin-left: 10px;">
<el-button v-if="scope.row.status === 'UP'" type="text" size="mini" @click="onDisable(scope.row)">禁用</el-button>
<el-button v-if="scope.row.status === 'OUT_OF_SERVICE'" type="text" size="mini" @click="onEnable(scope.row)">启用</el-button>
</span>
</div>
</template>
</el-table-column>
@ -234,11 +236,9 @@ export default {
})
},
loadRouteList: function(serviceId) {
if (this.routeList.length === 0) {
this.post('route.list/1.2', { serviceId: serviceId.toLowerCase() }, function(resp) {
this.routeList = resp.data
})
}
this.post('route.list/1.2', { serviceId: serviceId.toLowerCase() }, function(resp) {
this.routeList = resp.data
})
},
getGraySelectData: function(oldRouteId) {
return this.routeList.filter(routeNew => {
@ -393,11 +393,14 @@ export default {
},
renderServiceName: function(row) {
let instanceCount = ''
if (row.children && row.children.length > 0) {
const onlineCount = row.children.filter(el => {
//
if (row.parentId === 0) {
const children = row.children || []
const childCount = children.length
const onlineCount = children.filter(el => {
return el.status === 'UP'
}).length
instanceCount = ` (${onlineCount}/${row.children.length})`
instanceCount = `(${onlineCount}/${childCount})`
}
return row.serviceId + instanceCount
}

@ -5,7 +5,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.gitee.sop</groupId>
<artifactId>sop-common</artifactId>
<version>1.14.0-SNAPSHOT</version>
<version>1.15.0-SNAPSHOT</version>
<packaging>pom</packaging>
<properties>

@ -5,11 +5,11 @@
<parent>
<groupId>com.gitee.sop</groupId>
<artifactId>sop-common</artifactId>
<version>1.14.0-SNAPSHOT</version>
<version>1.15.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>sop-gateway-common</artifactId>
<version>1.14.0-SNAPSHOT</version>
<version>1.15.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>sop-gateway-common</name>

@ -5,18 +5,18 @@ import com.gitee.sop.gatewaycommon.gateway.result.GatewayResult;
import com.gitee.sop.gatewaycommon.gateway.result.GatewayResultExecutor;
import com.gitee.sop.gatewaycommon.limit.DefaultLimitManager;
import com.gitee.sop.gatewaycommon.limit.LimitManager;
import com.gitee.sop.gatewaycommon.manager.DefaultEnvGrayManager;
import com.gitee.sop.gatewaycommon.manager.DefaultIPBlacklistManager;
import com.gitee.sop.gatewaycommon.manager.DefaultIsvRoutePermissionManager;
import com.gitee.sop.gatewaycommon.manager.DefaultLimitConfigManager;
import com.gitee.sop.gatewaycommon.manager.DefaultRouteConfigManager;
import com.gitee.sop.gatewaycommon.manager.DefaultServiceErrorManager;
import com.gitee.sop.gatewaycommon.manager.DefaultEnvGrayManager;
import com.gitee.sop.gatewaycommon.manager.EnvGrayManager;
import com.gitee.sop.gatewaycommon.manager.IPBlacklistManager;
import com.gitee.sop.gatewaycommon.manager.IsvRoutePermissionManager;
import com.gitee.sop.gatewaycommon.manager.LimitConfigManager;
import com.gitee.sop.gatewaycommon.manager.RouteConfigManager;
import com.gitee.sop.gatewaycommon.manager.ServiceErrorManager;
import com.gitee.sop.gatewaycommon.manager.EnvGrayManager;
import com.gitee.sop.gatewaycommon.param.ParamBuilder;
import com.gitee.sop.gatewaycommon.result.DataNameBuilder;
import com.gitee.sop.gatewaycommon.result.DefaultDataNameBuilder;
@ -34,6 +34,7 @@ import com.gitee.sop.gatewaycommon.validate.Signer;
import com.gitee.sop.gatewaycommon.validate.Validator;
import com.gitee.sop.gatewaycommon.zuul.configuration.ZuulErrorController;
import com.gitee.sop.gatewaycommon.zuul.param.ZuulParamBuilder;
import com.gitee.sop.gatewaycommon.zuul.param.ZuulParameterFormatter;
import com.gitee.sop.gatewaycommon.zuul.result.ZuulResultExecutor;
import com.netflix.zuul.context.RequestContext;
import lombok.Data;
@ -149,6 +150,8 @@ public class ApiConfig {
*/
private ZuulErrorController zuulErrorController = new ZuulErrorController();
private ZuulParameterFormatter zuulParameterFormatter;
// -------- fields ---------
/**

@ -40,7 +40,7 @@ public class DefaultEnvGrayManager implements EnvGrayManager {
if (serviceId == null || nameVersion == null) {
return null;
}
boolean opened = instanceIdServiceIdMap.values().contains(serviceId);
boolean opened = instanceIdServiceIdMap.containsValue(serviceId);
// 没有开启灰度
if (!opened) {
return null;

@ -0,0 +1,18 @@
package com.gitee.sop.gatewaycommon.manager;
import java.util.Map;
/**
* 参数格式化
*
* @author tanghc
*/
public interface ParameterFormatter<T extends Map<String, Object>> {
/**
* 参数格式化即动态修改请求参数
*
* @param requestParams 原始请求参数在此基础上追加或修改参数
*/
void format(T requestParams);
}

@ -93,6 +93,14 @@ public class ApiValidator implements Validator {
* @param param 接口参数
*/
protected void checkEnable(ApiParam param) {
String name = param.fetchName();
if (name == null) {
throw ErrorEnum.ISV_MISSING_METHOD.getErrorMeta().getException();
}
String version = param.fetchVersion();
if (version == null) {
throw ErrorEnum.ISV_MISSING_VERSION.getErrorMeta().getException();
}
String routeId = param.fetchNameVersion();
// 检查路由是否存在
RouteRepositoryContext.checkExist(routeId, ErrorEnum.ISV_INVALID_METHOD);

@ -1,8 +1,10 @@
package com.gitee.sop.gatewaycommon.zuul.configuration;
import com.alibaba.fastjson.JSONObject;
import com.gitee.sop.gatewaycommon.bean.ApiConfig;
import com.gitee.sop.gatewaycommon.bean.ApiContext;
import com.gitee.sop.gatewaycommon.manager.AbstractConfiguration;
import com.gitee.sop.gatewaycommon.manager.ParameterFormatter;
import com.gitee.sop.gatewaycommon.manager.RouteRepositoryContext;
import com.gitee.sop.gatewaycommon.param.ParamBuilder;
import com.gitee.sop.gatewaycommon.zuul.filter.ErrorFilter;
@ -10,6 +12,7 @@ import com.gitee.sop.gatewaycommon.zuul.filter.FormBodyWrapperFilterExt;
import com.gitee.sop.gatewaycommon.zuul.filter.PostResultFilter;
import com.gitee.sop.gatewaycommon.zuul.filter.PreHttpServletRequestWrapperFilter;
import com.gitee.sop.gatewaycommon.zuul.filter.PreLimitFilter;
import com.gitee.sop.gatewaycommon.zuul.filter.PreParameterFormatterFilter;
import com.gitee.sop.gatewaycommon.zuul.filter.PreValidateFilter;
import com.gitee.sop.gatewaycommon.zuul.filter.PreVersionDecisionFilter;
import com.gitee.sop.gatewaycommon.zuul.filter.Servlet30WrapperFilterExt;
@ -44,6 +47,12 @@ public class BaseZuulConfiguration extends AbstractConfiguration {
return ApiConfig.getInstance().getZuulParamBuilder();
}
@Bean
@ConditionalOnMissingBean
ParameterFormatter<JSONObject> preParamFilter(){
return ApiConfig.getInstance().getZuulParameterFormatter();
}
/**
* 路由存储
* @return
@ -104,6 +113,11 @@ public class BaseZuulConfiguration extends AbstractConfiguration {
return new PreValidateFilter();
}
@Bean
PreParameterFormatterFilter preParameterFormatterFilter() {
return new PreParameterFormatterFilter();
}
/**
* 开启限流
*/
@ -120,6 +134,8 @@ public class BaseZuulConfiguration extends AbstractConfiguration {
return new PreVersionDecisionFilter();
}
/**
* 错误处理扩展
*/

@ -23,11 +23,14 @@ public abstract class BaseZuulFilter extends ZuulFilter {
/** 签名验证过滤 */
public static final int PRE_VALIDATE_FILTER_ORDER = -1000;
/** 参数格式化过滤器 */
public static final int PRE_PARAMETER_FORMATTER_FILTER_ORDER = PRE_VALIDATE_FILTER_ORDER + 1;
/** 权限验证过滤 */
public static final int PRE_ROUTE_PERMISSION_FILTER_ORDER = PRE_VALIDATE_FILTER_ORDER + 1;
public static final int PRE_ROUTE_PERMISSION_FILTER_ORDER = PRE_VALIDATE_FILTER_ORDER + 100;
/** 限流过滤 */
public static final int PRE_LIMIT_FILTER_ORDER = PRE_ROUTE_PERMISSION_FILTER_ORDER + 1;
public static final int PRE_LIMIT_FILTER_ORDER = PRE_ROUTE_PERMISSION_FILTER_ORDER + 100;
private Integer filterOrder;

@ -0,0 +1,42 @@
package com.gitee.sop.gatewaycommon.zuul.filter;
import com.gitee.sop.gatewaycommon.param.ApiParam;
import com.gitee.sop.gatewaycommon.param.ParamNames;
import com.gitee.sop.gatewaycommon.zuul.ZuulContext;
import com.gitee.sop.gatewaycommon.zuul.param.ZuulParameterFormatter;
import com.gitee.sop.gatewaycommon.zuul.param.ZuulParameterUtil;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.springframework.beans.factory.annotation.Autowired;
/**
* 参数格式化过滤器动态修改参数此过滤器放在前面校验后面
*
* @author tanghc
*/
public class PreParameterFormatterFilter extends BaseZuulFilter {
@Autowired(required = false)
private ZuulParameterFormatter zuulParameterFormatter;
@Override
protected FilterType getFilterType() {
return FilterType.PRE;
}
@Override
protected int getFilterOrder() {
return PRE_PARAMETER_FORMATTER_FILTER_ORDER;
}
@Override
protected Object doRun(RequestContext requestContext) throws ZuulException {
ApiParam apiParam = ZuulContext.getApiParam();
// 校验成功后进行参数转换
if (zuulParameterFormatter != null) {
ZuulParameterUtil.format(apiParam, zuulParameterFormatter::format);
requestContext.addZuulRequestHeader(ParamNames.HEADER_VERSION_NAME, apiParam.fetchVersion());
}
return null;
}
}

@ -0,0 +1,10 @@
package com.gitee.sop.gatewaycommon.zuul.param;
import com.alibaba.fastjson.JSONObject;
import com.gitee.sop.gatewaycommon.manager.ParameterFormatter;
/**
* @author tanghc
*/
public interface ZuulParameterFormatter extends ParameterFormatter<JSONObject> {
}

@ -0,0 +1,183 @@
package com.gitee.sop.gatewaycommon.zuul.param;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.gitee.sop.gatewaycommon.bean.SopConstants;
import com.gitee.sop.gatewaycommon.util.RequestUtil;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.http.HttpServletRequestWrapper;
import com.netflix.zuul.http.ServletInputStreamWrapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.cloud.netflix.zuul.util.RequestContentDataExtractor;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.MediaType;
import org.springframework.http.converter.FormHttpMessageConverter;
import org.springframework.util.MultiValueMap;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import java.util.stream.Collectors;
/**
* zuul参数工具
* @author tanghc
*/
@Slf4j
public class ZuulParameterUtil {
private static FormHttpMessageConverter formHttpMessageConverter = new FormHttpMessageConverter();
/**
* 格式化参数
* @param apiParam 请求的参数
* @param consumer 修改参数
* @param <T> 参数类型
*/
public static <T extends Map<String, Object>> void format(T apiParam, Consumer<T> consumer) {
RequestContext requestContext = RequestContext.getCurrentContext();
consumer.accept(apiParam);
HttpServletRequest request = requestContext.getRequest();
String contentType = request.getContentType();
if (StringUtils.containsIgnoreCase(contentType, MediaType.APPLICATION_JSON_VALUE)) {
String json = (apiParam instanceof JSONObject) ?
((JSONObject) apiParam).toJSONString()
: JSON.toJSONString(apiParam);
byte[] bytes = json.getBytes(StandardCharsets.UTF_8);
requestContext.setRequest(new ChangeParamsHttpServletRequestWrapper(request, bytes));
} else if(StringUtils.containsIgnoreCase(contentType, MediaType.APPLICATION_FORM_URLENCODED_VALUE)) {
List<String> list = new ArrayList<>(apiParam.size());
try {
for (Map.Entry<String, Object> entry : apiParam.entrySet()) {
String key = entry.getKey();
Object value = entry.getValue();
if (value instanceof Collection) {
Collection collection = (Collection) value;
for (Object el : collection) {
list.add(key + "=" + URLEncoder.encode(String.valueOf(el), SopConstants.UTF8));
}
} else {
list.add(key + "=" + URLEncoder.encode(String.valueOf(value), SopConstants.UTF8));
}
}
} catch (UnsupportedEncodingException e) {
log.error("字符集不支持", e);
}
String paramsStr = StringUtils.join(list, "&");
byte[] data = paramsStr.getBytes(StandardCharsets.UTF_8);
requestContext.setRequest(new ChangeParamsHttpServletRequestWrapper(request, data));
} else if(RequestUtil.isMultipart(request)) {
FormHttpOutputMessage outputMessage = new FormHttpOutputMessage();
try {
// 转成MultipartRequest
if (!(request instanceof MultipartHttpServletRequest)) {
CommonsMultipartResolver commonsMultipartResolver = new CommonsMultipartResolver(request.getServletContext());
request = commonsMultipartResolver.resolveMultipart(request);
}
// 重写新的值
MultiValueMap<String, Object> builder = RequestContentDataExtractor.extract(request);
for (Map.Entry<String, Object> entry : apiParam.entrySet()) {
Object value = entry.getValue();
if (value instanceof List) {
builder.put(entry.getKey(), (List)value);
} else {
builder.put(entry.getKey(), Collections.singletonList(String.valueOf(value)));
}
}
MediaType mediaType = MediaType.valueOf(request.getContentType());
// 将字段以及上传文件重写写入到流中
formHttpMessageConverter.write(builder, mediaType, outputMessage);
// 获取新的上传文件流
byte[] data = outputMessage.getInput();
requestContext.setRequest(new ChangeParamsHttpServletRequestWrapper(request, data));
// 必须要重新指定content-type,因为此时的boundary已经发生改变
requestContext.getZuulRequestHeaders().put("content-type", outputMessage.getHeaders().getContentType().toString());
} catch (Exception e) {
log.error("修改上传文件请求参数失败, apiParam:{}", apiParam, e);
}
} else if(HttpMethod.GET.name().equalsIgnoreCase(request.getMethod())) {
Map<String, List<String>> newParams = new HashMap<>();
for (Map.Entry<String, Object> entry : apiParam.entrySet()) {
Object value = entry.getValue();
if (value instanceof List) {
List<String> valueList = ((List<?>) value).stream().map(String::valueOf).collect(Collectors.toList());
newParams.put(entry.getKey(), valueList);
} else {
newParams.put(entry.getKey(), Collections.singletonList(String.valueOf(value)));
}
}
requestContext.setRequestQueryParams(newParams);
}
}
private static class FormHttpOutputMessage implements HttpOutputMessage {
private HttpHeaders headers = new HttpHeaders();
private ByteArrayOutputStream output = new ByteArrayOutputStream();
@Override
public HttpHeaders getHeaders() {
return this.headers;
}
@Override
public OutputStream getBody() throws IOException {
return this.output;
}
public byte[] getInput() throws IOException {
this.output.flush();
return this.output.toByteArray();
}
}
private static class ChangeParamsHttpServletRequestWrapper extends HttpServletRequestWrapper {
private byte[] data;
public ChangeParamsHttpServletRequestWrapper(HttpServletRequest request, byte[] data) {
super(request);
this.data = data;
}
@Override
public ServletInputStream getInputStream() throws IOException {
return new ServletInputStreamWrapper(data);
}
@Override
public byte[] getContentData() {
return data;
}
@Override
public int getContentLength() {
return data.length;
}
@Override
public long getContentLengthLong() {
return data.length;
}
}
}

@ -5,7 +5,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.gitee.sop</groupId>
<artifactId>sop-registry-api</artifactId>
<version>1.14.0-SNAPSHOT</version>
<version>1.15.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

@ -1,24 +1,16 @@
package com.gitee.sop.registryapi.bean;
import lombok.Getter;
import lombok.Setter;
import lombok.Data;
import java.util.Collections;
import java.util.List;
/**
* @author tanghc
*/
@Getter
@Setter
@Data
public class ServiceInfo {
/** 服务名称 */
private String serviceId;
/** 实例列表 */
private List<ServiceInstance> instances = Collections.emptyList();
@Override
public String toString() {
return "服务名称: " + serviceId + ", 实例数:" + instances.size();
}
private List<ServiceInstance> instances;
}

@ -18,6 +18,8 @@ import org.springframework.util.CollectionUtils;
import javax.annotation.PostConstruct;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ -51,7 +53,9 @@ public class RegistryServiceNacos implements RegistryService {
ServiceInfo serviceInfo = new ServiceInfo();
serviceInfo.setServiceId(serviceName);
List<Instance> instanceList = namingService.getAllInstances(serviceName);
if (!CollectionUtils.isEmpty(instanceList)) {
if (CollectionUtils.isEmpty(instanceList)) {
serviceInfo.setInstances(Collections.emptyList());
} else {
serviceInfo.setInstances(new ArrayList<>(instanceList.size()));
for (Instance instance : instanceList) {
ServiceInstance serviceInstance = new ServiceInstance();
@ -68,6 +72,7 @@ public class RegistryServiceNacos implements RegistryService {
}
serviceInfoList.add(serviceInfo);
}
serviceInfoList.sort(Comparator.comparingInt(o -> o.getInstances().size()));
return serviceInfoList;
}

@ -6,11 +6,11 @@
<parent>
<groupId>com.gitee.sop</groupId>
<artifactId>sop-common</artifactId>
<version>1.14.0-SNAPSHOT</version>
<version>1.15.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>sop-service-common</artifactId>
<version>1.14.0-SNAPSHOT</version>
<version>1.15.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>sop-service-common</name>

@ -8,4 +8,9 @@ public class ServiceConstants {
* zookeeper存放接口路由信息的根目录
*/
public static final String SOP_SERVICE_ROUTE_PATH = "/com.gitee.sop.route";
/**
* 服务临时节点
*/
public static final String SOP_SERVICE_TEMP_PATH = "/com.gitee.sop.service.tmp";
}

@ -9,6 +9,7 @@ import org.apache.commons.lang.math.NumberUtils;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.CreateMode;
import org.springframework.core.env.Environment;
import java.io.Closeable;
@ -94,6 +95,23 @@ public class ZookeeperTool implements Closeable {
.forPath(path, data.getBytes());
}
/**
* 创建临时序列节点
* @param path 节点路径
* @param data 数据
* @return 返回节点路径
* @throws Exception
*/
public String createOrUpdateEphemeralSequentialPath(String path, String data) throws Exception {
return getClient().create()
// 如果节点存在则Curator将会使用给出的数据设置这个节点的值
.orSetData()
// 如果指定节点的父节点不存在,则Curator将会自动级联创建父节点
.creatingParentContainersIfNeeded()
.withMode(CreateMode.EPHEMERAL_SEQUENTIAL)
.forPath(path, data.getBytes());
}
/**
* 新建或保存节点
*

@ -14,11 +14,15 @@ import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.core.env.Environment;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import javax.annotation.PostConstruct;
import java.nio.charset.StandardCharsets;
import java.util.List;
/**
* @author tanghc
@ -44,6 +48,12 @@ public class BaseServiceConfiguration extends WebMvcConfigurationSupport
super.addInterceptors(registry);
}
@Override
protected void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
// 解决controller返回字符串中文乱码问题
converters.add(new StringHttpMessageConverter(StandardCharsets.UTF_8));
}
/**
* 自定义Mapping详见@ApiMapping
* @return 返回RequestMappingHandlerMapping

@ -10,7 +10,6 @@ import com.gitee.sop.servercommon.route.ServiceRouteInfo;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.core.env.Environment;
import org.springframework.util.DigestUtils;
@ -81,6 +80,7 @@ public class ServiceZookeeperApiMetaManager implements ApiMetaManager {
String nodeData = JSON.toJSONString(serviceRouteInfo);
log.info("serviceId:{}, zookeeper保存路径:{}", serviceId, savePath);
this.zookeeperTool.createPath(savePath, nodeData);
this.zookeeperTool.createPath(serviceRouteInfo.getZookeeperTempServiceIdPath(), "");
} catch (Exception e) {
throw new IllegalStateException("zookeeper操作失败");
}
@ -91,8 +91,11 @@ public class ServiceZookeeperApiMetaManager implements ApiMetaManager {
try {
ServiceRouteInfo serviceRouteInfo = this.buildServiceGatewayInfo(serviceApiInfo);
this.uploadServiceRouteInfoToZookeeper(serviceRouteInfo);
} finally {
IOUtils.closeQuietly(zookeeperTool);
// 同时上传一个临时节点
String tempPath = serviceRouteInfo.getZookeeperTempServiceIdChildPath();
this.zookeeperTool.createOrUpdateEphemeralSequentialPath(tempPath, JSON.toJSONString(serviceRouteInfo));
} catch (Exception e) {
log.error("上传一个临时节点失败, serviceApiInfo:{}", serviceApiInfo, e);
}
}

@ -22,11 +22,10 @@ public class ServiceParamValidator implements ParamValidator {
public static final String COMMA = ",";
private static Object[] EMPTY_OBJ_ARRAY = {};
private static ValidatorFactory factory;
private static javax.validation.Validator validator;
static {
factory = Validation.buildDefaultValidatorFactory();
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
validator = factory.getValidator();
}

@ -13,6 +13,7 @@ import java.util.List;
@Data
public class ServiceRouteInfo {
private static final String SOP_SERVICE_ROUTE_PATH = ServiceConstants.SOP_SERVICE_ROUTE_PATH;
private static final String SOP_SERVICE_TEMP_PATH = ServiceConstants.SOP_SERVICE_TEMP_PATH;
/** 服务名称,对应spring.application.name */
private String serviceId;
@ -39,4 +40,22 @@ public class ServiceRouteInfo {
public String getZookeeperPath() {
return SOP_SERVICE_ROUTE_PATH + '/' + serviceId;
}
/**
* 返回zookeeper路径
* @return 返回zookeeper路径
*/
@JSONField(serialize = false)
public String getZookeeperTempServiceIdPath() {
return SOP_SERVICE_TEMP_PATH + '/' + serviceId;
}
/**
* 返回zookeeper路径
* @return 返回zookeeper路径
*/
@JSONField(serialize = false)
public String getZookeeperTempServiceIdChildPath() {
return getZookeeperTempServiceIdPath() + "/" + serviceId;
}
}

@ -29,6 +29,10 @@ public abstract class SwaggerSupport {
@Bean
public Docket createRestApi() {
return getDocket();
}
protected Docket getDocket() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()

@ -67,12 +67,8 @@ public class OpenUtil {
for (Map.Entry<String, String[]> entry : entrySet) {
String name = entry.getKey();
String[] values = entry.getValue();
if (values.length == 1) {
if (values.length >= 1) {
retMap.put(name, values[0]);
} else if (values.length > 1) {
retMap.put(name, values);
} else {
retMap.put(name, "");
}
}

@ -26,7 +26,7 @@
<dependency>
<groupId>com.gitee.sop</groupId>
<artifactId>sop-service-common</artifactId>
<version>1.14.0-SNAPSHOT</version>
<version>1.15.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>

@ -24,7 +24,7 @@
<dependency>
<groupId>com.gitee.sop</groupId>
<artifactId>sop-service-common</artifactId>
<version>1.14.0-SNAPSHOT</version>
<version>1.15.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.gitee.sop</groupId>

@ -29,7 +29,7 @@
<dependency>
<groupId>com.gitee.sop</groupId>
<artifactId>sop-service-common</artifactId>
<version>1.14.0-SNAPSHOT</version>
<version>1.15.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>

@ -20,7 +20,7 @@
<dependency>
<groupId>com.gitee.sop</groupId>
<artifactId>sop-service-common</artifactId>
<version>1.14.0-SNAPSHOT</version>
<version>1.15.0-SNAPSHOT</version>
</dependency>
<!-- eureka 服务发现 -->
<dependency>

@ -24,7 +24,7 @@
<dependency>
<groupId>com.gitee.sop</groupId>
<artifactId>sop-service-common</artifactId>
<version>1.14.0-SNAPSHOT</version>
<version>1.15.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.gitee.sop</groupId>
@ -79,22 +79,11 @@
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
<exclusions>
<exclusion>
<groupId>io.swagger</groupId>
<artifactId>swagger-models</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-models</artifactId>
<version>1.5.21</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
<groupId>com.github.xiaoymin</groupId>
<artifactId>swagger-bootstrap-ui</artifactId>
<version>1.9.5</version>
</dependency>
<dependency>

@ -22,15 +22,16 @@ public class OpenServiceConfig extends AlipayServiceConfiguration {
@Override
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
super.addResourceHandlers(registry);
registry.addResourceHandler("swagger-ui.html")
.addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/");
// 支持swagger-bootstrap-ui首页
registry.addResourceHandler("doc.html").addResourceLocations("classpath:/META-INF/resources/");
// 支持默认swagger
registry.addResourceHandler("swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
}
/**
* 开启文档
* 开启文档本地微服务文档地址http://localhost:2222/doc.html
* http://ip:port/v2/api-docs
*/
@Configuration
@ -43,9 +44,10 @@ public class OpenServiceConfig extends AlipayServiceConfiguration {
@Override
protected boolean swaggerAccessProtected() {
return true;
return false;
}
}
}
/**

@ -1,5 +1,6 @@
package com.gitee.sop.storyweb.controller;
import com.alibaba.fastjson.JSON;
import com.gitee.sop.servercommon.annotation.ApiAbility;
import com.gitee.sop.servercommon.annotation.ApiMapping;
import com.gitee.sop.servercommon.bean.OpenContext;
@ -127,13 +128,39 @@ public class AlipayController {
// http://localhost:2222/alipay.story.get/
@ApiMapping(value = "alipay.story.get")
public Story getStory() {
public Story getStory(Story param) {
Story story = new Story();
story.setId(1);
story.setName("海底小纵队(alipay.story.get1.0)");
story.setName("海底小纵队(alipay.story.get1.0), param:" + param);
return story;
}
/**
*
* @param param 对应biz_content中的内容并自动JSR-303校验
* @return
*/
@ApiMapping(value = "alipay.story.get", version = "1.2")
public Story getStory11(Story param) {
Story story2 = new Story();
story2.setId(1);
story2.setName("海底小纵队(alipay.story.get1.2), param:" + param);
return story2;
}
/**
* 验证字符串乱码问题
* @param param
* @return
*/
@ApiMapping(value = "story.string.get", version = "1.0")
public String string(Story param) {
Story story2 = new Story();
story2.setId(1);
story2.setName("海底小纵队");
return JSON.toJSONString(story2);
}
/**
* 参数绑定
* @param story 对应biz_content中的内容并自动JSR-303校验
@ -153,19 +180,6 @@ public class AlipayController {
return storyVO;
}
/**
*
* @param story 对应biz_content中的内容并自动JSR-303校验
* @return
*/
@ApiMapping(value = "alipay.story.get", version = "1.2")
public Story getStory11(Story story) {
Story story2 = new Story();
story2.setId(1);
story2.setName("海底小纵队(alipay.story.get1.2)");
return story2;
}
/**
* 演示文档表格树
* @param story

@ -23,7 +23,7 @@
<dependency>
<groupId>com.gitee.sop</groupId>
<artifactId>sop-gateway-common</artifactId>
<version>1.14.0-SNAPSHOT</version>
<version>1.15.0-SNAPSHOT</version>
</dependency>
<!-- ↓↓↓ 使用spring cloud zuul ↓↓↓ -->

@ -1,8 +1,6 @@
package com.gitee.sop.gateway.controller;
import com.gitee.sop.gatewaycommon.bean.SopConstants;
import com.gitee.sop.gatewaycommon.param.ParamNames;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
@ -31,14 +29,7 @@ public class RedirectController {
) throws ServletException, IOException {
request.setAttribute(SopConstants.REDIRECT_METHOD_KEY, method);
request.setAttribute(SopConstants.REDIRECT_VERSION_KEY, version);
String queryString = request.getQueryString();
String versionQuery = ParamNames.VERSION_NAME + '=' + version;
if (StringUtils.isBlank(queryString)) {
queryString = versionQuery;
} else {
queryString = queryString + '&' + versionQuery;
}
request.getRequestDispatcher(path + '?' + queryString).forward(request, response);
request.getRequestDispatcher(path).forward(request, response);
}
}

@ -31,4 +31,22 @@ public class CuratorTest extends TestCase {
} catch (Exception e) {
}
}
/**
* 删除临时节点
*/
public void testDelTemp() {
String tempRoot = "/com.gitee.sop.service.tmp";
CuratorFramework client = CuratorFrameworkFactory.builder()
.connectString(zookeeperServerAddr)
.retryPolicy(new ExponentialBackoffRetry(1000, 3))
.build();
client.start();
try {
client.delete().deletingChildrenIfNeeded().forPath(tempRoot);
} catch (Exception e) {
}
}
}

@ -1,6 +1,7 @@
package com.gitee.sop.sdk.client;
import com.gitee.sop.sdk.common.OpenConfig;
import com.gitee.sop.sdk.common.RequestMethod;
import com.gitee.sop.sdk.common.UploadFile;
import okhttp3.Cookie;
import okhttp3.CookieJar;
@ -118,7 +119,7 @@ public class OpenHttp {
* @return
* @throws IOException
*/
public String request(String url, Map<String, String> form, Map<String, String> header, HTTPMethod method) throws IOException {
public String request(String url, Map<String, String> form, Map<String, String> header, RequestMethod method) throws IOException {
Request.Builder requestBuilder = buildRequestBuilder(url, form, method);
// 添加header
addHeader(requestBuilder, header);
@ -134,7 +135,7 @@ public class OpenHttp {
}
}
public static Request.Builder buildRequestBuilder(String url, Map<String, String> form, HTTPMethod method) {
public static Request.Builder buildRequestBuilder(String url, Map<String, String> form, RequestMethod method) {
switch (method) {
case GET:
return new Request.Builder()
@ -241,22 +242,4 @@ public class OpenHttp {
this.httpClient = httpClient;
}
public enum HTTPMethod {
GET,
POST,
PUT,
HEAD,
DELETE;
private HTTPMethod() {
}
public String value() {
return this.name();
}
public static HTTPMethod fromValue(String v) {
return valueOf(v.toUpperCase());
}
}
}

@ -100,11 +100,9 @@ public class SdkTest extends TestCase {
if (response.isSuccess()) {
List<DemoFileUploadResponse.FileMeta> responseFiles = response.getFiles();
System.out.println("您上传的文件信息:");
responseFiles.stream().forEach(file->{
System.out.println(file);
});
responseFiles.forEach(System.out::println);
} else {
System.out.println("errorCode:" + response.getCode() + ",errorMsg:" + response.getMsg());
System.out.println(JSON.toJSONString(response));
}
System.out.println("--------------------");
}

@ -0,0 +1,280 @@
package com.gitee.sop.test;
import com.alibaba.fastjson.JSON;
import com.gitee.sop.test.alipay.AlipayApiException;
import com.gitee.sop.test.alipay.AlipaySignature;
import lombok.Data;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
/**
* 简易客户端
*
* @author tanghc
*/
@Data
public class Client {
/**
* http请求工具
*/
private static HttpTool httpTool = new HttpTool();
/**
* 请求url
*/
private String url;
/**
* 平台提供的appKey
*/
private String appId;
/**
* 平台提供的私钥
*/
private String privateKey;
/**
* 请求成功后处理
*/
private Callback callback;
/**
* 创建一个客户端
*
* @param url 请求url
* @param appId 平台提供的appKey
* @param privateKey 平台提供的私钥
*/
public Client(String url, String appId, String privateKey) {
this.url = url;
this.appId = appId;
this.privateKey = privateKey;
}
/**
* 创建一个客户端
*
* @param url 请求url
* @param appId 平台提供的appKey
* @param privateKey 平台提供的私钥
* @param callback 请求成功后处理
*/
public Client(String url, String appId, String privateKey, Callback callback) {
this.url = url;
this.appId = appId;
this.privateKey = privateKey;
this.callback = callback;
}
/**
* 发送请求
* @param requestBuilder 请求信息
* @return 返回结果
*/
public String execute(RequestBuilder requestBuilder) {
RequestInfo requestInfo = requestBuilder.build(appId, privateKey);
HttpTool.HTTPMethod httpMethod = requestInfo.getHttpMethod();
boolean postJson = requestInfo.isPostJson();
Map<String, ?> form = requestInfo.getForm();
Map<String, String> header = requestInfo.getHeader();
String requestUrl = requestInfo.getUrl() != null ? requestInfo.getUrl() : url;
String responseData = null;
try {
// 发送请求
if (httpMethod == HttpTool.HTTPMethod.POST && postJson) {
responseData = httpTool.requestJson(requestUrl, JSON.toJSONString(form), header);
} else {
responseData = httpTool.request(requestUrl, form, header, httpMethod);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
Callback call = requestBuilder.getCallback();
if (call == null) {
call = this.callback;
}
if (call != null) {
call.callback(requestInfo, responseData);
}
return responseData;
}
public interface Callback {
void callback(RequestInfo requestInfo, String responseData);
}
public static class RequestBuilder {
private static final String DEFAULT_VERSION = "1.0";
private String url;
private String method;
private String version = DEFAULT_VERSION;
private Map<String, String> bizContent;
private HttpTool.HTTPMethod httpMethod;
private Map<String, String> header;
private boolean ignoreSign;
private boolean postJson;
private Callback callback;
/**
* 设置请求url如果指定了将会优先使用不指定默认使用Client中的url
*
* @param url url
* @return 返回RequestBuilder
*/
public RequestBuilder url(String url) {
this.url = url;
return this;
}
/**
* 设置方法名
*
* @param method 方法名
* @return 返回RequestBuilder
*/
public RequestBuilder method(String method) {
this.method = method;
return this;
}
/**
* 设置版本号
*
* @param version 版本号
* @return 返回RequestBuilder
*/
public RequestBuilder version(String version) {
this.version = version;
return this;
}
/**
* 设置业务参数
*
* @param bizContent 业务参数
* @return 返回RequestBuilder
*/
public RequestBuilder bizContent(Map<String, String> bizContent) {
this.bizContent = bizContent;
return this;
}
/**
* 设置请求方法
*
* @param httpMethod 请求方法
* @return 返回RequestBuilder
*/
public RequestBuilder httpMethod(HttpTool.HTTPMethod httpMethod) {
this.httpMethod = httpMethod;
return this;
}
/**
* 设置请求头
*
* @param header 请求头
* @return 返回RequestBuilder
*/
public RequestBuilder header(Map<String, String> header) {
this.header = header;
return this;
}
/**
* 是否忽略签名验证
*
* @param ignoreSign 设置true不会构建sign字段
* @return 返回RequestBuilder
*/
public RequestBuilder ignoreSign(boolean ignoreSign) {
this.ignoreSign = ignoreSign;
return this;
}
/**
* 是否是json请求
*
* @param postJson 设置true请求方式变成jsonapplication/json
* @return 返回RequestBuilder
*/
public RequestBuilder postJson(boolean postJson) {
this.postJson = postJson;
return this;
}
/**
* 设置请求成功处理
*
* @param callback 回调处理
* @return 返回RequestBuilder
*/
public RequestBuilder callback(Callback callback) {
this.callback = callback;
return this;
}
public Callback getCallback() {
return callback;
}
public RequestInfo build(String appId, String privateKey) {
// 公共请求参数
Map<String, String> params = new HashMap<String, String>();
params.put("app_id", appId);
if (method != null) {
params.put("method", method);
}
if (version != null) {
params.put("version", version);
}
params.put("format", "json");
params.put("charset", "utf-8");
params.put("sign_type", "RSA2");
params.put("timestamp", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
// 业务参数
params.put("biz_content", JSON.toJSONString(bizContent == null ? Collections.emptyMap() : bizContent));
if (!ignoreSign) {
String content = AlipaySignature.getSignContent(params);
String sign = null;
try {
sign = AlipaySignature.rsa256Sign(content, privateKey, "utf-8");
} catch (AlipayApiException e) {
throw new RuntimeException(e);
}
params.put("sign", sign);
}
RequestInfo requestInfo = new RequestInfo();
requestInfo.setUrl(url);
requestInfo.setMethod(method);
requestInfo.setVersion(version);
requestInfo.setForm(params);
requestInfo.setHeader(header);
requestInfo.setPostJson(postJson);
requestInfo.setHttpMethod(httpMethod);
return requestInfo;
}
}
@Data
public static class RequestInfo {
private String url;
private String method;
private String version;
private boolean postJson;
private Map<String, ?> form;
private Map<String, String> header;
private HttpTool.HTTPMethod httpMethod;
}
}

@ -0,0 +1,219 @@
package com.gitee.sop.test;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.junit.Assert;
import java.util.HashMap;
import java.util.Optional;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;
/**
* 涵盖所有测试情况发版前运行这个类确保功能没有问题
*
* @author tanghc
*/
public class AllInOneTest extends TestBase {
String url = "http://localhost:8081/api";
String appId = "2019032617262200001";
String privateKey = "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCXJv1pQFqWNA/++OYEV7WYXwexZK/J8LY1OWlP9X0T6wHFOvxNKRvMkJ5544SbgsJpVcvRDPrcxmhPbi/sAhdO4x2PiPKIz9Yni2OtYCCeaiE056B+e1O2jXoLeXbfi9fPivJZkxH/tb4xfLkH3bA8ZAQnQsoXA0SguykMRZntF0TndUfvDrLqwhlR8r5iRdZLB6F8o8qXH6UPDfNEnf/K8wX5T4EB1b8x8QJ7Ua4GcIUqeUxGHdQpzNbJdaQvoi06lgccmL+PHzminkFYON7alj1CjDN833j7QMHdPtS9l7B67fOU/p2LAAkPMtoVBfxQt9aFj7B8rEhGCz02iJIBAgMBAAECggEARqOuIpY0v6WtJBfmR3lGIOOokLrhfJrGTLF8CiZMQha+SRJ7/wOLPlsH9SbjPlopyViTXCuYwbzn2tdABigkBHYXxpDV6CJZjzmRZ+FY3S/0POlTFElGojYUJ3CooWiVfyUMhdg5vSuOq0oCny53woFrf32zPHYGiKdvU5Djku1onbDU0Lw8w+5tguuEZ76kZ/lUcccGy5978FFmYpzY/65RHCpvLiLqYyWTtaNT1aQ/9pw4jX9HO9NfdJ9gYFK8r/2f36ZE4hxluAfeOXQfRC/WhPmiw/ReUhxPznG/WgKaa/OaRtAx3inbQ+JuCND7uuKeRe4osP2jLPHPP6AUwQKBgQDUNu3BkLoKaimjGOjCTAwtp71g1oo+k5/uEInAo7lyEwpV0EuUMwLA/HCqUgR4K9pyYV+Oyb8d6f0+Hz0BMD92I2pqlXrD7xV2WzDvyXM3s63NvorRooKcyfd9i6ccMjAyTR2qfLkxv0hlbBbsPHz4BbU63xhTJp3Ghi0/ey/1HQKBgQC2VsgqC6ykfSidZUNLmQZe3J0p/Qf9VLkfrQ+xaHapOs6AzDU2H2osuysqXTLJHsGfrwVaTs00ER2z8ljTJPBUtNtOLrwNRlvgdnzyVAKHfOgDBGwJgiwpeE9voB1oAV/mXqSaUWNnuwlOIhvQEBwekqNyWvhLqC7nCAIhj3yvNQKBgQCqYbeec56LAhWP903Zwcj9VvG7sESqXUhIkUqoOkuIBTWFFIm54QLTA1tJxDQGb98heoCIWf5x/A3xNI98RsqNBX5JON6qNWjb7/dobitti3t99v/ptDp9u8JTMC7penoryLKK0Ty3bkan95Kn9SC42YxaSghzqkt+uvfVQgiNGQKBgGxU6P2aDAt6VNwWosHSe+d2WWXt8IZBhO9d6dn0f7ORvcjmCqNKTNGgrkewMZEuVcliueJquR47IROdY8qmwqcBAN7Vg2K7r7CPlTKAWTRYMJxCT1Hi5gwJb+CZF3+IeYqsJk2NF2s0w5WJTE70k1BSvQsfIzAIDz2yE1oPHvwVAoGAA6e+xQkVH4fMEph55RJIZ5goI4Y76BSvt2N5OKZKd4HtaV+eIhM3SDsVYRLIm9ZquJHMiZQGyUGnsvrKL6AAVNK7eQZCRDk9KQz+0GKOGqku0nOZjUbAu6A2/vtXAaAuFSFx1rUQVVjFulLexkXR3KcztL1Qu2k5pB6Si0K/uwQ=";
private Client client = new Client(url, appId, privateKey, AllInOneTest::assertResult);
/**
* 以get方式提交
*/
public void testGet() {
Client.RequestBuilder requestBuilder = new Client.RequestBuilder()
.method("alipay.story.get")
.version("1.0")
.bizContent(new BizContent().add("id", "1").add("name", "葫芦娃"))
.httpMethod(HttpTool.HTTPMethod.GET);
client.execute(requestBuilder);
}
/**
* 以表单方式提交(application/x-www-form-urlencoded)
*/
public void testPostForm() {
Client.RequestBuilder requestBuilder = new Client.RequestBuilder()
.method("alipay.story.get")
.version("1.0")
.bizContent(new BizContent().add("id", "1").add("name", "葫芦娃"))
.httpMethod(HttpTool.HTTPMethod.POST);
client.execute(requestBuilder);
}
/**
* 以json方式提交(application/json)
*/
public void testPostJSON() {
Client.RequestBuilder requestBuilder = new Client.RequestBuilder()
.method("alipay.story.get")
.version("1.0")
// 以json方式提交
.postJson(true)
.bizContent(new BizContent().add("id", "1").add("name", "葫芦娃"))
.httpMethod(HttpTool.HTTPMethod.POST);
client.execute(requestBuilder);
}
/**
* 测试feigngateway -> book-service(consumer) -> story-service(provider)
*/
public void testFeign() {
Client.RequestBuilder requestBuilder = new Client.RequestBuilder()
.method("alipay.book.story.get")
.version("1.0")
.bizContent(new BizContent())
.httpMethod(HttpTool.HTTPMethod.GET);
client.execute(requestBuilder);
}
/**
* 测试dubbo服务book会调用story提供的服务参见DemoConsumerController.java
*/
public void testDubbo() {
Client.RequestBuilder requestBuilder = new Client.RequestBuilder()
.method("dubbo.story.get")
.version("1.0")
.bizContent(new BizContent().add("id", "222"))
.httpMethod(HttpTool.HTTPMethod.GET);
client.execute(requestBuilder);
}
/**
* 忽略验证,不校验签名只需传接口名版本号业务参数
*/
public void testIgnoreSign() {
Client.RequestBuilder requestBuilder = new Client.RequestBuilder()
.method("story.get")
.version("2.1")
.ignoreSign(true)
.bizContent(new BizContent().add("id", "222").add("name", "忽略222"))
.httpMethod(HttpTool.HTTPMethod.GET);
client.execute(requestBuilder);
}
/**
* JSR-303参数校验
*/
public void testJSR303() {
Client.RequestBuilder requestBuilder = new Client.RequestBuilder()
.method("goods.add")
.version("1.0")
.bizContent(new BizContent().add("goods_name", "iphone6").add("goods_remark", "iphone6").add("goods_comment", "1"))
.httpMethod(HttpTool.HTTPMethod.POST);
client.execute(requestBuilder);
}
/**
* 测试是否有权限访问可在sop-admin中设置权限
*/
public void testPermission() {
Client.RequestBuilder requestBuilder = new Client.RequestBuilder()
.method("permission.story.get")
.version("1.0")
.bizContent(new BizContent())
.httpMethod(HttpTool.HTTPMethod.GET);
client.execute(requestBuilder);
}
/**
* 演示将接口名版本号跟在url后面规则:http://host:port/{method}/{version}/
*/
public void testRestful() {
Client.RequestBuilder requestBuilder = new Client.RequestBuilder()
.url("http://localhost:8081/alipay.story.get/1.0/")
.bizContent(new BizContent().add("name", "name111"))
.httpMethod(HttpTool.HTTPMethod.GET);
client.execute(requestBuilder);
}
/**
* 验证中文乱码问题
*/
public void testString() {
Client.RequestBuilder requestBuilder = new Client.RequestBuilder()
.method("story.string.get")
.version("1.0")
.bizContent(new BizContent().add("name", "name111"))
.httpMethod(HttpTool.HTTPMethod.GET)
.callback((requestInfo, responseData) -> {
JSONObject jsonObject = JSON.parseObject(responseData);
JSONObject data = jsonObject.getJSONObject("story_string_get_response");
Assert.assertEquals("海底小纵队", data.getString("name"));
});
client.execute(requestBuilder);
}
/**
* 限流测试根据路由id限流
*
* @throws InterruptedException
*/
public void testLimit() throws InterruptedException {
int threadsCount = 10; // threadsCount个线程同时提交
final CountDownLatch countDownLatch = new CountDownLatch(1);
final CountDownLatch count = new CountDownLatch(threadsCount);
final AtomicInteger success = new AtomicInteger();
for (int i = 0; i < threadsCount; i++) {
new Thread(new Runnable() {
@Override
public void run() {
try {
countDownLatch.await(); // 等在这里,执行countDownLatch.countDown();集体触发
// 业务方法
Client.RequestBuilder requestBuilder = new Client.RequestBuilder()
.method("alipay.story.get")
.version("1.2")
.bizContent(new BizContent().add("id", "1").add("name", "葫芦娃"))
.httpMethod(HttpTool.HTTPMethod.GET);
client.execute(requestBuilder);
success.incrementAndGet();
} catch (Exception e) {
} finally {
count.countDown();
}
}
}).start();
}
countDownLatch.countDown();
count.await();
System.out.println("成功次数:" + success);
}
class BizContent extends HashMap<String, String> {
public BizContent add(String key, String value) {
this.put(key, value);
return this;
}
}
public static void assertResult(Client.RequestInfo requestInfo, String responseData) {
System.out.println(responseData);
String method = requestInfo.getMethod();
if (method == null) {
return;
}
String node = method.replace('.', '_') + "_response";
JSONObject jsonObject = JSON.parseObject(responseData).getJSONObject(node);
String code = Optional.ofNullable(jsonObject).map(json -> json.getString("code")).orElse("20000");
Assert.assertEquals("10000", code);
}
}

@ -25,7 +25,7 @@
<dependency>
<groupId>com.gitee.sop</groupId>
<artifactId>sop-registry-api</artifactId>
<version>1.14.0-SNAPSHOT</version>
<version>1.15.0-SNAPSHOT</version>
</dependency>
<dependency>

@ -1,5 +1,6 @@
package com.gitee.sop.websiteserver.bean;
import com.alibaba.fastjson.annotation.JSONField;
import lombok.Data;
import java.util.List;
@ -10,5 +11,7 @@ import java.util.List;
@Data
public class DocInfo {
private String title;
@JSONField(serialize = false)
private String serviceId;
private List<DocModule> docModuleList;
}

@ -8,4 +8,9 @@ public class WebsiteConstants {
* zookeeper存放接口路由信息的根目录
*/
public static final String SOP_SERVICE_ROUTE_PATH = "/com.gitee.sop.route";
/**
* 服务临时节点
*/
public static final String SOP_SERVICE_TEMP_PATH = "/com.gitee.sop.service.tmp";
}

@ -5,11 +5,18 @@ import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.math.NumberUtils;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.cache.ChildData;
import org.apache.curator.framework.recipes.cache.PathChildrenCache;
import org.apache.curator.framework.recipes.cache.PathChildrenCacheListener;
import org.apache.curator.framework.recipes.cache.TreeCache;
import org.apache.curator.framework.recipes.cache.TreeCacheListener;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.springframework.core.env.Environment;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import java.util.List;
import java.util.function.Consumer;
/**
* @author tanghc
@ -50,6 +57,10 @@ public class ZookeeperContext {
return WebsiteConstants.SOP_SERVICE_ROUTE_PATH;
}
public static String getServiceTempRootPath() {
return WebsiteConstants.SOP_SERVICE_TEMP_PATH;
}
public static CuratorFramework getClient() {
return client;
}
@ -58,10 +69,99 @@ public class ZookeeperContext {
ZookeeperContext.client = client;
}
public static boolean isPathExist(String path) {
try {
return client.checkExists().forPath(path) != null;
} catch (Exception e) {
return false;
}
}
/**
* 是否有子节点
* @param parentPath
* @return
* @throws Exception
*/
public static boolean hasChildren(String parentPath) throws Exception {
List<String> children = client.getChildren().forPath(parentPath);
return !CollectionUtils.isEmpty(children);
}
/**
* 创建path如果path存在不报错静默返回path名称
*
* @param path
* @param data
* @return
* @throws Exception
*/
public static String createPath(String path, String data) throws Exception {
if (isPathExist(path)) {
return path;
}
return getClient().create()
// 如果指定节点的父节点不存在,则Curator将会自动级联创建父节点
.creatingParentContainersIfNeeded()
.forPath(path, data.getBytes());
}
/**
* 获取子节点信息并监听子节点
*
* @param parentPath 父节点路径
* @param listConsumer 子节点数据
* @param listener 监听事件
* @throws Exception
*/
public static void getChildrenAndListen(String parentPath, Consumer<List<ChildData>> listConsumer, PathChildrenCacheListener listener) throws Exception {
// 为子节点添加watcher
// PathChildrenCache: 监听数据节点的增删改,可以设置触发的事件
PathChildrenCache childrenCache = new PathChildrenCache(client, parentPath, true);
/**
* StartMode: 初始化方式
* POST_INITIALIZED_EVENT异步初始化初始化之后会触发事件
* NORMAL异步初始化
* BUILD_INITIAL_CACHE同步初始化
*/
childrenCache.start(PathChildrenCache.StartMode.BUILD_INITIAL_CACHE);
// 列出子节点数据列表,需要使用BUILD_INITIAL_CACHE同步初始化模式才能获得,异步是获取不到的
List<ChildData> childDataList = childrenCache.getCurrentData();
listConsumer.accept(childDataList);
log.info("监听子节点增删改,监听路径:{}", parentPath);
// 监听根节点下面的子节点
childrenCache.getListenable().addListener(listener);
}
/**
* 监听子节点的增删改
*
* @param parentPath 父节点路径
* @param listener
* @throws Exception
*/
public static void listenChildren(String parentPath, PathChildrenCacheListener listener) throws Exception {
// 为子节点添加watcher
// PathChildrenCache: 监听数据节点的增删改,可以设置触发的事件
PathChildrenCache childrenCache = new PathChildrenCache(client, parentPath, true);
/**
* StartMode: 初始化方式
* POST_INITIALIZED_EVENT异步初始化初始化之后会触发事件
* NORMAL异步初始化
* BUILD_INITIAL_CACHE同步初始化
*/
childrenCache.start(PathChildrenCache.StartMode.BUILD_INITIAL_CACHE);
// 监听根节点下面的子节点
childrenCache.getListenable().addListener(listener);
}
/**
* 监听子节点可以自定义层级
* @param parentPath 父节点路径
* @param maxDepth 层级从1开始比如当前监听节点/t1目录最深为/t1/t2/t3/t4,则maxDepth=3,说明下面3级子目录全
* @param maxDepth 层级从1开始比如当前监听节点/t1目录最深为/t1/t2/t3/t4,则maxDepth=3,说明下面3级子目录全部监听
* @param listener
* @throws Exception
*/
@ -73,7 +173,6 @@ public class ZookeeperContext {
.build();
treeCache.getListenable().addListener(listener);
//没有开启模式作为入参的方法
treeCache.start();
}

@ -1,7 +1,6 @@
package com.gitee.sop.websiteserver.controller;
import com.gitee.sop.websiteserver.bean.DocInfo;
import com.gitee.sop.websiteserver.bean.DocItem;
import com.gitee.sop.websiteserver.manager.DocManager;
import com.gitee.sop.websiteserver.vo.DocBaseInfoVO;
import com.gitee.sop.websiteserver.vo.DocInfoVO;
@ -59,11 +58,6 @@ public class DocController {
return docManager.getByTitle(title);
}
@GetMapping("/item/{method}/{version}/")
public DocItem getDocItem(@PathVariable("method") String method, @PathVariable("version") String version) {
return docManager.get(method, version);
}
// 后门地址,可手动更新文档内容,一般情况下用不到
@GetMapping("/reload")

@ -1,7 +1,6 @@
package com.gitee.sop.websiteserver.manager;
import com.gitee.sop.websiteserver.bean.DocInfo;
import com.gitee.sop.websiteserver.bean.DocItem;
import java.util.Collection;
@ -12,8 +11,6 @@ public interface DocManager {
void load(String serviceId);
DocItem get(String method, String version);
DocInfo getByTitle(String title);
Collection<DocInfo> listAll();

@ -7,12 +7,14 @@ import com.gitee.sop.registryapi.bean.ServiceInfo;
import com.gitee.sop.registryapi.bean.ServiceInstance;
import com.gitee.sop.registryapi.service.RegistryService;
import com.gitee.sop.websiteserver.bean.DocInfo;
import com.gitee.sop.websiteserver.bean.DocItem;
import com.gitee.sop.websiteserver.bean.ZookeeperContext;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.curator.framework.recipes.cache.TreeCacheEvent;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.curator.framework.recipes.cache.ChildData;
import org.apache.curator.framework.recipes.cache.PathChildrenCacheEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.env.Environment;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
@ -41,21 +43,17 @@ import java.util.stream.Collectors;
public class DocManagerImpl implements DocManager {
// key:title
Map<String, DocInfo> docDefinitionMap = new HashMap<>();
private Map<String, DocInfo> docDefinitionMap = new HashMap<>();
// key: name+version
Map<String, DocItem> docItemMap = new HashMap<>();
private RestTemplate restTemplate = new RestTemplate();
private DocParser swaggerDocParser = new SwaggerDocParser();
RestTemplate restTemplate = new RestTemplate();
private DocParser easyopenDocParser = new EasyopenDocParser();
DocParser swaggerDocParser = new SwaggerDocParser();
private ExecutorService executorService = Executors.newSingleThreadExecutor();
DocParser easyopenDocParser = new EasyopenDocParser();
ExecutorService executorService = Executors.newSingleThreadExecutor();
DelayQueue<Msg> queue = new DelayQueue<>();
private DelayQueue<Msg> queue = new DelayQueue<>();
private String secret = "b749a2ec000f4f29";
@ -65,14 +63,13 @@ public class DocManagerImpl implements DocManager {
@Autowired
private RegistryService registryService;
private volatile boolean listenInited;
@Value("${doc.refresh-seconds:60}")
private String refreshSeconds;
@Override
public void load(String serviceId) {
try {
List<ServiceInfo> serviceInfoList = registryService.listAllService(1, 9999);
log.info("服务列表:{}", serviceInfoList);
serviceInfoList
.stream()
// 网关没有文档提供,需要排除
@ -105,6 +102,7 @@ public class DocManagerImpl implements DocManager {
JSONObject docRoot = JSON.parseObject(docInfoJson, Feature.OrderedField, Feature.DisableCircularReferenceDetect);
DocParser docParser = this.buildDocParser(docRoot);
DocInfo docInfo = docParser.parseJson(docRoot);
docInfo.setServiceId(serviceInstance.getServiceId());
docDefinitionMap.put(docInfo.getTitle(), docInfo);
} catch (Exception e) {
// 这里报错可能是因为有些微服务没有配置swagger文档,导致404访问不到
@ -129,11 +127,6 @@ public class DocManagerImpl implements DocManager {
}
}
@Override
public DocItem get(String method, String version) {
return docItemMap.get(method + version);
}
@Override
public DocInfo getByTitle(String title) {
return docDefinitionMap.get(title);
@ -159,28 +152,73 @@ public class DocManagerImpl implements DocManager {
executorService.execute(new Consumer(queue, this));
ZookeeperContext.setEnvironment(environment);
String routeRootPath = ZookeeperContext.getRouteRootPath();
String serviceTempRootPath = ZookeeperContext.getServiceTempRootPath();
ZookeeperContext.createPath(serviceTempRootPath, "{}");
// 如果节点内容有变化则自动更新文档
ZookeeperContext.listenChildren(routeRootPath, 1, (client, event) -> {
if (listenInited) {
long id = System.currentTimeMillis();
ZookeeperContext.getChildrenAndListen(serviceTempRootPath, childDataList -> {
for (ChildData childData : childDataList) {
String serviceIdPath = childData.getPath();
try {
boolean hasChildren = ZookeeperContext.hasChildren(serviceIdPath);
if (hasChildren) {
log.info("加载文档服务器,path:{}", serviceIdPath);
listenServiceIdPath(serviceIdPath);
}
} catch (Exception e) {
log.error("监听路径失败,serviceIdPath:{}", serviceIdPath);
}
}
}, (client, event) -> {
PathChildrenCacheEvent.Type type = event.getType();
if (type == PathChildrenCacheEvent.Type.CHILD_ADDED) {
String serviceIdPath = event.getData().getPath();
log.info("新增文档服务器,path:{}", serviceIdPath);
listenServiceIdPath(serviceIdPath);
}
});
}
private void listenServiceIdPath(String serviceIdPath) throws Exception {
ZookeeperContext.listenChildren(serviceIdPath, (client, event) -> {
String path = event.getData().getPath();
PathChildrenCacheEvent.Type type = event.getType();
log.info("服务节点变更,path:{}, eventType:{}", path, event.getType().name());
if (type == PathChildrenCacheEvent.Type.CHILD_ADDED
|| type == PathChildrenCacheEvent.Type.CHILD_UPDATED) {
byte[] data = event.getData().getData();
String serviceInfoJson = new String(data);
if (StringUtils.isEmpty(serviceInfoJson)) {
return;
}
ZKServiceInfo serviceInfo = JSON.parseObject(serviceInfoJson, ZKServiceInfo.class);
String serviceId = serviceInfo.getServiceId();
log.info("微服务[{}]推送更新", serviceId);
Msg msg = new Msg(id, 1000 * 20);
int delaySeconds = NumberUtils.toInt(refreshSeconds, 60);
log.info("微服务[{}]推送更新,{}秒后加载文档内容", serviceId, delaySeconds);
long id = System.currentTimeMillis();
Msg msg = new Msg(id, delaySeconds * 1000);
msg.serviceId = serviceId;
// 延迟20秒执行
queue.offer(msg);
}
TreeCacheEvent.Type type = event.getType();
if (type == TreeCacheEvent.Type.INITIALIZED) {
listenInited = true;
} else if (event.getType() == PathChildrenCacheEvent.Type.CHILD_REMOVED) {
byte[] data = event.getData().getData();
String serviceInfoJson = new String(data);
ZKServiceInfo serviceInfo = JSON.parseObject(serviceInfoJson, ZKServiceInfo.class);
String serviceId = serviceInfo.getServiceId();
boolean hasChildren = ZookeeperContext.hasChildren(serviceIdPath);
// 如果没有子节点就删除
if (!hasChildren) {
log.info("服务节点已删除,删除对应文档信息,path:{}", event.getData().getPath());
removeDoc(serviceId);
}
}
});
}
public void removeDoc(String serviceId) {
docDefinitionMap.entrySet().removeIf(entry -> serviceId.equalsIgnoreCase(entry.getValue().getServiceId()));
}
static class Msg implements Delayed {
private long id;
private long delay;
@ -197,8 +235,7 @@ public class DocManagerImpl implements DocManager {
@Override
public int compareTo(Delayed delayed) {
Msg msg = (Msg) delayed;
return Long.valueOf(this.id) > Long.valueOf(msg.id) ? 1
: (Long.valueOf(this.id) < Long.valueOf(msg.id) ? -1 : 0);
return Long.compare(this.id, msg.id);
}
// 延迟任务是否到时就是按照这个方法判断如果返回的是负数则说明到期否则还没到期

@ -1,4 +1,10 @@
CREATE DATABASE IF NOT EXISTS `sop` DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci;
USE `sop`;
SET @PREVIOUS_FOREIGN_KEY_CHECKS = @@FOREIGN_KEY_CHECKS;
SET FOREIGN_KEY_CHECKS = 0;
@ -7,16 +13,17 @@ DROP TABLE IF EXISTS `user_info`;
DROP TABLE IF EXISTS `perm_role_permission`;
DROP TABLE IF EXISTS `perm_role`;
DROP TABLE IF EXISTS `perm_isv_role`;
DROP TABLE IF EXISTS `isv_keys`;
DROP TABLE IF EXISTS `isv_info`;
DROP TABLE IF EXISTS `config_route_limit`;
DROP TABLE IF EXISTS `config_route_base`;
DROP TABLE IF EXISTS `config_limit`;
DROP TABLE IF EXISTS `admin_user_info`;
DROP TABLE IF EXISTS `config_common`;
DROP TABLE IF EXISTS `isv_keys`;
DROP TABLE IF EXISTS `config_ip_blacklist`;
DROP TABLE IF EXISTS `config_gray`;
DROP TABLE IF EXISTS `config_gray_instance`;
DROP TABLE IF EXISTS `config_gray`;
DROP TABLE IF EXISTS `config_common`;
DROP TABLE IF EXISTS `admin_user_info`;
CREATE TABLE `admin_user_info` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
@ -30,6 +37,55 @@ CREATE TABLE `admin_user_info` (
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COMMENT='后台用户表';
CREATE TABLE `config_common` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`config_group` varchar(64) NOT NULL DEFAULT '' COMMENT '配置分组',
`config_key` varchar(64) NOT NULL DEFAULT '' COMMENT '配置key',
`content` varchar(128) NOT NULL DEFAULT '' COMMENT '内容',
`remark` varchar(128) DEFAULT NULL COMMENT '备注',
`gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_groupkey` (`config_group`,`config_key`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='通用配置表';
CREATE TABLE `config_gray` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`service_id` varchar(64) NOT NULL DEFAULT '',
`user_key_content` text COMMENT '用户key,多个用引文逗号隔开',
`name_version_content` text COMMENT '需要灰度的接口,goods.get1.0=1.2,多个用英文逗号隔开',
`gmt_create` datetime DEFAULT CURRENT_TIMESTAMP,
`gmt_modified` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_serviceid` (`service_id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='服务灰度配置';
CREATE TABLE `config_gray_instance` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`instance_id` varchar(128) NOT NULL DEFAULT '' COMMENT 'instance_id',
`service_id` varchar(64) NOT NULL DEFAULT '' COMMENT 'service_id',
`status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '0:禁用,1:启用',
`gmt_create` datetime DEFAULT CURRENT_TIMESTAMP,
`gmt_modified` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_instanceid` (`instance_id`) USING BTREE,
KEY `idx_serviceid` (`service_id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='开启灰度服务器实例';
CREATE TABLE `config_ip_blacklist` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`ip` varchar(64) NOT NULL DEFAULT '' COMMENT 'ip',
`remark` varchar(128) DEFAULT NULL COMMENT '备注',
`gmt_create` datetime DEFAULT CURRENT_TIMESTAMP,
`gmt_modified` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_ip` (`ip`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='IP黑名单';
CREATE TABLE `config_limit` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`route_id` varchar(128) DEFAULT NULL COMMENT '路由id',
@ -81,7 +137,7 @@ CREATE TABLE `config_route_limit` (
CREATE TABLE `isv_info` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`app_key` varchar(100) NOT NULL COMMENT 'appKey',
`secret` varchar(200) COMMENT 'secret',
`secret` varchar(200) DEFAULT NULL COMMENT 'secret',
`pub_key` text COMMENT '公钥',
`pri_key` text COMMENT '私钥',
`status` tinyint(4) unsigned NOT NULL DEFAULT '0' COMMENT '1启用,2禁用',
@ -94,6 +150,23 @@ CREATE TABLE `isv_info` (
) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8 COMMENT='isv信息表';
CREATE TABLE `isv_keys` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`app_key` varchar(128) NOT NULL DEFAULT '',
`sign_type` tinyint(4) NOT NULL DEFAULT '1' COMMENT '1:RSA2,2:MD5',
`secret` varchar(200) NOT NULL DEFAULT '' COMMENT 'sign_type=2时使用',
`key_format` tinyint(4) NOT NULL DEFAULT '1' COMMENT '秘钥格式,1:PKCS8(JAVA适用),2:PKCS1(非JAVA适用)',
`public_key_isv` text NOT NULL COMMENT '开发者生成的公钥',
`private_key_isv` text NOT NULL COMMENT '开发者生成的私钥(交给开发者)',
`public_key_platform` text NOT NULL COMMENT '平台生成的公钥(交给开发者)',
`private_key_platform` text NOT NULL COMMENT '平台生成的私钥',
`gmt_create` datetime DEFAULT CURRENT_TIMESTAMP,
`gmt_modified` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_appkey` (`app_key`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8 COMMENT='ISV秘钥';
CREATE TABLE `perm_isv_role` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`isv_id` bigint(20) NOT NULL COMMENT 'isv_info表id',
@ -139,67 +212,7 @@ CREATE TABLE `user_info` (
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COMMENT='用户信息表';
CREATE TABLE `config_common` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`config_group` varchar(64) NOT NULL DEFAULT '' COMMENT '配置分组',
`config_key` varchar(64) NOT NULL DEFAULT '' COMMENT '配置key',
`content` varchar(128) NOT NULL DEFAULT '' COMMENT '内容',
`remark` varchar(128) DEFAULT NULL COMMENT '备注',
`gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_groupkey` (`config_group`,`config_key`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='通用配置表';
CREATE TABLE `isv_keys` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`app_key` varchar(128) NOT NULL DEFAULT '',
`sign_type` tinyint(4) NOT NULL DEFAULT '1' COMMENT '1:RSA2,2:MD5',
`secret` varchar(200) NOT NULL DEFAULT '' COMMENT 'sign_type=2时使用',
`key_format` tinyint(4) NOT NULL DEFAULT '1' COMMENT '秘钥格式,1:PKCS8(JAVA适用),2:PKCS1(非JAVA适用)',
`public_key_isv` text NOT NULL COMMENT '开发者生成的公钥',
`private_key_isv` text NOT NULL COMMENT '开发者生成的私钥(交给开发者)',
`public_key_platform` text NOT NULL COMMENT '平台生成的公钥(交给开发者)',
`private_key_platform` text NOT NULL COMMENT '平台生成的私钥',
`gmt_create` datetime DEFAULT CURRENT_TIMESTAMP,
`gmt_modified` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_appkey` (`app_key`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='ISV秘钥';
CREATE TABLE `config_ip_blacklist` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`ip` varchar(64) NOT NULL DEFAULT '' COMMENT 'ip',
`remark` varchar(128) DEFAULT NULL COMMENT '备注',
`gmt_create` datetime DEFAULT CURRENT_TIMESTAMP,
`gmt_modified` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_ip` (`ip`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='IP黑名单';
CREATE TABLE `config_gray` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`service_id` varchar(64) NOT NULL DEFAULT '',
`user_key_content` text COMMENT '用户key,多个用引文逗号隔开',
`name_version_content` text COMMENT '需要灰度的接口,goods.get1.0=1.2,多个用英文逗号隔开',
`gmt_create` datetime DEFAULT CURRENT_TIMESTAMP,
`gmt_modified` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_serviceid` (`service_id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='服务灰度配置';
CREATE TABLE `config_gray_instance` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`instance_id` varchar(128) NOT NULL DEFAULT '' COMMENT 'instance_id',
`service_id` varchar(64) NOT NULL DEFAULT '' COMMENT 'service_id',
`status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '0:禁用,1:启用',
`gmt_create` datetime DEFAULT CURRENT_TIMESTAMP,
`gmt_modified` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_instanceid` (`instance_id`) USING BTREE,
KEY `idx_serviceid` (`service_id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='开启灰度服务器实例';
SET FOREIGN_KEY_CHECKS = @PREVIOUS_FOREIGN_KEY_CHECKS;
@ -216,13 +229,37 @@ ALTER TABLE `admin_user_info` ENABLE KEYS;
UNLOCK TABLES;
LOCK TABLES `config_common` WRITE;
ALTER TABLE `config_common` DISABLE KEYS;
ALTER TABLE `config_common` ENABLE KEYS;
UNLOCK TABLES;
LOCK TABLES `config_gray` WRITE;
ALTER TABLE `config_gray` DISABLE KEYS;
ALTER TABLE `config_gray` ENABLE KEYS;
UNLOCK TABLES;
LOCK TABLES `config_gray_instance` WRITE;
ALTER TABLE `config_gray_instance` DISABLE KEYS;
ALTER TABLE `config_gray_instance` ENABLE KEYS;
UNLOCK TABLES;
LOCK TABLES `config_ip_blacklist` WRITE;
ALTER TABLE `config_ip_blacklist` DISABLE KEYS;
ALTER TABLE `config_ip_blacklist` ENABLE KEYS;
UNLOCK TABLES;
LOCK TABLES `config_limit` WRITE;
ALTER TABLE `config_limit` DISABLE KEYS;
INSERT INTO `config_limit` (`id`, `route_id`, `app_key`, `limit_ip`, `service_id`, `limit_type`, `exec_count_per_second`, `limit_code`, `limit_msg`, `token_bucket_count`, `limit_status`, `order_index`, `remark`, `gmt_create`, `gmt_modified`) VALUES
(1,'alipay.story.get1.0','','192.168.1.1,172.2.2.3','story-service',2,5,'','',6,1,3,NULL,'2019-05-17 19:21:35','2019-05-21 09:12:15'),
(2,'alipay.story.get1.0','2019032617262200001','','story-service',1,5,'service-budy','服务器忙',5,1,0,NULL,'2019-05-17 19:39:30','2019-05-21 15:36:52'),
(2,'alipay.story.get1.0','2019032617262200001','','story-service',2,5,'service-budy','服务器忙',10,1,0,'','2019-05-17 19:39:30','2019-05-21 15:36:52'),
(3,'alipay.story.find1.0','20190331562013861008375808','','story-service',1,3,'service-busy','服务器忙',5,1,1,NULL,'2019-05-17 20:20:32','2019-05-20 17:40:17'),
(4,'alipay.story.get1.2','','','story-service',2,5,'','',3,1,1,NULL,'2019-05-20 16:27:21','2019-05-21 15:53:10'),
(4,'alipay.story.get1.2','','','story-service',1,5,'service-busy','服务器忙',3,1,1,'','2019-05-20 16:27:21','2019-05-21 15:53:10'),
(5,'','20190401562373796095328256','','story-service',1,5,'service-busy','服务器忙',5,1,0,'这个appKey调用很频繁,重点照顾','2019-05-21 15:48:08','2019-05-21 18:45:32'),
(6,'','','10.1.30.54','story-service',1,5,'service-busy','服务器忙',5,1,0,'这个ip在攻击我们','2019-05-21 15:55:33','2019-05-21 18:17:29'),
(7,'story.get1.1','','10.1.30.54','story-service',1,5,'service-busy','服务器忙',5,1,0,NULL,'2019-05-21 16:30:48','2019-05-21 16:30:48'),
@ -259,21 +296,38 @@ UNLOCK TABLES;
LOCK TABLES `isv_info` WRITE;
ALTER TABLE `isv_info` DISABLE KEYS;
INSERT INTO `isv_info` (`id`, `app_key`, `secret`, `pub_key`, `pri_key`, `status`, `sign_type`, `gmt_create`, `gmt_modified`) VALUES
(1,'2019032617262200001','','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',1,1,'2019-03-27 10:10:34','2019-05-09 11:10:38'),
(3,'asdfasdf','','MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOJTAsGoAsNGJdzaWm835mtpcY2YxGr4NPjnhQmfUrPdT+Zgi6jmm+olYuygNeB8cOSALmTzgXlef+6SdwfRJVEMYVAO7hqF0Ood9zTOc+kolgnWJtqX54CoodfABt0SNS/bsr6hCAWu17RGnbgBaK+ZaJD3NVqXVXE8E30cYHiQIDAQAB','MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAM4lMCwagCw0Yl3Npabzfma2lxjZjEavg0+OeFCZ9Ss91P5mCLqOab6iVi7KA14Hxw5IAuZPOBeV5/7pJ3B9ElUQxhUA7uGoXQ6h33NM5z6SiWCdYm2pfngKih18AG3RI1L9uyvqEIBa7XtEaduAFor5lokPc1WpdVcTwTfRxgeJAgMBAAECgYAM3XFGL1k0aQiChiUCaEvJKTgAywLgHm/5dRC5JwKP8knqnn+I9P5QcV0jimPvaFjZ4VCdAvCjOC3EUNSvRn7wR2Lb1+BGZZePTdxtHWE2aqJ1W1SvgQTqMsLlPBRPnXo5XH/ng3WEH15ynd5NR035xAluaI0X/y+PsRxE6TlfIQJBAPSYUyXa2yaEqmvIN+ECKALCLLeDdi2YW3Kjahgz0X9V4Y4aTdrHh8y603zXC0Wy8HeOhwGoyciaS8SmjxCMn4UCQQDXweW8xsUreLH8hfVUtyiY/KgUz+R5foJDNXD7TLE9CDoPSHy09qBe99HyVCZg/gNJH4O+tNr6C4916dYaVk01AkBYZ2HOEc8ZmeOaty/zJHtfm9zbqykgi6upwISNINV8Z4bxfHJdO7bKeVANFBBf7a/aFmqXX/EmjxYJioW03o6dAkEAp7ViXJCtJpNU1pNSFZ2hgvmxtSu7zuyVWKSrw8rjYiuI5eRUe13RXsCHgzQB+Ra5exdyEsUGCaL+yosPD73RmQJBALGuM8EQUcBgrpgpeLZ39Ni1DYXYG9aj+u+ar/UL6kI1mCNFgwroO4EVIvXPVxikMxUgiE2tVaBML5nm8VDNJ7s=',2,1,'2019-03-27 11:01:11','2019-05-11 10:45:01'),
(5,'20190331562013861008375808','29864b93427447f5ac6c44df746f84ef','MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC4aMIx2q8rCVu5z6dgNQQSX2vwhvIcRb7FaqSk0ZK8AV9qQeE1TvfFVlAzOHlysE1yTRb0Mb6W2aw7IAS7Bkc3onYBQR4zNQYjYoDBzLukjF8o84hoVFRnh7sV8zszid2vb5H/YQr3M+5sYhlXY8KfILk3vhdbWpHM/umplcrxlwIDAQAB','MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBALhowjHarysJW7nPp2A1BBJfa/CG8hxFvsVqpKTRkrwBX2pB4TVO98VWUDM4eXKwTXJNFvQxvpbZrDsgBLsGRzeidgFBHjM1BiNigMHMu6SMXyjziGhUVGeHuxXzOzOJ3a9vkf9hCvcz7mxiGVdjwp8guTe+F1takcz+6amVyvGXAgMBAAECgYBj40LFVGoryp7n0CYeg7kX5p4GJGKCk/jY4IIcUPTFZ4zydorxoDuvpag9hmqqh/r7XeyAC23sMi4LvLUzRRxPh+7PuwL6nLce7vytsMCZQTPpBgz7dUfbi2HAxsuMOLjH3sVGycutARJsz6bT+9PyBEuVtUqwBrDGpFvwT0z6yQJBAOANC8nysb+O4rn/fbJtHIhtQoV74yu00mLnfwv8/J1+WyAEc32WZ4KYINqCe8ft1UknhPQx9UV6JaPCnlpF6w0CQQDStJhd38uQ7dVUQZHGP24xS/K38AYiSheEr7uewhkJfC2cKqE/lBk3oEG4s7asjhwlFLWLWSBLVM/Ta9Yj0hYzAkBe82hxl1bY9bcEWFBu02rqLlOouk4V8bXPkIf5DqgIHsqDkR9Ys+r+H3ac4/uNSS/ApuzjiGCHpzJYalwtqb/pAkEAvAKlSm5dCC8QAaSYXJtQyfAI3hPwhTwzjBP6iAiNqqcBU62+QCr37Wiz/Alv4LzVZEj8TSDz7gP5hZ9dbo0RfQJBALJ7NhTaeMN4jxBJ6Xg4rNZPb4yhAXuFxCp+a+FyXTsbWnW/ar8KJ3LHox0GOao6wne4qN3h7eqLOrYnnvOSFl0=',1,2,'2019-03-31 20:34:12','2019-04-19 17:30:09'),
(6,'20190331562037310372184064','d6b2a6603236491f87eed958292be136','','',2,2,'2019-03-31 22:07:20','2019-05-07 18:14:53'),
(7,'20190401562373672858288128','','MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCOgSo6GfwM8a+rUT4m61nZa7q5cJpjL7luxQKuJvkMl/QydVrzRPinCh6zqgBJDa7YY2X6z5TyTkjYuDkYMrdyHcYvCDuJ0NpRPZMR+QDE70yp9wJ+kOqTa8bepJtxzuCYLxFz+wRsIFt0nIxC6ttCaM9OEw/Bflhws3xczw4uqQIDAQAB','MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAI6BKjoZ/Azxr6tRPibrWdlrurlwmmMvuW7FAq4m+QyX9DJ1WvNE+KcKHrOqAEkNrthjZfrPlPJOSNi4ORgyt3Idxi8IO4nQ2lE9kxH5AMTvTKn3An6Q6pNrxt6km3HO4JgvEXP7BGwgW3ScjELq20Joz04TD8F+WHCzfFzPDi6pAgMBAAECgYA/zuQ6ieILZbjUDBe5U46yxQMh/6KRoQ/14m81zauckPm+EkA8R3jTSru+lPN1wpO0vqUuLf6ylI0XxT2DcUokOgY07ZdE54pu5XAsyY0eanFwt6C1LrHYpORV3Mp9XuI3fXrxYqVlxLuj1N7MGinXUuW7aZCHaEuSnZ55OL9dkQJBANKOeFiYDISSuIFHSrndSgr+a8E44jS/2/7lE49p5l3WVOFTHh0IZQNTs/IKsKJkUnYDE4W/Ab7NTnWZpXYeM30CQQCtQrtxPEzLl4dtupPOBJJoApj2lq7Q6tIGx178K6wS9Rz3GEvkA7fz1Tpm+nmPZflWZ9mVmEaVuMTMpl3HN/edAkBylyzx8lYltIALg5QskT1hvFNChkW9tYjyMROzIkxIV4Q8WPLzlAT9iYlOOfkld/nU1hnC2VAG2k9P+z2sigU1AkBAl1AptsEqZSMn1RalBy9NdypvQ12IpQIHZOwUNnO/3YEe3P/t0TUSwbs0CMyomOuLOsvy6QHnbypu4Na1HjhBAkAWjtdhuvU15HAa5jMgiUVfQM3YFuz2k3QkRagtZZ33bqnYs4wNxEZqB5t+vEj+8r3fmSN0BpNR1VW71j53Ir0H',1,1,'2019-04-01 20:24:01','2019-04-01 20:27:33'),
(8,'20190401562373796095328256','','MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCbxn0En2cj29t8i+m1dT7seF9XQx3cEaoClXFTlmc78Y1ZuQFbyY99VSwv8JbtpGxPvBSVD9SPmXWNBRBbSHT+gxStcdXD9QeD3knGFy/1V+z3E2Rj/6LIlFmgTlGh1fmEgttPjsUW1Dj704/ydyIrw+CAyAMKQyrFg0wYmNW+UQIDAQAB','MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAJvGfQSfZyPb23yL6bV1Pux4X1dDHdwRqgKVcVOWZzvxjVm5AVvJj31VLC/wlu2kbE+8FJUP1I+ZdY0FEFtIdP6DFK1x1cP1B4PeScYXL/VX7PcTZGP/osiUWaBOUaHV+YSC20+OxRbUOPvTj/J3IivD4IDIAwpDKsWDTBiY1b5RAgMBAAECgYAE27/ycPZKjATgcYyseCeqQGbY1eMMhhCDXB3YuYwmtnXuInMEZdjv08Q5CovqhYJLSlZp/8BlaifcahgEgNIFQXmxAF0U0HsNC6W4Dk1gGgQaVmYaZv5ex7uIcFB1qFvlO60kWf82YeRnO5KsFBODOJ1XSNwqjL2GeLSHBSVyQQJBAOsvDmClBsETSdiNSFMz+D9WCnCh1Ip4AoCzA/yG+PRSwYjZDdceP2DXieiZXPlxTFZ7MIXxAafgeyeQA2hpkQUCQQCpkCUSbrZ+nd4BYdnxZOSf0//cUT0o6+3kROX7gsXV7zRAWWxojT6DkGVlduDLZM/hjWeHRjWUxKC/jgbzvundAkBckhUSrWJPNQxoFJRXS6l3JKLPWqOSLVKu3ce/6lCrurc66lSsS9eegrhhuZwDAzmNAMhEsGx6a72OAP2WZ5cRAkBd8cT4X2qw4BpePa6YdcPNYZHCqSfvgje9XwbkwGGH1A3pESJlEsxt7BShkKmfRu1+E/AmHJoXIJHHT5M+fKnpAkA+VfyAAviKeCwUSq+5oUa0B+ozEA3frp/40cKQP7k02aamocAQCDRaC1ZlWffeQqYMnYe1/Mjr/SdX/Ut3X0CC',1,1,'2019-04-01 20:24:25','2019-04-01 20:24:48'),
(9,'201904035630907729292csharp','','MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5+OvJxeSzf44NxQ/cl7Ii+BzPg2k6sRcvH4ffOtU5Dzq1/oEvg02nxIhmwOHBZmjbmuUu0aLsfglUTAwqfXftfAKZidshsgj9NNh0/kxk0avRZ1UoljWGz/FxVZA0ogbxxhohPZ9jWcD+eBQcIwF2DtHfAJqWWZrYFnCMeHD8mPzxo2kwXSvDzi0vf9I2tKiYvNG26a9FqeYtPOoi81sdS3+70HOMdxP8ejXtyfnKpKz7Dx506LCIRS5moWS3Q5eTLV3NGX/1CSJ8wpQA2DAQTjVhX5eVu7Yqz12t8W+sjWM/tHUR6cgwYYR10p7tSCeCPzkigjGxKm4cYXWtATQJQIDAQAB','MIIEowIBAAKCAQEA5+OvJxeSzf44NxQ/cl7Ii+BzPg2k6sRcvH4ffOtU5Dzq1/oEvg02nxIhmwOHBZmjbmuUu0aLsfglUTAwqfXftfAKZidshsgj9NNh0/kxk0avRZ1UoljWGz/FxVZA0ogbxxhohPZ9jWcD+eBQcIwF2DtHfAJqWWZrYFnCMeHD8mPzxo2kwXSvDzi0vf9I2tKiYvNG26a9FqeYtPOoi81sdS3+70HOMdxP8ejXtyfnKpKz7Dx506LCIRS5moWS3Q5eTLV3NGX/1CSJ8wpQA2DAQTjVhX5eVu7Yqz12t8W+sjWM/tHUR6cgwYYR10p7tSCeCPzkigjGxKm4cYXWtATQJQIDAQABAoIBAHFDsgrrJca+NKEan77ycwx3jnKx4WrWjOF4zVKL9AQjiSYDNgvKknJyPb3kpC/lEoHdxGERHSzJoxib7DkoIqRQYhPxj73pxj5QfYk3P7LLJNNg/LTrpXDb3nL8JV9wIflGf87qQvstZTDJEyFWE4jBs7Hr0BxovWvri8InnzkmERJ1cbGJgNHe1Y3Zo2tw0yaHxQCxLuajP+notRZhD9bEp7uKeI0w9AvlW6k8m/7y10F0BK/TlyW8rQiEC391yOiRYoMcUh4hd2Q9bMx3jngZgX8PXIvZZcup4/pvWlv1alwhB2tsnLdazP62r1MO80vLyLunzGO+7WwCjEYlVaECgYEA+lQRFmbhKaPuAuXMtY31Fbga8nedka5TjnEV7+/kX+yowE2OlNujF+ZG8UTddTxAGv56yVNi/mjRlgD74j8z0eOsgvOq9mwbCrgLhLo51H9O/wAxtb+hBKtC5l50pBr4gER6d8W6EQNTSGojnMIaLXTkAZ5Qf6Z8e2HFVdOn0X0CgYEA7SSrTokwzukt5KldNu5ukyyd+C3D1i6orbg6qD73EP9CfNMfGSBn7dDv9wMSJH01+Ty+RgTROgtjGRDbMJWnfbdt/61NePr9ar5sb6Nbsf7/I0w7cZF5dsaFYgzaOfQYquzXPbLQHkpMT64bqpv/Mwy4F2lFvaYWY5fA4pC2uckCgYEAg75Ym9ybJaoTqky8ttQ2Jy8UZ4VSVQhVC0My02sCWwWXLlXi8y7An+Rec73Ve0yxREOn5WrQT6pkmzh7V/ABWrYi5WxODpCIjtSbo0fLBa3Wqle00b0/hdCITetqIa/cFs1zUrOqICgK3bKWeXqiAkhhcwSZwwSgwOKM04Wn7ZUCgYBvhHX2mbdVJfyJ8kc+hMOE/E9RHRxiBVEXWHJlGi8PVCqNDq8qHr4g7Mdbzprig+s0yKblwHAvrpkseWvKHiZEjVTyDipHgShY4TGXEigVvUd37uppTrLi8xpYcJjS9gH/px7VCdiq1d+q/MJP6coJ1KphgATm2UrgDMYNBWaYWQKBgEHRxrmER7btUF60/YgcqPHFc8RpYQB2ZZE0kyKGDqk2Data1XYUY6vsPAU28yRLAaWr/D2H17iyLkxP80VLm6QhifxCadv90Q/Wl1DFfOJQMW6avyQ0so6G0wFq/LJxaFK4iLXQn1RJnmTp6BYiJMmK2BhFbRzw8ssMoF6ad2rr',1,1,'2019-04-03 19:54:05','2019-04-03 20:11:58'),
(10,'easyopen_test','G9w0BAQEFAAOCAQ8AMIIBCgKCA','','',1,2,'2019-04-19 17:19:34','2019-04-19 17:30:09'),
(11,'20190513577548661718777856','','MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCdGjz3IE2VQteDjQaFacXLCAIqdEIIVcf7LW7f142V55Q0xtcjDTOHjBHExZsG64/Y5WKz4oQVWGnXwtrled8Qg0YAA7ueat8mE8NzJSm9txbfU9hwXB77nJxVkFyaSG1p0IZFrNQpbbUxTX9755deP7DdcSF148LLr091V++S3QIDAQAB','MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAJ0aPPcgTZVC14ONBoVpxcsIAip0QghVx/stbt/XjZXnlDTG1yMNM4eMEcTFmwbrj9jlYrPihBVYadfC2uV53xCDRgADu55q3yYTw3MlKb23Ft9T2HBcHvucnFWQXJpIbWnQhkWs1ClttTFNf3vnl14/sN1xIXXjwsuvT3VX75LdAgMBAAECgYB68z/nQDa3q/oykDocS21qujfHtfi/wTKjVylAsdezC+wnab6RRhGf8XUuhGARiGWpn8whcBNjCTC8lVju4vQ5IIx4Hb74vwDDMtNXeqwkLmARLYu2ELibauezSeqom8/J8cR3ho7Hr4VHPTiC8qvePRmu8AvXVQz2T7SOhEjDGQJBAOm8XOivr+atiknLbQhmo508ON3sjoN9VMwK9cmnup+ZPCsurJTHRja0MJQNdOXObUVJ6wJhs1PHWT+vITfXGJ8CQQCsESzxOYTkZaqBUFjbWVf1rSwjOOsylweTuq44YIJkHhwMjHf3kN/UTXbxsBPUGeT7/+2K5UwQ9snUPr0yTBcDAkA0FMezBWqxgNu+g7iA1bYBVCjrskkzHVsmuA56Z4hbBZ71lEnaQOjxSYdFhhYVGsEYXlciSbjWoyXM3e4N7jzLAkB0ejv+H33CTsAZQZalBdnxSQTz4vf0CyDp9BkzuMELnQZHyF79i2i5gqbd/N+vWMgVfq4CtC3F3gnKT54rii6ZAkAMBIvHriT5Zbs1fW+oxBP1rHqdsRvqs1zEyIadvJgKAFwFEisryfdw2mWm3vxQQ22RlOquBiZEDIlyM0z2m9PJ',1,1,'2019-05-13 17:24:17','2019-05-13 17:24:17'),
(12,'20190513577548661718777857','','MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCdGjz3IE2VQteDjQaFacXLCAIqdEIIVcf7LW7f142V55Q0xtcjDTOHjBHExZsG64/Y5WKz4oQVWGnXwtrled8Qg0YAA7ueat8mE8NzJSm9txbfU9hwXB77nJxVkFyaSG1p0IZFrNQpbbUxTX9755deP7DdcSF148LLr091V++S3QIDAQAB','MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAJ0aPPcgTZVC14ONBoVpxcsIAip0QghVx/stbt/XjZXnlDTG1yMNM4eMEcTFmwbrj9jlYrPihBVYadfC2uV53xCDRgADu55q3yYTw3MlKb23Ft9T2HBcHvucnFWQXJpIbWnQhkWs1ClttTFNf3vnl14/sN1xIXXjwsuvT3VX75LdAgMBAAECgYB68z/nQDa3q/oykDocS21qujfHtfi/wTKjVylAsdezC+wnab6RRhGf8XUuhGARiGWpn8whcBNjCTC8lVju4vQ5IIx4Hb74vwDDMtNXeqwkLmARLYu2ELibauezSeqom8/J8cR3ho7Hr4VHPTiC8qvePRmu8AvXVQz2T7SOhEjDGQJBAOm8XOivr+atiknLbQhmo508ON3sjoN9VMwK9cmnup+ZPCsurJTHRja0MJQNdOXObUVJ6wJhs1PHWT+vITfXGJ8CQQCsESzxOYTkZaqBUFjbWVf1rSwjOOsylweTuq44YIJkHhwMjHf3kN/UTXbxsBPUGeT7/+2K5UwQ9snUPr0yTBcDAkA0FMezBWqxgNu+g7iA1bYBVCjrskkzHVsmuA56Z4hbBZ71lEnaQOjxSYdFhhYVGsEYXlciSbjWoyXM3e4N7jzLAkB0ejv+H33CTsAZQZalBdnxSQTz4vf0CyDp9BkzuMELnQZHyF79i2i5gqbd/N+vWMgVfq4CtC3F3gnKT54rii6ZAkAMBIvHriT5Zbs1fW+oxBP1rHqdsRvqs1zEyIadvJgKAFwFEisryfdw2mWm3vxQQ22RlOquBiZEDIlyM0z2m9PJ',1,1,'2019-05-13 17:24:17','2019-05-13 17:24:17');
INSERT INTO `isv_info` (`id`, `app_key`, `secret`, `pub_key`, `pri_key`, `status`, `sign_type`, `remark`, `gmt_create`, `gmt_modified`) VALUES
(1,'2019032617262200001','','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',1,1,NULL,'2019-03-27 10:10:34','2019-05-09 11:10:38'),
(3,'asdfasdf','','MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOJTAsGoAsNGJdzaWm835mtpcY2YxGr4NPjnhQmfUrPdT+Zgi6jmm+olYuygNeB8cOSALmTzgXlef+6SdwfRJVEMYVAO7hqF0Ood9zTOc+kolgnWJtqX54CoodfABt0SNS/bsr6hCAWu17RGnbgBaK+ZaJD3NVqXVXE8E30cYHiQIDAQAB','MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAM4lMCwagCw0Yl3Npabzfma2lxjZjEavg0+OeFCZ9Ss91P5mCLqOab6iVi7KA14Hxw5IAuZPOBeV5/7pJ3B9ElUQxhUA7uGoXQ6h33NM5z6SiWCdYm2pfngKih18AG3RI1L9uyvqEIBa7XtEaduAFor5lokPc1WpdVcTwTfRxgeJAgMBAAECgYAM3XFGL1k0aQiChiUCaEvJKTgAywLgHm/5dRC5JwKP8knqnn+I9P5QcV0jimPvaFjZ4VCdAvCjOC3EUNSvRn7wR2Lb1+BGZZePTdxtHWE2aqJ1W1SvgQTqMsLlPBRPnXo5XH/ng3WEH15ynd5NR035xAluaI0X/y+PsRxE6TlfIQJBAPSYUyXa2yaEqmvIN+ECKALCLLeDdi2YW3Kjahgz0X9V4Y4aTdrHh8y603zXC0Wy8HeOhwGoyciaS8SmjxCMn4UCQQDXweW8xsUreLH8hfVUtyiY/KgUz+R5foJDNXD7TLE9CDoPSHy09qBe99HyVCZg/gNJH4O+tNr6C4916dYaVk01AkBYZ2HOEc8ZmeOaty/zJHtfm9zbqykgi6upwISNINV8Z4bxfHJdO7bKeVANFBBf7a/aFmqXX/EmjxYJioW03o6dAkEAp7ViXJCtJpNU1pNSFZ2hgvmxtSu7zuyVWKSrw8rjYiuI5eRUe13RXsCHgzQB+Ra5exdyEsUGCaL+yosPD73RmQJBALGuM8EQUcBgrpgpeLZ39Ni1DYXYG9aj+u+ar/UL6kI1mCNFgwroO4EVIvXPVxikMxUgiE2tVaBML5nm8VDNJ7s=',2,1,NULL,'2019-03-27 11:01:11','2019-05-11 10:45:01'),
(5,'20190331562013861008375808','29864b93427447f5ac6c44df746f84ef','MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC4aMIx2q8rCVu5z6dgNQQSX2vwhvIcRb7FaqSk0ZK8AV9qQeE1TvfFVlAzOHlysE1yTRb0Mb6W2aw7IAS7Bkc3onYBQR4zNQYjYoDBzLukjF8o84hoVFRnh7sV8zszid2vb5H/YQr3M+5sYhlXY8KfILk3vhdbWpHM/umplcrxlwIDAQAB','MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBALhowjHarysJW7nPp2A1BBJfa/CG8hxFvsVqpKTRkrwBX2pB4TVO98VWUDM4eXKwTXJNFvQxvpbZrDsgBLsGRzeidgFBHjM1BiNigMHMu6SMXyjziGhUVGeHuxXzOzOJ3a9vkf9hCvcz7mxiGVdjwp8guTe+F1takcz+6amVyvGXAgMBAAECgYBj40LFVGoryp7n0CYeg7kX5p4GJGKCk/jY4IIcUPTFZ4zydorxoDuvpag9hmqqh/r7XeyAC23sMi4LvLUzRRxPh+7PuwL6nLce7vytsMCZQTPpBgz7dUfbi2HAxsuMOLjH3sVGycutARJsz6bT+9PyBEuVtUqwBrDGpFvwT0z6yQJBAOANC8nysb+O4rn/fbJtHIhtQoV74yu00mLnfwv8/J1+WyAEc32WZ4KYINqCe8ft1UknhPQx9UV6JaPCnlpF6w0CQQDStJhd38uQ7dVUQZHGP24xS/K38AYiSheEr7uewhkJfC2cKqE/lBk3oEG4s7asjhwlFLWLWSBLVM/Ta9Yj0hYzAkBe82hxl1bY9bcEWFBu02rqLlOouk4V8bXPkIf5DqgIHsqDkR9Ys+r+H3ac4/uNSS/ApuzjiGCHpzJYalwtqb/pAkEAvAKlSm5dCC8QAaSYXJtQyfAI3hPwhTwzjBP6iAiNqqcBU62+QCr37Wiz/Alv4LzVZEj8TSDz7gP5hZ9dbo0RfQJBALJ7NhTaeMN4jxBJ6Xg4rNZPb4yhAXuFxCp+a+FyXTsbWnW/ar8KJ3LHox0GOao6wne4qN3h7eqLOrYnnvOSFl0=',1,2,NULL,'2019-03-31 20:34:12','2019-04-19 17:30:09'),
(6,'20190331562037310372184064','d6b2a6603236491f87eed958292be136','','',2,2,NULL,'2019-03-31 22:07:20','2019-05-07 18:14:53'),
(7,'20190401562373672858288128','','MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCOgSo6GfwM8a+rUT4m61nZa7q5cJpjL7luxQKuJvkMl/QydVrzRPinCh6zqgBJDa7YY2X6z5TyTkjYuDkYMrdyHcYvCDuJ0NpRPZMR+QDE70yp9wJ+kOqTa8bepJtxzuCYLxFz+wRsIFt0nIxC6ttCaM9OEw/Bflhws3xczw4uqQIDAQAB','MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAI6BKjoZ/Azxr6tRPibrWdlrurlwmmMvuW7FAq4m+QyX9DJ1WvNE+KcKHrOqAEkNrthjZfrPlPJOSNi4ORgyt3Idxi8IO4nQ2lE9kxH5AMTvTKn3An6Q6pNrxt6km3HO4JgvEXP7BGwgW3ScjELq20Joz04TD8F+WHCzfFzPDi6pAgMBAAECgYA/zuQ6ieILZbjUDBe5U46yxQMh/6KRoQ/14m81zauckPm+EkA8R3jTSru+lPN1wpO0vqUuLf6ylI0XxT2DcUokOgY07ZdE54pu5XAsyY0eanFwt6C1LrHYpORV3Mp9XuI3fXrxYqVlxLuj1N7MGinXUuW7aZCHaEuSnZ55OL9dkQJBANKOeFiYDISSuIFHSrndSgr+a8E44jS/2/7lE49p5l3WVOFTHh0IZQNTs/IKsKJkUnYDE4W/Ab7NTnWZpXYeM30CQQCtQrtxPEzLl4dtupPOBJJoApj2lq7Q6tIGx178K6wS9Rz3GEvkA7fz1Tpm+nmPZflWZ9mVmEaVuMTMpl3HN/edAkBylyzx8lYltIALg5QskT1hvFNChkW9tYjyMROzIkxIV4Q8WPLzlAT9iYlOOfkld/nU1hnC2VAG2k9P+z2sigU1AkBAl1AptsEqZSMn1RalBy9NdypvQ12IpQIHZOwUNnO/3YEe3P/t0TUSwbs0CMyomOuLOsvy6QHnbypu4Na1HjhBAkAWjtdhuvU15HAa5jMgiUVfQM3YFuz2k3QkRagtZZ33bqnYs4wNxEZqB5t+vEj+8r3fmSN0BpNR1VW71j53Ir0H',1,1,NULL,'2019-04-01 20:24:01','2019-04-01 20:27:33'),
(8,'20190401562373796095328256','','MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCbxn0En2cj29t8i+m1dT7seF9XQx3cEaoClXFTlmc78Y1ZuQFbyY99VSwv8JbtpGxPvBSVD9SPmXWNBRBbSHT+gxStcdXD9QeD3knGFy/1V+z3E2Rj/6LIlFmgTlGh1fmEgttPjsUW1Dj704/ydyIrw+CAyAMKQyrFg0wYmNW+UQIDAQAB','MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAJvGfQSfZyPb23yL6bV1Pux4X1dDHdwRqgKVcVOWZzvxjVm5AVvJj31VLC/wlu2kbE+8FJUP1I+ZdY0FEFtIdP6DFK1x1cP1B4PeScYXL/VX7PcTZGP/osiUWaBOUaHV+YSC20+OxRbUOPvTj/J3IivD4IDIAwpDKsWDTBiY1b5RAgMBAAECgYAE27/ycPZKjATgcYyseCeqQGbY1eMMhhCDXB3YuYwmtnXuInMEZdjv08Q5CovqhYJLSlZp/8BlaifcahgEgNIFQXmxAF0U0HsNC6W4Dk1gGgQaVmYaZv5ex7uIcFB1qFvlO60kWf82YeRnO5KsFBODOJ1XSNwqjL2GeLSHBSVyQQJBAOsvDmClBsETSdiNSFMz+D9WCnCh1Ip4AoCzA/yG+PRSwYjZDdceP2DXieiZXPlxTFZ7MIXxAafgeyeQA2hpkQUCQQCpkCUSbrZ+nd4BYdnxZOSf0//cUT0o6+3kROX7gsXV7zRAWWxojT6DkGVlduDLZM/hjWeHRjWUxKC/jgbzvundAkBckhUSrWJPNQxoFJRXS6l3JKLPWqOSLVKu3ce/6lCrurc66lSsS9eegrhhuZwDAzmNAMhEsGx6a72OAP2WZ5cRAkBd8cT4X2qw4BpePa6YdcPNYZHCqSfvgje9XwbkwGGH1A3pESJlEsxt7BShkKmfRu1+E/AmHJoXIJHHT5M+fKnpAkA+VfyAAviKeCwUSq+5oUa0B+ozEA3frp/40cKQP7k02aamocAQCDRaC1ZlWffeQqYMnYe1/Mjr/SdX/Ut3X0CC',1,1,NULL,'2019-04-01 20:24:25','2019-04-01 20:24:48'),
(9,'201904035630907729292csharp','','MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5+OvJxeSzf44NxQ/cl7Ii+BzPg2k6sRcvH4ffOtU5Dzq1/oEvg02nxIhmwOHBZmjbmuUu0aLsfglUTAwqfXftfAKZidshsgj9NNh0/kxk0avRZ1UoljWGz/FxVZA0ogbxxhohPZ9jWcD+eBQcIwF2DtHfAJqWWZrYFnCMeHD8mPzxo2kwXSvDzi0vf9I2tKiYvNG26a9FqeYtPOoi81sdS3+70HOMdxP8ejXtyfnKpKz7Dx506LCIRS5moWS3Q5eTLV3NGX/1CSJ8wpQA2DAQTjVhX5eVu7Yqz12t8W+sjWM/tHUR6cgwYYR10p7tSCeCPzkigjGxKm4cYXWtATQJQIDAQAB','MIIEowIBAAKCAQEA5+OvJxeSzf44NxQ/cl7Ii+BzPg2k6sRcvH4ffOtU5Dzq1/oEvg02nxIhmwOHBZmjbmuUu0aLsfglUTAwqfXftfAKZidshsgj9NNh0/kxk0avRZ1UoljWGz/FxVZA0ogbxxhohPZ9jWcD+eBQcIwF2DtHfAJqWWZrYFnCMeHD8mPzxo2kwXSvDzi0vf9I2tKiYvNG26a9FqeYtPOoi81sdS3+70HOMdxP8ejXtyfnKpKz7Dx506LCIRS5moWS3Q5eTLV3NGX/1CSJ8wpQA2DAQTjVhX5eVu7Yqz12t8W+sjWM/tHUR6cgwYYR10p7tSCeCPzkigjGxKm4cYXWtATQJQIDAQABAoIBAHFDsgrrJca+NKEan77ycwx3jnKx4WrWjOF4zVKL9AQjiSYDNgvKknJyPb3kpC/lEoHdxGERHSzJoxib7DkoIqRQYhPxj73pxj5QfYk3P7LLJNNg/LTrpXDb3nL8JV9wIflGf87qQvstZTDJEyFWE4jBs7Hr0BxovWvri8InnzkmERJ1cbGJgNHe1Y3Zo2tw0yaHxQCxLuajP+notRZhD9bEp7uKeI0w9AvlW6k8m/7y10F0BK/TlyW8rQiEC391yOiRYoMcUh4hd2Q9bMx3jngZgX8PXIvZZcup4/pvWlv1alwhB2tsnLdazP62r1MO80vLyLunzGO+7WwCjEYlVaECgYEA+lQRFmbhKaPuAuXMtY31Fbga8nedka5TjnEV7+/kX+yowE2OlNujF+ZG8UTddTxAGv56yVNi/mjRlgD74j8z0eOsgvOq9mwbCrgLhLo51H9O/wAxtb+hBKtC5l50pBr4gER6d8W6EQNTSGojnMIaLXTkAZ5Qf6Z8e2HFVdOn0X0CgYEA7SSrTokwzukt5KldNu5ukyyd+C3D1i6orbg6qD73EP9CfNMfGSBn7dDv9wMSJH01+Ty+RgTROgtjGRDbMJWnfbdt/61NePr9ar5sb6Nbsf7/I0w7cZF5dsaFYgzaOfQYquzXPbLQHkpMT64bqpv/Mwy4F2lFvaYWY5fA4pC2uckCgYEAg75Ym9ybJaoTqky8ttQ2Jy8UZ4VSVQhVC0My02sCWwWXLlXi8y7An+Rec73Ve0yxREOn5WrQT6pkmzh7V/ABWrYi5WxODpCIjtSbo0fLBa3Wqle00b0/hdCITetqIa/cFs1zUrOqICgK3bKWeXqiAkhhcwSZwwSgwOKM04Wn7ZUCgYBvhHX2mbdVJfyJ8kc+hMOE/E9RHRxiBVEXWHJlGi8PVCqNDq8qHr4g7Mdbzprig+s0yKblwHAvrpkseWvKHiZEjVTyDipHgShY4TGXEigVvUd37uppTrLi8xpYcJjS9gH/px7VCdiq1d+q/MJP6coJ1KphgATm2UrgDMYNBWaYWQKBgEHRxrmER7btUF60/YgcqPHFc8RpYQB2ZZE0kyKGDqk2Data1XYUY6vsPAU28yRLAaWr/D2H17iyLkxP80VLm6QhifxCadv90Q/Wl1DFfOJQMW6avyQ0so6G0wFq/LJxaFK4iLXQn1RJnmTp6BYiJMmK2BhFbRzw8ssMoF6ad2rr',1,1,NULL,'2019-04-03 19:54:05','2019-04-03 20:11:58'),
(10,'easyopen_test','G9w0BAQEFAAOCAQ8AMIIBCgKCA','','',1,2,NULL,'2019-04-19 17:19:34','2019-04-19 17:30:09'),
(11,'20190513577548661718777856','','MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCdGjz3IE2VQteDjQaFacXLCAIqdEIIVcf7LW7f142V55Q0xtcjDTOHjBHExZsG64/Y5WKz4oQVWGnXwtrled8Qg0YAA7ueat8mE8NzJSm9txbfU9hwXB77nJxVkFyaSG1p0IZFrNQpbbUxTX9755deP7DdcSF148LLr091V++S3QIDAQAB','MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAJ0aPPcgTZVC14ONBoVpxcsIAip0QghVx/stbt/XjZXnlDTG1yMNM4eMEcTFmwbrj9jlYrPihBVYadfC2uV53xCDRgADu55q3yYTw3MlKb23Ft9T2HBcHvucnFWQXJpIbWnQhkWs1ClttTFNf3vnl14/sN1xIXXjwsuvT3VX75LdAgMBAAECgYB68z/nQDa3q/oykDocS21qujfHtfi/wTKjVylAsdezC+wnab6RRhGf8XUuhGARiGWpn8whcBNjCTC8lVju4vQ5IIx4Hb74vwDDMtNXeqwkLmARLYu2ELibauezSeqom8/J8cR3ho7Hr4VHPTiC8qvePRmu8AvXVQz2T7SOhEjDGQJBAOm8XOivr+atiknLbQhmo508ON3sjoN9VMwK9cmnup+ZPCsurJTHRja0MJQNdOXObUVJ6wJhs1PHWT+vITfXGJ8CQQCsESzxOYTkZaqBUFjbWVf1rSwjOOsylweTuq44YIJkHhwMjHf3kN/UTXbxsBPUGeT7/+2K5UwQ9snUPr0yTBcDAkA0FMezBWqxgNu+g7iA1bYBVCjrskkzHVsmuA56Z4hbBZ71lEnaQOjxSYdFhhYVGsEYXlciSbjWoyXM3e4N7jzLAkB0ejv+H33CTsAZQZalBdnxSQTz4vf0CyDp9BkzuMELnQZHyF79i2i5gqbd/N+vWMgVfq4CtC3F3gnKT54rii6ZAkAMBIvHriT5Zbs1fW+oxBP1rHqdsRvqs1zEyIadvJgKAFwFEisryfdw2mWm3vxQQ22RlOquBiZEDIlyM0z2m9PJ',1,1,NULL,'2019-05-13 17:24:17','2019-05-13 17:24:17'),
(12,'20190513577548661718777857','','MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCdGjz3IE2VQteDjQaFacXLCAIqdEIIVcf7LW7f142V55Q0xtcjDTOHjBHExZsG64/Y5WKz4oQVWGnXwtrled8Qg0YAA7ueat8mE8NzJSm9txbfU9hwXB77nJxVkFyaSG1p0IZFrNQpbbUxTX9755deP7DdcSF148LLr091V++S3QIDAQAB','MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAJ0aPPcgTZVC14ONBoVpxcsIAip0QghVx/stbt/XjZXnlDTG1yMNM4eMEcTFmwbrj9jlYrPihBVYadfC2uV53xCDRgADu55q3yYTw3MlKb23Ft9T2HBcHvucnFWQXJpIbWnQhkWs1ClttTFNf3vnl14/sN1xIXXjwsuvT3VX75LdAgMBAAECgYB68z/nQDa3q/oykDocS21qujfHtfi/wTKjVylAsdezC+wnab6RRhGf8XUuhGARiGWpn8whcBNjCTC8lVju4vQ5IIx4Hb74vwDDMtNXeqwkLmARLYu2ELibauezSeqom8/J8cR3ho7Hr4VHPTiC8qvePRmu8AvXVQz2T7SOhEjDGQJBAOm8XOivr+atiknLbQhmo508ON3sjoN9VMwK9cmnup+ZPCsurJTHRja0MJQNdOXObUVJ6wJhs1PHWT+vITfXGJ8CQQCsESzxOYTkZaqBUFjbWVf1rSwjOOsylweTuq44YIJkHhwMjHf3kN/UTXbxsBPUGeT7/+2K5UwQ9snUPr0yTBcDAkA0FMezBWqxgNu+g7iA1bYBVCjrskkzHVsmuA56Z4hbBZ71lEnaQOjxSYdFhhYVGsEYXlciSbjWoyXM3e4N7jzLAkB0ejv+H33CTsAZQZalBdnxSQTz4vf0CyDp9BkzuMELnQZHyF79i2i5gqbd/N+vWMgVfq4CtC3F3gnKT54rii6ZAkAMBIvHriT5Zbs1fW+oxBP1rHqdsRvqs1zEyIadvJgKAFwFEisryfdw2mWm3vxQQ22RlOquBiZEDIlyM0z2m9PJ',1,1,NULL,'2019-05-13 17:24:17','2019-05-13 17:24:17');
ALTER TABLE `isv_info` ENABLE KEYS;
UNLOCK TABLES;
LOCK TABLES `isv_keys` WRITE;
ALTER TABLE `isv_keys` DISABLE KEYS;
INSERT INTO `isv_keys` (`id`, `app_key`, `sign_type`, `secret`, `key_format`, `public_key_isv`, `private_key_isv`, `public_key_platform`, `private_key_platform`, `gmt_create`, `gmt_modified`) VALUES
(1,'2019032617262200001',1,'',1,'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','','','2019-08-13 15:18:39','2019-08-13 15:18:39'),
(2,'asdfasdf',1,'',1,'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOJTAsGoAsNGJdzaWm835mtpcY2YxGr4NPjnhQmfUrPdT+Zgi6jmm+olYuygNeB8cOSALmTzgXlef+6SdwfRJVEMYVAO7hqF0Ood9zTOc+kolgnWJtqX54CoodfABt0SNS/bsr6hCAWu17RGnbgBaK+ZaJD3NVqXVXE8E30cYHiQIDAQAB','MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAM4lMCwagCw0Yl3Npabzfma2lxjZjEavg0+OeFCZ9Ss91P5mCLqOab6iVi7KA14Hxw5IAuZPOBeV5/7pJ3B9ElUQxhUA7uGoXQ6h33NM5z6SiWCdYm2pfngKih18AG3RI1L9uyvqEIBa7XtEaduAFor5lokPc1WpdVcTwTfRxgeJAgMBAAECgYAM3XFGL1k0aQiChiUCaEvJKTgAywLgHm/5dRC5JwKP8knqnn+I9P5QcV0jimPvaFjZ4VCdAvCjOC3EUNSvRn7wR2Lb1+BGZZePTdxtHWE2aqJ1W1SvgQTqMsLlPBRPnXo5XH/ng3WEH15ynd5NR035xAluaI0X/y+PsRxE6TlfIQJBAPSYUyXa2yaEqmvIN+ECKALCLLeDdi2YW3Kjahgz0X9V4Y4aTdrHh8y603zXC0Wy8HeOhwGoyciaS8SmjxCMn4UCQQDXweW8xsUreLH8hfVUtyiY/KgUz+R5foJDNXD7TLE9CDoPSHy09qBe99HyVCZg/gNJH4O+tNr6C4916dYaVk01AkBYZ2HOEc8ZmeOaty/zJHtfm9zbqykgi6upwISNINV8Z4bxfHJdO7bKeVANFBBf7a/aFmqXX/EmjxYJioW03o6dAkEAp7ViXJCtJpNU1pNSFZ2hgvmxtSu7zuyVWKSrw8rjYiuI5eRUe13RXsCHgzQB+Ra5exdyEsUGCaL+yosPD73RmQJBALGuM8EQUcBgrpgpeLZ39Ni1DYXYG9aj+u+ar/UL6kI1mCNFgwroO4EVIvXPVxikMxUgiE2tVaBML5nm8VDNJ7s=','','','2019-08-13 15:18:39','2019-08-13 15:18:39'),
(3,'20190331562013861008375808',2,'29864b93427447f5ac6c44df746f84ef',1,'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC4aMIx2q8rCVu5z6dgNQQSX2vwhvIcRb7FaqSk0ZK8AV9qQeE1TvfFVlAzOHlysE1yTRb0Mb6W2aw7IAS7Bkc3onYBQR4zNQYjYoDBzLukjF8o84hoVFRnh7sV8zszid2vb5H/YQr3M+5sYhlXY8KfILk3vhdbWpHM/umplcrxlwIDAQAB','MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBALhowjHarysJW7nPp2A1BBJfa/CG8hxFvsVqpKTRkrwBX2pB4TVO98VWUDM4eXKwTXJNFvQxvpbZrDsgBLsGRzeidgFBHjM1BiNigMHMu6SMXyjziGhUVGeHuxXzOzOJ3a9vkf9hCvcz7mxiGVdjwp8guTe+F1takcz+6amVyvGXAgMBAAECgYBj40LFVGoryp7n0CYeg7kX5p4GJGKCk/jY4IIcUPTFZ4zydorxoDuvpag9hmqqh/r7XeyAC23sMi4LvLUzRRxPh+7PuwL6nLce7vytsMCZQTPpBgz7dUfbi2HAxsuMOLjH3sVGycutARJsz6bT+9PyBEuVtUqwBrDGpFvwT0z6yQJBAOANC8nysb+O4rn/fbJtHIhtQoV74yu00mLnfwv8/J1+WyAEc32WZ4KYINqCe8ft1UknhPQx9UV6JaPCnlpF6w0CQQDStJhd38uQ7dVUQZHGP24xS/K38AYiSheEr7uewhkJfC2cKqE/lBk3oEG4s7asjhwlFLWLWSBLVM/Ta9Yj0hYzAkBe82hxl1bY9bcEWFBu02rqLlOouk4V8bXPkIf5DqgIHsqDkR9Ys+r+H3ac4/uNSS/ApuzjiGCHpzJYalwtqb/pAkEAvAKlSm5dCC8QAaSYXJtQyfAI3hPwhTwzjBP6iAiNqqcBU62+QCr37Wiz/Alv4LzVZEj8TSDz7gP5hZ9dbo0RfQJBALJ7NhTaeMN4jxBJ6Xg4rNZPb4yhAXuFxCp+a+FyXTsbWnW/ar8KJ3LHox0GOao6wne4qN3h7eqLOrYnnvOSFl0=','','','2019-08-13 15:18:39','2019-08-13 15:18:39'),
(4,'20190331562037310372184064',2,'d6b2a6603236491f87eed958292be136',1,'','','','','2019-08-13 15:18:39','2019-08-13 15:18:39'),
(5,'20190401562373672858288128',1,'',1,'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCOgSo6GfwM8a+rUT4m61nZa7q5cJpjL7luxQKuJvkMl/QydVrzRPinCh6zqgBJDa7YY2X6z5TyTkjYuDkYMrdyHcYvCDuJ0NpRPZMR+QDE70yp9wJ+kOqTa8bepJtxzuCYLxFz+wRsIFt0nIxC6ttCaM9OEw/Bflhws3xczw4uqQIDAQAB','MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAI6BKjoZ/Azxr6tRPibrWdlrurlwmmMvuW7FAq4m+QyX9DJ1WvNE+KcKHrOqAEkNrthjZfrPlPJOSNi4ORgyt3Idxi8IO4nQ2lE9kxH5AMTvTKn3An6Q6pNrxt6km3HO4JgvEXP7BGwgW3ScjELq20Joz04TD8F+WHCzfFzPDi6pAgMBAAECgYA/zuQ6ieILZbjUDBe5U46yxQMh/6KRoQ/14m81zauckPm+EkA8R3jTSru+lPN1wpO0vqUuLf6ylI0XxT2DcUokOgY07ZdE54pu5XAsyY0eanFwt6C1LrHYpORV3Mp9XuI3fXrxYqVlxLuj1N7MGinXUuW7aZCHaEuSnZ55OL9dkQJBANKOeFiYDISSuIFHSrndSgr+a8E44jS/2/7lE49p5l3WVOFTHh0IZQNTs/IKsKJkUnYDE4W/Ab7NTnWZpXYeM30CQQCtQrtxPEzLl4dtupPOBJJoApj2lq7Q6tIGx178K6wS9Rz3GEvkA7fz1Tpm+nmPZflWZ9mVmEaVuMTMpl3HN/edAkBylyzx8lYltIALg5QskT1hvFNChkW9tYjyMROzIkxIV4Q8WPLzlAT9iYlOOfkld/nU1hnC2VAG2k9P+z2sigU1AkBAl1AptsEqZSMn1RalBy9NdypvQ12IpQIHZOwUNnO/3YEe3P/t0TUSwbs0CMyomOuLOsvy6QHnbypu4Na1HjhBAkAWjtdhuvU15HAa5jMgiUVfQM3YFuz2k3QkRagtZZ33bqnYs4wNxEZqB5t+vEj+8r3fmSN0BpNR1VW71j53Ir0H','','','2019-08-13 15:18:39','2019-08-13 15:18:39'),
(6,'20190401562373796095328256',1,'',1,'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCbxn0En2cj29t8i+m1dT7seF9XQx3cEaoClXFTlmc78Y1ZuQFbyY99VSwv8JbtpGxPvBSVD9SPmXWNBRBbSHT+gxStcdXD9QeD3knGFy/1V+z3E2Rj/6LIlFmgTlGh1fmEgttPjsUW1Dj704/ydyIrw+CAyAMKQyrFg0wYmNW+UQIDAQAB','MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAJvGfQSfZyPb23yL6bV1Pux4X1dDHdwRqgKVcVOWZzvxjVm5AVvJj31VLC/wlu2kbE+8FJUP1I+ZdY0FEFtIdP6DFK1x1cP1B4PeScYXL/VX7PcTZGP/osiUWaBOUaHV+YSC20+OxRbUOPvTj/J3IivD4IDIAwpDKsWDTBiY1b5RAgMBAAECgYAE27/ycPZKjATgcYyseCeqQGbY1eMMhhCDXB3YuYwmtnXuInMEZdjv08Q5CovqhYJLSlZp/8BlaifcahgEgNIFQXmxAF0U0HsNC6W4Dk1gGgQaVmYaZv5ex7uIcFB1qFvlO60kWf82YeRnO5KsFBODOJ1XSNwqjL2GeLSHBSVyQQJBAOsvDmClBsETSdiNSFMz+D9WCnCh1Ip4AoCzA/yG+PRSwYjZDdceP2DXieiZXPlxTFZ7MIXxAafgeyeQA2hpkQUCQQCpkCUSbrZ+nd4BYdnxZOSf0//cUT0o6+3kROX7gsXV7zRAWWxojT6DkGVlduDLZM/hjWeHRjWUxKC/jgbzvundAkBckhUSrWJPNQxoFJRXS6l3JKLPWqOSLVKu3ce/6lCrurc66lSsS9eegrhhuZwDAzmNAMhEsGx6a72OAP2WZ5cRAkBd8cT4X2qw4BpePa6YdcPNYZHCqSfvgje9XwbkwGGH1A3pESJlEsxt7BShkKmfRu1+E/AmHJoXIJHHT5M+fKnpAkA+VfyAAviKeCwUSq+5oUa0B+ozEA3frp/40cKQP7k02aamocAQCDRaC1ZlWffeQqYMnYe1/Mjr/SdX/Ut3X0CC','','','2019-08-13 15:18:39','2019-08-13 15:18:39'),
(7,'201904035630907729292csharp',1,'',1,'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5+OvJxeSzf44NxQ/cl7Ii+BzPg2k6sRcvH4ffOtU5Dzq1/oEvg02nxIhmwOHBZmjbmuUu0aLsfglUTAwqfXftfAKZidshsgj9NNh0/kxk0avRZ1UoljWGz/FxVZA0ogbxxhohPZ9jWcD+eBQcIwF2DtHfAJqWWZrYFnCMeHD8mPzxo2kwXSvDzi0vf9I2tKiYvNG26a9FqeYtPOoi81sdS3+70HOMdxP8ejXtyfnKpKz7Dx506LCIRS5moWS3Q5eTLV3NGX/1CSJ8wpQA2DAQTjVhX5eVu7Yqz12t8W+sjWM/tHUR6cgwYYR10p7tSCeCPzkigjGxKm4cYXWtATQJQIDAQAB','MIIEowIBAAKCAQEA5+OvJxeSzf44NxQ/cl7Ii+BzPg2k6sRcvH4ffOtU5Dzq1/oEvg02nxIhmwOHBZmjbmuUu0aLsfglUTAwqfXftfAKZidshsgj9NNh0/kxk0avRZ1UoljWGz/FxVZA0ogbxxhohPZ9jWcD+eBQcIwF2DtHfAJqWWZrYFnCMeHD8mPzxo2kwXSvDzi0vf9I2tKiYvNG26a9FqeYtPOoi81sdS3+70HOMdxP8ejXtyfnKpKz7Dx506LCIRS5moWS3Q5eTLV3NGX/1CSJ8wpQA2DAQTjVhX5eVu7Yqz12t8W+sjWM/tHUR6cgwYYR10p7tSCeCPzkigjGxKm4cYXWtATQJQIDAQABAoIBAHFDsgrrJca+NKEan77ycwx3jnKx4WrWjOF4zVKL9AQjiSYDNgvKknJyPb3kpC/lEoHdxGERHSzJoxib7DkoIqRQYhPxj73pxj5QfYk3P7LLJNNg/LTrpXDb3nL8JV9wIflGf87qQvstZTDJEyFWE4jBs7Hr0BxovWvri8InnzkmERJ1cbGJgNHe1Y3Zo2tw0yaHxQCxLuajP+notRZhD9bEp7uKeI0w9AvlW6k8m/7y10F0BK/TlyW8rQiEC391yOiRYoMcUh4hd2Q9bMx3jngZgX8PXIvZZcup4/pvWlv1alwhB2tsnLdazP62r1MO80vLyLunzGO+7WwCjEYlVaECgYEA+lQRFmbhKaPuAuXMtY31Fbga8nedka5TjnEV7+/kX+yowE2OlNujF+ZG8UTddTxAGv56yVNi/mjRlgD74j8z0eOsgvOq9mwbCrgLhLo51H9O/wAxtb+hBKtC5l50pBr4gER6d8W6EQNTSGojnMIaLXTkAZ5Qf6Z8e2HFVdOn0X0CgYEA7SSrTokwzukt5KldNu5ukyyd+C3D1i6orbg6qD73EP9CfNMfGSBn7dDv9wMSJH01+Ty+RgTROgtjGRDbMJWnfbdt/61NePr9ar5sb6Nbsf7/I0w7cZF5dsaFYgzaOfQYquzXPbLQHkpMT64bqpv/Mwy4F2lFvaYWY5fA4pC2uckCgYEAg75Ym9ybJaoTqky8ttQ2Jy8UZ4VSVQhVC0My02sCWwWXLlXi8y7An+Rec73Ve0yxREOn5WrQT6pkmzh7V/ABWrYi5WxODpCIjtSbo0fLBa3Wqle00b0/hdCITetqIa/cFs1zUrOqICgK3bKWeXqiAkhhcwSZwwSgwOKM04Wn7ZUCgYBvhHX2mbdVJfyJ8kc+hMOE/E9RHRxiBVEXWHJlGi8PVCqNDq8qHr4g7Mdbzprig+s0yKblwHAvrpkseWvKHiZEjVTyDipHgShY4TGXEigVvUd37uppTrLi8xpYcJjS9gH/px7VCdiq1d+q/MJP6coJ1KphgATm2UrgDMYNBWaYWQKBgEHRxrmER7btUF60/YgcqPHFc8RpYQB2ZZE0kyKGDqk2Data1XYUY6vsPAU28yRLAaWr/D2H17iyLkxP80VLm6QhifxCadv90Q/Wl1DFfOJQMW6avyQ0so6G0wFq/LJxaFK4iLXQn1RJnmTp6BYiJMmK2BhFbRzw8ssMoF6ad2rr','','','2019-08-13 15:18:39','2019-08-13 15:18:39'),
(8,'easyopen_test',2,'G9w0BAQEFAAOCAQ8AMIIBCgKCA',1,'','','','','2019-08-13 15:18:39','2019-08-13 15:18:39'),
(9,'20190513577548661718777856',1,'',1,'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCdGjz3IE2VQteDjQaFacXLCAIqdEIIVcf7LW7f142V55Q0xtcjDTOHjBHExZsG64/Y5WKz4oQVWGnXwtrled8Qg0YAA7ueat8mE8NzJSm9txbfU9hwXB77nJxVkFyaSG1p0IZFrNQpbbUxTX9755deP7DdcSF148LLr091V++S3QIDAQAB','MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAJ0aPPcgTZVC14ONBoVpxcsIAip0QghVx/stbt/XjZXnlDTG1yMNM4eMEcTFmwbrj9jlYrPihBVYadfC2uV53xCDRgADu55q3yYTw3MlKb23Ft9T2HBcHvucnFWQXJpIbWnQhkWs1ClttTFNf3vnl14/sN1xIXXjwsuvT3VX75LdAgMBAAECgYB68z/nQDa3q/oykDocS21qujfHtfi/wTKjVylAsdezC+wnab6RRhGf8XUuhGARiGWpn8whcBNjCTC8lVju4vQ5IIx4Hb74vwDDMtNXeqwkLmARLYu2ELibauezSeqom8/J8cR3ho7Hr4VHPTiC8qvePRmu8AvXVQz2T7SOhEjDGQJBAOm8XOivr+atiknLbQhmo508ON3sjoN9VMwK9cmnup+ZPCsurJTHRja0MJQNdOXObUVJ6wJhs1PHWT+vITfXGJ8CQQCsESzxOYTkZaqBUFjbWVf1rSwjOOsylweTuq44YIJkHhwMjHf3kN/UTXbxsBPUGeT7/+2K5UwQ9snUPr0yTBcDAkA0FMezBWqxgNu+g7iA1bYBVCjrskkzHVsmuA56Z4hbBZ71lEnaQOjxSYdFhhYVGsEYXlciSbjWoyXM3e4N7jzLAkB0ejv+H33CTsAZQZalBdnxSQTz4vf0CyDp9BkzuMELnQZHyF79i2i5gqbd/N+vWMgVfq4CtC3F3gnKT54rii6ZAkAMBIvHriT5Zbs1fW+oxBP1rHqdsRvqs1zEyIadvJgKAFwFEisryfdw2mWm3vxQQ22RlOquBiZEDIlyM0z2m9PJ','','','2019-08-13 15:18:39','2019-08-13 15:18:39'),
(10,'20190513577548661718777857',1,'',1,'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCdGjz3IE2VQteDjQaFacXLCAIqdEIIVcf7LW7f142V55Q0xtcjDTOHjBHExZsG64/Y5WKz4oQVWGnXwtrled8Qg0YAA7ueat8mE8NzJSm9txbfU9hwXB77nJxVkFyaSG1p0IZFrNQpbbUxTX9755deP7DdcSF148LLr091V++S3QIDAQAB','MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAJ0aPPcgTZVC14ONBoVpxcsIAip0QghVx/stbt/XjZXnlDTG1yMNM4eMEcTFmwbrj9jlYrPihBVYadfC2uV53xCDRgADu55q3yYTw3MlKb23Ft9T2HBcHvucnFWQXJpIbWnQhkWs1ClttTFNf3vnl14/sN1xIXXjwsuvT3VX75LdAgMBAAECgYB68z/nQDa3q/oykDocS21qujfHtfi/wTKjVylAsdezC+wnab6RRhGf8XUuhGARiGWpn8whcBNjCTC8lVju4vQ5IIx4Hb74vwDDMtNXeqwkLmARLYu2ELibauezSeqom8/J8cR3ho7Hr4VHPTiC8qvePRmu8AvXVQz2T7SOhEjDGQJBAOm8XOivr+atiknLbQhmo508ON3sjoN9VMwK9cmnup+ZPCsurJTHRja0MJQNdOXObUVJ6wJhs1PHWT+vITfXGJ8CQQCsESzxOYTkZaqBUFjbWVf1rSwjOOsylweTuq44YIJkHhwMjHf3kN/UTXbxsBPUGeT7/+2K5UwQ9snUPr0yTBcDAkA0FMezBWqxgNu+g7iA1bYBVCjrskkzHVsmuA56Z4hbBZ71lEnaQOjxSYdFhhYVGsEYXlciSbjWoyXM3e4N7jzLAkB0ejv+H33CTsAZQZalBdnxSQTz4vf0CyDp9BkzuMELnQZHyF79i2i5gqbd/N+vWMgVfq4CtC3F3gnKT54rii6ZAkAMBIvHriT5Zbs1fW+oxBP1rHqdsRvqs1zEyIadvJgKAFwFEisryfdw2mWm3vxQQ22RlOquBiZEDIlyM0z2m9PJ','','','2019-08-13 15:18:39','2019-08-13 15:18:39');
ALTER TABLE `isv_keys` ENABLE KEYS;
UNLOCK TABLES;
LOCK TABLES `perm_isv_role` WRITE;
ALTER TABLE `perm_isv_role` DISABLE KEYS;
INSERT INTO `perm_isv_role` (`id`, `isv_id`, `role_code`, `gmt_create`, `gmt_modified`) VALUES
@ -314,8 +368,7 @@ ALTER TABLE `user_info` ENABLE KEYS;
UNLOCK TABLES;
INSERT INTO `sop`.`isv_keys` (`app_key`,`sign_type`, `secret`,`key_format`, `public_key_isv`, `private_key_isv`, `public_key_platform`, `private_key_platform`)
select app_key, sign_type, secret, 1, pub_key,pri_key,'','' from isv_info;
SET FOREIGN_KEY_CHECKS = @PREVIOUS_FOREIGN_KEY_CHECKS;

Loading…
Cancel
Save