mirror of
https://gitee.com/durcframework/SOP.git
synced 2025-08-11 21:57:56 +08:00
添加沙箱环境
This commit is contained in:
@@ -463,4 +463,21 @@ body .site-demo-nav .layui-nav-item{line-height: 40px}
|
||||
}
|
||||
.site-out-up{-webkit-animation-duration: 3s; animation-duration: 3s; -webkit-animation-fill-mode: both; animation-fill-mode: both; -webkit-animation-name: site-anim-closeup; animation-name: site-anim-closeup; overflow: hidden;}
|
||||
|
||||
.layui-table-input {
|
||||
display: block;
|
||||
width: 100%;
|
||||
padding-left: 10px;
|
||||
|
||||
height: 28px;
|
||||
line-height: 1.3;
|
||||
line-height: 38px\9;
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
background-color: #fff;
|
||||
border-radius: 2px;
|
||||
border-color: #e6e6e6;
|
||||
}
|
||||
|
||||
.layui-table-cell .layui-input,td .layui-input,th .layui-input {
|
||||
height: 28px;
|
||||
}
|
||||
|
48
sop-website/website-front/assets/js/inputcache.js
Normal file
48
sop-website/website-front/assets/js/inputcache.js
Normal file
@@ -0,0 +1,48 @@
|
||||
/**
|
||||
* 自动保存输入框的值
|
||||
* @type {{init: InputCache.init}}
|
||||
*/
|
||||
var InputCache = {
|
||||
init: function () {
|
||||
var storage = window.localStorage;
|
||||
if (storage) {
|
||||
var dataKey = location.host;
|
||||
|
||||
$('body').find('input[type="text"]').unbind().change(function () {
|
||||
var id = this.id;
|
||||
if (id) {
|
||||
var data = getCache();
|
||||
data[id] = this.value;
|
||||
setCache(data);
|
||||
}
|
||||
});
|
||||
|
||||
function getCache() {
|
||||
var jsonStr = storage.getItem(dataKey);
|
||||
if (!jsonStr) {
|
||||
jsonStr = '{}';
|
||||
}
|
||||
return JSON.parse(jsonStr);
|
||||
}
|
||||
|
||||
function setCache(jsonObj) {
|
||||
var jsonStr = JSON.stringify(jsonObj);
|
||||
storage.setItem(dataKey, jsonStr);
|
||||
}
|
||||
|
||||
// load data
|
||||
var cache = getCache();
|
||||
var docu = document;
|
||||
|
||||
for (var id in cache) {
|
||||
var dom = docu.getElementById(id);
|
||||
if (dom) {
|
||||
var oldVal = dom.value;
|
||||
var val = cache[id] || oldVal;
|
||||
dom.value = val;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -75,10 +75,11 @@ layui.define(['layer', 'table'], function (exports) {
|
||||
count: param.data.length,
|
||||
limit: param.data.length
|
||||
};
|
||||
param.cols[0][param.treeColIndex].templet = function (d) {
|
||||
var mId = d.id;
|
||||
var mPid = d.pid;
|
||||
var isDir = d.isParent;
|
||||
var firstTemplet = param.firstTemplet;
|
||||
param.cols[0][param.treeColIndex].templet = function (row) {
|
||||
var mId = row.id;
|
||||
var mPid = row.pid;
|
||||
var isDir = row.isParent;
|
||||
var emptyNum = treetable.getEmptyNum(mPid, mData);
|
||||
var iconHtml = '';
|
||||
for (var i = 0; i < emptyNum; i++) {
|
||||
@@ -92,7 +93,9 @@ layui.define(['layer', 'table'], function (exports) {
|
||||
iconHtml += ' ';
|
||||
var ttype = isDir ? 'dir' : 'file';
|
||||
var vg = '<span class="treeTable-icon open" lay-tid="' + mId + '" lay-tpid="' + mPid + '" lay-ttype="' + ttype + '">';
|
||||
return vg + iconHtml + d[param.cols[0][param.treeColIndex].field] + '</span>'
|
||||
var field = param.cols[0][param.treeColIndex].field;
|
||||
var cellVal = firstTemplet ? firstTemplet(row) : row[field];
|
||||
return vg + iconHtml + cellVal + '</span>'
|
||||
};
|
||||
|
||||
param.done = function (res, curr, count) {
|
||||
|
@@ -59,7 +59,7 @@
|
||||
<h1>第三方应用授权</h1>
|
||||
<div class="site-title">
|
||||
<fieldset class="layui-elem-field layui-field-title site-title">
|
||||
<legend><a name="use">概述</a></legend>
|
||||
<legend>概述</legend>
|
||||
</fieldset>
|
||||
</div>
|
||||
<div class="site-text">
|
||||
@@ -72,7 +72,7 @@
|
||||
|
||||
<div class="site-title">
|
||||
<fieldset class="layui-elem-field layui-field-title site-title">
|
||||
<legend><a name="use">快速接入</a></legend>
|
||||
<legend>快速接入</legend>
|
||||
</fieldset>
|
||||
</div>
|
||||
<div class="site-text">
|
||||
|
@@ -88,7 +88,7 @@
|
||||
<div class="site-content">
|
||||
<div class="site-title">
|
||||
<fieldset class="layui-elem-field layui-field-title site-title">
|
||||
<legend><a name="use">公共错误码</a></legend>
|
||||
<legend>公共错误码</legend>
|
||||
</fieldset>
|
||||
</div>
|
||||
<div class="site-text">
|
||||
|
@@ -58,9 +58,13 @@
|
||||
开放平台
|
||||
</a>
|
||||
<ul class="layui-nav">
|
||||
<li class="layui-nav-item layui-this">
|
||||
<a href="doc.html">文档中心<!-- --></a>
|
||||
<li class="layui-nav-item">
|
||||
<a href="../sandbox/sandbox.html">沙箱环境</a>
|
||||
</li>
|
||||
<li class="layui-nav-item layui-this">
|
||||
<a href="doc.html">文档中心</a>
|
||||
</li>
|
||||
|
||||
|
||||
<span class="layui-nav-bar" style="left: 162px; top: 55px; width: 0px; opacity: 0;"></span>
|
||||
</ul>
|
||||
@@ -118,7 +122,7 @@
|
||||
|
||||
<div class="site-title">
|
||||
<fieldset class="layui-elem-field layui-field-title site-title">
|
||||
<legend><a name="use">公共参数</a></legend>
|
||||
<legend>公共参数</legend>
|
||||
</fieldset>
|
||||
</div>
|
||||
|
||||
@@ -240,7 +244,7 @@
|
||||
|
||||
<div class="site-title">
|
||||
<fieldset class="layui-elem-field layui-field-title site-title">
|
||||
<legend><a name="use">请求参数</a></legend>
|
||||
<legend>请求参数</legend>
|
||||
</fieldset>
|
||||
</div>
|
||||
<div class="site-text">
|
||||
@@ -249,7 +253,7 @@
|
||||
|
||||
<div class="site-title">
|
||||
<fieldset class="layui-elem-field layui-field-title site-title">
|
||||
<legend><a name="use">公共响应参数</a></legend>
|
||||
<legend>公共响应参数</legend>
|
||||
</fieldset>
|
||||
</div>
|
||||
<div class="site-text">
|
||||
@@ -304,7 +308,7 @@
|
||||
|
||||
<div class="site-title">
|
||||
<fieldset class="layui-elem-field layui-field-title site-title">
|
||||
<legend><a name="use">响应参数</a></legend>
|
||||
<legend>响应参数</legend>
|
||||
</fieldset>
|
||||
</div>
|
||||
<div class="site-text">
|
||||
@@ -313,7 +317,7 @@
|
||||
|
||||
<div class="site-title">
|
||||
<fieldset class="layui-elem-field layui-field-title site-title">
|
||||
<legend><a name="use">响应示例</a></legend>
|
||||
<legend>响应示例</legend>
|
||||
</fieldset>
|
||||
</div>
|
||||
<div class="site-text">
|
||||
@@ -323,7 +327,7 @@
|
||||
|
||||
<div class="site-title">
|
||||
<fieldset class="layui-elem-field layui-field-title site-title">
|
||||
<legend><a name="use">异常示例</a></legend>
|
||||
<legend>异常示例</legend>
|
||||
</fieldset>
|
||||
</div>
|
||||
<div class="site-text">
|
||||
@@ -344,6 +348,8 @@
|
||||
<script src="../../config/config.js" charset="utf-8"></script>
|
||||
<script src="../../assets/lib/jquery/3.2.1/jquery.min.js" charset="utf-8"></script>
|
||||
|
||||
<script src="doc.js" charset="utf-8"></script>
|
||||
<script src="doc.js" type="text/javascript"></script>
|
||||
<script src="docEvent.js" type="text/javascript"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
@@ -1,3 +1,9 @@
|
||||
var docEvent = {
|
||||
bind: function (fn) {
|
||||
this.onSelectDocItem = fn;
|
||||
},
|
||||
onSelectDocItem: function () {}
|
||||
}
|
||||
layui.config({
|
||||
base: '../../assets/lib/layuiext/module/'
|
||||
}).extend({
|
||||
@@ -22,6 +28,7 @@ layui.config({
|
||||
}
|
||||
$('#moduleList').html(html.join(''));
|
||||
$('.url-prod').text(baseInfo.urlProd);
|
||||
$('.url-sandbox').text(baseInfo.urlSandbox);
|
||||
form.render('select');
|
||||
|
||||
if (docInfoList && docInfoList.length > 0) {
|
||||
@@ -54,7 +61,7 @@ layui.config({
|
||||
</li>
|
||||
*/
|
||||
html.push('<li class="site-tree-noicon" nameversion="'+docItem.nameVersion+'">');
|
||||
html.push('<a href="#"><cite>'+docItem.summary+'</cite></a>')
|
||||
html.push('<a href="#"><cite>' + docItem['summary'] + '</cite></a>')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,119 +84,8 @@ layui.config({
|
||||
|
||||
function selectDocItem(nameVersion) {
|
||||
var docItem = docItemStore[nameVersion];
|
||||
$('.sop-name').text(docItem.name);
|
||||
$('.sop-version').text(docItem.version);
|
||||
$('.sop-summary').text(docItem.summary);
|
||||
$('.sop-description').text(docItem.description || docItem.summary);
|
||||
|
||||
createRequestParameter(docItem);
|
||||
createResponseParameter(docItem);
|
||||
createResponseCode(docItem);
|
||||
|
||||
var $li = $('#docItemTree').find('li[nameversion="'+nameVersion+'"]');
|
||||
$li.addClass('layui-this').siblings().removeClass('layui-this');
|
||||
}
|
||||
|
||||
function createRequestParameter(docItem) {
|
||||
var data = buildTreeData(docItem.requestParameters);
|
||||
createTreeTable('treeTableReq', data);
|
||||
}
|
||||
|
||||
function createResponseParameter(docItem) {
|
||||
var data = buildTreeData(docItem.responseParameters);
|
||||
createTreeTable('treeTableResp', data);
|
||||
}
|
||||
|
||||
function buildTreeData(parameters, parentId) {
|
||||
var data = [];
|
||||
parentId = parentId || 0;
|
||||
for (var i = 0; i < parameters.length; i++) {
|
||||
var parameter = parameters[i];
|
||||
parameter.id = parentId * 100 + (i + 1);
|
||||
parameter.parentId = parentId;
|
||||
data.push(parameter);
|
||||
var refs = parameter.refs;
|
||||
if (refs && refs.length > 0) {
|
||||
var childData = buildTreeData(refs, parameter.id);
|
||||
data = data.concat(childData);
|
||||
}
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
function createTreeTable(id, data) {
|
||||
var el = '#' + id;
|
||||
$(el).text('');
|
||||
treetable.render({
|
||||
elem: el,
|
||||
treeColIndex: 0,
|
||||
treeSpid: 0,
|
||||
treeIdName: 'id',
|
||||
treePidName: 'parentId',
|
||||
treeDefaultClose: false,
|
||||
treeLinkage: false,
|
||||
data: data,
|
||||
page: false,
|
||||
cols: [[
|
||||
{field: 'name', title: '参数'}
|
||||
,{field: 'type', title: '类型', width: 80}
|
||||
,{field: 'required', title: '是否必填', width: 100, templet:function (row) {
|
||||
return row.required ? '<span style="color: red;">是</span>' : '否';
|
||||
}}
|
||||
,{field: 'maxLength', title: '最大长度', width: 100}
|
||||
,{field: 'description', title: '描述', width: 200}
|
||||
,{field: 'paramExample', title: '示例值', width: 200}
|
||||
]]
|
||||
});
|
||||
}
|
||||
|
||||
function createResponseCode(docItem) {
|
||||
var method = docItem.name.replace(/\./g, '_');
|
||||
var responseParameters = docItem.responseParameters;
|
||||
var bizResult = buildResult(responseParameters);
|
||||
var json = '{\n' +
|
||||
' "'+method+'_response": {\n' +
|
||||
' "code": "10000",\n' +
|
||||
' "msg": "Success",\n' +
|
||||
bizResult +
|
||||
' }' +
|
||||
'}';
|
||||
json = formatJson(json);
|
||||
$('#responseExampleJson').text(json);
|
||||
|
||||
var errorJson = '{\n' +
|
||||
' "'+method+'_response": {\n' +
|
||||
' "code": "20000",\n' +
|
||||
' "msg": "Service is temporarily unavailable",\n' +
|
||||
' "sub_code": "isp.unknow-error",\n' +
|
||||
' "sub_msg": "服务暂不可用"\n' +
|
||||
' }' +
|
||||
'}';
|
||||
errorJson = formatJson(errorJson);
|
||||
$('#responseErrorJson').text(errorJson);
|
||||
}
|
||||
|
||||
function buildResult(parameters) {
|
||||
var result = [];
|
||||
for (var i = 0; i < parameters.length; i++) {
|
||||
var parameter = parameters[i];
|
||||
result.push('\"'+parameter.name+'\": ' + buildExample(parameter))
|
||||
}
|
||||
return result.join(",");
|
||||
}
|
||||
|
||||
function buildExample(parameter) {
|
||||
var refs = parameter.refs;
|
||||
if (refs) {
|
||||
// {...}
|
||||
var content = '{' + buildResult(refs) + '}';
|
||||
if (parameter.type == 'array') {
|
||||
// [{...}]
|
||||
content = '[' + content + ']';
|
||||
}
|
||||
return content;
|
||||
} else {
|
||||
return '\"' + parameter.example + '\"';
|
||||
if (docItem) {
|
||||
docEvent.onSelectDocItem(docItem, layui);
|
||||
}
|
||||
}
|
||||
|
||||
|
124
sop-website/website-front/pages/doc/docEvent.js
Normal file
124
sop-website/website-front/pages/doc/docEvent.js
Normal file
@@ -0,0 +1,124 @@
|
||||
|
||||
docEvent.bind(function (docItem,layui) {
|
||||
selectItem(docItem, layui);
|
||||
});
|
||||
|
||||
var treetable;
|
||||
|
||||
function selectItem(docItem, layui) {
|
||||
var nameVersion = docItem.nameVersion;
|
||||
treetable = treetable || layui.treetable;
|
||||
$('.sop-name').text(docItem.name);
|
||||
$('.sop-version').text(docItem.version);
|
||||
$('.sop-summary').text(docItem['summary']);
|
||||
$('.sop-description').text(docItem.description || docItem['summary']);
|
||||
|
||||
createRequestParameter(docItem);
|
||||
createResponseParameter(docItem);
|
||||
createResponseCode(docItem);
|
||||
|
||||
var $li = $('#docItemTree').find('li[nameversion="'+nameVersion+'"]');
|
||||
$li.addClass('layui-this').siblings().removeClass('layui-this');
|
||||
}
|
||||
|
||||
function createRequestParameter(docItem) {
|
||||
var data = buildTreeData(docItem.requestParameters);
|
||||
createTreeTable('treeTableReq', data);
|
||||
}
|
||||
|
||||
function createResponseParameter(docItem) {
|
||||
var data = buildTreeData(docItem.responseParameters);
|
||||
createTreeTable('treeTableResp', data);
|
||||
}
|
||||
|
||||
function buildTreeData(parameters, parentId) {
|
||||
var data = [];
|
||||
parentId = parentId || 0;
|
||||
for (var i = 0; i < parameters.length; i++) {
|
||||
var parameter = parameters[i];
|
||||
parameter.id = parentId * 100 + (i + 1);
|
||||
parameter.parentId = parentId;
|
||||
data.push(parameter);
|
||||
var refs = parameter.refs;
|
||||
if (refs && refs.length > 0) {
|
||||
var childData = buildTreeData(refs, parameter.id);
|
||||
data = data.concat(childData);
|
||||
}
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
function createTreeTable(id, data) {
|
||||
var el = '#' + id;
|
||||
treetable.render({
|
||||
elem: el,
|
||||
treeColIndex: 0,
|
||||
treeSpid: 0,
|
||||
treeIdName: 'id',
|
||||
treePidName: 'parentId',
|
||||
treeDefaultClose: false,
|
||||
treeLinkage: false,
|
||||
data: data,
|
||||
page: false,
|
||||
cols: [[
|
||||
{field: 'name', title: '参数'}
|
||||
,{field: 'type', title: '类型', width: 80}
|
||||
,{field: 'required', title: '是否必填', width: 100, templet:function (row) {
|
||||
return row.required ? '<span style="color: red;">是</span>' : '否';
|
||||
}}
|
||||
,{field: 'maxLength', title: '最大长度', width: 100}
|
||||
,{field: 'description', title: '描述', width: 200}
|
||||
,{field: 'paramExample', title: '示例值', width: 200}
|
||||
]]
|
||||
});
|
||||
}
|
||||
|
||||
function createResponseCode(docItem) {
|
||||
var method = docItem.name.replace(/\./g, '_');
|
||||
var responseParameters = docItem.responseParameters;
|
||||
var bizResult = buildResult(responseParameters);
|
||||
var json = '{\n' +
|
||||
' "'+method+'_response": {\n' +
|
||||
' "code": "10000",\n' +
|
||||
' "msg": "Success",\n' +
|
||||
bizResult +
|
||||
' }' +
|
||||
'}';
|
||||
json = formatJson(json);
|
||||
$('#responseExampleJson').text(json);
|
||||
|
||||
var errorJson = '{\n' +
|
||||
' "'+method+'_response": {\n' +
|
||||
' "code": "20000",\n' +
|
||||
' "msg": "Service is temporarily unavailable",\n' +
|
||||
' "sub_code": "isp.unknow-error",\n' +
|
||||
' "sub_msg": "服务暂不可用"\n' +
|
||||
' }' +
|
||||
'}';
|
||||
errorJson = formatJson(errorJson);
|
||||
$('#responseErrorJson').text(errorJson);
|
||||
}
|
||||
|
||||
function buildResult(parameters) {
|
||||
var result = [];
|
||||
for (var i = 0; i < parameters.length; i++) {
|
||||
var parameter = parameters[i];
|
||||
result.push('\"'+parameter.name+'\": ' + buildExample(parameter))
|
||||
}
|
||||
return result.join(",");
|
||||
}
|
||||
|
||||
function buildExample(parameter) {
|
||||
var refs = parameter.refs;
|
||||
if (refs) {
|
||||
// {...}
|
||||
var content = '{' + buildResult(refs) + '}';
|
||||
if (parameter.type == 'array') {
|
||||
// [{...}]
|
||||
content = '[' + content + ']';
|
||||
}
|
||||
return content;
|
||||
} else {
|
||||
return '\"' + parameter.example + '\"';
|
||||
}
|
||||
}
|
@@ -62,7 +62,7 @@
|
||||
<p>如果未使用开放平台SDK,需要自行实现签名过程。</p>
|
||||
|
||||
<fieldset class="layui-elem-field layui-field-title site-title">
|
||||
<legend><a name="use">如何签名</a></legend>
|
||||
<legend>如何签名</legend>
|
||||
</fieldset>
|
||||
<p>1.筛选并排序</p>
|
||||
<p>
|
||||
|
142
sop-website/website-front/pages/sandbox/sandbox.html
Normal file
142
sop-website/website-front/pages/sandbox/sandbox.html
Normal file
@@ -0,0 +1,142 @@
|
||||
<html data-find="_6">
|
||||
<head>
|
||||
<script src="https://www.googletagservices.com/activeview/js/current/osd.js?cb=%2Fr20100101"></script>
|
||||
<meta charset="utf-8">
|
||||
<title>文档中心</title>
|
||||
<meta name="renderer" content="webkit">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta name="format-detection" content="telephone=no">
|
||||
|
||||
<link rel="stylesheet" href="../../assets/lib/layui/css/layui.css" media="all">
|
||||
<link rel="stylesheet" href="../../assets/css/global.css?v=1" media="all">
|
||||
<link id="layuicss-skincodecss" rel="stylesheet" href="../../assets/lib/layui/css/modules/code.css" media="all">
|
||||
<link id="layuicss-layer" rel="stylesheet" href="../../assets/lib/layui/css/modules/layer/default/layer.css?v=3.1.1"
|
||||
media="all">
|
||||
<style type="text/css">
|
||||
.layui-table {
|
||||
word-wrap: break-word;
|
||||
word-break: break-all;
|
||||
}
|
||||
.layui-table th {white-space: nowrap !important;}
|
||||
/** 修改文件夹图标:未展开 */
|
||||
.treeTable-icon .layui-icon-layer:before {content: "";}
|
||||
/** 修改文件夹图标:展开 */
|
||||
.treeTable-icon.open .layui-icon-layer:before {content: "";}
|
||||
/* 修改文件图标:*/
|
||||
.treeTable-icon .layui-icon-file:before {content: "";}
|
||||
table .table-title {width: 180px;}
|
||||
.layui-tab-item span {color: #6e6e6e;}
|
||||
.input-tip {color: #6e6e6e;}
|
||||
</style>
|
||||
</head>
|
||||
<body data-find="_5">
|
||||
|
||||
<div class="layui-header header header-doc" spring="">
|
||||
<div class="layui-main">
|
||||
<a class="logo" href="#" style="color: #ffffff">
|
||||
开放平台
|
||||
</a>
|
||||
<ul class="layui-nav">
|
||||
<li class="layui-nav-item layui-this">
|
||||
<a href="sandbox.html">沙箱环境</a>
|
||||
</li>
|
||||
<li class="layui-nav-item">
|
||||
<a href="../doc/doc.html">文档中心</a>
|
||||
</li>
|
||||
|
||||
<span class="layui-nav-bar" style="left: 162px; top: 55px; width: 0px; opacity: 0;"></span>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 让IE8/9支持媒体查询,从而兼容栅格 -->
|
||||
<!--[if lt IE 9]>
|
||||
<script src="https://cdn.staticfile.org/html5shiv/r29/html5.min.js"></script>
|
||||
<script src="https://cdn.staticfile.org/respond.js/1.4.2/respond.min.js"></script>
|
||||
<![endif]-->
|
||||
<div class="layui-main site-inline">
|
||||
<div class="site-tree">
|
||||
<div class="layui-form" style="height: 38px; margin: 10px 13px 0 0;">
|
||||
<select id="moduleList" lay-filter="moduleListFilter">
|
||||
<!--<option value="故事API" selected="selected">故事API</option>
|
||||
<option value="书本API">书本API</option>-->
|
||||
</select>
|
||||
</div>
|
||||
<ul id="docItemTree" class="layui-tree">
|
||||
|
||||
<!--<li><h2 class="docModule">支付API</h2></li>
|
||||
|
||||
<li class="site-tree-noicon layui-this">
|
||||
<a href="/">
|
||||
<cite>xxx</cite>
|
||||
</a>
|
||||
</li>-->
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="site-content">
|
||||
<h1 class="site-h1"><i class="layui-icon layui-icon-slider"></i> <span class="sop-name"></span>(<span
|
||||
class="sop-summary"></span>)
|
||||
</h1>
|
||||
<blockquote class="layui-elem-quote layui-text sop-description">
|
||||
</blockquote>
|
||||
|
||||
<div class="site-text">
|
||||
<h3>参数配置</h3>
|
||||
<table class="layui-table">
|
||||
<tr>
|
||||
<td class="table-title">AppId</td>
|
||||
<td><input id="appId" type="text" name="appId" class="layui-input" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>PrivateKey</td>
|
||||
<td><input id="privateKey" type="text" name="privateKey" class="layui-input" /></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="site-title">
|
||||
<fieldset class="layui-elem-field layui-field-title site-title">
|
||||
<legend>请求参数</legend>
|
||||
</fieldset>
|
||||
</div>
|
||||
<form class="layui-form" action="">
|
||||
<table id="treeTableReq" class="layui-table" lay-size="sm"></table>
|
||||
<button lay-submit lay-filter="formSend" class="layui-btn layui-btn-normal">发送请求</button>
|
||||
</form>
|
||||
|
||||
<div id="resultDiv" class="layui-tab layui-tab-card" style="display: none;">
|
||||
<ul class="layui-tab-title">
|
||||
<li class="req-info">请求信息</li>
|
||||
<li class="resp-info layui-this">响应信息</li>
|
||||
</ul>
|
||||
<div class="layui-tab-content">
|
||||
<div class="layui-tab-item req-info-content" style="overflow: auto;">
|
||||
<textarea id="req-info-result" wrap="off" class="layui-textarea" readonly="readonly"></textarea>
|
||||
</div>
|
||||
<div class="layui-tab-item resp-info-content layui-show">
|
||||
<pre id="resp-info-result"></pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div><!-- layui-main end~ -->
|
||||
<div class="layui-footer footer footer-doc">
|
||||
<div class="layui-main">
|
||||
<p>© 2019 <a href="https://gitee.com/durcframework/SOP" target="_blank">SOP</a> MIT license</p>
|
||||
</div>
|
||||
</div>
|
||||
<script src="../../assets/lib/layui/layui.js" charset="utf-8"></script>
|
||||
<script src="../../assets/js/format.js" charset="utf-8"></script>
|
||||
<script src="../../config/config.js" charset="utf-8"></script>
|
||||
<script src="../../assets/lib/jquery/3.2.1/jquery.min.js" charset="utf-8"></script>
|
||||
<script src="../../assets/js/inputcache.js" type="text/javascript"></script>
|
||||
|
||||
<script src="../doc/doc.js" type="text/javascript"></script>
|
||||
<script src="sandbox.js" type="text/javascript"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
161
sop-website/website-front/pages/sandbox/sandbox.js
Normal file
161
sop-website/website-front/pages/sandbox/sandbox.js
Normal file
@@ -0,0 +1,161 @@
|
||||
|
||||
docEvent.bind(function (docItem,layui) {
|
||||
selectItem(docItem, layui);
|
||||
});
|
||||
|
||||
layui.use('form', function(){
|
||||
var form = layui.form;
|
||||
|
||||
//监听提交
|
||||
form.on('submit(formSend)', function(data){
|
||||
doTest();
|
||||
return false;
|
||||
});
|
||||
});
|
||||
|
||||
var $body = $('body');
|
||||
var treetable;
|
||||
var method,version;
|
||||
var nameVersion;
|
||||
|
||||
function selectItem(docItem, layui) {
|
||||
resetResultDiv();
|
||||
nameVersion = docItem.nameVersion;
|
||||
method = docItem.name;
|
||||
version = docItem.version;
|
||||
treetable = treetable || layui.treetable;
|
||||
$('.sop-name').text(docItem.name);
|
||||
$('.sop-version').text(docItem.version);
|
||||
$('.sop-summary').text(docItem['summary']);
|
||||
$('.sop-description').text(docItem.description || docItem['summary']);
|
||||
|
||||
createRequestParameter(docItem);
|
||||
|
||||
var $li = $('#docItemTree').find('li[nameversion="'+nameVersion+'"]');
|
||||
$li.addClass('layui-this').siblings().removeClass('layui-this');
|
||||
InputCache.init();
|
||||
}
|
||||
|
||||
function createRequestParameter(docItem) {
|
||||
var data = buildTreeData(docItem.requestParameters);
|
||||
createTreeTable('treeTableReq', data);
|
||||
}
|
||||
|
||||
function buildTreeData(parameters, parentId) {
|
||||
var data = [];
|
||||
parentId = parentId || 0;
|
||||
for (var i = 0; i < parameters.length; i++) {
|
||||
var parameter = parameters[i];
|
||||
parameter.id = parentId * 100 + (i + 1);
|
||||
parameter.parentId = parentId;
|
||||
data.push(parameter);
|
||||
var refs = parameter.refs;
|
||||
if (refs && refs.length > 0) {
|
||||
var childData = buildTreeData(refs, parameter.id);
|
||||
data = data.concat(childData);
|
||||
}
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
function createTreeTable(id, data) {
|
||||
var el = '#' + id;
|
||||
treetable.render({
|
||||
elem: el,
|
||||
treeColIndex: 0,
|
||||
treeSpid: 0,
|
||||
treeIdName: 'id',
|
||||
treePidName: 'parentId',
|
||||
treeDefaultClose: false,
|
||||
treeLinkage: false,
|
||||
data: data,
|
||||
page: false,
|
||||
firstTemplet: function (row) {
|
||||
var required = row.required ? '<span style="color: red;">*</span> ' : '';
|
||||
return required + row.name;
|
||||
},
|
||||
cols: [[
|
||||
{field: 'name', title: '参数',width: 200}
|
||||
,{field: 'val', title: '值', width: 300, templet:function (row) {
|
||||
var id = nameVersion + '-' + row.name;
|
||||
var requiredTxt = row.required ? 'required lay-verify="required"' : '';
|
||||
return !row.refs ? '<input id="' + id + '" ' + requiredTxt + ' type="text" name="' + row.name + '" class="layui-input test-input"/>' : '';
|
||||
}}
|
||||
,{field: 'description', title: '描述'}
|
||||
]]
|
||||
});
|
||||
}
|
||||
|
||||
function doTest() {
|
||||
var data = {
|
||||
appId: $('#appId').val(),
|
||||
privateKey: $('#privateKey').val(),
|
||||
method: method,
|
||||
version: version
|
||||
};
|
||||
var $inputs = $body.find('.test-input');
|
||||
var bizContent = {};
|
||||
$inputs.each(function () {
|
||||
bizContent[this.name] = this.value;
|
||||
});
|
||||
data.bizContent = JSON.stringify(bizContent);
|
||||
$.ajax({
|
||||
url: SopConfig.url + '/sandbox/test'
|
||||
, dataType: 'json'
|
||||
, data: data
|
||||
, method: 'post'
|
||||
, success: function (resp) {
|
||||
setReqInfo(resp);
|
||||
showRespnfo(resp.apiResult);
|
||||
}
|
||||
, error: function (xhr,status,error) {
|
||||
// {"timestamp":"2019-06-19 15:57:36","status":500,"error":"Internal Server Error","message":"appId不能为空","path":"/sandbox/test"}
|
||||
var errorData = xhr.responseJSON;
|
||||
if (errorData) {
|
||||
setReqInfo('');
|
||||
showRespnfo(errorData.message);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function showRespnfo(info) {
|
||||
var json = formatJson(info);
|
||||
setRespInfo(json);
|
||||
$('#resultDiv').show();
|
||||
}
|
||||
|
||||
function setReqInfo(resp) {
|
||||
var txt = '';
|
||||
if (resp) {
|
||||
var html = [];
|
||||
html.push('【请求参数】:' + resp.params);
|
||||
html.push('【待签名内容】:' + resp.beforeSign);
|
||||
html.push('【签名(sign)】:' + resp.sign);
|
||||
txt = html.join('\r\n')
|
||||
}
|
||||
$('#req-info-result').val(txt);
|
||||
}
|
||||
|
||||
function setRespInfo(info) {
|
||||
$('#resp-info-result').text(info);
|
||||
}
|
||||
|
||||
function resetResultDiv() {
|
||||
setReqInfo({
|
||||
beforeSign: '',
|
||||
params: '',
|
||||
privateKey: '',
|
||||
sign: ''
|
||||
});
|
||||
setRespInfo('');
|
||||
$('.resp-info-content')
|
||||
.addClass('layui-show')
|
||||
.siblings().removeClass('layui-show');
|
||||
|
||||
$('.resp-info')
|
||||
.addClass('layui-this')
|
||||
.siblings().removeClass('layui-this');
|
||||
|
||||
$('#resultDiv').hide();
|
||||
}
|
@@ -82,6 +82,11 @@
|
||||
<version>1.2.56</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpclient</artifactId>
|
||||
<version>4.5.6</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
@@ -0,0 +1,146 @@
|
||||
package com.gitee.sop.websiteserver.controller;
|
||||
|
||||
import com.gitee.sop.websiteserver.sign.AlipayApiException;
|
||||
import com.gitee.sop.websiteserver.sign.AlipaySignature;
|
||||
import lombok.Data;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.http.NameValuePair;
|
||||
import org.apache.http.client.entity.UrlEncodedFormEntity;
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.HttpClients;
|
||||
import org.apache.http.message.BasicNameValuePair;
|
||||
import org.apache.http.util.EntityUtils;
|
||||
import org.apache.tomcat.util.http.fileupload.IOUtils;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 沙箱环境代理类
|
||||
* @author tanghc
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("sandbox")
|
||||
public class SandboxController {
|
||||
|
||||
@Value("${api.url-sandbox}")
|
||||
private String url;
|
||||
|
||||
@RequestMapping("/test")
|
||||
public SandboxResult proxy(
|
||||
@RequestParam String appId
|
||||
, @RequestParam String privateKey
|
||||
, @RequestParam String method
|
||||
, @RequestParam String version
|
||||
, @RequestParam String bizContent) throws AlipayApiException {
|
||||
|
||||
Assert.isTrue(StringUtils.isNotBlank(appId), "appId不能为空");
|
||||
Assert.isTrue(StringUtils.isNotBlank(privateKey), "privateKey不能为空");
|
||||
Assert.isTrue(StringUtils.isNotBlank(method), "method不能为空");
|
||||
|
||||
// 公共请求参数
|
||||
Map<String, String> params = new HashMap<String, String>();
|
||||
params.put("app_id", appId);
|
||||
params.put("method", method);
|
||||
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("version", version);
|
||||
|
||||
// 业务参数
|
||||
params.put("biz_content", bizContent);
|
||||
|
||||
SandboxResult result = new SandboxResult();
|
||||
|
||||
result.params = buildParamQuery(params);
|
||||
|
||||
String content = AlipaySignature.getSignContent(params);
|
||||
result.beforeSign = content;
|
||||
|
||||
String sign = AlipaySignature.rsa256Sign(content, privateKey, "utf-8");
|
||||
result.sign = sign;
|
||||
|
||||
params.put("sign", sign);
|
||||
|
||||
String responseData = get(url, params);// 发送请求
|
||||
result.apiResult = responseData;
|
||||
return result;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class SandboxResult {
|
||||
private String params;
|
||||
private String beforeSign;
|
||||
private String sign;
|
||||
|
||||
private String apiResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送get请求
|
||||
* @param url
|
||||
* @return JSON或者字符串
|
||||
* @throws Exception
|
||||
*/
|
||||
public static String get(String url, Map<String, String> params) {
|
||||
CloseableHttpClient client = null;
|
||||
CloseableHttpResponse response = null;
|
||||
try{
|
||||
/**
|
||||
* 创建一个httpclient对象
|
||||
*/
|
||||
client = HttpClients.createDefault();
|
||||
|
||||
List<NameValuePair> nameValuePairs = params.entrySet()
|
||||
.stream()
|
||||
.map(entry -> new BasicNameValuePair(entry.getKey(), String.valueOf(entry.getValue())))
|
||||
.collect(Collectors.toList());
|
||||
/**
|
||||
* 包装成一个Entity对象
|
||||
*/
|
||||
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(nameValuePairs, "UTF-8");
|
||||
//参数转换为字符串
|
||||
String paramsStr = EntityUtils.toString(entity);
|
||||
url = url + "?" + paramsStr;
|
||||
/**
|
||||
* 创建一个post对象
|
||||
*/
|
||||
HttpGet get = new HttpGet(url);
|
||||
|
||||
/**
|
||||
* 执行post请求
|
||||
*/
|
||||
response = client.execute(get);
|
||||
/**
|
||||
* 通过EntityUitls获取返回内容
|
||||
*/
|
||||
return EntityUtils.toString(response.getEntity(),"UTF-8");
|
||||
}catch (Exception e){
|
||||
e.printStackTrace();
|
||||
}finally {
|
||||
IOUtils.closeQuietly(client);
|
||||
IOUtils.closeQuietly(response);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected String buildParamQuery(Map<String, String> params) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (Map.Entry<String, String> entry : params.entrySet()) {
|
||||
sb.append("&").append(entry.getKey()).append("=").append(entry.getValue());
|
||||
}
|
||||
return sb.toString().substring(1);
|
||||
}
|
||||
}
|
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
* Alipay.com Inc.
|
||||
* Copyright (c) 2004-2012 All Rights Reserved.
|
||||
*/
|
||||
package com.gitee.sop.websiteserver.sign;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @author runzhi
|
||||
*/
|
||||
public class AlipayApiException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = -238091758285157331L;
|
||||
|
||||
private String errCode;
|
||||
private String errMsg;
|
||||
|
||||
public AlipayApiException() {
|
||||
super();
|
||||
}
|
||||
|
||||
public AlipayApiException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public AlipayApiException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public AlipayApiException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
public AlipayApiException(String errCode, String errMsg) {
|
||||
super(errCode + ":" + errMsg);
|
||||
this.errCode = errCode;
|
||||
this.errMsg = errMsg;
|
||||
}
|
||||
|
||||
public String getErrCode() {
|
||||
return this.errCode;
|
||||
}
|
||||
|
||||
public String getErrMsg() {
|
||||
return this.errMsg;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,97 @@
|
||||
/**
|
||||
* Alipay.com Inc.
|
||||
* Copyright (c) 2004-2012 All Rights Reserved.
|
||||
*/
|
||||
package com.gitee.sop.websiteserver.sign;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author runzhi
|
||||
*/
|
||||
public class AlipayConstants {
|
||||
|
||||
public static final String SIGN_TYPE = "sign_type";
|
||||
|
||||
public static final String SIGN_TYPE_RSA = "RSA";
|
||||
|
||||
/**
|
||||
* sha256WithRsa 算法请求类型
|
||||
*/
|
||||
public static final String SIGN_TYPE_RSA2 = "RSA2";
|
||||
|
||||
public static final String SIGN_ALGORITHMS = "SHA1WithRSA";
|
||||
|
||||
public static final String SIGN_SHA256RSA_ALGORITHMS = "SHA256WithRSA";
|
||||
|
||||
public static final String ENCRYPT_TYPE_AES = "AES";
|
||||
|
||||
public static final String APP_ID = "app_id";
|
||||
|
||||
public static final String FORMAT = "format";
|
||||
|
||||
public static final String METHOD = "method";
|
||||
|
||||
public static final String TIMESTAMP = "timestamp";
|
||||
|
||||
public static final String VERSION = "version";
|
||||
|
||||
public static final String SIGN = "sign";
|
||||
|
||||
public static final String ALIPAY_SDK = "alipay_sdk";
|
||||
|
||||
public static final String ACCESS_TOKEN = "auth_token";
|
||||
|
||||
public static final String APP_AUTH_TOKEN = "app_auth_token";
|
||||
|
||||
public static final String TERMINAL_TYPE = "terminal_type";
|
||||
|
||||
public static final String TERMINAL_INFO = "terminal_info";
|
||||
|
||||
public static final String CHARSET = "charset";
|
||||
|
||||
public static final String NOTIFY_URL = "notify_url";
|
||||
|
||||
public static final String RETURN_URL = "return_url";
|
||||
|
||||
public static final String ENCRYPT_TYPE = "encrypt_type";
|
||||
|
||||
//-----===-------///
|
||||
|
||||
public static final String BIZ_CONTENT_KEY = "biz_content";
|
||||
|
||||
/** 默认时间格式 **/
|
||||
public static final String DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
|
||||
|
||||
/** Date默认时区 **/
|
||||
public static final String DATE_TIMEZONE = "GMT+8";
|
||||
|
||||
/** UTF-8字符集 **/
|
||||
public static final String CHARSET_UTF8 = "UTF-8";
|
||||
|
||||
/** GBK字符集 **/
|
||||
public static final String CHARSET_GBK = "GBK";
|
||||
|
||||
/** JSON 应格式 */
|
||||
public static final String FORMAT_JSON = "json";
|
||||
|
||||
/** XML 应格式 */
|
||||
public static final String FORMAT_XML = "xml";
|
||||
|
||||
/** SDK版本号 */
|
||||
public static final String SDK_VERSION = "alipay-sdk-java-3.6.0.ALL";
|
||||
|
||||
public static final String PROD_CODE = "prod_code";
|
||||
|
||||
/** 老版本失败节点 */
|
||||
public static final String ERROR_RESPONSE = "error_response";
|
||||
|
||||
/** 新版本节点后缀 */
|
||||
public static final String RESPONSE_SUFFIX = "_response";
|
||||
|
||||
/** 加密后XML返回报文的节点名字 */
|
||||
public static final String RESPONSE_XML_ENCRYPT_NODE_NAME = "response_encrypted";
|
||||
|
||||
/** 批量请求id **/
|
||||
public static final String BATCH_REQUEST_ID = "batch_request_id";
|
||||
|
||||
}
|
@@ -0,0 +1,611 @@
|
||||
/**
|
||||
* Alipay.com Inc.
|
||||
* Copyright (c) 2004-2012 All Rights Reserved.
|
||||
*/
|
||||
package com.gitee.sop.websiteserver.sign;
|
||||
|
||||
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.StringWriter;
|
||||
import java.security.KeyFactory;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.PublicKey;
|
||||
import java.security.spec.InvalidKeySpecException;
|
||||
import java.security.spec.PKCS8EncodedKeySpec;
|
||||
import java.security.spec.X509EncodedKeySpec;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author runzhi
|
||||
*/
|
||||
public class AlipaySignature {
|
||||
|
||||
/** RSA最大加密明文大小 */
|
||||
private static final int MAX_ENCRYPT_BLOCK = 117;
|
||||
|
||||
/** RSA最大解密密文大小 */
|
||||
private static final int MAX_DECRYPT_BLOCK = 128;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @param sortedParams
|
||||
* @return
|
||||
*/
|
||||
public static String getSignContent(Map<String, String> sortedParams) {
|
||||
StringBuffer content = new StringBuffer();
|
||||
List<String> keys = new ArrayList<String>(sortedParams.keySet());
|
||||
Collections.sort(keys);
|
||||
int index = 0;
|
||||
for (int i = 0; i < keys.size(); i++) {
|
||||
String key = keys.get(i);
|
||||
String value = sortedParams.get(key);
|
||||
if (StringUtils.areNotEmpty(key, value)) {
|
||||
content.append((index == 0 ? "" : "&") + key + "=" + value);
|
||||
index++;
|
||||
}
|
||||
}
|
||||
return content.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* rsa内容签名
|
||||
*
|
||||
* @param content
|
||||
* @param privateKey
|
||||
* @param charset
|
||||
* @return
|
||||
* @throws AlipayApiException
|
||||
*/
|
||||
public static String rsaSign(String content, String privateKey, String charset,
|
||||
String signType) throws AlipayApiException {
|
||||
|
||||
if (AlipayConstants.SIGN_TYPE_RSA.equals(signType)) {
|
||||
|
||||
return rsaSign(content, privateKey, charset);
|
||||
} else if (AlipayConstants.SIGN_TYPE_RSA2.equals(signType)) {
|
||||
|
||||
return rsa256Sign(content, privateKey, charset);
|
||||
} else {
|
||||
|
||||
throw new AlipayApiException("Sign Type is Not Support : signType=" + signType);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* sha256WithRsa 加签
|
||||
*
|
||||
* @param content
|
||||
* @param privateKey
|
||||
* @param charset
|
||||
* @return
|
||||
* @throws AlipayApiException
|
||||
*/
|
||||
public static String rsa256Sign(String content, String privateKey,
|
||||
String charset) throws AlipayApiException {
|
||||
|
||||
try {
|
||||
PrivateKey priKey = getPrivateKeyFromPKCS8(AlipayConstants.SIGN_TYPE_RSA,
|
||||
new ByteArrayInputStream(privateKey.getBytes()));
|
||||
|
||||
java.security.Signature signature = java.security.Signature
|
||||
.getInstance(AlipayConstants.SIGN_SHA256RSA_ALGORITHMS);
|
||||
|
||||
signature.initSign(priKey);
|
||||
|
||||
if (StringUtils.isEmpty(charset)) {
|
||||
signature.update(content.getBytes());
|
||||
} else {
|
||||
signature.update(content.getBytes(charset));
|
||||
}
|
||||
|
||||
byte[] signed = signature.sign();
|
||||
|
||||
return new String(Base64.encodeBase64(signed));
|
||||
} catch (Exception e) {
|
||||
throw new AlipayApiException("RSAcontent = " + content + "; charset = " + charset, e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* sha1WithRsa 加签
|
||||
*
|
||||
* @param content
|
||||
* @param privateKey
|
||||
* @param charset
|
||||
* @return
|
||||
* @throws AlipayApiException
|
||||
*/
|
||||
public static String rsaSign(String content, String privateKey,
|
||||
String charset) throws AlipayApiException {
|
||||
try {
|
||||
PrivateKey priKey = getPrivateKeyFromPKCS8(AlipayConstants.SIGN_TYPE_RSA,
|
||||
new ByteArrayInputStream(privateKey.getBytes()));
|
||||
|
||||
java.security.Signature signature = java.security.Signature
|
||||
.getInstance(AlipayConstants.SIGN_ALGORITHMS);
|
||||
|
||||
signature.initSign(priKey);
|
||||
|
||||
if (StringUtils.isEmpty(charset)) {
|
||||
signature.update(content.getBytes());
|
||||
} else {
|
||||
signature.update(content.getBytes(charset));
|
||||
}
|
||||
|
||||
byte[] signed = signature.sign();
|
||||
|
||||
return new String(Base64.encodeBase64(signed));
|
||||
} catch (InvalidKeySpecException ie) {
|
||||
throw new AlipayApiException("RSA私钥格式不正确,请检查是否正确配置了PKCS8格式的私钥", ie);
|
||||
} catch (Exception e) {
|
||||
throw new AlipayApiException("RSAcontent = " + content + "; charset = " + charset, e);
|
||||
}
|
||||
}
|
||||
|
||||
public static String rsaSign(Map<String, String> params, String privateKey,
|
||||
String charset) throws AlipayApiException {
|
||||
String signContent = getSignContent(params);
|
||||
|
||||
return rsaSign(signContent, privateKey, charset);
|
||||
|
||||
}
|
||||
|
||||
public static PrivateKey getPrivateKeyFromPKCS8(String algorithm,
|
||||
InputStream ins) throws Exception {
|
||||
if (ins == null || StringUtils.isEmpty(algorithm)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
|
||||
|
||||
byte[] encodedKey = StreamUtil.readText(ins).getBytes();
|
||||
|
||||
encodedKey = Base64.decodeBase64(encodedKey);
|
||||
|
||||
return keyFactory.generatePrivate(new PKCS8EncodedKeySpec(encodedKey));
|
||||
}
|
||||
|
||||
public static String getSignCheckContentV1(Map<String, String> params) {
|
||||
if (params == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
params.remove("sign");
|
||||
params.remove("sign_type");
|
||||
|
||||
StringBuffer content = new StringBuffer();
|
||||
List<String> keys = new ArrayList<String>(params.keySet());
|
||||
Collections.sort(keys);
|
||||
|
||||
for (int i = 0; i < keys.size(); i++) {
|
||||
String key = keys.get(i);
|
||||
String value = params.get(key);
|
||||
content.append((i == 0 ? "" : "&") + key + "=" + value);
|
||||
}
|
||||
|
||||
return content.toString();
|
||||
}
|
||||
|
||||
public static String getSignCheckContentV2(Map<String, String> params) {
|
||||
if (params == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
params.remove("sign");
|
||||
|
||||
StringBuffer content = new StringBuffer();
|
||||
List<String> keys = new ArrayList<String>(params.keySet());
|
||||
Collections.sort(keys);
|
||||
|
||||
for (int i = 0; i < keys.size(); i++) {
|
||||
String key = keys.get(i);
|
||||
String value = params.get(key);
|
||||
content.append((i == 0 ? "" : "&") + key + "=" + value);
|
||||
}
|
||||
|
||||
return content.toString();
|
||||
}
|
||||
|
||||
public static boolean rsaCheckV1(Map<String, String> params, String publicKey,
|
||||
String charset) throws AlipayApiException {
|
||||
String sign = params.get("sign");
|
||||
String content = getSignCheckContentV1(params);
|
||||
|
||||
return rsaCheckContent(content, sign, publicKey, charset);
|
||||
}
|
||||
|
||||
public static boolean rsaCheckV1(Map<String, String> params, String publicKey,
|
||||
String charset,String signType) throws AlipayApiException {
|
||||
String sign = params.get("sign");
|
||||
String content = getSignCheckContentV1(params);
|
||||
|
||||
return rsaCheck(content, sign, publicKey, charset,signType);
|
||||
}
|
||||
|
||||
public static boolean rsaCheckV2(Map<String, String> params, String publicKey,
|
||||
String charset) throws AlipayApiException {
|
||||
String sign = params.get("sign");
|
||||
String content = getSignCheckContentV2(params);
|
||||
|
||||
return rsaCheckContent(content, sign, publicKey, charset);
|
||||
}
|
||||
|
||||
public static boolean rsaCheckV2(Map<String, String> params, String publicKey,
|
||||
String charset,String signType) throws AlipayApiException {
|
||||
String sign = params.get("sign");
|
||||
String content = getSignCheckContentV2(params);
|
||||
|
||||
return rsaCheck(content, sign, publicKey, charset,signType);
|
||||
}
|
||||
|
||||
public static boolean rsaCheck(String content, String sign, String publicKey, String charset,
|
||||
String signType) throws AlipayApiException {
|
||||
|
||||
if (AlipayConstants.SIGN_TYPE_RSA.equals(signType)) {
|
||||
|
||||
return rsaCheckContent(content, sign, publicKey, charset);
|
||||
|
||||
} else if (AlipayConstants.SIGN_TYPE_RSA2.equals(signType)) {
|
||||
|
||||
return rsa256CheckContent(content, sign, publicKey, charset);
|
||||
|
||||
} else {
|
||||
|
||||
throw new AlipayApiException("Sign Type is Not Support : signType=" + signType);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static boolean rsa256CheckContent(String content, String sign, String publicKey,
|
||||
String charset) throws AlipayApiException {
|
||||
try {
|
||||
PublicKey pubKey = getPublicKeyFromX509("RSA",
|
||||
new ByteArrayInputStream(publicKey.getBytes()));
|
||||
|
||||
java.security.Signature signature = java.security.Signature
|
||||
.getInstance(AlipayConstants.SIGN_SHA256RSA_ALGORITHMS);
|
||||
|
||||
signature.initVerify(pubKey);
|
||||
|
||||
if (StringUtils.isEmpty(charset)) {
|
||||
signature.update(content.getBytes());
|
||||
} else {
|
||||
signature.update(content.getBytes(charset));
|
||||
}
|
||||
|
||||
return signature.verify(Base64.decodeBase64(sign.getBytes()));
|
||||
} catch (Exception e) {
|
||||
throw new AlipayApiException(
|
||||
"RSAcontent = " + content + ",sign=" + sign + ",charset = " + charset, e);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean rsaCheckContent(String content, String sign, String publicKey,
|
||||
String charset) throws AlipayApiException {
|
||||
try {
|
||||
PublicKey pubKey = getPublicKeyFromX509("RSA",
|
||||
new ByteArrayInputStream(publicKey.getBytes()));
|
||||
|
||||
java.security.Signature signature = java.security.Signature
|
||||
.getInstance(AlipayConstants.SIGN_ALGORITHMS);
|
||||
|
||||
signature.initVerify(pubKey);
|
||||
|
||||
if (StringUtils.isEmpty(charset)) {
|
||||
signature.update(content.getBytes());
|
||||
} else {
|
||||
signature.update(content.getBytes(charset));
|
||||
}
|
||||
|
||||
return signature.verify(Base64.decodeBase64(sign.getBytes()));
|
||||
} catch (Exception e) {
|
||||
throw new AlipayApiException(
|
||||
"RSAcontent = " + content + ",sign=" + sign + ",charset = " + charset, e);
|
||||
}
|
||||
}
|
||||
|
||||
public static PublicKey getPublicKeyFromX509(String algorithm,
|
||||
InputStream ins) throws Exception {
|
||||
KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
|
||||
|
||||
StringWriter writer = new StringWriter();
|
||||
StreamUtil.io(new InputStreamReader(ins), writer);
|
||||
|
||||
byte[] encodedKey = writer.toString().getBytes();
|
||||
|
||||
encodedKey = Base64.decodeBase64(encodedKey);
|
||||
|
||||
return keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey));
|
||||
}
|
||||
|
||||
/**
|
||||
* 验签并解密
|
||||
* <p>
|
||||
* <b>目前适用于公众号</b><br>
|
||||
* params参数示例:
|
||||
* <br>{
|
||||
* <br>biz_content=M0qGiGz+8kIpxe8aF4geWJdBn0aBTuJRQItLHo9R7o5JGhpic/MIUjvXo2BLB++BbkSq2OsJCEQFDZ0zK5AJYwvBgeRX30gvEj6eXqXRt16/IkB9HzAccEqKmRHrZJ7PjQWE0KfvDAHsJqFIeMvEYk1Zei2QkwSQPlso7K0oheo/iT+HYE8aTATnkqD/ByD9iNDtGg38pCa2xnnns63abKsKoV8h0DfHWgPH62urGY7Pye3r9FCOXA2Ykm8X4/Bl1bWFN/PFCEJHWe/HXj8KJKjWMO6ttsoV0xRGfeyUO8agu6t587Dl5ux5zD/s8Lbg5QXygaOwo3Fz1G8EqmGhi4+soEIQb8DBYanQOS3X+m46tVqBGMw8Oe+hsyIMpsjwF4HaPKMr37zpW3fe7xOMuimbZ0wq53YP/jhQv6XWodjT3mL0H5ACqcsSn727B5ztquzCPiwrqyjUHjJQQefFTzOse8snaWNQTUsQS7aLsHq0FveGpSBYORyA90qPdiTjXIkVP7mAiYiAIWW9pCEC7F3XtViKTZ8FRMM9ySicfuAlf3jtap6v2KPMtQv70X+hlmzO/IXB6W0Ep8DovkF5rB4r/BJYJLw/6AS0LZM9w5JfnAZhfGM2rKzpfNsgpOgEZS1WleG4I2hoQC0nxg9IcP0Hs+nWIPkEUcYNaiXqeBc=,
|
||||
* <br>sign=rlqgA8O+RzHBVYLyHmrbODVSANWPXf3pSrr82OCO/bm3upZiXSYrX5fZr6UBmG6BZRAydEyTIguEW6VRuAKjnaO/sOiR9BsSrOdXbD5Rhos/Xt7/mGUWbTOt/F+3W0/XLuDNmuYg1yIC/6hzkg44kgtdSTsQbOC9gWM7ayB4J4c=,
|
||||
* sign_type=RSA,
|
||||
* <br>charset=UTF-8
|
||||
* <br>}
|
||||
* </p>
|
||||
* @param params
|
||||
* @param alipayPublicKey 支付宝公钥
|
||||
* @param cusPrivateKey 商户私钥
|
||||
* @param isCheckSign 是否验签
|
||||
* @param isDecrypt 是否解密
|
||||
* @return 解密后明文,验签失败则异常抛出
|
||||
* @throws AlipayApiException
|
||||
*/
|
||||
public static String checkSignAndDecrypt(Map<String, String> params, String alipayPublicKey,
|
||||
String cusPrivateKey, boolean isCheckSign,
|
||||
boolean isDecrypt) throws AlipayApiException {
|
||||
String charset = params.get("charset");
|
||||
String bizContent = params.get("biz_content");
|
||||
if (isCheckSign) {
|
||||
if (!rsaCheckV2(params, alipayPublicKey, charset)) {
|
||||
throw new AlipayApiException("rsaCheck failure:rsaParams=" + params);
|
||||
}
|
||||
}
|
||||
|
||||
if (isDecrypt) {
|
||||
return rsaDecrypt(bizContent, cusPrivateKey, charset);
|
||||
}
|
||||
|
||||
return bizContent;
|
||||
}
|
||||
|
||||
/**
|
||||
* 验签并解密
|
||||
* <p>
|
||||
* <b>目前适用于公众号</b><br>
|
||||
* params参数示例:
|
||||
* <br>{
|
||||
* <br>biz_content=M0qGiGz+8kIpxe8aF4geWJdBn0aBTuJRQItLHo9R7o5JGhpic/MIUjvXo2BLB++BbkSq2OsJCEQFDZ0zK5AJYwvBgeRX30gvEj6eXqXRt16/IkB9HzAccEqKmRHrZJ7PjQWE0KfvDAHsJqFIeMvEYk1Zei2QkwSQPlso7K0oheo/iT+HYE8aTATnkqD/ByD9iNDtGg38pCa2xnnns63abKsKoV8h0DfHWgPH62urGY7Pye3r9FCOXA2Ykm8X4/Bl1bWFN/PFCEJHWe/HXj8KJKjWMO6ttsoV0xRGfeyUO8agu6t587Dl5ux5zD/s8Lbg5QXygaOwo3Fz1G8EqmGhi4+soEIQb8DBYanQOS3X+m46tVqBGMw8Oe+hsyIMpsjwF4HaPKMr37zpW3fe7xOMuimbZ0wq53YP/jhQv6XWodjT3mL0H5ACqcsSn727B5ztquzCPiwrqyjUHjJQQefFTzOse8snaWNQTUsQS7aLsHq0FveGpSBYORyA90qPdiTjXIkVP7mAiYiAIWW9pCEC7F3XtViKTZ8FRMM9ySicfuAlf3jtap6v2KPMtQv70X+hlmzO/IXB6W0Ep8DovkF5rB4r/BJYJLw/6AS0LZM9w5JfnAZhfGM2rKzpfNsgpOgEZS1WleG4I2hoQC0nxg9IcP0Hs+nWIPkEUcYNaiXqeBc=,
|
||||
* <br>sign=rlqgA8O+RzHBVYLyHmrbODVSANWPXf3pSrr82OCO/bm3upZiXSYrX5fZr6UBmG6BZRAydEyTIguEW6VRuAKjnaO/sOiR9BsSrOdXbD5Rhos/Xt7/mGUWbTOt/F+3W0/XLuDNmuYg1yIC/6hzkg44kgtdSTsQbOC9gWM7ayB4J4c=,
|
||||
* sign_type=RSA,
|
||||
* <br>charset=UTF-8
|
||||
* <br>}
|
||||
* </p>
|
||||
* @param params
|
||||
* @param alipayPublicKey 支付宝公钥
|
||||
* @param cusPrivateKey 商户私钥
|
||||
* @param isCheckSign 是否验签
|
||||
* @param isDecrypt 是否解密
|
||||
* @return 解密后明文,验签失败则异常抛出
|
||||
* @throws AlipayApiException
|
||||
*/
|
||||
public static String checkSignAndDecrypt(Map<String, String> params, String alipayPublicKey,
|
||||
String cusPrivateKey, boolean isCheckSign,
|
||||
boolean isDecrypt, String signType) throws AlipayApiException {
|
||||
String charset = params.get("charset");
|
||||
String bizContent = params.get("biz_content");
|
||||
if (isCheckSign) {
|
||||
if (!rsaCheckV2(params, alipayPublicKey, charset,signType)) {
|
||||
throw new AlipayApiException("rsaCheck failure:rsaParams=" + params);
|
||||
}
|
||||
}
|
||||
|
||||
if (isDecrypt) {
|
||||
return rsaDecrypt(bizContent, cusPrivateKey, charset);
|
||||
}
|
||||
|
||||
return bizContent;
|
||||
}
|
||||
|
||||
/**
|
||||
* 加密并签名<br>
|
||||
* <b>目前适用于公众号</b>
|
||||
* @param bizContent 待加密、签名内容
|
||||
* @param alipayPublicKey 支付宝公钥
|
||||
* @param cusPrivateKey 商户私钥
|
||||
* @param charset 字符集,如UTF-8, GBK, GB2312
|
||||
* @param isEncrypt 是否加密,true-加密 false-不加密
|
||||
* @param isSign 是否签名,true-签名 false-不签名
|
||||
* @return 加密、签名后xml内容字符串
|
||||
* <p>
|
||||
* 返回示例:
|
||||
* <alipay>
|
||||
* <response>密文</response>
|
||||
* <encryption_type>RSA</encryption_type>
|
||||
* <sign>sign</sign>
|
||||
* <sign_type>RSA</sign_type>
|
||||
* </alipay>
|
||||
* </p>
|
||||
* @throws AlipayApiException
|
||||
*/
|
||||
public static String encryptAndSign(String bizContent, String alipayPublicKey,
|
||||
String cusPrivateKey, String charset, boolean isEncrypt,
|
||||
boolean isSign) throws AlipayApiException {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (StringUtils.isEmpty(charset)) {
|
||||
charset = AlipayConstants.CHARSET_GBK;
|
||||
}
|
||||
sb.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>");
|
||||
if (isEncrypt) {// 加密
|
||||
sb.append("<alipay>");
|
||||
String encrypted = rsaEncrypt(bizContent, alipayPublicKey, charset);
|
||||
sb.append("<response>" + encrypted + "</response>");
|
||||
sb.append("<encryption_type>RSA</encryption_type>");
|
||||
if (isSign) {
|
||||
String sign = rsaSign(encrypted, cusPrivateKey, charset);
|
||||
sb.append("<sign>" + sign + "</sign>");
|
||||
sb.append("<sign_type>RSA</sign_type>");
|
||||
}
|
||||
sb.append("</alipay>");
|
||||
} else if (isSign) {// 不加密,但需要签名
|
||||
sb.append("<alipay>");
|
||||
sb.append("<response>" + bizContent + "</response>");
|
||||
String sign = rsaSign(bizContent, cusPrivateKey, charset);
|
||||
sb.append("<sign>" + sign + "</sign>");
|
||||
sb.append("<sign_type>RSA</sign_type>");
|
||||
sb.append("</alipay>");
|
||||
} else {// 不加密,不加签
|
||||
sb.append(bizContent);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 加密并签名<br>
|
||||
* <b>目前适用于公众号</b>
|
||||
* @param bizContent 待加密、签名内容
|
||||
* @param alipayPublicKey 支付宝公钥
|
||||
* @param cusPrivateKey 商户私钥
|
||||
* @param charset 字符集,如UTF-8, GBK, GB2312
|
||||
* @param isEncrypt 是否加密,true-加密 false-不加密
|
||||
* @param isSign 是否签名,true-签名 false-不签名
|
||||
* @return 加密、签名后xml内容字符串
|
||||
* <p>
|
||||
* 返回示例:
|
||||
* <alipay>
|
||||
* <response>密文</response>
|
||||
* <encryption_type>RSA</encryption_type>
|
||||
* <sign>sign</sign>
|
||||
* <sign_type>RSA</sign_type>
|
||||
* </alipay>
|
||||
* </p>
|
||||
* @throws AlipayApiException
|
||||
*/
|
||||
public static String encryptAndSign(String bizContent, String alipayPublicKey,
|
||||
String cusPrivateKey, String charset, boolean isEncrypt,
|
||||
boolean isSign,String signType) throws AlipayApiException {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (StringUtils.isEmpty(charset)) {
|
||||
charset = AlipayConstants.CHARSET_GBK;
|
||||
}
|
||||
sb.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>");
|
||||
if (isEncrypt) {// 加密
|
||||
sb.append("<alipay>");
|
||||
String encrypted = rsaEncrypt(bizContent, alipayPublicKey, charset);
|
||||
sb.append("<response>" + encrypted + "</response>");
|
||||
sb.append("<encryption_type>RSA</encryption_type>");
|
||||
if (isSign) {
|
||||
String sign = rsaSign(encrypted, cusPrivateKey, charset, signType);
|
||||
sb.append("<sign>" + sign + "</sign>");
|
||||
sb.append("<sign_type>");
|
||||
sb.append(signType);
|
||||
sb.append("</sign_type>");
|
||||
}
|
||||
sb.append("</alipay>");
|
||||
} else if (isSign) {// 不加密,但需要签名
|
||||
sb.append("<alipay>");
|
||||
sb.append("<response>" + bizContent + "</response>");
|
||||
String sign = rsaSign(bizContent, cusPrivateKey, charset, signType);
|
||||
sb.append("<sign>" + sign + "</sign>");
|
||||
sb.append("<sign_type>");
|
||||
sb.append(signType);
|
||||
sb.append("</sign_type>");
|
||||
sb.append("</alipay>");
|
||||
} else {// 不加密,不加签
|
||||
sb.append(bizContent);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 公钥加密
|
||||
*
|
||||
* @param content 待加密内容
|
||||
* @param publicKey 公钥
|
||||
* @param charset 字符集,如UTF-8, GBK, GB2312
|
||||
* @return 密文内容
|
||||
* @throws AlipayApiException
|
||||
*/
|
||||
public static String rsaEncrypt(String content, String publicKey,
|
||||
String charset) throws AlipayApiException {
|
||||
try {
|
||||
PublicKey pubKey = getPublicKeyFromX509(AlipayConstants.SIGN_TYPE_RSA,
|
||||
new ByteArrayInputStream(publicKey.getBytes()));
|
||||
Cipher cipher = Cipher.getInstance(AlipayConstants.SIGN_TYPE_RSA);
|
||||
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
|
||||
byte[] data = StringUtils.isEmpty(charset) ? content.getBytes()
|
||||
: content.getBytes(charset);
|
||||
int inputLen = data.length;
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
int offSet = 0;
|
||||
byte[] cache;
|
||||
int i = 0;
|
||||
// 对数据分段加密
|
||||
while (inputLen - offSet > 0) {
|
||||
if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
|
||||
cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
|
||||
} else {
|
||||
cache = cipher.doFinal(data, offSet, inputLen - offSet);
|
||||
}
|
||||
out.write(cache, 0, cache.length);
|
||||
i++;
|
||||
offSet = i * MAX_ENCRYPT_BLOCK;
|
||||
}
|
||||
byte[] encryptedData = Base64.encodeBase64(out.toByteArray());
|
||||
out.close();
|
||||
|
||||
return StringUtils.isEmpty(charset) ? new String(encryptedData)
|
||||
: new String(encryptedData, charset);
|
||||
} catch (Exception e) {
|
||||
throw new AlipayApiException("EncryptContent = " + content + ",charset = " + charset,
|
||||
e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 私钥解密
|
||||
*
|
||||
* @param content 待解密内容
|
||||
* @param privateKey 私钥
|
||||
* @param charset 字符集,如UTF-8, GBK, GB2312
|
||||
* @return 明文内容
|
||||
* @throws AlipayApiException
|
||||
*/
|
||||
public static String rsaDecrypt(String content, String privateKey,
|
||||
String charset) throws AlipayApiException {
|
||||
try {
|
||||
PrivateKey priKey = getPrivateKeyFromPKCS8(AlipayConstants.SIGN_TYPE_RSA,
|
||||
new ByteArrayInputStream(privateKey.getBytes()));
|
||||
Cipher cipher = Cipher.getInstance(AlipayConstants.SIGN_TYPE_RSA);
|
||||
cipher.init(Cipher.DECRYPT_MODE, priKey);
|
||||
byte[] encryptedData = StringUtils.isEmpty(charset)
|
||||
? Base64.decodeBase64(content.getBytes())
|
||||
: Base64.decodeBase64(content.getBytes(charset));
|
||||
int inputLen = encryptedData.length;
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
int offSet = 0;
|
||||
byte[] cache;
|
||||
int i = 0;
|
||||
// 对数据分段解密
|
||||
while (inputLen - offSet > 0) {
|
||||
if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
|
||||
cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);
|
||||
} else {
|
||||
cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);
|
||||
}
|
||||
out.write(cache, 0, cache.length);
|
||||
i++;
|
||||
offSet = i * MAX_DECRYPT_BLOCK;
|
||||
}
|
||||
byte[] decryptedData = out.toByteArray();
|
||||
out.close();
|
||||
|
||||
return StringUtils.isEmpty(charset) ? new String(decryptedData)
|
||||
: new String(decryptedData, charset);
|
||||
} catch (Exception e) {
|
||||
throw new AlipayApiException("EncodeContent = " + content + ",charset = " + charset, e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,139 @@
|
||||
/**
|
||||
* Alipay.com Inc.
|
||||
* Copyright (c) 2004-2012 All Rights Reserved.
|
||||
*/
|
||||
package com.gitee.sop.websiteserver.sign;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.io.Reader;
|
||||
import java.io.StringWriter;
|
||||
import java.io.Writer;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author runzhi
|
||||
*/
|
||||
public class StreamUtil {
|
||||
private static final int DEFAULT_BUFFER_SIZE = 8192;
|
||||
|
||||
public static void io(InputStream in, OutputStream out) throws IOException {
|
||||
io(in, out, -1);
|
||||
}
|
||||
|
||||
public static void io(InputStream in, OutputStream out, int bufferSize) throws IOException {
|
||||
if (bufferSize == -1) {
|
||||
bufferSize = DEFAULT_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
byte[] buffer = new byte[bufferSize];
|
||||
int amount;
|
||||
|
||||
while ((amount = in.read(buffer)) >= 0) {
|
||||
out.write(buffer, 0, amount);
|
||||
}
|
||||
}
|
||||
|
||||
public static void io(Reader in, Writer out) throws IOException {
|
||||
io(in, out, -1);
|
||||
}
|
||||
|
||||
public static void io(Reader in, Writer out, int bufferSize) throws IOException {
|
||||
if (bufferSize == -1) {
|
||||
bufferSize = DEFAULT_BUFFER_SIZE >> 1;
|
||||
}
|
||||
|
||||
char[] buffer = new char[bufferSize];
|
||||
int amount;
|
||||
|
||||
while ((amount = in.read(buffer)) >= 0) {
|
||||
out.write(buffer, 0, amount);
|
||||
}
|
||||
}
|
||||
|
||||
public static OutputStream synchronizedOutputStream(OutputStream out) {
|
||||
return new SynchronizedOutputStream(out);
|
||||
}
|
||||
|
||||
public static OutputStream synchronizedOutputStream(OutputStream out, Object lock) {
|
||||
return new SynchronizedOutputStream(out, lock);
|
||||
}
|
||||
|
||||
public static String readText(InputStream in) throws IOException {
|
||||
return readText(in, null, -1);
|
||||
}
|
||||
|
||||
public static String readText(InputStream in, String encoding) throws IOException {
|
||||
return readText(in, encoding, -1);
|
||||
}
|
||||
|
||||
public static String readText(InputStream in, String encoding, int bufferSize)
|
||||
throws IOException {
|
||||
Reader reader = (encoding == null) ? new InputStreamReader(in) : new InputStreamReader(in,
|
||||
encoding);
|
||||
|
||||
return readText(reader, bufferSize);
|
||||
}
|
||||
|
||||
public static String readText(Reader reader) throws IOException {
|
||||
return readText(reader, -1);
|
||||
}
|
||||
|
||||
public static String readText(Reader reader, int bufferSize) throws IOException {
|
||||
StringWriter writer = new StringWriter();
|
||||
|
||||
io(reader, writer, bufferSize);
|
||||
return writer.toString();
|
||||
}
|
||||
|
||||
private static class SynchronizedOutputStream extends OutputStream {
|
||||
private OutputStream out;
|
||||
private Object lock;
|
||||
|
||||
SynchronizedOutputStream(OutputStream out) {
|
||||
this(out, out);
|
||||
}
|
||||
|
||||
SynchronizedOutputStream(OutputStream out, Object lock) {
|
||||
this.out = out;
|
||||
this.lock = lock;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(int datum) throws IOException {
|
||||
synchronized (lock) {
|
||||
out.write(datum);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(byte[] data) throws IOException {
|
||||
synchronized (lock) {
|
||||
out.write(data);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(byte[] data, int offset, int length) throws IOException {
|
||||
synchronized (lock) {
|
||||
out.write(data, offset, length);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() throws IOException {
|
||||
synchronized (lock) {
|
||||
out.flush();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
synchronized (lock) {
|
||||
out.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,171 @@
|
||||
package com.gitee.sop.websiteserver.sign;
|
||||
|
||||
/**
|
||||
* 字符串工具类。
|
||||
*
|
||||
* @author carver.gu
|
||||
* @since 1.0, Sep 12, 2009
|
||||
*/
|
||||
public abstract class StringUtils {
|
||||
|
||||
private StringUtils() {}
|
||||
|
||||
/**
|
||||
* 检查指定的字符串是否为空。
|
||||
* <ul>
|
||||
* <li>SysUtils.isEmpty(null) = true</li>
|
||||
* <li>SysUtils.isEmpty("") = true</li>
|
||||
* <li>SysUtils.isEmpty(" ") = true</li>
|
||||
* <li>SysUtils.isEmpty("abc") = false</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param value 待检查的字符串
|
||||
* @return true/false
|
||||
*/
|
||||
public static boolean isEmpty(String value) {
|
||||
int strLen;
|
||||
if (value == null || (strLen = value.length()) == 0) {
|
||||
return true;
|
||||
}
|
||||
for (int i = 0; i < strLen; i++) {
|
||||
if ((Character.isWhitespace(value.charAt(i)) == false)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查对象是否为数字型字符串,包含负数开头的。
|
||||
*/
|
||||
public static boolean isNumeric(Object obj) {
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
char[] chars = obj.toString().toCharArray();
|
||||
int length = chars.length;
|
||||
if(length < 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
if(length > 1 && chars[0] == '-') {
|
||||
i = 1;
|
||||
}
|
||||
|
||||
for (; i < length; i++) {
|
||||
if (!Character.isDigit(chars[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查指定的字符串列表是否不为空。
|
||||
*/
|
||||
public static boolean areNotEmpty(String... values) {
|
||||
boolean result = true;
|
||||
if (values == null || values.length == 0) {
|
||||
result = false;
|
||||
} else {
|
||||
for (String value : values) {
|
||||
result &= !isEmpty(value);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 把通用字符编码的字符串转化为汉字编码。
|
||||
*/
|
||||
public static String unicodeToChinese(String unicode) {
|
||||
StringBuilder out = new StringBuilder();
|
||||
if (!isEmpty(unicode)) {
|
||||
for (int i = 0; i < unicode.length(); i++) {
|
||||
out.append(unicode.charAt(i));
|
||||
}
|
||||
}
|
||||
return out.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 过滤不可见字符
|
||||
*/
|
||||
public static String stripNonValidXMLCharacters(String input) {
|
||||
if (input == null || ("".equals(input))) {
|
||||
return "";
|
||||
}
|
||||
StringBuilder out = new StringBuilder();
|
||||
char current;
|
||||
for (int i = 0; i < input.length(); i++) {
|
||||
current = input.charAt(i);
|
||||
if ((current == 0x9) || (current == 0xA) || (current == 0xD)
|
||||
|| ((current >= 0x20) && (current <= 0xD7FF))
|
||||
|| ((current >= 0xE000) && (current <= 0xFFFD))
|
||||
|| ((current >= 0x10000) && (current <= 0x10FFFF))) {
|
||||
out.append(current);
|
||||
}
|
||||
}
|
||||
return out.toString();
|
||||
}
|
||||
|
||||
public static String leftPad(String str, int size, char padChar) {
|
||||
if (str == null) {
|
||||
return null;
|
||||
} else {
|
||||
int pads = size - str.length();
|
||||
if (pads <= 0) {
|
||||
return str;
|
||||
} else {
|
||||
return pads > 8192 ? leftPad(str, size, String.valueOf(padChar)) : padding(pads, padChar).concat(str);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static String leftPad(String str, int size, String padStr) {
|
||||
if (str == null) {
|
||||
return null;
|
||||
} else {
|
||||
if (isEmpty(padStr)) {
|
||||
padStr = " ";
|
||||
}
|
||||
|
||||
int padLen = padStr.length();
|
||||
int strLen = str.length();
|
||||
int pads = size - strLen;
|
||||
if (pads <= 0) {
|
||||
return str;
|
||||
} else if (padLen == 1 && pads <= 8192) {
|
||||
return leftPad(str, size, padStr.charAt(0));
|
||||
} else if (pads == padLen) {
|
||||
return padStr.concat(str);
|
||||
} else if (pads < padLen) {
|
||||
return padStr.substring(0, pads).concat(str);
|
||||
} else {
|
||||
char[] padding = new char[pads];
|
||||
char[] padChars = padStr.toCharArray();
|
||||
|
||||
for(int i = 0; i < pads; ++i) {
|
||||
padding[i] = padChars[i % padLen];
|
||||
}
|
||||
|
||||
return (new String(padding)).concat(str);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static String padding(int repeat, char padChar) throws IndexOutOfBoundsException {
|
||||
if (repeat < 0) {
|
||||
throw new IndexOutOfBoundsException("Cannot pad a negative amount: " + repeat);
|
||||
} else {
|
||||
char[] buf = new char[repeat];
|
||||
|
||||
for(int i = 0; i < buf.length; ++i) {
|
||||
buf[i] = padChar;
|
||||
}
|
||||
|
||||
return new String(buf);
|
||||
}
|
||||
}
|
||||
}
|
@@ -19,6 +19,8 @@ spring:
|
||||
api:
|
||||
# 测试地址
|
||||
url-test: http://api-test.yourdomain.com/api
|
||||
# 沙箱环境
|
||||
url-sandbox: http://localhost:8081/api
|
||||
# 正式地址
|
||||
url-prod: http://open.yourdomain.com/api
|
||||
pwd: doc#123
|
Reference in New Issue
Block a user