Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
jinli gu
Jeepay
Commits
aa8011de
"...src/views/layout/git@ustchcs.com:gujinli1118/litemall.git" did not exist on "2786b410bda03fe821db2d5e435f331392db5393"
Commit
aa8011de
authored
Aug 23, 2017
by
jmdhappy
Browse files
升级支付宝为最新接口
parent
6bb11b08
Changes
27
Show whitespace changes
Inline
Side-by-side
init_db.sql
View file @
aa8011de
...
@@ -20,7 +20,7 @@ CREATE TABLE `t_pay_channel` (
...
@@ -20,7 +20,7 @@ CREATE TABLE `t_pay_channel` (
`ChannelMchId`
varchar
(
32
)
NOT
NULL
COMMENT
'渠道商户ID'
,
`ChannelMchId`
varchar
(
32
)
NOT
NULL
COMMENT
'渠道商户ID'
,
`MchId`
varchar
(
30
)
NOT
NULL
COMMENT
'商户ID'
,
`MchId`
varchar
(
30
)
NOT
NULL
COMMENT
'商户ID'
,
`State`
tinyint
(
6
)
NOT
NULL
DEFAULT
'1'
COMMENT
'渠道状态,0-停止使用,1-使用中'
,
`State`
tinyint
(
6
)
NOT
NULL
DEFAULT
'1'
COMMENT
'渠道状态,0-停止使用,1-使用中'
,
`Param`
varchar
(
2048
)
NOT
NULL
COMMENT
'配置参数,json字符串'
,
`Param`
varchar
(
4096
)
NOT
NULL
COMMENT
'配置参数,json字符串'
,
`Remark`
varchar
(
128
)
DEFAULT
NULL
COMMENT
'备注'
,
`Remark`
varchar
(
128
)
DEFAULT
NULL
COMMENT
'备注'
,
`CreateTime`
timestamp
NOT
NULL
DEFAULT
CURRENT_TIMESTAMP
COMMENT
'创建时间'
,
`CreateTime`
timestamp
NOT
NULL
DEFAULT
CURRENT_TIMESTAMP
COMMENT
'创建时间'
,
`UpdateTime`
timestamp
NOT
NULL
DEFAULT
CURRENT_TIMESTAMP
ON
UPDATE
CURRENT_TIMESTAMP
COMMENT
'更新时间'
,
`UpdateTime`
timestamp
NOT
NULL
DEFAULT
CURRENT_TIMESTAMP
ON
UPDATE
CURRENT_TIMESTAMP
COMMENT
'更新时间'
,
...
...
xxpay-common/src/main/java/org/xxpay/common/constant/PayConstant.java
View file @
aa8011de
...
@@ -53,7 +53,7 @@ public class PayConstant {
...
@@ -53,7 +53,7 @@ public class PayConstant {
public
static
final
String
RETURN_VALUE_FAIL
=
"FAIL"
;
public
static
final
String
RETURN_VALUE_FAIL
=
"FAIL"
;
public
static
final
String
RETURN_ALIPAY_VALUE_SUCCESS
=
"success"
;
public
static
final
String
RETURN_ALIPAY_VALUE_SUCCESS
=
"success"
;
public
static
final
String
RETURN_ALIPAY_VALUE_FAIL
=
"fail
ed
"
;
public
static
final
String
RETURN_ALIPAY_VALUE_FAIL
=
"fail"
;
public
static
class
JdConstant
{
public
static
class
JdConstant
{
public
final
static
String
CONFIG_PATH
=
"jd"
+
File
.
separator
+
"jd"
;
// 京东支付配置文件路径
public
final
static
String
CONFIG_PATH
=
"jd"
+
File
.
separator
+
"jd"
;
// 京东支付配置文件路径
...
...
xxpay-shop/src/main/java/org/xxpay/shop/controller/GoodsOrderController.java
View file @
aa8011de
...
@@ -5,13 +5,13 @@ import com.alibaba.fastjson.JSONObject;
...
@@ -5,13 +5,13 @@ import com.alibaba.fastjson.JSONObject;
import
org.apache.commons.lang3.StringUtils
;
import
org.apache.commons.lang3.StringUtils
;
import
org.apache.commons.lang3.math.NumberUtils
;
import
org.apache.commons.lang3.math.NumberUtils
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.beans.factory.annotation.Value
;
import
org.springframework.stereotype.Controller
;
import
org.springframework.stereotype.Controller
;
import
org.springframework.ui.ModelMap
;
import
org.springframework.ui.ModelMap
;
import
org.springframework.web.bind.annotation.PathVariable
;
import
org.springframework.web.bind.annotation.PathVariable
;
import
org.springframework.web.bind.annotation.RequestMapping
;
import
org.springframework.web.bind.annotation.RequestMapping
;
import
org.springframework.web.bind.annotation.RequestMethod
;
import
org.springframework.web.bind.annotation.RequestMethod
;
import
org.springframework.web.bind.annotation.ResponseBody
;
import
org.springframework.web.bind.annotation.ResponseBody
;
import
org.xxpay.common.constant.PayConstant
;
import
org.xxpay.common.util.*
;
import
org.xxpay.common.util.*
;
import
org.xxpay.shop.dao.model.GoodsOrder
;
import
org.xxpay.shop.dao.model.GoodsOrder
;
import
org.xxpay.shop.service.GoodsOrderService
;
import
org.xxpay.shop.service.GoodsOrderService
;
...
@@ -24,7 +24,6 @@ import javax.servlet.http.HttpServletRequest;
...
@@ -24,7 +24,6 @@ import javax.servlet.http.HttpServletRequest;
import
javax.servlet.http.HttpServletResponse
;
import
javax.servlet.http.HttpServletResponse
;
import
java.io.IOException
;
import
java.io.IOException
;
import
java.io.PrintWriter
;
import
java.io.PrintWriter
;
import
java.util.Date
;
import
java.util.HashMap
;
import
java.util.HashMap
;
import
java.util.Map
;
import
java.util.Map
;
import
java.util.concurrent.atomic.AtomicLong
;
import
java.util.concurrent.atomic.AtomicLong
;
...
@@ -383,6 +382,32 @@ public class GoodsOrderController {
...
@@ -383,6 +382,32 @@ public class GoodsOrderController {
_log
.
info
(
"====== 支付中心通知处理完成 ======"
);
_log
.
info
(
"====== 支付中心通知处理完成 ======"
);
}
}
@RequestMapping
(
"/toAliPay.html"
)
@ResponseBody
public
String
toAliPay
(
HttpServletRequest
request
,
Long
amount
,
String
channelId
)
{
String
logPrefix
=
"【支付宝支付】"
;
_log
.
info
(
"====== 开始接收支付宝支付请求 ======"
);
String
goodsId
=
"G_0001"
;
_log
.
info
(
"{}接收参数:goodsId={},amount={},channelId={}"
,
logPrefix
,
goodsId
,
amount
,
channelId
);
// 先插入订单数据
Map
params
=
new
HashMap
<>();
params
.
put
(
"channelId"
,
channelId
);
// 下单
GoodsOrder
goodsOrder
=
createGoodsOrder
(
goodsId
,
amount
);
Map
<
String
,
String
>
orderMap
=
createPayOrder
(
goodsOrder
,
params
);
if
(
orderMap
!=
null
&&
"success"
.
equalsIgnoreCase
(
orderMap
.
get
(
"resCode"
)))
{
String
payOrderId
=
orderMap
.
get
(
"payOrderId"
);
GoodsOrder
go
=
new
GoodsOrder
();
go
.
setGoodsOrderId
(
goodsOrder
.
getGoodsOrderId
());
go
.
setPayOrderId
(
payOrderId
);
go
.
setChannelId
(
channelId
);
int
ret
=
goodsOrderService
.
update
(
go
);
_log
.
info
(
"修改商品订单,返回:{}"
,
ret
);
}
if
(
PayConstant
.
PAY_CHANNEL_ALIPAY_MOBILE
.
equalsIgnoreCase
(
channelId
))
return
orderMap
.
get
(
"payParams"
);
return
orderMap
.
get
(
"payUrl"
);
}
void
outResult
(
HttpServletResponse
response
,
String
content
)
{
void
outResult
(
HttpServletResponse
response
,
String
content
)
{
response
.
setContentType
(
"text/html"
);
response
.
setContentType
(
"text/html"
);
PrintWriter
pw
;
PrintWriter
pw
;
...
...
xxpay-shop/src/main/java/org/xxpay/shop/demo/PayOrderDemo.java
View file @
aa8011de
...
@@ -13,14 +13,14 @@ import java.util.Map;
...
@@ -13,14 +13,14 @@ import java.util.Map;
public
class
PayOrderDemo
{
public
class
PayOrderDemo
{
// 商户ID
// 商户ID
static
final
String
mchId
=
"20001223"
;
static
final
String
mchId
=
"20001223"
;
//20001223,20001245
// 加签key
// 加签key
static
final
String
reqKey
=
"M86l522AV6q613Ii4W6u8K48uW8vM1N6bFgyv769220MdYe9u37N4y7rI5mQ"
;
static
final
String
reqKey
=
"M86l522AV6q613Ii4W6u8K48uW8vM1N6bFgyv769220MdYe9u37N4y7rI5mQ"
;
// 验签key
// 验签key
static
final
String
repKey
=
"Hpcl522AV6q613KIi46u6g6XuW8vM1N8bFgyv769770MdYe9u37M4y7rIpl8"
;
static
final
String
repKey
=
"Hpcl522AV6q613KIi46u6g6XuW8vM1N8bFgyv769770MdYe9u37M4y7rIpl8"
;
//
static final String baseUrl = "http://api.xxpay.org/api";
static
final
String
baseUrl
=
"http://api.xxpay.org/api"
;
static
final
String
baseUrl
=
"http://localhost:3020/api"
;
//
static final String baseUrl = "http://localhost:3020/api";
static
final
String
notifyUrl
=
"http://www.baidu.com"
;
// 本地环境测试,可到ngrok.cc网站注册
static
final
String
notifyUrl
=
"http://www.baidu.com"
;
// 本地环境测试,可到ngrok.cc网站注册
public
static
void
main
(
String
[]
args
)
{
public
static
void
main
(
String
[]
args
)
{
...
@@ -32,8 +32,8 @@ public class PayOrderDemo {
...
@@ -32,8 +32,8 @@ public class PayOrderDemo {
JSONObject
paramMap
=
new
JSONObject
();
JSONObject
paramMap
=
new
JSONObject
();
paramMap
.
put
(
"mchId"
,
mchId
);
// 商户ID
paramMap
.
put
(
"mchId"
,
mchId
);
// 商户ID
paramMap
.
put
(
"mchOrderNo"
,
System
.
currentTimeMillis
());
// 商户订单号
paramMap
.
put
(
"mchOrderNo"
,
System
.
currentTimeMillis
());
// 商户订单号
paramMap
.
put
(
"channelId"
,
"
WX_NATIVE"
);
// 支付渠道ID, WX_NATIVE,ALIPAY_WAP
paramMap
.
put
(
"channelId"
,
"
ALIPAY_PC"
);
// 支付渠道ID, WX_NATIVE,ALIPAY_WAP
,ALIPAY_PC,ALIPAY_MOBILE
paramMap
.
put
(
"amount"
,
1
00
);
// 支付金额,单位分
paramMap
.
put
(
"amount"
,
1
);
// 支付金额,单位分
paramMap
.
put
(
"currency"
,
"cny"
);
// 币种, cny-人民币
paramMap
.
put
(
"currency"
,
"cny"
);
// 币种, cny-人民币
paramMap
.
put
(
"clientIp"
,
"114.112.124.236"
);
// 用户地址
paramMap
.
put
(
"clientIp"
,
"114.112.124.236"
);
// 用户地址
paramMap
.
put
(
"device"
,
"WEB"
);
// 设备
paramMap
.
put
(
"device"
,
"WEB"
);
// 设备
...
...
xxpay-shop/src/main/resources/templates/qrPay.ftl
View file @
aa8011de
...
@@ -32,9 +32,7 @@
...
@@ -32,9 +32,7 @@
</table>
</table>
</
div
>
</
div
>
<#if (client == 'alipay')>
<#if (client == 'alipay')>
<script>
$
{
orderMap
.payUrl
}
location.href = '$
{
orderMap
.payUrl
}
';
</script>
</#if>
</#if>
<#if (client == 'wx')>
<#if (client == 'wx')>
<script>
<script>
...
...
xxpay4spring-cloud/xxpay-config/src/main/resources/shared/xxpay-service-dev.properties
View file @
aa8011de
# \u652F\u4ED8\u5B9D\u
56DE\u8C03\u5730\u5740
# \u652F\u4ED8\u5B9D\u
670D\u52A1\u5668\u5F02\u6B65\u901A\u77E5\u9875\u9762\u8DEF\u5F84
ali.notify_url
=
http://api.xxpay.org/notify/pay/aliPayNotifyRes.htm
ali.notify_url
=
http://api.xxpay.org/notify/pay/aliPayNotifyRes.htm
# \u652F\u4ED8\u5B9D\u9875\u9762\u8DF3\u8F6C\u540C\u6B65\u901A\u77E5\u9875\u9762\u8DEF\u5F84(\u81EA\u884C\u914D\u7F6E)
ali.return_url
=
http://www.xxpay.org
# \u5FAE\u4FE1\u652F\u4ED8\u56DE\u8C03\u5730\u5740
# \u5FAE\u4FE1\u652F\u4ED8\u56DE\u8C03\u5730\u5740
wx.notify_url
=
http://api.xxpay.org/notify/pay/wxPayNotifyRes.htm
wx.notify_url
=
http://api.xxpay.org/notify/pay/wxPayNotifyRes.htm
# \u652F\u4ED8\u8BC1\u4E66\u6839\u8DEF\u5F84
# \u652F\u4ED8\u8BC1\u4E66\u6839\u8DEF\u5F84
cert.root.path
=
/Users/dingzhiwei/java/tmp/cert
cert.root.path
=
/home/xxpay/service/cert
\ No newline at end of file
\ No newline at end of file
xxpay4spring-cloud/xxpay-config/src/main/resources/shared/xxpay-service-prod.properties
View file @
aa8011de
# \u652F\u4ED8\u5B9D\u56DE\u8C03\u5730\u5740
# \u652F\u4ED8\u5B9D\u56DE\u8C03\u5730\u5740
ali.notify_url
=
http://api.xxpay.org/notify/pay/aliPayNotifyRes.htm
ali.notify_url
=
http://api.xxpay.org/notify/pay/aliPayNotifyRes.htm
ali.return_url
=
http://www.xxpay.org
# \u5FAE\u4FE1\u652F\u4ED8\u56DE\u8C03\u5730\u5740
# \u5FAE\u4FE1\u652F\u4ED8\u56DE\u8C03\u5730\u5740
wx.notify_url
=
http://api.xxpay.org/notify/pay/wxPayNotifyRes.htm
wx.notify_url
=
http://api.xxpay.org/notify/pay/wxPayNotifyRes.htm
# \u652F\u4ED8\u8BC1\u4E66\u6839\u8DEF\u5F84
# \u652F\u4ED8\u8BC1\u4E66\u6839\u8DEF\u5F84
cert.root.path
=
/Users/dingzhiwei/java/tmp/cert
cert.root.path
=
/home/xxpay/service/cert
\ No newline at end of file
\ No newline at end of file
xxpay4spring-cloud/xxpay-config/src/main/resources/shared/xxpay-service-test.properties
View file @
aa8011de
# \u652F\u4ED8\u5B9D\u56DE\u8C03\u5730\u5740
# \u652F\u4ED8\u5B9D\u56DE\u8C03\u5730\u5740
ali.notify_url
=
http://api.xxpay.org/notify/pay/aliPayNotifyRes.htm
ali.notify_url
=
http://api.xxpay.org/notify/pay/aliPayNotifyRes.htm
ali.return_url
=
http://www.xxpay.org
# \u5FAE\u4FE1\u652F\u4ED8\u56DE\u8C03\u5730\u5740
# \u5FAE\u4FE1\u652F\u4ED8\u56DE\u8C03\u5730\u5740
wx.notify_url
=
http://api.xxpay.org/notify/pay/wxPayNotifyRes.htm
wx.notify_url
=
http://api.xxpay.org/notify/pay/wxPayNotifyRes.htm
# \u652F\u4ED8\u8BC1\u4E66\u6839\u8DEF\u5F84
# \u652F\u4ED8\u8BC1\u4E66\u6839\u8DEF\u5F84
cert.root.path
=
/Users/dingzhiwei/java/tmp/cert
cert.root.path
=
/home/xxpay/service/cert
\ No newline at end of file
\ No newline at end of file
xxpay4spring-cloud/xxpay-service/pom.xml
View file @
aa8011de
...
@@ -55,18 +55,28 @@
...
@@ -55,18 +55,28 @@
</dependency>
</dependency>
<!--ali_pay-->
<!--ali_pay-->
<dependency>
<dependency>
<groupId>
commons-httpclient
</groupId>
<groupId>
com.alipay
</groupId>
<artifactId>
commons-httpclient
</artifactId>
<artifactId>
sdk
</artifactId>
<version>
3.0.1
</version>
<version>
1.5
</version>
</dependency>
<scope>
system
</scope>
<dependency>
<systemPath>
${basedir}/src/main/webapp/WEB-INF/lib/alipay-sdk-java20170818173712.jar
</systemPath>
<groupId>
jaxen
</groupId>
<artifactId>
jaxen
</artifactId>
<version>
1.1.6
</version>
</dependency>
</dependency>
</dependencies>
</dependencies>
<build>
<build>
<resources>
<resource>
<directory>
src/main/webapp/WEB-INF/lib/
</directory>
<targetPath>
BOOT-INF/lib/
</targetPath>
<includes>
<include>
**/*.jar
</include>
</includes>
</resource>
<resource>
<directory>
src/main/resources
</directory>
<targetPath>
BOOT-INF/classes/
</targetPath>
</resource>
</resources>
<plugins>
<plugins>
<plugin>
<plugin>
<groupId>
org.springframework.boot
</groupId>
<groupId>
org.springframework.boot
</groupId>
...
...
xxpay4spring-cloud/xxpay-service/src/main/java/org/xxpay/service/channel/alipay/AlipayConfig.java
0 → 100644
View file @
aa8011de
package
org.xxpay.service.channel.alipay
;
import
com.alibaba.fastjson.JSON
;
import
com.alibaba.fastjson.JSONObject
;
import
org.springframework.beans.factory.annotation.Value
;
import
org.springframework.cloud.context.config.annotation.RefreshScope
;
import
org.springframework.stereotype.Service
;
import
org.springframework.util.Assert
;
/**
* @author: dingzhiwei
* @date: 17/8/21
* @description:
*/
@RefreshScope
@Service
public
class
AlipayConfig
{
// 商户appid
private
String
app_id
;
// 私钥 pkcs8格式的
private
String
rsa_private_key
;
// 服务器异步通知页面路径 需http://或者https://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
@Value
(
"${ali.notify_url}"
)
private
String
notify_url
;
// 页面跳转同步通知页面路径 需http://或者https://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问 商户可以自定义同步跳转地址
@Value
(
"${ali.return_url}"
)
private
String
return_url
;
// 请求网关地址
private
String
url
=
"https://openapi.alipay.com/gateway.do"
;
// 编码
public
static
String
CHARSET
=
"UTF-8"
;
// 返回格式
public
static
String
FORMAT
=
"json"
;
// 支付宝公钥
public
String
alipay_public_key
;
// RSA2
public
static
String
SIGNTYPE
=
"RSA2"
;
// 是否沙箱环境,1:沙箱,0:正式环境
private
Short
isSandbox
=
0
;
/**
* 初始化支付宝配置
* @param configParam
* @return
*/
public
AlipayConfig
init
(
String
configParam
)
{
Assert
.
notNull
(
configParam
,
"init alipay config error"
);
JSONObject
paramObj
=
JSON
.
parseObject
(
configParam
);
this
.
setApp_id
(
paramObj
.
getString
(
"appid"
));
this
.
setRsa_private_key
(
paramObj
.
getString
(
"private_key"
));
this
.
setAlipay_public_key
(
paramObj
.
getString
(
"alipay_public_key"
));
this
.
setIsSandbox
(
paramObj
.
getShortValue
(
"isSandbox"
));
if
(
this
.
getIsSandbox
()
==
1
)
this
.
setUrl
(
"https://openapi.alipaydev.com/gateway.do"
);
return
this
;
}
public
String
getApp_id
()
{
return
app_id
;
}
public
void
setApp_id
(
String
app_id
)
{
this
.
app_id
=
app_id
;
}
public
String
getRsa_private_key
()
{
return
rsa_private_key
;
}
public
void
setRsa_private_key
(
String
rsa_private_key
)
{
this
.
rsa_private_key
=
rsa_private_key
;
}
public
String
getNotify_url
()
{
return
notify_url
;
}
public
void
setNotify_url
(
String
notify_url
)
{
this
.
notify_url
=
notify_url
;
}
public
String
getReturn_url
()
{
return
return_url
;
}
public
void
setReturn_url
(
String
return_url
)
{
this
.
return_url
=
return_url
;
}
public
String
getUrl
()
{
return
url
;
}
public
void
setUrl
(
String
url
)
{
this
.
url
=
url
;
}
public
Short
getIsSandbox
()
{
return
isSandbox
;
}
public
void
setIsSandbox
(
Short
isSandbox
)
{
this
.
isSandbox
=
isSandbox
;
}
public
String
getAlipay_public_key
()
{
return
alipay_public_key
;
}
public
void
setAlipay_public_key
(
String
alipay_public_key
)
{
this
.
alipay_public_key
=
alipay_public_key
;
}
}
xxpay4spring-cloud/xxpay-service/src/main/java/org/xxpay/service/channel/alipay/config/AlipayConfig.java
deleted
100644 → 0
View file @
6bb11b08
package
org.xxpay.service.channel.alipay.config
;
/* *
*类名:AlipayConfig
*功能:基础配置类
*详细:设置帐户有关信息及返回路径
*版本:3.3
*日期:2012-08-10
*说明:
*以下代码只是为了方便商户测试而提供的样例代码,商户可以根据自己网站的需要,按照技术文档编写,并非一定要使用该代码。
*该代码仅供学习和研究支付宝接口使用,只是提供一个参考。
*提示:如何获取安全校验码和合作身份者ID
*1.用您的签约支付宝账号登录支付宝网站(www.alipay.com)
*2.点击“商家服务”(https://b.alipay.com/order/myOrder.htm)
*3.点击“查询合作者身份(PID)”、“查询安全校验码(Key)”
*安全校验码查看时,输入支付密码后,页面呈灰色的现象,怎么办?
*解决方法:
*1、检查浏览器配置,不让浏览器做弹框屏蔽设置
*2、更换浏览器或电脑,重新登录查询。
*/
import
com.alibaba.fastjson.JSON
;
import
com.alibaba.fastjson.JSONObject
;
import
org.springframework.beans.factory.annotation.Value
;
import
org.springframework.boot.context.properties.ConfigurationProperties
;
import
org.springframework.cloud.context.config.annotation.RefreshScope
;
import
org.springframework.stereotype.Component
;
import
org.springframework.stereotype.Service
;
import
org.springframework.util.Assert
;
import
org.springframework.web.bind.annotation.RestController
;
import
org.xxpay.common.constant.PayConstant
;
import
org.xxpay.common.util.MyLog
;
import
org.xxpay.common.util.PropertiesFileUtil
;
import
java.util.Date
;
import
java.util.Map
;
@RefreshScope
@Service
public
class
AlipayConfig
{
private
static
final
MyLog
_log
=
MyLog
.
getLog
(
AlipayConfig
.
class
);
public
AlipayConfig
init
(
String
configParam
)
{
Assert
.
notNull
(
configParam
,
"init alipay config error"
);
JSONObject
paramObj
=
JSON
.
parseObject
(
configParam
);
this
.
setAppId
(
paramObj
.
getString
(
"appid"
));
this
.
setPartner
(
paramObj
.
getString
(
"partner"
));
this
.
setAli_account
(
paramObj
.
getString
(
"ali_account"
));
this
.
setPrivate_key
(
paramObj
.
getString
(
"private_key"
));
return
this
;
}
//↓↓↓↓↓↓↓↓↓↓请在这里配置您的基本信息↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
// 合作身份者ID,以2088开头由16位纯数字组成的字符串
public
String
partner
=
""
;
// 商户的私钥
public
String
private_key
=
""
;
// 支付宝的公钥,无需修改该值
public
static
String
ali_public_key
=
"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCnxj/9qwVfgoUh/y2W89L6BkRAFljhNhgPdyPuBV64bfQNN1PjbCzkIM6qRdKBoLPXmKKMiFYnkd6rAoprih3/PrQEB/VsW8OoM8fxn67UDYuyBTqA23MML9q1+ilIZwBC2AQ2UBVOrFXfFl75p6/B5KsiNG9zpgmLCUYuLkxpLQIDAQAB"
;
//↑↑↑↑↑↑↑↑↑↑请在这里配置您的基本信息↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
// 支付宝账号
public
String
ali_account
=
""
;
// 字符编码格式 目前支持 gbk 或 utf-8
public
static
String
input_charset
=
"utf-8"
;
// 签名方式 不需修改
public
static
String
sign_type
=
"RSA"
;
// 提供给支付宝的通知地址
@Value
(
"${ali.notify_url}"
)
private
String
notify_url
;
// 是否验证支付宝的通知地址
private
boolean
is_verify_notify_url
=
true
;
// 支付宝即时到帐网关
private
String
gateway
=
"https://mapi.alipay.com/gateway.do"
;
// 支付宝新网关(查询等)
private
String
openapiGateway
=
"https://openapi.alipay.com/gateway.do"
;
// appid
public
String
appId
=
""
;
// 配置加载时间
private
Long
loadTime
=
new
Date
().
getTime
();
public
String
getAppId
()
{
return
appId
;
}
public
void
setAppId
(
String
appId
)
{
this
.
appId
=
appId
;
}
public
String
getPartner
()
{
return
partner
;
}
public
void
setPartner
(
String
partner
)
{
this
.
partner
=
partner
;
}
public
String
getPrivate_key
()
{
return
private_key
;
}
public
void
setPrivate_key
(
String
private_key
)
{
this
.
private_key
=
private_key
;
}
public
String
getAli_account
()
{
return
ali_account
;
}
public
void
setAli_account
(
String
ali_account
)
{
this
.
ali_account
=
ali_account
;
}
public
String
getNotify_url
()
{
return
notify_url
;
}
public
void
setNotify_url
(
String
notify_url
)
{
this
.
notify_url
=
notify_url
;
}
public
boolean
is_verify_notify_url
()
{
return
is_verify_notify_url
;
}
public
void
setIs_verify_notify_url
(
boolean
is_verify_notify_url
)
{
this
.
is_verify_notify_url
=
is_verify_notify_url
;
}
public
String
getGateway
()
{
return
gateway
;
}
public
void
setGateway
(
String
gateway
)
{
this
.
gateway
=
gateway
;
}
public
String
getOpenapiGateway
()
{
return
openapiGateway
;
}
public
void
setOpenapiGateway
(
String
openapiGateway
)
{
this
.
openapiGateway
=
openapiGateway
;
}
public
Long
getLoadTime
()
{
return
loadTime
;
}
public
void
setLoadTime
(
Long
loadTime
)
{
this
.
loadTime
=
loadTime
;
}
@Override
public
String
toString
()
{
return
"AlipayConfig{"
+
"partner='"
+
partner
+
'\''
+
", private_key='"
+
private_key
+
'\''
+
", ali_account='"
+
ali_account
+
'\''
+
", notify_url='"
+
notify_url
+
'\''
+
", is_verify_notify_url='"
+
is_verify_notify_url
+
'\''
+
", gateway='"
+
gateway
+
'\''
+
", openapiGateway='"
+
openapiGateway
+
'\''
+
", appId='"
+
appId
+
'\''
+
", loadTime="
+
loadTime
+
'}'
;
}
}
\ No newline at end of file
xxpay4spring-cloud/xxpay-service/src/main/java/org/xxpay/service/channel/alipay/sign/Base64.java
deleted
100755 → 0
View file @
6bb11b08
/*
* Copyright (C) 2010 The MobileSecurePay Project
* All right reserved.
* author: shiqun.shi@alipay.com
*/
package
org.xxpay.service.channel.alipay.sign
;
public
final
class
Base64
{
static
private
final
int
BASELENGTH
=
128
;
static
private
final
int
LOOKUPLENGTH
=
64
;
static
private
final
int
TWENTYFOURBITGROUP
=
24
;
static
private
final
int
EIGHTBIT
=
8
;
static
private
final
int
SIXTEENBIT
=
16
;
static
private
final
int
FOURBYTE
=
4
;
static
private
final
int
SIGN
=
-
128
;
static
private
final
char
PAD
=
'='
;
static
private
final
boolean
fDebug
=
false
;
static
final
private
byte
[]
base64Alphabet
=
new
byte
[
BASELENGTH
];
static
final
private
char
[]
lookUpBase64Alphabet
=
new
char
[
LOOKUPLENGTH
];
static
{
for
(
int
i
=
0
;
i
<
BASELENGTH
;
++
i
)
{
base64Alphabet
[
i
]
=
-
1
;
}
for
(
int
i
=
'Z'
;
i
>=
'A'
;
i
--)
{
base64Alphabet
[
i
]
=
(
byte
)
(
i
-
'A'
);
}
for
(
int
i
=
'z'
;
i
>=
'a'
;
i
--)
{
base64Alphabet
[
i
]
=
(
byte
)
(
i
-
'a'
+
26
);
}
for
(
int
i
=
'9'
;
i
>=
'0'
;
i
--)
{
base64Alphabet
[
i
]
=
(
byte
)
(
i
-
'0'
+
52
);
}
base64Alphabet
[
'+'
]
=
62
;
base64Alphabet
[
'/'
]
=
63
;
for
(
int
i
=
0
;
i
<=
25
;
i
++)
{
lookUpBase64Alphabet
[
i
]
=
(
char
)
(
'A'
+
i
);
}
for
(
int
i
=
26
,
j
=
0
;
i
<=
51
;
i
++,
j
++)
{
lookUpBase64Alphabet
[
i
]
=
(
char
)
(
'a'
+
j
);
}
for
(
int
i
=
52
,
j
=
0
;
i
<=
61
;
i
++,
j
++)
{
lookUpBase64Alphabet
[
i
]
=
(
char
)
(
'0'
+
j
);
}
lookUpBase64Alphabet
[
62
]
=
(
char
)
'+'
;
lookUpBase64Alphabet
[
63
]
=
(
char
)
'/'
;
}
private
static
boolean
isWhiteSpace
(
char
octect
)
{
return
(
octect
==
0x20
||
octect
==
0xd
||
octect
==
0xa
||
octect
==
0x9
);
}
private
static
boolean
isPad
(
char
octect
)
{
return
(
octect
==
PAD
);
}
private
static
boolean
isData
(
char
octect
)
{
return
(
octect
<
BASELENGTH
&&
base64Alphabet
[
octect
]
!=
-
1
);
}
/**
* Encodes hex octects into Base64
*
* @param binaryData Array containing binaryData
* @return Encoded Base64 array
*/
public
static
String
encode
(
byte
[]
binaryData
)
{
if
(
binaryData
==
null
)
{
return
null
;
}
int
lengthDataBits
=
binaryData
.
length
*
EIGHTBIT
;
if
(
lengthDataBits
==
0
)
{
return
""
;
}
int
fewerThan24bits
=
lengthDataBits
%
TWENTYFOURBITGROUP
;
int
numberTriplets
=
lengthDataBits
/
TWENTYFOURBITGROUP
;
int
numberQuartet
=
fewerThan24bits
!=
0
?
numberTriplets
+
1
:
numberTriplets
;
char
encodedData
[]
=
null
;
encodedData
=
new
char
[
numberQuartet
*
4
];
byte
k
=
0
,
l
=
0
,
b1
=
0
,
b2
=
0
,
b3
=
0
;
int
encodedIndex
=
0
;
int
dataIndex
=
0
;
if
(
fDebug
)
{
System
.
out
.
println
(
"number of triplets = "
+
numberTriplets
);
}
for
(
int
i
=
0
;
i
<
numberTriplets
;
i
++)
{
b1
=
binaryData
[
dataIndex
++];
b2
=
binaryData
[
dataIndex
++];
b3
=
binaryData
[
dataIndex
++];
if
(
fDebug
)
{
System
.
out
.
println
(
"b1= "
+
b1
+
", b2= "
+
b2
+
", b3= "
+
b3
);
}
l
=
(
byte
)
(
b2
&
0x0f
);
k
=
(
byte
)
(
b1
&
0x03
);
byte
val1
=
((
b1
&
SIGN
)
==
0
)
?
(
byte
)
(
b1
>>
2
)
:
(
byte
)
((
b1
)
>>
2
^
0xc0
);
byte
val2
=
((
b2
&
SIGN
)
==
0
)
?
(
byte
)
(
b2
>>
4
)
:
(
byte
)
((
b2
)
>>
4
^
0xf0
);
byte
val3
=
((
b3
&
SIGN
)
==
0
)
?
(
byte
)
(
b3
>>
6
)
:
(
byte
)
((
b3
)
>>
6
^
0xfc
);
if
(
fDebug
)
{
System
.
out
.
println
(
"val2 = "
+
val2
);
System
.
out
.
println
(
"k4 = "
+
(
k
<<
4
));
System
.
out
.
println
(
"vak = "
+
(
val2
|
(
k
<<
4
)));
}
encodedData
[
encodedIndex
++]
=
lookUpBase64Alphabet
[
val1
];
encodedData
[
encodedIndex
++]
=
lookUpBase64Alphabet
[
val2
|
(
k
<<
4
)];
encodedData
[
encodedIndex
++]
=
lookUpBase64Alphabet
[(
l
<<
2
)
|
val3
];
encodedData
[
encodedIndex
++]
=
lookUpBase64Alphabet
[
b3
&
0x3f
];
}
// form integral number of 6-bit groups
if
(
fewerThan24bits
==
EIGHTBIT
)
{
b1
=
binaryData
[
dataIndex
];
k
=
(
byte
)
(
b1
&
0x03
);
if
(
fDebug
)
{
System
.
out
.
println
(
"b1="
+
b1
);
System
.
out
.
println
(
"b1<<2 = "
+
(
b1
>>
2
));
}
byte
val1
=
((
b1
&
SIGN
)
==
0
)
?
(
byte
)
(
b1
>>
2
)
:
(
byte
)
((
b1
)
>>
2
^
0xc0
);
encodedData
[
encodedIndex
++]
=
lookUpBase64Alphabet
[
val1
];
encodedData
[
encodedIndex
++]
=
lookUpBase64Alphabet
[
k
<<
4
];
encodedData
[
encodedIndex
++]
=
PAD
;
encodedData
[
encodedIndex
++]
=
PAD
;
}
else
if
(
fewerThan24bits
==
SIXTEENBIT
)
{
b1
=
binaryData
[
dataIndex
];
b2
=
binaryData
[
dataIndex
+
1
];
l
=
(
byte
)
(
b2
&
0x0f
);
k
=
(
byte
)
(
b1
&
0x03
);
byte
val1
=
((
b1
&
SIGN
)
==
0
)
?
(
byte
)
(
b1
>>
2
)
:
(
byte
)
((
b1
)
>>
2
^
0xc0
);
byte
val2
=
((
b2
&
SIGN
)
==
0
)
?
(
byte
)
(
b2
>>
4
)
:
(
byte
)
((
b2
)
>>
4
^
0xf0
);
encodedData
[
encodedIndex
++]
=
lookUpBase64Alphabet
[
val1
];
encodedData
[
encodedIndex
++]
=
lookUpBase64Alphabet
[
val2
|
(
k
<<
4
)];
encodedData
[
encodedIndex
++]
=
lookUpBase64Alphabet
[
l
<<
2
];
encodedData
[
encodedIndex
++]
=
PAD
;
}
return
new
String
(
encodedData
);
}
/**
* Decodes Base64 data into octects
*
* @param encoded string containing Base64 data
* @return Array containind decoded data.
*/
public
static
byte
[]
decode
(
String
encoded
)
{
if
(
encoded
==
null
)
{
return
null
;
}
char
[]
base64Data
=
encoded
.
toCharArray
();
// remove white spaces
int
len
=
removeWhiteSpace
(
base64Data
);
if
(
len
%
FOURBYTE
!=
0
)
{
return
null
;
//should be divisible by four
}
int
numberQuadruple
=
(
len
/
FOURBYTE
);
if
(
numberQuadruple
==
0
)
{
return
new
byte
[
0
];
}
byte
decodedData
[]
=
null
;
byte
b1
=
0
,
b2
=
0
,
b3
=
0
,
b4
=
0
;
char
d1
=
0
,
d2
=
0
,
d3
=
0
,
d4
=
0
;
int
i
=
0
;
int
encodedIndex
=
0
;
int
dataIndex
=
0
;
decodedData
=
new
byte
[(
numberQuadruple
)
*
3
];
for
(;
i
<
numberQuadruple
-
1
;
i
++)
{
if
(!
isData
((
d1
=
base64Data
[
dataIndex
++]))
||
!
isData
((
d2
=
base64Data
[
dataIndex
++]))
||
!
isData
((
d3
=
base64Data
[
dataIndex
++]))
||
!
isData
((
d4
=
base64Data
[
dataIndex
++])))
{
return
null
;
}
//if found "no data" just return null
b1
=
base64Alphabet
[
d1
];
b2
=
base64Alphabet
[
d2
];
b3
=
base64Alphabet
[
d3
];
b4
=
base64Alphabet
[
d4
];
decodedData
[
encodedIndex
++]
=
(
byte
)
(
b1
<<
2
|
b2
>>
4
);
decodedData
[
encodedIndex
++]
=
(
byte
)
(((
b2
&
0xf
)
<<
4
)
|
((
b3
>>
2
)
&
0xf
));
decodedData
[
encodedIndex
++]
=
(
byte
)
(
b3
<<
6
|
b4
);
}
if
(!
isData
((
d1
=
base64Data
[
dataIndex
++]))
||
!
isData
((
d2
=
base64Data
[
dataIndex
++])))
{
return
null
;
//if found "no data" just return null
}
b1
=
base64Alphabet
[
d1
];
b2
=
base64Alphabet
[
d2
];
d3
=
base64Data
[
dataIndex
++];
d4
=
base64Data
[
dataIndex
++];
if
(!
isData
((
d3
))
||
!
isData
((
d4
)))
{
//Check if they are PAD characters
if
(
isPad
(
d3
)
&&
isPad
(
d4
))
{
if
((
b2
&
0xf
)
!=
0
)
//last 4 bits should be zero
{
return
null
;
}
byte
[]
tmp
=
new
byte
[
i
*
3
+
1
];
System
.
arraycopy
(
decodedData
,
0
,
tmp
,
0
,
i
*
3
);
tmp
[
encodedIndex
]
=
(
byte
)
(
b1
<<
2
|
b2
>>
4
);
return
tmp
;
}
else
if
(!
isPad
(
d3
)
&&
isPad
(
d4
))
{
b3
=
base64Alphabet
[
d3
];
if
((
b3
&
0x3
)
!=
0
)
//last 2 bits should be zero
{
return
null
;
}
byte
[]
tmp
=
new
byte
[
i
*
3
+
2
];
System
.
arraycopy
(
decodedData
,
0
,
tmp
,
0
,
i
*
3
);
tmp
[
encodedIndex
++]
=
(
byte
)
(
b1
<<
2
|
b2
>>
4
);
tmp
[
encodedIndex
]
=
(
byte
)
(((
b2
&
0xf
)
<<
4
)
|
((
b3
>>
2
)
&
0xf
));
return
tmp
;
}
else
{
return
null
;
}
}
else
{
//No PAD e.g 3cQl
b3
=
base64Alphabet
[
d3
];
b4
=
base64Alphabet
[
d4
];
decodedData
[
encodedIndex
++]
=
(
byte
)
(
b1
<<
2
|
b2
>>
4
);
decodedData
[
encodedIndex
++]
=
(
byte
)
(((
b2
&
0xf
)
<<
4
)
|
((
b3
>>
2
)
&
0xf
));
decodedData
[
encodedIndex
++]
=
(
byte
)
(
b3
<<
6
|
b4
);
}
return
decodedData
;
}
/**
* remove WhiteSpace from MIME containing encoded Base64 data.
*
* @param data the byte array of base64 data (with WS)
* @return the new length
*/
private
static
int
removeWhiteSpace
(
char
[]
data
)
{
if
(
data
==
null
)
{
return
0
;
}
// count characters that's not whitespace
int
newSize
=
0
;
int
len
=
data
.
length
;
for
(
int
i
=
0
;
i
<
len
;
i
++)
{
if
(!
isWhiteSpace
(
data
[
i
]))
{
data
[
newSize
++]
=
data
[
i
];
}
}
return
newSize
;
}
}
xxpay4spring-cloud/xxpay-service/src/main/java/org/xxpay/service/channel/alipay/sign/RSA.java
deleted
100755 → 0
View file @
6bb11b08
package
org.xxpay.service.channel.alipay.sign
;
import
javax.crypto.Cipher
;
import
java.io.ByteArrayInputStream
;
import
java.io.ByteArrayOutputStream
;
import
java.io.InputStream
;
import
java.security.KeyFactory
;
import
java.security.PrivateKey
;
import
java.security.PublicKey
;
import
java.security.spec.PKCS8EncodedKeySpec
;
import
java.security.spec.X509EncodedKeySpec
;
public
class
RSA
{
public
static
final
String
SIGN_ALGORITHMS
=
"SHA1WithRSA"
;
/**
* RSA签名
* @param content 待签名数据
* @param privateKey 商户私钥
* @param input_charset 编码格式
* @return 签名值
*/
public
static
String
sign
(
String
content
,
String
privateKey
,
String
input_charset
)
{
try
{
PKCS8EncodedKeySpec
priPKCS8
=
new
PKCS8EncodedKeySpec
(
Base64
.
decode
(
privateKey
)
);
KeyFactory
keyf
=
KeyFactory
.
getInstance
(
"RSA"
);
PrivateKey
priKey
=
keyf
.
generatePrivate
(
priPKCS8
);
java
.
security
.
Signature
signature
=
java
.
security
.
Signature
.
getInstance
(
SIGN_ALGORITHMS
);
signature
.
initSign
(
priKey
);
signature
.
update
(
content
.
getBytes
(
input_charset
)
);
byte
[]
signed
=
signature
.
sign
();
return
Base64
.
encode
(
signed
);
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
}
return
null
;
}
/**
* RSA验签名检查
* @param content 待签名数据
* @param sign 签名值
* @param ali_public_key 支付宝公钥
* @param input_charset 编码格式
* @return 布尔值
*/
public
static
boolean
verify
(
String
content
,
String
sign
,
String
ali_public_key
,
String
input_charset
)
{
try
{
KeyFactory
keyFactory
=
KeyFactory
.
getInstance
(
"RSA"
);
byte
[]
encodedKey
=
Base64
.
decode
(
ali_public_key
);
PublicKey
pubKey
=
keyFactory
.
generatePublic
(
new
X509EncodedKeySpec
(
encodedKey
));
java
.
security
.
Signature
signature
=
java
.
security
.
Signature
.
getInstance
(
SIGN_ALGORITHMS
);
signature
.
initVerify
(
pubKey
);
signature
.
update
(
content
.
getBytes
(
input_charset
)
);
boolean
bverify
=
signature
.
verify
(
Base64
.
decode
(
sign
)
);
return
bverify
;
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
}
return
false
;
}
/**
* 解密
* @param content 密文
* @param private_key 商户私钥
* @param input_charset 编码格式
* @return 解密后的字符串
*/
public
static
String
decrypt
(
String
content
,
String
private_key
,
String
input_charset
)
throws
Exception
{
PrivateKey
prikey
=
getPrivateKey
(
private_key
);
Cipher
cipher
=
Cipher
.
getInstance
(
"RSA"
);
cipher
.
init
(
Cipher
.
DECRYPT_MODE
,
prikey
);
InputStream
ins
=
new
ByteArrayInputStream
(
Base64
.
decode
(
content
));
ByteArrayOutputStream
writer
=
new
ByteArrayOutputStream
();
//rsa解密的字节大小最多是128,将需要解密的内容,按128位拆开解密
byte
[]
buf
=
new
byte
[
128
];
int
bufl
;
while
((
bufl
=
ins
.
read
(
buf
))
!=
-
1
)
{
byte
[]
block
=
null
;
if
(
buf
.
length
==
bufl
)
{
block
=
buf
;
}
else
{
block
=
new
byte
[
bufl
];
for
(
int
i
=
0
;
i
<
bufl
;
i
++)
{
block
[
i
]
=
buf
[
i
];
}
}
writer
.
write
(
cipher
.
doFinal
(
block
));
}
return
new
String
(
writer
.
toByteArray
(),
input_charset
);
}
/**
* 得到私钥
* @param key 密钥字符串(经过base64编码)
* @throws Exception
*/
public
static
PrivateKey
getPrivateKey
(
String
key
)
throws
Exception
{
byte
[]
keyBytes
;
keyBytes
=
Base64
.
decode
(
key
);
PKCS8EncodedKeySpec
keySpec
=
new
PKCS8EncodedKeySpec
(
keyBytes
);
KeyFactory
keyFactory
=
KeyFactory
.
getInstance
(
"RSA"
);
PrivateKey
privateKey
=
keyFactory
.
generatePrivate
(
keySpec
);
return
privateKey
;
}
/*public static void main(String[] args) {
System.out.println(RSA.sign(
"_input_charset=utf-8&app_pay=Y&body=VV直播下单测试&it_b_pay=60m¬ify_url=${pay.url}/notify/aliPayNotifyRes.htm&out_trade_no=1494684553763&partner=2088521108562983&payment_type=1&seller_id=2088521108562983&service=alipay.wap.create.direct.pay.by.user&show_url=http://www.xxpay.org&subject=null&total_fee=0.01",
"MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAKOuhY6LYZBMiRrvRw2s71CjPW7OPCvapjZdJJNPt5x471E3kDCb9A7kQTyqFIIVcUNKDlKRNztKBhhlxAiI7d95UkN5pAMK+XUItjyA9nj9cqK/ajHjwC4AlIRUZhlsPvj6lt1Oj1Kf1sNDJMM/NZL9IR8EXr7HlIsCjJNVHFPvAgMBAAECgYBY1S7G3f5lQiRm6dW2JlT7fpyotmURp+jtOD/Rc0JDOZ8ohO9McldSfa6qLeRTdS+zRU3goc9H7jTAqPprZ2UxNTUwJ4uMh+2bCtXkvUPwoWF4fb095xGtEUdbKMFkv+yKpCQASrjDhqzVq5xD/uc796wd7HOHwr8xPNOrKKSGAQJBANfgcaiIyFeo8KK4vIUWtqSiqLgG6gp7ABx2WpMWX3wsjbiCBQGVbJbnFcCkB+bofCuKYj7BGLjEEqc3c6y+Ph8CQQDCGprovroKw09dOzqFFPpkMrZvkOpO2e+RhDhhLYq2e5lRLVePtB/ZX2iy2yKQEp/7VWbNFzobqYR6KPXEH5AxAkBx3oD1XhkXLBSqMHm4Ve/HTcljMLp5BsJbQQ6rsUxyimnC3kpXuILL4l61+4/ze8Qrj1YdNeudYkdYjsZkYwEPAkBoWedIEylvmdqz86CdZU7LyVu9FPpyk8WwxJWO4O3+9unQ84BseFjbAukFprupGuo5M4uF3OPXdUYMarLd0l4xAkAMjec0KXp15a93I5y/vfIEAMQ+CQj/LwOxyAM6tTSPVGJHu70pXFQVWtwY+ycMuzbxTdSLuQYxITstHnV3mu76", "utf-8"));
}*/
}
xxpay4spring-cloud/xxpay-service/src/main/java/org/xxpay/service/channel/alipay/util/AlipayCore.java
deleted
100755 → 0
View file @
6bb11b08
package
org.xxpay.service.channel.alipay.util
;
import
org.apache.commons.codec.digest.DigestUtils
;
import
org.apache.commons.httpclient.methods.multipart.FilePartSource
;
import
org.apache.commons.httpclient.methods.multipart.PartSource
;
import
java.io.File
;
import
java.io.IOException
;
import
java.util.*
;
/* *
*类名:AlipayFunction
*功能:支付宝接口公用函数类
*详细:该类是请求、通知返回两个文件所调用的公用函数核心处理文件,不需要修改
*版本:3.3
*日期:2012-08-14
*说明:
*以下代码只是为了方便商户测试而提供的样例代码,商户可以根据自己网站的需要,按照技术文档编写,并非一定要使用该代码。
*该代码仅供学习和研究支付宝接口使用,只是提供一个参考。
*/
public
class
AlipayCore
{
/**
* 除去数组中的空值和签名参数
* @param sArray 签名参数组
* @return 去掉空值与签名参数后的新签名参数组
*/
public
static
Map
<
String
,
String
>
paraFilter
(
Map
<
String
,
String
>
sArray
)
{
Map
<
String
,
String
>
result
=
new
HashMap
<
String
,
String
>();
if
(
sArray
==
null
||
sArray
.
size
()
<=
0
)
{
return
result
;
}
for
(
String
key
:
sArray
.
keySet
())
{
String
value
=
sArray
.
get
(
key
);
if
(
value
==
null
||
value
.
equals
(
""
)
||
key
.
equalsIgnoreCase
(
"sign"
)
||
key
.
equalsIgnoreCase
(
"sign_type"
))
{
continue
;
}
result
.
put
(
key
,
value
);
}
return
result
;
}
/**
* 把数组所有元素排序,并按照“参数=参数值”的模式用“&”字符拼接成字符串
* @param params 需要排序并参与字符拼接的参数组
* @return 拼接后字符串
*/
public
static
String
createLinkString
(
Map
<
String
,
String
>
params
)
{
List
<
String
>
keys
=
new
ArrayList
<
String
>(
params
.
keySet
());
Collections
.
sort
(
keys
);
String
prestr
=
""
;
for
(
int
i
=
0
;
i
<
keys
.
size
();
i
++)
{
String
key
=
keys
.
get
(
i
);
String
value
=
params
.
get
(
key
);
if
(
i
==
keys
.
size
()
-
1
)
{
//拼接时,不包括最后一个&字符
prestr
=
prestr
+
key
+
"="
+
value
;
}
else
{
prestr
=
prestr
+
key
+
"="
+
value
+
"&"
;
}
}
return
prestr
;
}
/**
* 生成文件摘要
* @param strFilePath 文件路径
* @param file_digest_type 摘要算法
* @return 文件摘要结果
*/
public
static
String
getAbstract
(
String
strFilePath
,
String
file_digest_type
)
throws
IOException
{
PartSource
file
=
new
FilePartSource
(
new
File
(
strFilePath
));
if
(
file_digest_type
.
equals
(
"MD5"
)){
return
DigestUtils
.
md5Hex
(
file
.
createInputStream
());
}
else
if
(
file_digest_type
.
equals
(
"SHA"
))
{
return
DigestUtils
.
sha256Hex
(
file
.
createInputStream
());
}
else
{
return
""
;
}
}
}
xxpay4spring-cloud/xxpay-service/src/main/java/org/xxpay/service/channel/alipay/util/AlipayNotify.java
deleted
100644 → 0
View file @
6bb11b08
package
org.xxpay.service.channel.alipay.util
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.stereotype.Component
;
import
org.springframework.stereotype.Service
;
import
org.xxpay.service.channel.alipay.config.AlipayConfig
;
import
org.xxpay.service.channel.alipay.sign.RSA
;
import
org.xxpay.common.util.MyLog
;
import
java.io.BufferedReader
;
import
java.io.InputStreamReader
;
import
java.net.HttpURLConnection
;
import
java.net.URL
;
import
java.util.Map
;
/* *
*类名:AlipayNotify
*功能:支付宝通知处理类
*详细:处理支付宝各接口通知返回
*版本:3.3
*日期:2012-08-17
*说明:
*以下代码只是为了方便商户测试而提供的样例代码,商户可以根据自己网站的需要,按照技术文档编写,并非一定要使用该代码。
*该代码仅供学习和研究支付宝接口使用,只是提供一个参考
*************************注意*************************
*调试通知返回时,可查看或改写log日志的写入TXT里的数据,来检查通知返回是否正常
*/
@Component
public
class
AlipayNotify
{
private
static
final
MyLog
_log
=
MyLog
.
getLog
(
AlipayNotify
.
class
);
/**
* 支付宝消息验证地址
*/
private
static
final
String
HTTPS_VERIFY_URL
=
"https://mapi.alipay.com/gateway.do?service=notify_verify&"
;
/**
* 验证消息是否是支付宝发出的合法消息
* @param params 通知返回来的参数数组
* @return 验证结果
*/
public
static
boolean
verify
(
AlipayConfig
alipayConfig
,
Map
<
String
,
String
>
params
)
{
//判断responsetTxt是否为true,isSign是否为true
//responsetTxt的结果不是true,与服务器设置问题、合作身份者ID、notify_id一分钟失效有关
//isSign不是true,与安全校验码、请求时的参数格式(如:带自定义参数等)、编码格式有关
String
responseTxt
=
"true"
;
if
(
alipayConfig
.
is_verify_notify_url
())
{
responseTxt
=
"false"
;
if
(
params
.
get
(
"notify_id"
)
!=
null
)
{
String
notify_id
=
params
.
get
(
"notify_id"
);
responseTxt
=
verifyResponse
(
alipayConfig
,
notify_id
);
}
_log
.
info
(
"验证支付宝请求地址,结果responseTxt={}"
,
responseTxt
);
}
String
sign
=
""
;
if
(
params
.
get
(
"sign"
)
!=
null
)
{
sign
=
params
.
get
(
"sign"
);}
boolean
isSign
=
getSignVeryfy
(
params
,
sign
);
_log
.
info
(
"验证支付宝通知签名,isSign={}"
,
isSign
);
//写日志记录(若要调试,请取消下面两行注释)
//String sWord = "responseTxt=" + responseTxt + "\n isSign=" + isSign + "\n 返回回来的参数:" + AlipayCore.createLinkString(params);
//AlipayCore.logResult(sWord);
if
(
isSign
&&
responseTxt
.
equals
(
"true"
))
{
return
true
;
}
else
{
return
false
;
}
}
/**
* 根据反馈回来的信息,生成签名结果
* @param Params 通知返回来的参数数组
* @param sign 比对的签名结果
* @return 生成的签名结果
*/
private
static
boolean
getSignVeryfy
(
Map
<
String
,
String
>
Params
,
String
sign
)
{
//过滤空值、sign与sign_type参数
Map
<
String
,
String
>
sParaNew
=
AlipayCore
.
paraFilter
(
Params
);
//获取待签名字符串
String
preSignStr
=
AlipayCore
.
createLinkString
(
sParaNew
);
//获得签名验证结果
boolean
isSign
=
false
;
if
(
AlipayConfig
.
sign_type
.
equals
(
"RSA"
)){
isSign
=
RSA
.
verify
(
preSignStr
,
sign
,
AlipayConfig
.
ali_public_key
,
AlipayConfig
.
input_charset
);
}
return
isSign
;
}
/**
* 获取远程服务器ATN结果,验证返回URL
* @param notify_id 通知校验ID
* @return 服务器ATN结果
* 验证结果集:
* invalid命令参数不对 出现这个错误,请检测返回处理中partner和key是否为空
* true 返回正确信息
* false 请检查防火墙或者是服务器阻止端口问题以及验证时间是否超过一分钟
*/
private
static
String
verifyResponse
(
AlipayConfig
alipayConfig
,
String
notify_id
)
{
//获取远程服务器ATN结果,验证是否是支付宝服务器发来的请求
String
partner
=
alipayConfig
.
getPartner
();
String
veryfy_url
=
HTTPS_VERIFY_URL
+
"partner="
+
partner
+
"¬ify_id="
+
notify_id
;
_log
.
info
(
"请求支付宝URL={}"
,
veryfy_url
);
return
checkUrl
(
veryfy_url
);
}
/**
* 获取远程服务器ATN结果
* @param urlvalue 指定URL路径地址
* @return 服务器ATN结果
* 验证结果集:
* invalid命令参数不对 出现这个错误,请检测返回处理中partner和key是否为空
* true 返回正确信息
* false 请检查防火墙或者是服务器阻止端口问题以及验证时间是否超过一分钟
*/
private
static
String
checkUrl
(
String
urlvalue
)
{
String
inputLine
=
""
;
try
{
URL
url
=
new
URL
(
urlvalue
);
HttpURLConnection
urlConnection
=
(
HttpURLConnection
)
url
.
openConnection
();
BufferedReader
in
=
new
BufferedReader
(
new
InputStreamReader
(
urlConnection
.
getInputStream
()));
inputLine
=
in
.
readLine
().
toString
();
}
catch
(
Exception
e
)
{
_log
.
error
(
e
,
"验证支付宝通知请求地址异常.URL=%s"
,
urlvalue
);
inputLine
=
""
;
}
return
inputLine
;
}
}
xxpay4spring-cloud/xxpay-service/src/main/java/org/xxpay/service/channel/alipay/util/UtilDate.java
deleted
100755 → 0
View file @
6bb11b08
package
org.xxpay.service.channel.alipay.util
;
import
java.text.DateFormat
;
import
java.text.SimpleDateFormat
;
import
java.util.Date
;
import
java.util.Random
;
/* *
*类名:UtilDate
*功能:自定义订单类
*详细:工具类,可以用作获取系统日期、订单编号等
*版本:3.3
*日期:2012-08-17
*说明:
*以下代码只是为了方便商户测试而提供的样例代码,商户可以根据自己网站的需要,按照技术文档编写,并非一定要使用该代码。
*该代码仅供学习和研究支付宝接口使用,只是提供一个参考。
*/
public
class
UtilDate
{
/** 年月日时分秒(无下划线) yyyyMMddHHmmss */
public
static
final
String
dtLong
=
"yyyyMMddHHmmss"
;
/** 完整时间 yyyy-MM-dd HH:mm:ss */
public
static
final
String
simple
=
"yyyy-MM-dd HH:mm:ss"
;
/** 年月日(无下划线) yyyyMMdd */
public
static
final
String
dtShort
=
"yyyyMMdd"
;
/**
* 返回系统当前时间(精确到毫秒),作为一个唯一的订单编号
* @return
* 以yyyyMMddHHmmss为格式的当前系统时间
*/
public
static
String
getOrderNum
(){
Date
date
=
new
Date
();
DateFormat
df
=
new
SimpleDateFormat
(
dtLong
);
return
df
.
format
(
date
);
}
/**
* 获取系统当前日期(精确到毫秒),格式:yyyy-MM-dd HH:mm:ss
* @return
*/
public
static
String
getDateFormatter
(){
Date
date
=
new
Date
();
DateFormat
df
=
new
SimpleDateFormat
(
simple
);
return
df
.
format
(
date
);
}
/**
* 获取系统当期年月日(精确到天),格式:yyyyMMdd
* @return
*/
public
static
String
getDate
(){
Date
date
=
new
Date
();
DateFormat
df
=
new
SimpleDateFormat
(
dtShort
);
return
df
.
format
(
date
);
}
/**
* 产生随机的三位数
* @return
*/
public
static
String
getThree
(){
Random
rad
=
new
Random
();
return
rad
.
nextInt
(
1000
)+
""
;
}
}
xxpay4spring-cloud/xxpay-service/src/main/java/org/xxpay/service/channel/alipay/util/httpClient/HttpProtocolHandler.java
deleted
100755 → 0
View file @
6bb11b08
package
org.xxpay.service.channel.alipay.util.httpClient
;
import
org.apache.commons.httpclient.*
;
import
org.apache.commons.httpclient.methods.GetMethod
;
import
org.apache.commons.httpclient.methods.PostMethod
;
import
org.apache.commons.httpclient.methods.multipart.*
;
import
org.apache.commons.httpclient.params.HttpMethodParams
;
import
org.apache.commons.httpclient.util.IdleConnectionTimeoutThread
;
import
java.io.File
;
import
java.io.IOException
;
import
java.net.UnknownHostException
;
import
java.util.ArrayList
;
import
java.util.List
;
/* *
*类名:HttpProtocolHandler
*功能:HttpClient方式访问
*详细:获取远程HTTP数据
*版本:3.3
*日期:2012-08-17
*说明:
*以下代码只是为了方便商户测试而提供的样例代码,商户可以根据自己网站的需要,按照技术文档编写,并非一定要使用该代码。
*该代码仅供学习和研究支付宝接口使用,只是提供一个参考。
*/
public
class
HttpProtocolHandler
{
private
static
String
DEFAULT_CHARSET
=
"GBK"
;
/** 连接超时时间,由bean factory设置,缺省为8秒钟 */
private
int
defaultConnectionTimeout
=
8000
;
/** 回应超时时间, 由bean factory设置,缺省为30秒钟 */
private
int
defaultSoTimeout
=
30000
;
/** 闲置连接超时时间, 由bean factory设置,缺省为60秒钟 */
private
int
defaultIdleConnTimeout
=
60000
;
private
int
defaultMaxConnPerHost
=
30
;
private
int
defaultMaxTotalConn
=
80
;
/** 默认等待HttpConnectionManager返回连接超时(只有在达到最大连接数时起作用):1秒*/
private
static
final
long
defaultHttpConnectionManagerTimeout
=
3
*
1000
;
/**
* HTTP连接管理器,该连接管理器必须是线程安全的.
*/
private
HttpConnectionManager
connectionManager
;
private
static
HttpProtocolHandler
httpProtocolHandler
=
new
HttpProtocolHandler
();
/**
* 工厂方法
*
* @return
*/
public
static
HttpProtocolHandler
getInstance
()
{
return
httpProtocolHandler
;
}
/**
* 私有的构造方法
*/
private
HttpProtocolHandler
()
{
// 创建一个线程安全的HTTP连接池
connectionManager
=
new
MultiThreadedHttpConnectionManager
();
connectionManager
.
getParams
().
setDefaultMaxConnectionsPerHost
(
defaultMaxConnPerHost
);
connectionManager
.
getParams
().
setMaxTotalConnections
(
defaultMaxTotalConn
);
IdleConnectionTimeoutThread
ict
=
new
IdleConnectionTimeoutThread
();
ict
.
addConnectionManager
(
connectionManager
);
ict
.
setConnectionTimeout
(
defaultIdleConnTimeout
);
ict
.
start
();
}
/**
* 执行Http请求
*
* @param request 请求数据
* @param strParaFileName 文件类型的参数名
* @param strFilePath 文件路径
* @return
* @throws HttpException, IOException
*/
public
HttpResponse
execute
(
HttpRequest
request
,
String
strParaFileName
,
String
strFilePath
)
throws
HttpException
,
IOException
{
HttpClient
httpclient
=
new
HttpClient
(
connectionManager
);
// 设置连接超时
int
connectionTimeout
=
defaultConnectionTimeout
;
if
(
request
.
getConnectionTimeout
()
>
0
)
{
connectionTimeout
=
request
.
getConnectionTimeout
();
}
httpclient
.
getHttpConnectionManager
().
getParams
().
setConnectionTimeout
(
connectionTimeout
);
// 设置回应超时
int
soTimeout
=
defaultSoTimeout
;
if
(
request
.
getTimeout
()
>
0
)
{
soTimeout
=
request
.
getTimeout
();
}
httpclient
.
getHttpConnectionManager
().
getParams
().
setSoTimeout
(
soTimeout
);
// 设置等待ConnectionManager释放connection的时间
httpclient
.
getParams
().
setConnectionManagerTimeout
(
defaultHttpConnectionManagerTimeout
);
String
charset
=
request
.
getCharset
();
charset
=
charset
==
null
?
DEFAULT_CHARSET
:
charset
;
HttpMethod
method
=
null
;
//get模式且不带上传文件
if
(
request
.
getMethod
().
equals
(
HttpRequest
.
METHOD_GET
))
{
method
=
new
GetMethod
(
request
.
getUrl
());
method
.
getParams
().
setCredentialCharset
(
charset
);
// parseNotifyConfig会保证使用GET方法时,request一定使用QueryString
method
.
setQueryString
(
request
.
getQueryString
());
}
else
if
(
strParaFileName
.
equals
(
""
)
&&
strFilePath
.
equals
(
""
))
{
//post模式且不带上传文件
method
=
new
PostMethod
(
request
.
getUrl
());
((
PostMethod
)
method
).
addParameters
(
request
.
getParameters
());
method
.
addRequestHeader
(
"Content-Type"
,
"application/x-www-form-urlencoded; text/html; charset="
+
charset
);
}
else
{
//post模式且带上传文件
method
=
new
PostMethod
(
request
.
getUrl
());
List
<
Part
>
parts
=
new
ArrayList
<
Part
>();
for
(
int
i
=
0
;
i
<
request
.
getParameters
().
length
;
i
++)
{
parts
.
add
(
new
StringPart
(
request
.
getParameters
()[
i
].
getName
(),
request
.
getParameters
()[
i
].
getValue
(),
charset
));
}
//增加文件参数,strParaFileName是参数名,使用本地文件
parts
.
add
(
new
FilePart
(
strParaFileName
,
new
FilePartSource
(
new
File
(
strFilePath
))));
// 设置请求体
((
PostMethod
)
method
).
setRequestEntity
(
new
MultipartRequestEntity
(
parts
.
toArray
(
new
Part
[
0
]),
new
HttpMethodParams
()));
}
// 设置Http Header中的User-Agent属性
method
.
addRequestHeader
(
"User-Agent"
,
"Mozilla/4.0"
);
HttpResponse
response
=
new
HttpResponse
();
try
{
httpclient
.
executeMethod
(
method
);
if
(
request
.
getResultType
().
equals
(
HttpResultType
.
STRING
))
{
response
.
setStringResult
(
method
.
getResponseBodyAsString
());
}
else
if
(
request
.
getResultType
().
equals
(
HttpResultType
.
BYTES
))
{
response
.
setByteResult
(
method
.
getResponseBody
());
}
response
.
setResponseHeaders
(
method
.
getResponseHeaders
());
}
catch
(
UnknownHostException
ex
)
{
return
null
;
}
catch
(
IOException
ex
)
{
return
null
;
}
catch
(
Exception
ex
)
{
return
null
;
}
finally
{
method
.
releaseConnection
();
}
return
response
;
}
/**
* 将NameValuePairs数组转变为字符串
*
* @param nameValues
* @return
*/
protected
String
toString
(
NameValuePair
[]
nameValues
)
{
if
(
nameValues
==
null
||
nameValues
.
length
==
0
)
{
return
"null"
;
}
StringBuffer
buffer
=
new
StringBuffer
();
for
(
int
i
=
0
;
i
<
nameValues
.
length
;
i
++)
{
NameValuePair
nameValue
=
nameValues
[
i
];
if
(
i
==
0
)
{
buffer
.
append
(
nameValue
.
getName
()
+
"="
+
nameValue
.
getValue
());
}
else
{
buffer
.
append
(
"&"
+
nameValue
.
getName
()
+
"="
+
nameValue
.
getValue
());
}
}
return
buffer
.
toString
();
}
}
xxpay4spring-cloud/xxpay-service/src/main/java/org/xxpay/service/channel/alipay/util/httpClient/HttpRequest.java
deleted
100755 → 0
View file @
6bb11b08
package
org.xxpay.service.channel.alipay.util.httpClient
;
import
org.apache.commons.httpclient.NameValuePair
;
/* *
*类名:HttpRequest
*功能:Http请求对象的封装
*详细:封装Http请求
*版本:3.3
*日期:2011-08-17
*说明:
*以下代码只是为了方便商户测试而提供的样例代码,商户可以根据自己网站的需要,按照技术文档编写,并非一定要使用该代码。
*该代码仅供学习和研究支付宝接口使用,只是提供一个参考。
*/
public
class
HttpRequest
{
/** HTTP GET method */
public
static
final
String
METHOD_GET
=
"GET"
;
/** HTTP POST method */
public
static
final
String
METHOD_POST
=
"POST"
;
/**
* 待请求的url
*/
private
String
url
=
null
;
/**
* 默认的请求方式
*/
private
String
method
=
METHOD_POST
;
private
int
timeout
=
0
;
private
int
connectionTimeout
=
0
;
/**
* Post方式请求时组装好的参数值对
*/
private
NameValuePair
[]
parameters
=
null
;
/**
* Get方式请求时对应的参数
*/
private
String
queryString
=
null
;
/**
* 默认的请求编码方式
*/
private
String
charset
=
"GBK"
;
/**
* 请求发起方的ip地址
*/
private
String
clientIp
;
/**
* 请求返回的方式
*/
private
HttpResultType
resultType
=
HttpResultType
.
BYTES
;
public
HttpRequest
(
HttpResultType
resultType
)
{
super
();
this
.
resultType
=
resultType
;
}
/**
* @return Returns the clientIp.
*/
public
String
getClientIp
()
{
return
clientIp
;
}
/**
* @param clientIp The clientIp to set.
*/
public
void
setClientIp
(
String
clientIp
)
{
this
.
clientIp
=
clientIp
;
}
public
NameValuePair
[]
getParameters
()
{
return
parameters
;
}
public
void
setParameters
(
NameValuePair
[]
parameters
)
{
this
.
parameters
=
parameters
;
}
public
String
getQueryString
()
{
return
queryString
;
}
public
void
setQueryString
(
String
queryString
)
{
this
.
queryString
=
queryString
;
}
public
String
getUrl
()
{
return
url
;
}
public
void
setUrl
(
String
url
)
{
this
.
url
=
url
;
}
public
String
getMethod
()
{
return
method
;
}
public
void
setMethod
(
String
method
)
{
this
.
method
=
method
;
}
public
int
getConnectionTimeout
()
{
return
connectionTimeout
;
}
public
void
setConnectionTimeout
(
int
connectionTimeout
)
{
this
.
connectionTimeout
=
connectionTimeout
;
}
public
int
getTimeout
()
{
return
timeout
;
}
public
void
setTimeout
(
int
timeout
)
{
this
.
timeout
=
timeout
;
}
/**
* @return Returns the charset.
*/
public
String
getCharset
()
{
return
charset
;
}
/**
* @param charset The charset to set.
*/
public
void
setCharset
(
String
charset
)
{
this
.
charset
=
charset
;
}
public
HttpResultType
getResultType
()
{
return
resultType
;
}
public
void
setResultType
(
HttpResultType
resultType
)
{
this
.
resultType
=
resultType
;
}
}
xxpay4spring-cloud/xxpay-service/src/main/java/org/xxpay/service/channel/alipay/util/httpClient/HttpResponse.java
deleted
100755 → 0
View file @
6bb11b08
package
org.xxpay.service.channel.alipay.util.httpClient
;
import
org.apache.commons.httpclient.Header
;
import
org.xxpay.service.channel.alipay.config.AlipayConfig
;
import
java.io.UnsupportedEncodingException
;
/* *
*类名:HttpResponse
*功能:Http返回对象的封装
*详细:封装Http返回信息
*版本:3.3
*日期:2011-08-17
*说明:
*以下代码只是为了方便商户测试而提供的样例代码,商户可以根据自己网站的需要,按照技术文档编写,并非一定要使用该代码。
*该代码仅供学习和研究支付宝接口使用,只是提供一个参考。
*/
public
class
HttpResponse
{
/**
* 返回中的Header信息
*/
private
Header
[]
responseHeaders
;
/**
* String类型的result
*/
private
String
stringResult
;
/**
* btye类型的result
*/
private
byte
[]
byteResult
;
public
Header
[]
getResponseHeaders
()
{
return
responseHeaders
;
}
public
void
setResponseHeaders
(
Header
[]
responseHeaders
)
{
this
.
responseHeaders
=
responseHeaders
;
}
public
byte
[]
getByteResult
()
{
if
(
byteResult
!=
null
)
{
return
byteResult
;
}
if
(
stringResult
!=
null
)
{
return
stringResult
.
getBytes
();
}
return
null
;
}
public
void
setByteResult
(
byte
[]
byteResult
)
{
this
.
byteResult
=
byteResult
;
}
public
String
getStringResult
()
throws
UnsupportedEncodingException
{
if
(
stringResult
!=
null
)
{
return
stringResult
;
}
if
(
byteResult
!=
null
)
{
return
new
String
(
byteResult
,
AlipayConfig
.
input_charset
);
}
return
null
;
}
public
void
setStringResult
(
String
stringResult
)
{
this
.
stringResult
=
stringResult
;
}
}
xxpay4spring-cloud/xxpay-service/src/main/java/org/xxpay/service/channel/alipay/util/httpClient/HttpResultType.java
deleted
100755 → 0
View file @
6bb11b08
/*
* Alipay.com Inc.
* Copyright (c) 2004-2005 All Rights Reserved.
*/
package
org.xxpay.service.channel.alipay.util.httpClient
;
/* *
*类名:HttpResultType
*功能:表示Http返回的结果字符方式
*详细:表示Http返回的结果字符方式
*版本:3.3
*日期:2012-08-17
*说明:
*以下代码只是为了方便商户测试而提供的样例代码,商户可以根据自己网站的需要,按照技术文档编写,并非一定要使用该代码。
*该代码仅供学习和研究支付宝接口使用,只是提供一个参考。
*/
public
enum
HttpResultType
{
/**
* 字符串方式
*/
STRING
,
/**
* 字节数组方式
*/
BYTES
}
Prev
1
2
Next
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment