parent
9f2e659523
commit
326edf661e
@ -1,29 +1,29 @@ |
|||||||
* [首页](/?t=1560480225362) |
* [首页](/?t=1560912863431) |
||||||
* 开发文档 |
* 开发文档 |
||||||
* [快速体验](files/10010_快速体验.md?t=1560480225362) |
* [快速体验](files/10010_快速体验.md?t=1560912863434) |
||||||
* [项目接入到SOP](files/10011_项目接入到SOP.md?t=1560480225379) |
* [项目接入到SOP](files/10011_项目接入到SOP.md?t=1560912863453) |
||||||
* [新增接口](files/10020_新增接口.md?t=1560480225379) |
* [新增接口](files/10020_新增接口.md?t=1560912863453) |
||||||
* [业务参数校验](files/10030_业务参数校验.md?t=1560480225380) |
* [业务参数校验](files/10030_业务参数校验.md?t=1560912863453) |
||||||
* [错误处理](files/10040_错误处理.md?t=1560480225380) |
* [错误处理](files/10040_错误处理.md?t=1560912863453) |
||||||
* [编写文档](files/10041_编写文档.md?t=1560480225380) |
* [编写文档](files/10041_编写文档.md?t=1560912863453) |
||||||
* [接口交互详解](files/10050_接口交互详解.md?t=1560480225380) |
* [接口交互详解](files/10050_接口交互详解.md?t=1560912863453) |
||||||
* [easyopen支持](files/10070_easyopen支持.md?t=1560480225380) |
* [easyopen支持](files/10070_easyopen支持.md?t=1560912863454) |
||||||
* [使用签名校验工具](files/10080_使用签名校验工具.md?t=1560480225380) |
* [使用签名校验工具](files/10080_使用签名校验工具.md?t=1560912863454) |
||||||
* [ISV管理](files/10085_ISV管理.md?t=1560480225380) |
* [ISV管理](files/10085_ISV管理.md?t=1560912863454) |
||||||
* [自定义路由](files/10086_自定义路由.md?t=1560480225381) |
* [自定义路由](files/10086_自定义路由.md?t=1560912863454) |
||||||
* [路由授权](files/10090_路由授权.md?t=1560480225381) |
* [路由授权](files/10090_路由授权.md?t=1560912863454) |
||||||
* [接口限流](files/10092_接口限流.md?t=1560480225381) |
* [接口限流](files/10092_接口限流.md?t=1560912863454) |
||||||
* [监控日志](files/10093_监控日志.md?t=1560480225381) |
* [监控日志](files/10093_监控日志.md?t=1560912863454) |
||||||
* [SDK开发](files/10095_SDK开发.md?t=1560480225381) |
* [SDK开发](files/10095_SDK开发.md?t=1560912863455) |
||||||
* [使用SpringCloudGateway](files/10096_使用SpringCloudGateway.md?t=1560480225382) |
* [使用SpringCloudGateway](files/10096_使用SpringCloudGateway.md?t=1560912863455) |
||||||
* [应用授权](files/10097_应用授权.md?t=1560480225382) |
* [应用授权](files/10097_应用授权.md?t=1560912863455) |
||||||
* [更改数据节点名称](files/10099_更改数据节点名称.md?t=1560480225382) |
* [更改数据节点名称](files/10099_更改数据节点名称.md?t=1560912863455) |
||||||
* [对接前端](files/10100_对接前端.md?t=1560480225382) |
* [对接前端](files/10100_对接前端.md?t=1560912863455) |
||||||
* [自定义过滤器](files/10102_自定义过滤器.md?t=1560480225382) |
* [自定义过滤器](files/10102_自定义过滤器.md?t=1560912863455) |
||||||
* [文件上传](files/10104_文件上传.md?t=1560480225382) |
* [文件上传](files/10104_文件上传.md?t=1560912863455) |
||||||
* 原理分析 |
* 原理分析 |
||||||
* [原理分析之@ApiMapping](files/90010_原理分析之@ApiMapping.md?t=1560480225382) |
* [原理分析之@ApiMapping](files/90010_原理分析之@ApiMapping.md?t=1560912863455) |
||||||
* [原理分析之路由存储](files/90011_原理分析之路由存储.md?t=1560480225382) |
* [原理分析之路由存储](files/90011_原理分析之路由存储.md?t=1560912863456) |
||||||
* [原理分析之如何路由](files/90012_原理分析之如何路由.md?t=1560480225383) |
* [原理分析之如何路由](files/90012_原理分析之如何路由.md?t=1560912863456) |
||||||
* [原理分析之文档归纳](files/90013_原理分析之文档归纳.md?t=1560480225383) |
* [原理分析之文档归纳](files/90013_原理分析之文档归纳.md?t=1560912863456) |
||||||
* [常见问题](files/90100_常见问题.md?t=1560480225383) |
* [常见问题](files/90100_常见问题.md?t=1560912863456) |
||||||
|
@ -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; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
@ -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 + '\"'; |
||||||
|
} |
||||||
|
} |
@ -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(); |
||||||
|
} |
@ -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); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue