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
5def62fe
Commit
5def62fe
authored
Aug 25, 2017
by
jmdhappy
Browse files
微信支付SDK更换为weixin-java-pay,增加微信H5支付,优化一些异常情况的处理
parent
dd9d81f9
Changes
70
Hide whitespace changes
Inline
Side-by-side
xxpay-common/src/main/java/org/xxpay/common/constant/PayConstant.java
View file @
5def62fe
...
...
@@ -16,6 +16,7 @@ public class PayConstant {
public
final
static
String
PAY_CHANNEL_WX_JSAPI
=
"WX_JSAPI"
;
// 微信公众号支付
public
final
static
String
PAY_CHANNEL_WX_NATIVE
=
"WX_NATIVE"
;
// 微信原生扫码支付
public
final
static
String
PAY_CHANNEL_WX_APP
=
"WX_APP"
;
// 微信APP支付
public
final
static
String
PAY_CHANNEL_WX_MWEB
=
"WX_MWEB"
;
// 微信H5支付
public
final
static
String
PAY_CHANNEL_IAP
=
"IAP"
;
// 苹果应用内支付
public
final
static
String
PAY_CHANNEL_ALIPAY_MOBILE
=
"ALIPAY_MOBILE"
;
// 支付宝移动支付
public
final
static
String
PAY_CHANNEL_ALIPAY_PC
=
"ALIPAY_PC"
;
// 支付宝PC支付
...
...
@@ -61,8 +62,10 @@ public class PayConstant {
public
static
class
WxConstant
{
public
final
static
String
TRADE_TYPE_APP
=
"APP"
;
// APP支付
public
final
static
String
TRADE_TYPE_JSPAI
=
"JSAPI"
;
// 公众号支付
public
final
static
String
TRADE_TYPE_JSPAI
=
"JSAPI"
;
// 公众号支付
或小程序支付
public
final
static
String
TRADE_TYPE_NATIVE
=
"NATIVE"
;
// 原生扫码支付
public
final
static
String
TRADE_TYPE_MWEB
=
"MWEB"
;
// H5支付
}
public
static
class
IapConstant
{
...
...
xxpay-shop/src/main/java/org/xxpay/shop/demo/PayOrderDemo.java
View file @
5def62fe
...
...
@@ -19,8 +19,8 @@ public class PayOrderDemo {
// 验签key
static
final
String
repKey
=
"Hpcl522AV6q613KIi46u6g6XuW8vM1N8bFgyv769770MdYe9u37M4y7rIpl8"
;
static
final
String
baseUrl
=
"http://api.xxpay.org/api"
;
//
static final String baseUrl = "http://localhost:3020/api";
//
static final String baseUrl = "http://api.xxpay.org/api";
static
final
String
baseUrl
=
"http://localhost:3020/api"
;
static
final
String
notifyUrl
=
"http://www.baidu.com"
;
// 本地环境测试,可到ngrok.cc网站注册
public
static
void
main
(
String
[]
args
)
{
...
...
@@ -32,17 +32,31 @@ public class PayOrderDemo {
JSONObject
paramMap
=
new
JSONObject
();
paramMap
.
put
(
"mchId"
,
mchId
);
// 商户ID
paramMap
.
put
(
"mchOrderNo"
,
System
.
currentTimeMillis
());
// 商户订单号
paramMap
.
put
(
"channelId"
,
"ALIPAY_PC"
);
// 支付渠道ID, WX_NATIVE,ALIPAY_WAP,ALIPAY_PC,ALIPAY_MOBILE
// 支付渠道ID, WX_NATIVE(微信扫码),WX_JSAPI(微信公众号或微信小程序),WX_APP(微信APP),WX_MWEB(微信H5),ALIPAY_WAP(支付宝手机支付),ALIPAY_PC(支付宝网站支付),ALIPAY_MOBILE(支付宝移动支付)
paramMap
.
put
(
"channelId"
,
"WX_MWEB"
);
paramMap
.
put
(
"amount"
,
1
);
// 支付金额,单位分
paramMap
.
put
(
"currency"
,
"cny"
);
// 币种, cny-人民币
paramMap
.
put
(
"clientIp"
,
"114.11
2.124.236
"
);
// 用户地址
paramMap
.
put
(
"clientIp"
,
"
2
11
.9
4.11
6.218
"
);
// 用户地址
,微信H5支付时要真实的
paramMap
.
put
(
"device"
,
"WEB"
);
// 设备
paramMap
.
put
(
"subject"
,
"XXPAY支付测试"
);
paramMap
.
put
(
"body"
,
"XXPAY支付测试"
);
paramMap
.
put
(
"notifyUrl"
,
notifyUrl
);
// 回调URL
paramMap
.
put
(
"param1"
,
""
);
// 扩展参数1
paramMap
.
put
(
"param2"
,
""
);
// 扩展参数2
paramMap
.
put
(
"extra"
,
"{\"productId\":\"120989823\",\"openId\":\"o2RvowBf7sOVJf8kJksUEMceaDqo\"}"
);
// 附加参数
paramMap
.
put
(
"extra"
,
"{\n"
+
" \"productId\": \"120989823\",\n"
+
" \"openId\": \"o2RvowBf7sOVJf8kJksUEMceaDqo\",\n"
+
" \"sceneInfo\": {\n"
+
" \"h5_info\": {\n"
+
" \"type\": \"Wap\",\n"
+
" \"wap_url\": \"http://shop.xxpay.org\",\n"
+
" \"wap_name\": \"xxpay充值\"\n"
+
" }\n"
+
" }\n"
+
"}"
);
// 附加参数
//{"h5_info": {"type":"Wap","wap_url": "https://pay.qq.com","wap_name": "腾讯充值"}}
String
reqSign
=
PayDigestUtil
.
getSign
(
paramMap
,
reqKey
);
paramMap
.
put
(
"sign"
,
reqSign
);
// 签名
String
reqData
=
"params="
+
paramMap
.
toJSONString
();
...
...
xxpay4spring-cloud/xxpay-config/src/main/resources/shared/xxpay-service-dev.properties
View file @
5def62fe
# \u652F\u4ED8\u5B9D\u670D\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://xxpay.
ngrok.cc
/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
wx.notify_url
=
http://
api.
xxpay.
org
/notify/pay/wxPayNotifyRes.htm
wx.notify_url
=
http://xxpay.
ngrok.cc
/notify/pay/wxPayNotifyRes.htm
# \u652F\u4ED8\u8BC1\u4E66\u6839\u8DEF\u5F84
cert.root.path
=
/home/xxpay/service/cert
\ No newline at end of file
cert.root.path
=
/Users/dingzhiwei/java/tmp/cert
\ No newline at end of file
xxpay4spring-cloud/xxpay-server/pom.xml
View file @
5def62fe
...
...
@@ -24,22 +24,6 @@
</dependencies>
<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>
<resource>
<directory>
src/main/resources
</directory>
</resource>
</resources>
<plugins>
<plugin>
<groupId>
org.springframework.boot
</groupId>
...
...
xxpay4spring-cloud/xxpay-service/pom.xml
View file @
5def62fe
...
...
@@ -53,6 +53,11 @@
<artifactId>
xstream
</artifactId>
<version>
1.4.7
</version>
</dependency>
<dependency>
<groupId>
com.github.binarywang
</groupId>
<artifactId>
weixin-java-pay
</artifactId>
<version>
2.7.7
</version>
</dependency>
<!--ali_pay-->
<dependency>
<groupId>
com.alipay
</groupId>
...
...
xxpay4spring-cloud/xxpay-service/src/main/java/org/xxpay/service/channel/tencent/Main.java
deleted
100755 → 0
View file @
dd9d81f9
package
org.xxpay.service.channel.tencent
;
public
class
Main
{
/*public static void main(String[] args) {
try {
//--------------------------------------------------------------------
//温馨提示,第一次使用该SDK时请到com.tencent.common.Configure类里面进行配置
//--------------------------------------------------------------------
//--------------------------------------------------------------------
//PART One:基础组件测试
//--------------------------------------------------------------------
//1)https请求可用性测试
//HTTPSPostRquestWithCert.test();
//2)测试项目用到的XStream组件,本项目利用这个组件将Java对象转换成XML数据Post给API
//XStreamTest.test();
//--------------------------------------------------------------------
//PART Two:基础服务测试
//--------------------------------------------------------------------
//1)测试被扫支付API
//PayServiceTest.test();
//2)测试被扫订单查询API
//PayQueryServiceTest.test();
//3)测试撤销API
//温馨提示,测试支付API成功扣到钱之后,可以通过调用PayQueryServiceTest.test(),将支付成功返回的transaction_id和out_trade_no数据贴进去,完成撤销工作,把钱退回来 ^_^v
//ReverseServiceTest.test();
//4)测试退款申请API
//RefundServiceTest.test();
//5)测试退款查询API
//RefundQueryServiceTest.test();
//6)测试对账单API
//DownloadBillServiceTest.test();
//本地通过xml进行API数据模拟的时候,先按需手动修改xml各个节点的值,然后通过以下方法对这个新的xml数据进行签名得到一串合法的签名,最后把这串签名放到这个xml里面的sign字段里,这样进行模拟的时候就可以通过签名验证了
// Util.log(Signature.getSignFromResponseString(Util.getLocalXMLString("/test/com/tencent/business/refundqueryserviceresponsedata/refundquerysuccess2.xml")));
//Util.log(new Date().getTime());
//Util.log(System.currentTimeMillis());
} catch (Exception e){
Util.log(e.getMessage());
}
}*/
}
xxpay4spring-cloud/xxpay-service/src/main/java/org/xxpay/service/channel/tencent/WXPay.java
deleted
100755 → 0
View file @
dd9d81f9
package
org.xxpay.service.channel.tencent
;
import
org.xxpay.service.channel.tencent.protocol.downloadbill_protocol.DownloadBillReqData
;
import
org.xxpay.service.channel.tencent.protocol.pay_protocol.ScanPayReqData
;
import
org.xxpay.service.channel.tencent.protocol.pay_query_protocol.ScanPayQueryReqData
;
import
org.xxpay.service.channel.tencent.protocol.refund_protocol.RefundReqData
;
import
org.xxpay.service.channel.tencent.protocol.refund_query_protocol.RefundQueryReqData
;
import
org.xxpay.service.channel.tencent.protocol.reverse_protocol.ReverseReqData
;
import
org.xxpay.service.channel.tencent.service.*
;
/**
* SDK总入口
*/
public
class
WXPay
{
/**
* 初始化SDK依赖的几个关键配置
* @param key 签名算法需要用到的秘钥
* @param appID 公众账号ID
* @param mchID 商户ID
* @param sdbMchID 子商户ID,受理模式必填
* @param certLocalPath HTTP证书在服务器中的路径,用来加载证书用
* @param certPassword HTTP证书的密码,默认等于MCHID
*/
public
static
void
initSDKConfiguration
(
String
key
,
String
appID
,
String
mchID
,
String
sdbMchID
,
String
certLocalPath
,
String
certPassword
){
/* Configure.setKey(key);
Configure.setAppID(appID);
Configure.setMchID(mchID);
Configure.setSubMchID(sdbMchID);
Configure.setCertLocalPath(certLocalPath);
Configure.setCertPassword(certPassword);*/
}
/**
* 请求支付服务
* @param scanPayReqData 这个数据对象里面包含了API要求提交的各种数据字段
* @return API返回的数据
* @throws Exception
*/
public
static
String
requestScanPayService
(
ScanPayReqData
scanPayReqData
)
throws
Exception
{
return
new
ScanPayService
().
request
(
scanPayReqData
);
}
/**
* 请求支付查询服务
* @param scanPayQueryReqData 这个数据对象里面包含了API要求提交的各种数据字段
* @return API返回的XML数据
* @throws Exception
*/
public
static
String
requestScanPayQueryService
(
ScanPayQueryReqData
scanPayQueryReqData
)
throws
Exception
{
return
new
ScanPayQueryService
().
request
(
scanPayQueryReqData
);
}
/**
* 请求退款服务
* @param refundReqData 这个数据对象里面包含了API要求提交的各种数据字段
* @return API返回的XML数据
* @throws Exception
*/
public
static
String
requestRefundService
(
RefundReqData
refundReqData
)
throws
Exception
{
return
new
RefundService
().
request
(
refundReqData
);
}
/**
* 请求退款查询服务
* @param refundQueryReqData 这个数据对象里面包含了API要求提交的各种数据字段
* @return API返回的XML数据
* @throws Exception
*/
public
static
String
requestRefundQueryService
(
RefundQueryReqData
refundQueryReqData
)
throws
Exception
{
return
new
RefundQueryService
().
request
(
refundQueryReqData
);
}
/**
* 请求撤销服务
* @param reverseReqData 这个数据对象里面包含了API要求提交的各种数据字段
* @return API返回的XML数据
* @throws Exception
*/
public
static
String
requestReverseService
(
ReverseReqData
reverseReqData
)
throws
Exception
{
return
new
ReverseService
().
request
(
reverseReqData
);
}
/**
* 请求对账单下载服务
* @param downloadBillReqData 这个数据对象里面包含了API要求提交的各种数据字段
* @return API返回的XML数据
* @throws Exception
*/
public
static
String
requestDownloadBillService
(
DownloadBillReqData
downloadBillReqData
)
throws
Exception
{
return
new
DownloadBillService
().
request
(
downloadBillReqData
);
}
/*
*/
/**
* 直接执行被扫支付业务逻辑(包含最佳实践流程)
* @param scanPayReqData 这个数据对象里面包含了API要求提交的各种数据字段
* @param resultListener 商户需要自己监听被扫支付业务逻辑可能触发的各种分支事件,并做好合理的响应处理
* @throws Exception
*//*
public static void doScanPayBusiness(ScanPayReqData scanPayReqData, ScanPayBusiness.ResultListener resultListener) throws Exception {
//new ScanPayBusiness().run(scanPayReqData, resultListener);
}
*/
/**
* 调用退款业务逻辑
* @param refundReqData 这个数据对象里面包含了API要求提交的各种数据字段
* @param resultListener 业务逻辑可能走到的结果分支,需要商户处理
* @throws Exception
*//*
public static void doRefundBusiness(RefundReqData refundReqData, RefundBusiness.ResultListener resultListener) throws Exception {
//new RefundBusiness().run(refundReqData,resultListener);
}
*/
/**
* 运行退款查询的业务逻辑
* @param refundQueryReqData 这个数据对象里面包含了API要求提交的各种数据字段
* @param resultListener 商户需要自己监听被扫支付业务逻辑可能触发的各种分支事件,并做好合理的响应处理
* @throws Exception
*//*
public static void doRefundQueryBusiness(RefundQueryReqData refundQueryReqData, RefundQueryBusiness.ResultListener resultListener) throws Exception {
//new RefundQueryBusiness().run(refundQueryReqData,resultListener);
}
*/
/**
* 请求对账单下载服务
* @param downloadBillReqData 这个数据对象里面包含了API要求提交的各种数据字段
* @param resultListener 商户需要自己监听被扫支付业务逻辑可能触发的各种分支事件,并做好合理的响应处理
* @return API返回的XML数据
* @throws Exception
*//*
public static void doDownloadBillBusiness(DownloadBillReqData downloadBillReqData, DownloadBillBusiness.ResultListener resultListener) throws Exception {
//new DownloadBillBusiness().run(downloadBillReqData,resultListener);
}
*/
}
xxpay4spring-cloud/xxpay-service/src/main/java/org/xxpay/service/channel/tencent/bridge/IBridge.java
deleted
100755 → 0
View file @
dd9d81f9
package
org.xxpay.service.channel.tencent.bridge
;
/**
* User: rizenguo
* Date: 2014/12/1
* Time: 17:11
*/
public
interface
IBridge
{
/**
* 获取auth_code,这个是扫码终端设备从用户手机上扫取到的支付授权号,这个号是跟用户用来支付的银行卡绑定的,有效期是1分钟
* @return 授权码
*/
public
String
getAuthCode
();
/**
* 获取out_trade_no,这个是商户系统内自己可以用来唯一标识该笔订单的字符串,可以包含字母和数字,不超过32位
* @return 订单号
*/
public
String
getOutTradeNo
();
/**
* 获取body:要支付的商品的描述信息,用户会在支付成功页面里看到这个信息
* @return 描述信息
*/
public
String
getBody
();
/**
* 获取attach:支付订单里面可以填的附加数据,API会将提交的这个附加数据原样返回,有助于商户自己可以注明该笔消费的具体内容,方便后续的运营和记录
* @return 附加数据
*/
public
String
getAttach
();
/**
* 获取订单总额
* @return 订单总额
*/
public
int
getTotalFee
();
/**
* 获取device_info:商户自己定义的扫码支付终端设备号,方便追溯这笔交易发生在哪台终端设备上
* @return 支付终端设备号
*/
public
String
getDeviceInfo
();
/**
* 获取机器的ip地址
* @return 机器设备的ip地址
*/
public
String
getUserIp
();
/**
* 获取spBillCreateIP:订单生成的机器IP
* @return 订单生成的机器IP
*/
public
String
getSpBillCreateIP
();
/**
* 获取time_start:订单生成时间
* @return 订单生成时间
*/
public
String
getTimeStart
();
/**
* 获取time_end:订单生成时间
* @return 订单失效时间
*/
public
String
getTimeExpire
();
/**
* 获取goods_tag:商品标记,微信平台配置的商品标记,用于优惠券或者满减使用
* @return 商品标记
*/
public
String
getGoodsTag
();
/**
* 获取transaction_id:微信平台支付成功时给分配的唯一交易号,一般只要有这个tracnsacion_id,后续的查询、撤销、退款都建议优先用这个,而不是商户自己的那个out_trade_no
* @return 微信平台官方分配的交易号
*/
public
String
getTransactionID
();
/**
* 获取out_refund_no:商户系统内部的退款单号,商户系统内部唯一,同一退款单号多次请求只退一笔
* @return 商户系统内部的退款单号
*/
public
String
getOutRefundNo
();
/**
* 获取refund_fee:获取本次退款请求所要退的具体金额,这个金额不能比这个订单的total_fee(总金额)还大
* @return 本次退款请求所要退的具体金额
*/
public
int
getRefundFee
();
/**
* 获取refund_id:微信平台退款成功时给分配的唯一退款号,一般只要有这个refund_id,后续的查询建议优先用这个
* @return 微信平台官方分配的退款号
*/
public
String
getRefundID
();
/**
* 获取bill_date:获取对账单API需要的日期,格式是yyyyMMdd
* @return 要查询对账单的日期
*/
public
String
getBillDate
();
/**
* 获取bill_type:获取对账单API需要的数据类型,这些类型在DownloadBillService里面有定义
* @return 要查询对账单的类型
*/
public
String
getBillType
();
/**
* 获取操作员的ID,默认等于商户号
* @return 返回操作员的ID
*/
public
String
getOpUserID
();
/**
* 获取退款货币类型,符合ISO 4217标准的三位字母代码,默认为CNY(人民币)
* @return 获取退款货币类型
*/
public
String
getRefundFeeType
();
}
xxpay4spring-cloud/xxpay-service/src/main/java/org/xxpay/service/channel/tencent/common/Configure.java
deleted
100755 → 0
View file @
dd9d81f9
package
org.xxpay.service.channel.tencent.common
;
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.xxpay.common.util.IPUtility
;
import
org.xxpay.common.util.MyLog
;
import
java.io.File
;
import
java.util.Date
;
/**
* User: rizenguo
* Date: 2014/10/29
* Time: 14:40
* 这里放置各种配置数据
*/
@RefreshScope
@Service
public
class
Configure
{
private
static
final
MyLog
_log
=
MyLog
.
getLog
(
Configure
.
class
);
public
Configure
init
(
String
configParam
)
{
JSONObject
paramObj
=
JSON
.
parseObject
(
configParam
);
this
.
setMchID
(
paramObj
.
getString
(
"mchId"
));
this
.
setAppID
(
paramObj
.
getString
(
"appId"
));
this
.
setCertLocalPath
(
certRootPath
+
File
.
separator
+
paramObj
.
getString
(
"certLocalPath"
));
this
.
setCertPassword
(
paramObj
.
getString
(
"certPassword"
));
this
.
setKey
(
paramObj
.
getString
(
"key"
));
this
.
setIp
(
IPUtility
.
getLocalIP
());
return
this
;
}
// 这个就是自己要保管好的私有Key了(切记只能放在自己的后台代码里,不能放在任何可能被看到源代码的客户端程序中)
// 每次自己Post数据给API的时候都要用这个key来对所有字段进行签名,生成的签名会放在Sign这个字段,API收到Post数据的时候也会用同样的签名算法对Post过来的数据进行签名和验证
// 收到API的返回的时候也要用这个key来对返回的数据算下签名,跟API的Sign数据进行比较,如果值不一致,有可能数据被第三方给篡改
private
String
key
;
//微信分配的公众号ID(开通公众号之后可以获取到)
private
String
appID
;
private
String
mchID
;
//HTTPS证书的本地路径
// private static String certLocalPath = "/Users/dingzhiwei/java/tmp/wx.crt.p12";
private
String
certLocalPath
;
//HTTPS证书密码,默认密码等于商户号MCHID
private
String
certPassword
;
//是否使用异步线程的方式来上报API测速,默认为异步模式
private
static
boolean
useThreadToDoReport
=
true
;
//配置描述
private
String
desc
;
//机器IP
private
String
ip
;
@Value
(
"${cert.root.path}"
)
private
String
certRootPath
;
//以下是几个API的路径:
//1)被扫支付API
public
static
String
PAY_API
=
"https://api.mch.weixin.qq.com/pay/micropay"
;
//2)被扫支付查询API
public
static
String
ORDER_QUERY_API
=
"https://api.mch.weixin.qq.com/pay/orderquery"
;
//3)退款API
public
static
String
REFUND_API
=
"https://api.mch.weixin.qq.com/secapi/pay/refund"
;
//4)退款查询API
public
static
String
REFUND_QUERY_API
=
"https://api.mch.weixin.qq.com/pay/refundquery"
;
//5)撤销API
public
static
String
REVERSE_API
=
"https://api.mch.weixin.qq.com/secapi/pay/reverse"
;
//6)下载对账单API
public
static
String
DOWNLOAD_BILL_API
=
"https://api.mch.weixin.qq.com/pay/downloadbill"
;
//7) 统计上报API
public
static
String
REPORT_API
=
"https://api.mch.weixin.qq.com/payitil/report"
;
//8) 统一下单API
public
static
String
UNIFIED_ORDER_API
=
"https://api.mch.weixin.qq.com/pay/unifiedorder"
;
//9) 发送现金红包API
public
static
String
SEND_REDPACK_API
=
"https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack"
;
//10) 查询现金红包API
public
static
String
QUERY_REDPACK_API
=
"https://api.mch.weixin.qq.com/mmpaymkttransfers/gethbinfo"
;
//9) 企业付款API
public
static
String
TRANSFERS_API
=
"https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers"
;
//10) 查询企业付款API
public
static
String
GET_TRANSFERS_API
=
"https://api.mch.weixin.qq.com/mmpaymkttransfers/gettransferinfo"
;
@Value
(
"${wx.notify_url}"
)
private
String
notify_url
;
// 配置加载时间
private
Long
loadTime
=
new
Date
().
getTime
();
public
static
boolean
isUseThreadToDoReport
()
{
return
useThreadToDoReport
;
}
public
static
void
setUseThreadToDoReport
(
boolean
useThreadToDoReport
)
{
Configure
.
useThreadToDoReport
=
useThreadToDoReport
;
}
public
static
String
HttpsRequestClassName
=
"org.xxpay.service.channel.tencent.common.HttpsRequest"
;
public
static
void
setHttpsRequestClassName
(
String
name
){
HttpsRequestClassName
=
name
;
}
public
String
getAppID
()
{
return
appID
;
}
public
void
setAppID
(
String
appID
)
{
this
.
appID
=
appID
;
}
public
String
getCertLocalPath
()
{
return
certLocalPath
;
}
public
void
setCertLocalPath
(
String
certLocalPath
)
{
this
.
certLocalPath
=
certLocalPath
;
}
public
String
getCertPassword
()
{
return
certPassword
;
}
public
void
setCertPassword
(
String
certPassword
)
{
this
.
certPassword
=
certPassword
;
}
public
String
getIp
()
{
return
ip
;
}
public
void
setIp
(
String
ip
)
{
this
.
ip
=
ip
;
}
public
String
getKey
()
{
return
key
;
}
public
void
setKey
(
String
key
)
{
this
.
key
=
key
;
}
public
String
getMchID
()
{
return
mchID
;
}
public
void
setMchID
(
String
mchID
)
{
this
.
mchID
=
mchID
;
}
public
String
getDesc
()
{
return
desc
;
}
public
String
getNotify_url
()
{
return
notify_url
;
}
public
void
setNotify_url
(
String
notify_url
)
{
this
.
notify_url
=
notify_url
;
}
public
void
setDesc
(
String
desc
)
{
this
.
desc
=
desc
;
}
public
Long
getLoadTime
()
{
return
loadTime
;
}
public
void
setLoadTime
(
Long
loadTime
)
{
this
.
loadTime
=
loadTime
;
}
@Override
public
String
toString
()
{
return
"Configure{"
+
"key='"
+
key
+
'\''
+
", appID='"
+
appID
+
'\''
+
", certLocalPath='"
+
certLocalPath
+
'\''
+
", certPassword='"
+
certPassword
+
'\''
+
", desc='"
+
desc
+
'\''
+
", ip='"
+
ip
+
'\''
+
", loadTime="
+
loadTime
+
'}'
;
}
}
xxpay4spring-cloud/xxpay-service/src/main/java/org/xxpay/service/channel/tencent/common/HttpsRequest.java
deleted
100755 → 0
View file @
dd9d81f9
package
org.xxpay.service.channel.tencent.common
;
import
com.thoughtworks.xstream.XStream
;
import
com.thoughtworks.xstream.io.xml.DomDriver
;
import
com.thoughtworks.xstream.io.xml.XmlFriendlyNameCoder
;
import
org.xxpay.service.channel.tencent.service.IServiceRequest
;
import
org.apache.http.HttpEntity
;
import
org.apache.http.HttpResponse
;
import
org.apache.http.client.config.RequestConfig
;
import
org.apache.http.client.methods.HttpPost
;
import
org.apache.http.conn.ConnectTimeoutException
;
import
org.apache.http.conn.ConnectionPoolTimeoutException
;
import
org.apache.http.conn.ssl.SSLConnectionSocketFactory
;
import
org.apache.http.conn.ssl.SSLContexts
;
import
org.apache.http.entity.StringEntity
;
import
org.apache.http.impl.client.CloseableHttpClient
;
import
org.apache.http.impl.client.HttpClients
;
import
org.apache.http.util.EntityUtils
;
import
org.slf4j.LoggerFactory
;
import
javax.net.ssl.SSLContext
;
import
java.io.File
;
import
java.io.FileInputStream
;
import
java.io.IOException
;
import
java.net.SocketTimeoutException
;
import
java.security.*
;
import
java.security.cert.CertificateException
;
/**
* User: rizenguo
* Date: 2014/10/29
* Time: 14:36
*/
public
class
HttpsRequest
implements
IServiceRequest
{
public
interface
ResultListener
{
public
void
onConnectionPoolTimeoutError
();
}
private
static
Log
log
=
new
Log
(
LoggerFactory
.
getLogger
(
HttpsRequest
.
class
));
//表示请求器是否已经做了初始化工作
private
boolean
hasInit
=
false
;
//连接超时时间,默认10秒
private
int
socketTimeout
=
10000
;
//传输超时时间,默认30秒
private
int
connectTimeout
=
30000
;
//请求器的配置
private
RequestConfig
requestConfig
;
//HTTP请求器
private
CloseableHttpClient
httpClient
;
private
String
crtPath
;
private
String
crtPwd
;
public
HttpsRequest
()
throws
UnrecoverableKeyException
,
KeyManagementException
,
NoSuchAlgorithmException
,
KeyStoreException
,
IOException
{
//init();
}
public
void
init
()
throws
IOException
,
KeyStoreException
,
UnrecoverableKeyException
,
NoSuchAlgorithmException
,
KeyManagementException
{
KeyStore
keyStore
=
KeyStore
.
getInstance
(
"PKCS12"
);
FileInputStream
instream
=
new
FileInputStream
(
new
File
(
crtPath
));
//加载本地的证书进行https加密传输
try
{
keyStore
.
load
(
instream
,
crtPwd
.
toCharArray
());
//设置证书密码
}
catch
(
CertificateException
e
)
{
e
.
printStackTrace
();
}
catch
(
NoSuchAlgorithmException
e
)
{
e
.
printStackTrace
();
}
finally
{
instream
.
close
();
}
// Trust own CA and all self-signed certs
SSLContext
sslcontext
=
SSLContexts
.
custom
()
.
loadKeyMaterial
(
keyStore
,
crtPwd
.
toCharArray
())
.
build
();
// Allow TLSv1 protocol only
SSLConnectionSocketFactory
sslsf
=
new
SSLConnectionSocketFactory
(
sslcontext
,
new
String
[]{
"TLSv1"
},
null
,
SSLConnectionSocketFactory
.
BROWSER_COMPATIBLE_HOSTNAME_VERIFIER
);
httpClient
=
HttpClients
.
custom
()
.
setSSLSocketFactory
(
sslsf
)
.
build
();
//根据默认超时限制初始化requestConfig
requestConfig
=
RequestConfig
.
custom
().
setSocketTimeout
(
socketTimeout
).
setConnectTimeout
(
connectTimeout
).
build
();
hasInit
=
true
;
}
/**
* 通过Https往API post xml数据
*
* @param url API地址
* @param xmlObj 要提交的XML数据对象
* @return API回包的实际数据
* @throws IOException
* @throws KeyStoreException
* @throws UnrecoverableKeyException
* @throws NoSuchAlgorithmException
* @throws KeyManagementException
*/
public
String
sendPost
(
String
url
,
Object
xmlObj
)
throws
IOException
,
KeyStoreException
,
UnrecoverableKeyException
,
NoSuchAlgorithmException
,
KeyManagementException
{
if
(!
hasInit
)
{
init
();
}
String
result
=
null
;
HttpPost
httpPost
=
new
HttpPost
(
url
);
//解决XStream对出现双下划线的bug
XStream
xStreamForRequestPostData
=
new
XStream
(
new
DomDriver
(
"UTF-8"
,
new
XmlFriendlyNameCoder
(
"-_"
,
"_"
)));
//将要提交给API的数据对象转换成XML格式数据Post给API
String
postDataXML
=
xStreamForRequestPostData
.
toXML
(
xmlObj
);
Util
.
log
(
"API,POST过去的数据是:"
);
Util
.
log
(
postDataXML
);
//得指明使用UTF-8编码,否则到API服务器XML的中文不能被成功识别
StringEntity
postEntity
=
new
StringEntity
(
postDataXML
,
"UTF-8"
);
httpPost
.
addHeader
(
"Content-Type"
,
"text/xml"
);
httpPost
.
setEntity
(
postEntity
);
//设置请求器的配置
httpPost
.
setConfig
(
requestConfig
);
Util
.
log
(
"executing request"
+
httpPost
.
getRequestLine
());
try
{
HttpResponse
response
=
httpClient
.
execute
(
httpPost
);
HttpEntity
entity
=
response
.
getEntity
();
result
=
EntityUtils
.
toString
(
entity
,
"UTF-8"
);
}
catch
(
ConnectionPoolTimeoutException
e
)
{
log
.
e
(
"http get throw ConnectionPoolTimeoutException(wait time out)"
);
}
catch
(
ConnectTimeoutException
e
)
{
log
.
e
(
"http get throw ConnectTimeoutException"
);
}
catch
(
SocketTimeoutException
e
)
{
log
.
e
(
"http get throw SocketTimeoutException"
);
}
catch
(
Exception
e
)
{
log
.
e
(
"http get throw Exception"
);
}
finally
{
httpPost
.
abort
();
}
return
result
;
}
/**
* 设置连接超时时间
*
* @param socketTimeout 连接时长,默认10秒
*/
public
void
setSocketTimeout
(
int
socketTimeout
)
{
socketTimeout
=
socketTimeout
;
resetRequestConfig
();
}
/**
* 设置传输超时时间
*
* @param connectTimeout 传输时长,默认30秒
*/
public
void
setConnectTimeout
(
int
connectTimeout
)
{
connectTimeout
=
connectTimeout
;
resetRequestConfig
();
}
private
void
resetRequestConfig
(){
requestConfig
=
RequestConfig
.
custom
().
setSocketTimeout
(
socketTimeout
).
setConnectTimeout
(
connectTimeout
).
build
();
}
/**
* 允许商户自己做更高级更复杂的请求器配置
*
* @param requestConfig 设置HttpsRequest的请求器配置
*/
public
void
setRequestConfig
(
RequestConfig
requestConfig
)
{
requestConfig
=
requestConfig
;
}
public
void
setCrt
(
Configure
configure
)
{
this
.
crtPath
=
configure
.
getCertLocalPath
();
this
.
crtPwd
=
configure
.
getCertPassword
();
}
}
xxpay4spring-cloud/xxpay-service/src/main/java/org/xxpay/service/channel/tencent/common/Log.java
deleted
100755 → 0
View file @
dd9d81f9
package
org.xxpay.service.channel.tencent.common
;
import
org.slf4j.Logger
;
/**
* User: rizenguo
* Date: 2014/11/12
* Time: 14:32
*/
public
class
Log
{
public
static
final
String
LOG_TYPE_TRACE
=
"logTypeTrace"
;
public
static
final
String
LOG_TYPE_DEBUG
=
"logTypeDebug"
;
public
static
final
String
LOG_TYPE_INFO
=
"logTypeInfo"
;
public
static
final
String
LOG_TYPE_WARN
=
"logTypeWarn"
;
public
static
final
String
LOG_TYPE_ERROR
=
"logTypeError"
;
//打印日志
private
Logger
logger
;
public
Log
(
Logger
log
){
logger
=
log
;
}
public
void
t
(
String
s
){
logger
.
trace
(
s
);
}
public
void
d
(
String
s
){
logger
.
debug
(
s
);
}
public
void
i
(
String
s
){
logger
.
info
(
s
);
}
public
void
w
(
String
s
){
logger
.
warn
(
s
);
}
public
void
e
(
String
s
){
logger
.
error
(
s
);
}
public
void
log
(
String
type
,
String
s
){
if
(
type
.
equals
(
Log
.
LOG_TYPE_TRACE
)){
t
(
s
);
}
else
if
(
type
.
equals
(
Log
.
LOG_TYPE_DEBUG
)){
d
(
s
);
}
else
if
(
type
.
equals
(
Log
.
LOG_TYPE_INFO
)){
i
(
s
);
}
else
if
(
type
.
equals
(
Log
.
LOG_TYPE_WARN
)){
w
(
s
);
}
else
if
(
type
.
equals
(
Log
.
LOG_TYPE_ERROR
)){
e
(
s
);
}
}
}
xxpay4spring-cloud/xxpay-service/src/main/java/org/xxpay/service/channel/tencent/common/MD5.java
deleted
100755 → 0
View file @
dd9d81f9
package
org.xxpay.service.channel.tencent.common
;
import
java.security.MessageDigest
;
/**
* User: rizenguo
* Date: 2014/10/23
* Time: 15:43
*/
public
class
MD5
{
private
final
static
String
[]
hexDigits
=
{
"0"
,
"1"
,
"2"
,
"3"
,
"4"
,
"5"
,
"6"
,
"7"
,
"8"
,
"9"
,
"a"
,
"b"
,
"c"
,
"d"
,
"e"
,
"f"
};
/**
* 转换字节数组为16进制字串
* @param b 字节数组
* @return 16进制字串
*/
public
static
String
byteArrayToHexString
(
byte
[]
b
)
{
StringBuilder
resultSb
=
new
StringBuilder
();
for
(
byte
aB
:
b
)
{
resultSb
.
append
(
byteToHexString
(
aB
));
}
return
resultSb
.
toString
();
}
/**
* 转换byte到16进制
* @param b 要转换的byte
* @return 16进制格式
*/
private
static
String
byteToHexString
(
byte
b
)
{
int
n
=
b
;
if
(
n
<
0
)
{
n
=
256
+
n
;
}
int
d1
=
n
/
16
;
int
d2
=
n
%
16
;
return
hexDigits
[
d1
]
+
hexDigits
[
d2
];
}
/**
* MD5编码
* @param origin 原始字符串
* @return 经过MD5加密之后的结果
*/
public
static
String
MD5Encode
(
String
origin
)
{
String
resultString
=
null
;
try
{
resultString
=
origin
;
MessageDigest
md
=
MessageDigest
.
getInstance
(
"MD5"
);
resultString
=
byteArrayToHexString
(
md
.
digest
(
resultString
.
getBytes
()));
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
}
return
resultString
;
}
}
xxpay4spring-cloud/xxpay-service/src/main/java/org/xxpay/service/channel/tencent/common/RandomStringGenerator.java
deleted
100755 → 0
View file @
dd9d81f9
package
org.xxpay.service.channel.tencent.common
;
import
java.util.Random
;
/**
* User: rizenguo
* Date: 2014/10/29
* Time: 14:18
*/
public
class
RandomStringGenerator
{
/**
* 获取一定长度的随机字符串
* @param length 指定字符串长度
* @return 一定长度的字符串
*/
public
static
String
getRandomStringByLength
(
int
length
)
{
String
base
=
"abcdefghijklmnopqrstuvwxyz0123456789"
;
Random
random
=
new
Random
();
StringBuffer
sb
=
new
StringBuffer
();
for
(
int
i
=
0
;
i
<
length
;
i
++)
{
int
number
=
random
.
nextInt
(
base
.
length
());
sb
.
append
(
base
.
charAt
(
number
));
}
return
sb
.
toString
();
}
}
xxpay4spring-cloud/xxpay-service/src/main/java/org/xxpay/service/channel/tencent/common/Signature.java
deleted
100755 → 0
View file @
dd9d81f9
package
org.xxpay.service.channel.tencent.common
;
import
org.xml.sax.SAXException
;
import
javax.xml.parsers.ParserConfigurationException
;
import
java.io.IOException
;
import
java.lang.reflect.Field
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.Map
;
/**
* User: rizenguo
* Date: 2014/10/29
* Time: 15:23
*/
public
class
Signature
{
/**
* 签名算法
* @param o 要参与签名的数据对象
* @return 签名
* @throws IllegalAccessException
*/
public
static
String
getSign
(
Object
o
,
String
key
)
throws
IllegalAccessException
{
ArrayList
<
String
>
list
=
new
ArrayList
<
String
>();
Class
cls
=
o
.
getClass
();
Field
[]
fields
=
cls
.
getDeclaredFields
();
for
(
Field
f
:
fields
)
{
f
.
setAccessible
(
true
);
if
(
f
.
get
(
o
)
!=
null
&&
f
.
get
(
o
)
!=
""
)
{
list
.
add
(
f
.
getName
()
+
"="
+
f
.
get
(
o
)
+
"&"
);
}
}
int
size
=
list
.
size
();
String
[]
arrayToSort
=
list
.
toArray
(
new
String
[
size
]);
Arrays
.
sort
(
arrayToSort
,
String
.
CASE_INSENSITIVE_ORDER
);
StringBuilder
sb
=
new
StringBuilder
();
for
(
int
i
=
0
;
i
<
size
;
i
++)
{
sb
.
append
(
arrayToSort
[
i
]);
}
String
result
=
sb
.
toString
();
result
+=
"key="
+
key
;
Util
.
log
(
"Sign Before MD5:"
+
result
);
result
=
MD5
.
MD5Encode
(
result
).
toUpperCase
();
Util
.
log
(
"Sign Result:"
+
result
);
return
result
;
}
public
static
String
getSign
(
Map
<
String
,
Object
>
map
,
String
key
){
ArrayList
<
String
>
list
=
new
ArrayList
<
String
>();
for
(
Map
.
Entry
<
String
,
Object
>
entry:
map
.
entrySet
()){
if
(!
""
.
equals
(
entry
.
getValue
())){
list
.
add
(
entry
.
getKey
()
+
"="
+
entry
.
getValue
()
+
"&"
);
}
}
int
size
=
list
.
size
();
String
[]
arrayToSort
=
list
.
toArray
(
new
String
[
size
]);
Arrays
.
sort
(
arrayToSort
,
String
.
CASE_INSENSITIVE_ORDER
);
StringBuilder
sb
=
new
StringBuilder
();
for
(
int
i
=
0
;
i
<
size
;
i
++)
{
sb
.
append
(
arrayToSort
[
i
]);
}
String
result
=
sb
.
toString
();
result
+=
"key="
+
key
;
//Util.log("Sign Before MD5:" + result);
result
=
MD5
.
MD5Encode
(
result
).
toUpperCase
();
//Util.log("Sign Result:" + result);
return
result
;
}
/**
* 从API返回的XML数据里面重新计算一次签名
* @param responseString API返回的XML数据
* @return 新鲜出炉的签名
* @throws ParserConfigurationException
* @throws IOException
* @throws SAXException
*/
public
static
String
getSignFromResponseString
(
String
responseString
,
String
key
)
throws
IOException
,
SAXException
,
ParserConfigurationException
{
Map
<
String
,
Object
>
map
=
XMLParser
.
getMapFromXML
(
responseString
);
//清掉返回数据对象里面的Sign数据(不能把这个数据也加进去进行签名),然后用签名算法进行签名
map
.
put
(
"sign"
,
""
);
//将API返回的数据根据用签名算法进行计算新的签名,用来跟API返回的签名进行比较
return
Signature
.
getSign
(
map
,
key
);
}
/**
* 检验API返回的数据里面的签名是否合法,避免数据在传输的过程中被第三方篡改
* @param responseString API返回的XML数据字符串
* @return API签名是否合法
* @throws ParserConfigurationException
* @throws IOException
* @throws SAXException
*/
public
static
boolean
checkIsSignValidFromResponseString
(
String
responseString
,
String
key
)
throws
ParserConfigurationException
,
IOException
,
SAXException
{
Map
<
String
,
Object
>
map
=
XMLParser
.
getMapFromXML
(
responseString
);
Util
.
log
(
map
.
toString
());
String
signFromAPIResponse
=
map
.
get
(
"sign"
).
toString
();
if
(
signFromAPIResponse
==
""
||
signFromAPIResponse
==
null
){
Util
.
log
(
"API返回的数据签名数据不存在,有可能被第三方篡改!!!"
);
return
false
;
}
Util
.
log
(
"服务器回包里面的签名是:"
+
signFromAPIResponse
);
//清掉返回数据对象里面的Sign数据(不能把这个数据也加进去进行签名),然后用签名算法进行签名
map
.
put
(
"sign"
,
""
);
//将API返回的数据根据用签名算法进行计算新的签名,用来跟API返回的签名进行比较
String
signForAPIResponse
=
Signature
.
getSign
(
map
,
key
);
if
(!
signForAPIResponse
.
equals
(
signFromAPIResponse
)){
//签名验不过,表示这个API返回的数据有可能已经被篡改了
Util
.
log
(
"API返回的数据签名验证不通过,有可能被第三方篡改!!!"
);
return
false
;
}
Util
.
log
(
"恭喜,API返回的数据签名验证通过!!!"
);
return
true
;
}
}
xxpay4spring-cloud/xxpay-service/src/main/java/org/xxpay/service/channel/tencent/common/Util.java
deleted
100755 → 0
View file @
dd9d81f9
package
org.xxpay.service.channel.tencent.common
;
import
com.thoughtworks.xstream.XStream
;
import
com.thoughtworks.xstream.io.xml.DomDriver
;
import
com.thoughtworks.xstream.io.xml.XmlFriendlyNameCoder
;
import
org.slf4j.LoggerFactory
;
import
java.io.ByteArrayInputStream
;
import
java.io.ByteArrayOutputStream
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.lang.reflect.Field
;
import
java.util.Map
;
/**
* User: rizenguo
* Date: 2014/10/23
* Time: 14:59
*/
public
class
Util
{
//打log用
private
static
Log
logger
=
new
Log
(
LoggerFactory
.
getLogger
(
Util
.
class
));
/**
* 通过反射的方式遍历对象的属性和属性值,方便调试
*
* @param o 要遍历的对象
* @throws Exception
*/
public
static
void
reflect
(
Object
o
)
throws
Exception
{
Class
cls
=
o
.
getClass
();
Field
[]
fields
=
cls
.
getDeclaredFields
();
for
(
int
i
=
0
;
i
<
fields
.
length
;
i
++)
{
Field
f
=
fields
[
i
];
f
.
setAccessible
(
true
);
Util
.
log
(
f
.
getName
()
+
" -> "
+
f
.
get
(
o
));
}
}
public
static
byte
[]
readInput
(
InputStream
in
)
throws
IOException
{
ByteArrayOutputStream
out
=
new
ByteArrayOutputStream
();
int
len
=
0
;
byte
[]
buffer
=
new
byte
[
1024
];
while
((
len
=
in
.
read
(
buffer
))
>
0
)
{
out
.
write
(
buffer
,
0
,
len
);
}
out
.
close
();
in
.
close
();
return
out
.
toByteArray
();
}
public
static
String
inputStreamToString
(
InputStream
is
)
throws
IOException
{
ByteArrayOutputStream
baos
=
new
ByteArrayOutputStream
();
int
i
;
while
((
i
=
is
.
read
())
!=
-
1
)
{
baos
.
write
(
i
);
}
return
baos
.
toString
();
}
public
static
InputStream
getStringStream
(
String
sInputString
)
{
ByteArrayInputStream
tInputStringStream
=
null
;
if
(
sInputString
!=
null
&&
!
sInputString
.
trim
().
equals
(
""
))
{
tInputStringStream
=
new
ByteArrayInputStream
(
sInputString
.
getBytes
());
}
return
tInputStringStream
;
}
public
static
Object
getObjectFromXML
(
String
xml
,
Class
tClass
)
{
//将从API返回的XML数据映射到Java对象
XStream
xStreamForResponseData
=
new
XStream
();
xStreamForResponseData
.
alias
(
"xml"
,
tClass
);
xStreamForResponseData
.
ignoreUnknownElements
();
//暂时忽略掉一些新增的字段
return
xStreamForResponseData
.
fromXML
(
xml
);
}
public
static
String
getStringFromMap
(
Map
<
String
,
Object
>
map
,
String
key
,
String
defaultValue
)
{
if
(
key
==
""
||
key
==
null
)
{
return
defaultValue
;
}
String
result
=
(
String
)
map
.
get
(
key
);
if
(
result
==
null
)
{
return
defaultValue
;
}
else
{
return
result
;
}
}
public
static
int
getIntFromMap
(
Map
<
String
,
Object
>
map
,
String
key
)
{
if
(
key
==
""
||
key
==
null
)
{
return
0
;
}
if
(
map
.
get
(
key
)
==
null
)
{
return
0
;
}
return
Integer
.
parseInt
((
String
)
map
.
get
(
key
));
}
/**
* 打log接口
* @param log 要打印的log字符串
* @return 返回log
*/
public
static
String
log
(
Object
log
){
logger
.
i
(
log
.
toString
());
//System.out.println(log);
return
log
.
toString
();
}
/**
* 读取本地的xml数据,一般用来自测用
* @param localPath 本地xml文件路径
* @return 读到的xml字符串
*/
public
static
String
getLocalXMLString
(
String
localPath
)
throws
IOException
{
return
Util
.
inputStreamToString
(
Util
.
class
.
getResourceAsStream
(
localPath
));
}
public
static
String
objectToXML
(
Object
o
){
//解决XStream对出现双下划线的bug
XStream
xStreamForRequestPostData
=
new
XStream
(
new
DomDriver
(
"UTF-8"
,
new
XmlFriendlyNameCoder
(
"-_"
,
"_"
)));
//将要提交给API的数据对象转换成XML格式数据Post给API
return
xStreamForRequestPostData
.
toXML
(
o
);
}
}
xxpay4spring-cloud/xxpay-service/src/main/java/org/xxpay/service/channel/tencent/common/XMLParser.java
deleted
100755 → 0
View file @
dd9d81f9
package
org.xxpay.service.channel.tencent.common
;
import
org.xxpay.service.channel.tencent.protocol.refund_query_protocol.RefundOrderData
;
import
org.w3c.dom.Document
;
import
org.w3c.dom.Element
;
import
org.w3c.dom.Node
;
import
org.w3c.dom.NodeList
;
import
org.xml.sax.SAXException
;
import
javax.xml.parsers.DocumentBuilder
;
import
javax.xml.parsers.DocumentBuilderFactory
;
import
javax.xml.parsers.ParserConfigurationException
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.util.ArrayList
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.Map
;
/**
* User: rizenguo
* Date: 2014/11/1
* Time: 14:06
*/
public
class
XMLParser
{
/**
* 从RefunQueryResponseString里面解析出退款订单数据
* @param refundQueryResponseString RefundQuery API返回的数据
* @return 因为订单数据有可能是多个,所以返回一个列表
*/
public
static
List
<
RefundOrderData
>
getRefundOrderList
(
String
refundQueryResponseString
)
throws
IOException
,
SAXException
,
ParserConfigurationException
{
List
list
=
new
ArrayList
();
Map
<
String
,
Object
>
map
=
XMLParser
.
getMapFromXML
(
refundQueryResponseString
);
int
count
=
Integer
.
parseInt
((
String
)
map
.
get
(
"refund_count"
));
Util
.
log
(
"count:"
+
count
);
if
(
count
<
1
){
return
list
;
}
RefundOrderData
refundOrderData
;
for
(
int
i
=
0
;
i
<
count
;
i
++){
refundOrderData
=
new
RefundOrderData
();
refundOrderData
.
setOutRefundNo
(
Util
.
getStringFromMap
(
map
,
"out_refund_no_"
+
i
,
""
));
refundOrderData
.
setRefundID
(
Util
.
getStringFromMap
(
map
,
"refund_id_"
+
i
,
""
));
refundOrderData
.
setRefundChannel
(
Util
.
getStringFromMap
(
map
,
"refund_channel_"
+
i
,
""
));
refundOrderData
.
setRefundFee
(
Util
.
getIntFromMap
(
map
,
"refund_fee_"
+
i
));
refundOrderData
.
setCouponRefundFee
(
Util
.
getIntFromMap
(
map
,
"coupon_refund_fee_"
+
i
));
refundOrderData
.
setRefundStatus
(
Util
.
getStringFromMap
(
map
,
"refund_status_"
+
i
,
""
));
list
.
add
(
refundOrderData
);
}
return
list
;
}
public
static
Map
<
String
,
Object
>
getMapFromXML
(
String
xmlString
)
throws
ParserConfigurationException
,
IOException
,
SAXException
{
//这里用Dom的方式解析回包的最主要目的是防止API新增回包字段
DocumentBuilderFactory
factory
=
DocumentBuilderFactory
.
newInstance
();
DocumentBuilder
builder
=
factory
.
newDocumentBuilder
();
InputStream
is
=
Util
.
getStringStream
(
xmlString
);
Document
document
=
builder
.
parse
(
is
);
//获取到document里面的全部结点
NodeList
allNodes
=
document
.
getFirstChild
().
getChildNodes
();
Node
node
;
Map
<
String
,
Object
>
map
=
new
HashMap
<
String
,
Object
>();
int
i
=
0
;
while
(
i
<
allNodes
.
getLength
())
{
node
=
allNodes
.
item
(
i
);
if
(
node
instanceof
Element
){
map
.
put
(
node
.
getNodeName
(),
node
.
getTextContent
());
}
i
++;
}
return
map
;
}
}
xxpay4spring-cloud/xxpay-service/src/main/java/org/xxpay/service/channel/tencent/common/report/ReportRunable.java
deleted
100755 → 0
View file @
dd9d81f9
package
org.xxpay.service.channel.tencent.common.report
;
import
org.xxpay.service.channel.tencent.common.report.service.ReportService
;
import
java.io.IOException
;
import
java.security.KeyManagementException
;
import
java.security.KeyStoreException
;
import
java.security.NoSuchAlgorithmException
;
import
java.security.UnrecoverableKeyException
;
/**
* User: rizenguo
* Date: 2014/12/3
* Time: 16:34
*/
public
class
ReportRunable
implements
Runnable
{
private
ReportService
reportService
;
ReportRunable
(
ReportService
rs
){
reportService
=
rs
;
}
@Override
public
void
run
()
{
try
{
reportService
.
request
();
}
catch
(
UnrecoverableKeyException
e
)
{
e
.
printStackTrace
();
}
catch
(
KeyManagementException
e
)
{
e
.
printStackTrace
();
}
catch
(
NoSuchAlgorithmException
e
)
{
e
.
printStackTrace
();
}
catch
(
KeyStoreException
e
)
{
e
.
printStackTrace
();
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
}
}
xxpay4spring-cloud/xxpay-service/src/main/java/org/xxpay/service/channel/tencent/common/report/Reporter.java
deleted
100755 → 0
View file @
dd9d81f9
package
org.xxpay.service.channel.tencent.common.report
;
import
org.xxpay.service.channel.tencent.common.report.protocol.ReportReqData
;
import
org.xxpay.service.channel.tencent.common.report.service.ReportService
;
/**
* User: rizenguo
* Date: 2014/12/3
* Time: 11:42
*/
public
class
Reporter
{
private
ReportRunable
r
;
private
Thread
t
;
private
ReportService
rs
;
/**
* 请求统计上报API
* @param reportReqData 这个数据对象里面包含了API要求提交的各种数据字段
*/
public
Reporter
(
ReportReqData
reportReqData
){
rs
=
new
ReportService
(
reportReqData
);
}
public
void
run
(){
r
=
new
ReportRunable
(
rs
);
t
=
new
Thread
(
r
);
t
.
setDaemon
(
true
);
//后台线程
t
.
start
();
}
}
xxpay4spring-cloud/xxpay-service/src/main/java/org/xxpay/service/channel/tencent/common/report/ReporterFactory.java
deleted
100755 → 0
View file @
dd9d81f9
package
org.xxpay.service.channel.tencent.common.report
;
import
org.xxpay.service.channel.tencent.common.report.protocol.ReportReqData
;
/**
* User: rizenguo
* Date: 2014/12/3
* Time: 17:44
*/
public
class
ReporterFactory
{
/**
* 请求统计上报API
* @param reportReqData 这个数据对象里面包含了API要求提交的各种数据字段
* @return 返回一个Reporter
*/
public
static
Reporter
getReporter
(
ReportReqData
reportReqData
){
return
new
Reporter
(
reportReqData
);
}
}
xxpay4spring-cloud/xxpay-service/src/main/java/org/xxpay/service/channel/tencent/common/report/protocol/ReportReqData.java
deleted
100755 → 0
View file @
dd9d81f9
package
org.xxpay.service.channel.tencent.common.report.protocol
;
import
org.xxpay.service.channel.tencent.common.Configure
;
import
org.xxpay.service.channel.tencent.common.RandomStringGenerator
;
import
org.xxpay.service.channel.tencent.common.Signature
;
import
java.lang.reflect.Field
;
import
java.util.HashMap
;
import
java.util.Map
;
/**
* User: rizenguo
* Date: 2014/11/12
* Time: 17:05
*/
public
class
ReportReqData
{
//每个字段具体的意思请查看API文档
private
String
appid
;
private
String
mch_id
;
private
String
sub_mch_id
;
private
String
device_info
;
private
String
nonce_str
;
private
String
sign
;
//上报对应的接口的完整URL,类似:https://api.mch.weixin.qq.com/pay/unifiedorder
private
String
interface_url
;
//接口耗时情况,单位为毫秒
private
int
execute_time_cost
;
//发起接口调用时的机器IP
private
String
user_ip
;
//上报该统计请求时的系统时间,格式为yyyyMMddHHmmss
private
String
time
;
//以下是API接口返回的对应数据
private
String
return_code
;
private
String
return_msg
;
private
String
result_code
;
private
String
err_code
;
private
String
err_code_des
;
private
String
out_trade_no
;
/**
* 请求统计上报API
* @param deviceInfo 微信支付分配的终端设备号,商户自定义
* @param interfaceUrl 上报对应的接口的完整URL,类似: https://api.mch.weixin.qq.com/pay/unifiedorder
* @param executeTimeCost 接口耗时情况,单位为毫秒
* @param returnCode API返回的对应字段
* @param returnMsg API返回的对应字段
* @param resultCode API返回的对应字段
* @param errCode API返回的对应字段
* @param errCodeDes API返回的对应字段
* @param outTradeNo API返回的对应字段
* @param userIp 发起接口调用时的机器IP
*/
public
ReportReqData
(
Configure
configure
,
String
deviceInfo
,
String
interfaceUrl
,
int
executeTimeCost
,
String
returnCode
,
String
returnMsg
,
String
resultCode
,
String
errCode
,
String
errCodeDes
,
String
outTradeNo
,
String
userIp
){
//微信分配的公众号ID(开通公众号之后可以获取到)
setAppid
(
configure
.
getAppID
());
//微信支付分配的商户号ID(开通公众号的微信支付功能之后可以获取到)
setMch_id
(
configure
.
getMchID
());
//商户系统自己生成的唯一的订单号
setOut_trade_no
(
outTradeNo
);
setDevice_info
(
deviceInfo
);
setInterface_url
(
interfaceUrl
);
setExecute_time_cost
(
executeTimeCost
);
setReturn_code
(
returnCode
);
setReturn_msg
(
returnMsg
);
setResult_code
(
resultCode
);
setErr_code
(
errCode
);
setErr_code_des
(
errCodeDes
);
setUser_ip
(
userIp
);
setTime
(
getTime
());
//随机字符串,不长于32 位
setNonce_str
(
RandomStringGenerator
.
getRandomStringByLength
(
32
));
//根据API给的签名规则进行签名
String
sign
=
Signature
.
getSign
(
toMap
(),
configure
.
getKey
());
setSign
(
sign
);
//把签名数据设置到Sign这个属性中
}
public
String
getAppid
()
{
return
appid
;
}
public
void
setAppid
(
String
appid
)
{
this
.
appid
=
appid
;
}
public
String
getMch_id
()
{
return
mch_id
;
}
public
void
setMch_id
(
String
mch_id
)
{
this
.
mch_id
=
mch_id
;
}
public
String
getDevice_info
()
{
return
device_info
;
}
public
void
setDevice_info
(
String
device_info
)
{
this
.
device_info
=
device_info
;
}
public
String
getNonce_str
()
{
return
nonce_str
;
}
public
void
setNonce_str
(
String
nonce_str
)
{
this
.
nonce_str
=
nonce_str
;
}
public
String
getSign
()
{
return
sign
;
}
public
void
setSign
(
String
sign
)
{
this
.
sign
=
sign
;
}
public
String
getInterface_url
()
{
return
interface_url
;
}
public
void
setInterface_url
(
String
interface_url
)
{
this
.
interface_url
=
interface_url
;
}
public
int
getExecute_time_cost
()
{
return
execute_time_cost
;
}
public
void
setExecute_time_cost
(
int
execute_time
)
{
this
.
execute_time_cost
=
execute_time
;
}
public
String
getReturn_code
()
{
return
return_code
;
}
public
void
setReturn_code
(
String
return_code
)
{
this
.
return_code
=
return_code
;
}
public
String
getReturn_msg
()
{
return
return_msg
;
}
public
void
setReturn_msg
(
String
return_msg
)
{
this
.
return_msg
=
return_msg
;
}
public
String
getResult_code
()
{
return
result_code
;
}
public
void
setResult_code
(
String
result_code
)
{
this
.
result_code
=
result_code
;
}
public
String
getErr_code
()
{
return
err_code
;
}
public
void
setErr_code
(
String
err_code
)
{
this
.
err_code
=
err_code
;
}
public
String
getErr_code_des
()
{
return
err_code_des
;
}
public
void
setErr_code_des
(
String
err_code_des
)
{
this
.
err_code_des
=
err_code_des
;
}
public
String
getOut_trade_no
()
{
return
out_trade_no
;
}
public
void
setOut_trade_no
(
String
out_trade_no
)
{
this
.
out_trade_no
=
out_trade_no
;
}
public
String
getUser_ip
()
{
return
user_ip
;
}
public
void
setUser_ip
(
String
user_ip
)
{
this
.
user_ip
=
user_ip
;
}
public
String
getTime
()
{
return
time
;
}
public
void
setTime
(
String
time
)
{
this
.
time
=
time
;
}
public
Map
<
String
,
Object
>
toMap
(){
Map
<
String
,
Object
>
map
=
new
HashMap
<
String
,
Object
>();
Field
[]
fields
=
this
.
getClass
().
getDeclaredFields
();
for
(
Field
field
:
fields
)
{
Object
obj
;
try
{
obj
=
field
.
get
(
this
);
if
(
obj
!=
null
){
map
.
put
(
field
.
getName
(),
obj
);
}
}
catch
(
IllegalArgumentException
e
)
{
e
.
printStackTrace
();
}
catch
(
IllegalAccessException
e
)
{
e
.
printStackTrace
();
}
}
return
map
;
}
}
Prev
1
2
3
4
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