记得上下班打卡 | git大法好,push需谨慎
Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
L
liquidnet-bus-v1
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
董敬伟
liquidnet-bus-v1
Commits
4bb7fbf3
Commit
4bb7fbf3
authored
Nov 09, 2021
by
anjiabin
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
提交unionpay代码
parent
cb347737
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
382 additions
and
37 deletions
+382
-37
liquidnet-service-dragon-dev.yml
...-config/liquidnet-config/liquidnet-service-dragon-dev.yml
+2
-1
liquidnet-service-dragon-test.yml
...config/liquidnet-config/liquidnet-service-dragon-test.yml
+3
-1
liquidnet-service-dragon.yml
...-bus-config/liquidnet-config/liquidnet-service-dragon.yml
+8
-12
AcpService.java
...idnet/service/dragon/channel/unionpay/sdk/AcpService.java
+7
-4
QrcService.java
...idnet/service/dragon/channel/unionpay/sdk/QrcService.java
+24
-18
SDKConfig.java
...uidnet/service/dragon/channel/unionpay/sdk/SDKConfig.java
+1
-1
DemoBase.java
.../src/test/java/com/liquidnet/service/scpsdk/DemoBase.java
+216
-0
TestAcpService.java
...est/java/com/liquidnet/service/scpsdk/TestAcpService.java
+121
-0
No files found.
liquidnet-bus-config/liquidnet-config/liquidnet-service-dragon-dev.yml
View file @
4bb7fbf3
...
@@ -35,5 +35,6 @@ liquidnet:
...
@@ -35,5 +35,6 @@ liquidnet:
appId
:
wx3498304dda39c5a1
appId
:
wx3498304dda39c5a1
partnerKey
:
itIuO65O9yKmemOu3S8g1S4orqvCGwXK
partnerKey
:
itIuO65O9yKmemOu3S8g1S4orqvCGwXK
unionpay
:
unionpay
:
gateway-url
:
https://gateway.test.95516.comm
gateway-url
:
https://gateway.test.95516.com
certs-path
:
/Users/anjiabin/certs
liquidnet-bus-config/liquidnet-config/liquidnet-service-dragon-test.yml
View file @
4bb7fbf3
...
@@ -33,4 +33,6 @@ liquidnet:
...
@@ -33,4 +33,6 @@ liquidnet:
gataway-url
:
https://openapi.alipay.com/gateway.do
gataway-url
:
https://openapi.alipay.com/gateway.do
merchantId
:
1551961491
merchantId
:
1551961491
appId
:
wx3498304dda39c5a1
appId
:
wx3498304dda39c5a1
partnerKey
:
itIuO65O9yKmemOu3S8g1S4orqvCGwXK
partnerKey
:
itIuO65O9yKmemOu3S8g1S4orqvCGwXK
\ No newline at end of file
unionpay
:
gateway-url
:
https://gateway.test.95516.com
\ No newline at end of file
liquidnet-bus-config/liquidnet-config/liquidnet-service-dragon.yml
View file @
4bb7fbf3
...
@@ -197,26 +197,22 @@ acpsdk:
...
@@ -197,26 +197,22 @@ acpsdk:
# 多证书的情况证书路径为代码指定,可不对此块做配置。
# 多证书的情况证书路径为代码指定,可不对此块做配置。
# 签名证书路径,必须使用绝对路径,如果不想使用绝对路径,可以自行实现相对路径获取证书的方法;测试证书所有商户共用开发包中的测试签名证书,生产环境请从cfca下载得到。
# 签名证书路径,必须使用绝对路径,如果不想使用绝对路径,可以自行实现相对路径获取证书的方法;测试证书所有商户共用开发包中的测试签名证书,生产环境请从cfca下载得到。
# windows样例:
# windows样例:
signCert
:
signCertPath
:
${liquidnet.dragon.unionpay.certs-path}/acp_test_sign.pfx
path
:
D:/certs/acp_test_sign.pfx
# 签名证书密码,测试环境固定000000,生产环境请修改为从cfca下载的正式证书的密码,正式环境证书密码位数需小于等于6位,否则上传到商户服务网站会失败
# 签名证书密码,测试环境固定000000,生产环境请修改为从cfca下载的正式证书的密码,正式环境证书密码位数需小于等于6位,否则上传到商户服务网站会失败
pwd
:
000000
signCertPwd
:
'
000000'
# 签名证书类型,固定不需要修改
# 签名证书类型,固定不需要修改
t
ype
:
PKCS12
signCertT
ype
:
PKCS12
##########################加密证书配置################################
##########################加密证书配置################################
# 敏感信息加密证书路径(商户号开通了商户对敏感信息加密的权限,需要对 卡号accNo,pin和phoneNo,cvn2,expired加密(如果这些上送的话),对敏感信息加密使用)
# 敏感信息加密证书路径(商户号开通了商户对敏感信息加密的权限,需要对 卡号accNo,pin和phoneNo,cvn2,expired加密(如果这些上送的话),对敏感信息加密使用)
encryptCert
:
encryptCertPath
:
${liquidnet.dragon.unionpay.certs-path}/acp_test_enc.cer
path
:
d:/certs/acp_test_enc.cer
##########################验签证书配置################################
##########################验签证书配置################################
# 验签中级证书路径(银联提供)
# 验签中级证书路径(银联提供)
middleCert
:
middleCertPath
:
${liquidnet.dragon.unionpay.certs-path}/acp_test_middle.cer
path
:
D:/certs/acp_test_middle.cer
# 验签根证书路径(银联提供)
# 验签根证书路径(银联提供)
rootCert
:
rootCertPath
:
${liquidnet.dragon.unionpay.certs-path}/acp_test_root.cer
path
:
D:/certs/acp_test_root.cer
# -----------------------------------------------------------
# -----------------------------------------------------------
# -----------------------------------------------------------
# -----------------------------------------------------------
\ No newline at end of file
liquidnet-bus-service/liquidnet-service-dragon/liquidnet-service-dragon-impl/src/main/java/com/liquidnet/service/dragon/channel/unionpay/sdk/AcpService.java
View file @
4bb7fbf3
...
@@ -30,6 +30,9 @@ public class AcpService {
...
@@ -30,6 +30,9 @@ public class AcpService {
@Autowired
@Autowired
private
CertUtil
certUtil
;
private
CertUtil
certUtil
;
@Autowired
private
SDKUtil
sdkUtil
;
/**
/**
* 请求报文签名(使用配置文件中配置的私钥证书或者对称密钥签名)<br>
* 请求报文签名(使用配置文件中配置的私钥证书或者对称密钥签名)<br>
* 功能:对请求报文进行签名,并计算赋值certid,signature字段并返回<br>
* 功能:对请求报文进行签名,并计算赋值certid,signature字段并返回<br>
...
@@ -96,13 +99,13 @@ public class AcpService {
...
@@ -96,13 +99,13 @@ public class AcpService {
if
(
VERSION_5_0_1
.
equals
(
version
)
||
VERSION_5_0_0
.
equals
(
version
)){
if
(
VERSION_5_0_1
.
equals
(
version
)
||
VERSION_5_0_0
.
equals
(
version
)){
if
(
SIGNMETHOD_RSA
.
equals
(
signMethod
))
{
if
(
SIGNMETHOD_RSA
.
equals
(
signMethod
))
{
data
.
put
(
SDKConstants
.
param_certId
,
certUtil
.
getCertIdByKeyStoreMap
(
certPath
,
certPwd
));
data
.
put
(
SDKConstants
.
param_certId
,
certUtil
.
getCertIdByKeyStoreMap
(
certPath
,
certPwd
));
data
.
put
(
SDKConstants
.
param_signature
,
SDK
Util
.
signRsa
(
data
,
certPath
,
certPwd
,
encoding
));
data
.
put
(
SDKConstants
.
param_signature
,
sdk
Util
.
signRsa
(
data
,
certPath
,
certPwd
,
encoding
));
return
data
;
return
data
;
}
}
}
else
if
(
VERSION_5_1_0
.
equals
(
version
)){
}
else
if
(
VERSION_5_1_0
.
equals
(
version
)){
if
(
SIGNMETHOD_RSA
.
equals
(
signMethod
))
{
if
(
SIGNMETHOD_RSA
.
equals
(
signMethod
))
{
data
.
put
(
SDKConstants
.
param_certId
,
certUtil
.
getCertIdByKeyStoreMap
(
certPath
,
certPwd
));
data
.
put
(
SDKConstants
.
param_certId
,
certUtil
.
getCertIdByKeyStoreMap
(
certPath
,
certPwd
));
data
.
put
(
SDKConstants
.
param_signature
,
SDK
Util
.
signRsa2
(
data
,
certPath
,
certPwd
,
encoding
));
data
.
put
(
SDKConstants
.
param_signature
,
sdk
Util
.
signRsa2
(
data
,
certPath
,
certPwd
,
encoding
));
return
data
;
return
data
;
}
}
}
}
...
@@ -783,8 +786,8 @@ public class AcpService {
...
@@ -783,8 +786,8 @@ public class AcpService {
* 更新成功则返回1,无更新返回0,失败异常返回-1<br>
* 更新成功则返回1,无更新返回0,失败异常返回-1<br>
* @return
* @return
*/
*/
public
static
int
updateEncryptCert
(
Map
<
String
,
String
>
data
)
{
public
int
updateEncryptCert
(
Map
<
String
,
String
>
data
)
{
return
SDK
Util
.
updateEncryptCert
(
data
.
get
(
SDKConstants
.
param_encryptPubKeyCert
),
data
.
get
(
SDKConstants
.
param_certType
));
return
sdk
Util
.
updateEncryptCert
(
data
.
get
(
SDKConstants
.
param_encryptPubKeyCert
),
data
.
get
(
SDKConstants
.
param_certType
));
}
}
/**
/**
...
...
liquidnet-bus-service/liquidnet-service-dragon/liquidnet-service-dragon-impl/src/main/java/com/liquidnet/service/dragon/channel/unionpay/sdk/QrcService.java
View file @
4bb7fbf3
...
@@ -25,6 +25,12 @@ public class QrcService {
...
@@ -25,6 +25,12 @@ public class QrcService {
@Autowired
@Autowired
private
CertUtil
certUtil
;
private
CertUtil
certUtil
;
@Autowired
private
SDKUtil
sdkUtil
;
@Autowired
private
AcpService
acpService
;
/**
/**
* 请求报文签名(使用配置文件中配置的私钥证书或者对称密钥签名)<br>
* 请求报文签名(使用配置文件中配置的私钥证书或者对称密钥签名)<br>
* 功能:对请求报文进行签名,并计算赋值certid,signature字段并返回<br>
* 功能:对请求报文进行签名,并计算赋值certid,signature字段并返回<br>
...
@@ -73,11 +79,11 @@ public class QrcService {
...
@@ -73,11 +79,11 @@ public class QrcService {
||
"0420000903"
.
equals
(
reqType
)
||
"0420000903"
.
equals
(
reqType
)
||
"0410000903"
.
equals
(
reqType
))
{
||
"0410000903"
.
equals
(
reqType
))
{
data
.
put
(
SDKConstants
.
param_certId
,
certUtil
.
getCertIdByKeyStoreMap
(
certPath
,
certPwd
));
data
.
put
(
SDKConstants
.
param_certId
,
certUtil
.
getCertIdByKeyStoreMap
(
certPath
,
certPwd
));
data
.
put
(
SDKConstants
.
param_signature
,
SDK
Util
.
signRsa2
(
data
,
certPath
,
certPwd
,
encoding
));
data
.
put
(
SDKConstants
.
param_signature
,
sdk
Util
.
signRsa2
(
data
,
certPath
,
certPwd
,
encoding
));
return
data
;
return
data
;
}
else
if
(
QRC_SIGNTYPE_SHA1WITHRSA
.
equals
(
signType
))
{
}
else
if
(
QRC_SIGNTYPE_SHA1WITHRSA
.
equals
(
signType
))
{
data
.
put
(
SDKConstants
.
param_certId
,
certUtil
.
getCertIdByKeyStoreMap
(
certPath
,
certPwd
));
data
.
put
(
SDKConstants
.
param_certId
,
certUtil
.
getCertIdByKeyStoreMap
(
certPath
,
certPwd
));
data
.
put
(
SDKConstants
.
param_signature
,
SDK
Util
.
signRsa
(
data
,
certPath
,
certPwd
,
encoding
));
data
.
put
(
SDKConstants
.
param_signature
,
sdk
Util
.
signRsa
(
data
,
certPath
,
certPwd
,
encoding
));
return
data
;
return
data
;
}
else
if
(
QRC_SIGNTYPE_SM3WITHSM2
.
equals
(
signType
))
{
}
else
if
(
QRC_SIGNTYPE_SM3WITHSM2
.
equals
(
signType
))
{
log
.
error
(
"国密算法按要求必须通过加密机签名,本sdk不提供。"
);
log
.
error
(
"国密算法按要求必须通过加密机签名,本sdk不提供。"
);
...
@@ -151,8 +157,8 @@ public class QrcService {
...
@@ -151,8 +157,8 @@ public class QrcService {
* @param encoding<br>
* @param encoding<br>
* @return 加密的内容<br>
* @return 加密的内容<br>
*/
*/
public
static
String
encryptPin
(
String
accNo
,
String
pin
,
String
encoding
)
{
public
String
encryptPin
(
String
accNo
,
String
pin
,
String
encoding
)
{
return
A
cpService
.
encryptPin
(
accNo
,
pin
,
encoding
);
return
a
cpService
.
encryptPin
(
accNo
,
pin
,
encoding
);
}
}
/**
/**
...
@@ -161,8 +167,8 @@ public class QrcService {
...
@@ -161,8 +167,8 @@ public class QrcService {
* @param encoding<br>
* @param encoding<br>
* @return 加密的密文<br>
* @return 加密的密文<br>
*/
*/
public
static
String
encryptData
(
String
data
,
String
encoding
)
{
public
String
encryptData
(
String
data
,
String
encoding
)
{
return
A
cpService
.
encryptData
(
data
,
encoding
);
return
a
cpService
.
encryptData
(
data
,
encoding
);
}
}
/**
/**
...
@@ -171,8 +177,8 @@ public class QrcService {
...
@@ -171,8 +177,8 @@ public class QrcService {
* @param encoding<br>
* @param encoding<br>
* @return 解密后的明文<br>
* @return 解密后的明文<br>
*/
*/
public
static
String
decryptData
(
String
base64EncryptedInfo
,
String
encoding
)
{
public
String
decryptData
(
String
base64EncryptedInfo
,
String
encoding
)
{
return
A
cpService
.
decryptData
(
base64EncryptedInfo
,
encoding
);
return
a
cpService
.
decryptData
(
base64EncryptedInfo
,
encoding
);
}
}
/**
/**
...
@@ -183,9 +189,9 @@ public class QrcService {
...
@@ -183,9 +189,9 @@ public class QrcService {
* @param encoding<br>
* @param encoding<br>
* @return
* @return
*/
*/
public
static
String
decryptData
(
String
base64EncryptedInfo
,
String
certPath
,
public
String
decryptData
(
String
base64EncryptedInfo
,
String
certPath
,
String
certPwd
,
String
encoding
)
{
String
certPwd
,
String
encoding
)
{
return
A
cpService
.
decryptData
(
base64EncryptedInfo
,
certPath
,
certPwd
,
encoding
);
return
a
cpService
.
decryptData
(
base64EncryptedInfo
,
certPath
,
certPwd
,
encoding
);
}
}
/**
/**
...
@@ -203,8 +209,8 @@ public class QrcService {
...
@@ -203,8 +209,8 @@ public class QrcService {
* @param encoding<br>
* @param encoding<br>
* @return 应答http 200返回true ,其他false<br>
* @return 应答http 200返回true ,其他false<br>
*/
*/
public
static
Map
<
String
,
String
>
post
(
Map
<
String
,
String
>
reqData
,
String
reqUrl
,
String
encoding
)
{
public
Map
<
String
,
String
>
post
(
Map
<
String
,
String
>
reqData
,
String
reqUrl
,
String
encoding
)
{
return
A
cpService
.
post
(
reqData
,
reqUrl
,
encoding
);
return
a
cpService
.
post
(
reqData
,
reqUrl
,
encoding
);
}
}
/**
/**
...
@@ -227,12 +233,12 @@ public class QrcService {
...
@@ -227,12 +233,12 @@ public class QrcService {
* @param encoding
* @param encoding
* @return
* @return
*/
*/
public
static
String
getKVEncBase64Field
(
Map
<
String
,
String
>
map
,
String
encoding
){
public
String
getKVEncBase64Field
(
Map
<
String
,
String
>
map
,
String
encoding
){
StringBuffer
sf
=
new
StringBuffer
();
StringBuffer
sf
=
new
StringBuffer
();
String
info
=
sf
.
append
(
SDKConstants
.
LEFT_BRACE
)
String
info
=
sf
.
append
(
SDKConstants
.
LEFT_BRACE
)
.
append
(
SDKUtil
.
createLinkString
(
map
,
false
,
false
,
encoding
))
.
append
(
SDKUtil
.
createLinkString
(
map
,
false
,
false
,
encoding
))
.
append
(
SDKConstants
.
RIGHT_BRACE
).
toString
();
.
append
(
SDKConstants
.
RIGHT_BRACE
).
toString
();
return
QrcService
.
encryptData
(
info
,
encoding
);
return
this
.
encryptData
(
info
,
encoding
);
}
}
/**
/**
...
@@ -255,8 +261,8 @@ public class QrcService {
...
@@ -255,8 +261,8 @@ public class QrcService {
* @param encoding<br>
* @param encoding<br>
* @return
* @return
*/
*/
public
static
Map
<
String
,
String
>
parseKVEncBase64Field
(
String
base64data
,
String
encoding
){
public
Map
<
String
,
String
>
parseKVEncBase64Field
(
String
base64data
,
String
encoding
){
String
data
=
QrcService
.
decryptData
(
base64data
,
encoding
);
String
data
=
this
.
decryptData
(
base64data
,
encoding
);
data
=
data
.
substring
(
1
,
data
.
length
()
-
1
);
data
=
data
.
substring
(
1
,
data
.
length
()
-
1
);
return
SDKUtil
.
parseRespString
(
data
);
return
SDKUtil
.
parseRespString
(
data
);
}
}
...
@@ -268,9 +274,9 @@ public class QrcService {
...
@@ -268,9 +274,9 @@ public class QrcService {
* @param encoding<br>
* @param encoding<br>
* @return
* @return
*/
*/
public
static
Map
<
String
,
String
>
parseKVEncBase64Field
(
String
base64data
,
String
certPath
,
public
Map
<
String
,
String
>
parseKVEncBase64Field
(
String
base64data
,
String
certPath
,
String
certPwd
,
String
encoding
){
String
certPwd
,
String
encoding
){
String
data
=
QrcService
.
decryptData
(
base64data
,
certPath
,
certPwd
,
encoding
);
String
data
=
this
.
decryptData
(
base64data
,
certPath
,
certPwd
,
encoding
);
data
=
data
.
substring
(
1
,
data
.
length
()
-
1
);
data
=
data
.
substring
(
1
,
data
.
length
()
-
1
);
return
SDKUtil
.
parseRespString
(
data
);
return
SDKUtil
.
parseRespString
(
data
);
}
}
...
...
liquidnet-bus-service/liquidnet-service-dragon/liquidnet-service-dragon-impl/src/main/java/com/liquidnet/service/dragon/channel/unionpay/sdk/SDKConfig.java
View file @
4bb7fbf3
...
@@ -72,7 +72,7 @@ public class SDKConfig {
...
@@ -72,7 +72,7 @@ public class SDKConfig {
/** 有卡交易. */
/** 有卡交易. */
private
String
cardRequestUrl
;
private
String
cardRequestUrl
;
/** app交易 */
/** app交易 */
private
String
app
Request
Url
;
private
String
app
Trans
Url
;
/** 证书使用模式(单证书/多证书) */
/** 证书使用模式(单证书/多证书) */
private
String
singleMode
;
private
String
singleMode
;
/** 安全密钥(SHA256和SM3计算时使用) */
/** 安全密钥(SHA256和SM3计算时使用) */
...
...
liquidnet-bus-service/liquidnet-service-dragon/liquidnet-service-dragon-impl/src/test/java/com/liquidnet/service/scpsdk/DemoBase.java
0 → 100644
View file @
4bb7fbf3
package
com
.
liquidnet
.
service
.
scpsdk
;
import
com.liquidnet.service.dragon.channel.unionpay.sdk.SDKConfig
;
import
com.liquidnet.service.dragon.channel.unionpay.sdk.SDKConstants
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.stereotype.Component
;
import
java.io.*
;
import
java.text.SimpleDateFormat
;
import
java.util.*
;
import
java.util.Map.Entry
;
import
java.util.zip.ZipEntry
;
import
java.util.zip.ZipInputStream
;
/**
* 名称: demo中用到的方法<br>
* 日期: 2015-09<br>
* 版权: 中国银联<br>
* 声明:以下代码只是为了方便商户测试而提供的样例代码,商户可以根据自己需要,按照技术文档编写。该代码仅供参考,不提供编码,性能,规范性等方面的保障<br>
*/
@Component
public
class
DemoBase
{
@Autowired
private
SDKConfig
sdkConfig
;
//默认配置的是UTF-8
public
static
String
encoding
=
"UTF-8"
;
// //全渠道固定值
// public String version = sdkConfig.getVersion();
//
// //后台服务对应的写法参照 FrontRcvResponse.java
// public String frontUrl = sdkConfig.getFrontUrl();
//
// //后台服务对应的写法参照 BackRcvResponse.java
// public String backUrl = sdkConfig.getBackUrl();//受理方和发卡方自选填写的域[O]--后台通知地址
// 商户发送交易时间 格式:yyyyMMddHHmmss
public
static
String
getCurrentTime
()
{
return
new
SimpleDateFormat
(
"yyyyMMddHHmmss"
).
format
(
new
Date
());
}
// AN8..40 商户订单号,不能含"-"或"_"
public
static
String
getOrderId
()
{
return
new
SimpleDateFormat
(
"yyyyMMddHHmmssSSS"
).
format
(
new
Date
());
}
/**
* 组装请求,返回报文字符串用于显示
* @param data
* @return
*/
public
static
String
genHtmlResult
(
Map
<
String
,
String
>
data
){
TreeMap
<
String
,
String
>
tree
=
new
TreeMap
<
String
,
String
>();
Iterator
<
Entry
<
String
,
String
>>
it
=
data
.
entrySet
().
iterator
();
while
(
it
.
hasNext
())
{
Entry
<
String
,
String
>
en
=
it
.
next
();
tree
.
put
(
en
.
getKey
(),
en
.
getValue
());
}
it
=
tree
.
entrySet
().
iterator
();
StringBuffer
sf
=
new
StringBuffer
();
while
(
it
.
hasNext
())
{
Entry
<
String
,
String
>
en
=
it
.
next
();
String
key
=
en
.
getKey
();
String
value
=
en
.
getValue
();
if
(
"respCode"
.
equals
(
key
)){
sf
.
append
(
"<b>"
+
key
+
SDKConstants
.
EQUAL
+
value
+
"</br></b>"
);
}
else
sf
.
append
(
key
+
SDKConstants
.
EQUAL
+
value
+
"</br>"
);
}
return
sf
.
toString
();
}
/**
* 功能:解析全渠道商户对账文件中的ZM文件并以List<Map>方式返回
* 适用交易:对账文件下载后对文件的查看
* @param filePath ZM文件全路径
* @return 包含每一笔交易中 序列号 和 值 的map序列
*/
public
static
List
<
Map
>
parseZMFile
(
String
filePath
){
int
lengthArray
[]
=
{
3
,
11
,
11
,
6
,
10
,
19
,
12
,
4
,
2
,
21
,
2
,
32
,
2
,
6
,
10
,
13
,
13
,
4
,
15
,
2
,
2
,
6
,
2
,
4
,
32
,
1
,
21
,
15
,
1
,
15
,
32
,
13
,
13
,
8
,
32
,
13
,
13
,
12
,
2
,
1
,
32
,
98
};
return
parseFile
(
filePath
,
lengthArray
);
}
/**
* 功能:解析全渠道商户对账文件中的ZME文件并以List<Map>方式返回
* 适用交易:对账文件下载后对文件的查看
* @param filePath ZME文件全路径
* @return 包含每一笔交易中 序列号 和 值 的map序列
*/
public
static
List
<
Map
>
parseZMEFile
(
String
filePath
){
int
lengthArray
[]
=
{
3
,
11
,
11
,
6
,
10
,
19
,
12
,
4
,
2
,
2
,
6
,
10
,
4
,
12
,
13
,
13
,
15
,
15
,
1
,
12
,
2
,
135
};
return
parseFile
(
filePath
,
lengthArray
);
}
/**
* 功能:解析全渠道商户 ZM,ZME对账文件
* @param filePath
* @param lengthArray 参照《全渠道平台接入接口规范 第3部分 文件接口》 全渠道商户对账文件 6.1 ZM文件和6.2 ZME 文件 格式的类型长度组成int型数组
* @return
*/
private
static
List
<
Map
>
parseFile
(
String
filePath
,
int
lengthArray
[]){
List
<
Map
>
ZmDataList
=
new
ArrayList
<
Map
>();
try
{
String
encoding
=
"gbk"
;
//文件是gbk编码
File
file
=
new
File
(
filePath
);
if
(
file
.
isFile
()
&&
file
.
exists
()){
//判断文件是否存在
InputStreamReader
read
=
new
InputStreamReader
(
new
FileInputStream
(
file
),
"iso-8859-1"
);
BufferedReader
bufferedReader
=
new
BufferedReader
(
read
);
String
lineTxt
=
null
;
while
((
lineTxt
=
bufferedReader
.
readLine
())
!=
null
){
byte
[]
bs
=
lineTxt
.
getBytes
(
"iso-8859-1"
);
//解析的结果MAP,key为对账文件列序号,value为解析的值
Map
<
Integer
,
String
>
ZmDataMap
=
new
LinkedHashMap
<
Integer
,
String
>();
//左侧游标
int
leftIndex
=
0
;
//右侧游标
int
rightIndex
=
0
;
for
(
int
i
=
0
;
i
<
lengthArray
.
length
;
i
++){
rightIndex
=
leftIndex
+
lengthArray
[
i
];
String
filed
=
new
String
(
Arrays
.
copyOfRange
(
bs
,
leftIndex
,
rightIndex
),
encoding
);
leftIndex
=
rightIndex
+
1
;
ZmDataMap
.
put
(
i
,
filed
);
}
ZmDataList
.
add
(
ZmDataMap
);
}
read
.
close
();
}
else
{
System
.
out
.
println
(
"找不到指定的文件"
);
}
}
catch
(
Exception
e
)
{
System
.
out
.
println
(
"读取文件内容出错"
);
e
.
printStackTrace
();
}
return
ZmDataList
;
}
public
static
String
getFileContentTable
(
List
<
Map
>
dataList
,
String
file
){
StringBuffer
tableSb
=
new
StringBuffer
(
"对账文件的规范参考 https://open.unionpay.com/ajweb/help/file/ 产品接口规范->平台接口规范:文件接口</br> 文件【"
+
file
+
"】解析后内容如下:"
);
tableSb
.
append
(
"<table border=\"1\">"
);
if
(
dataList
.
size
()
>
0
){
Map
<
Integer
,
String
>
dataMapTmp
=
dataList
.
get
(
0
);
tableSb
.
append
(
"<tr>"
);
for
(
Iterator
<
Integer
>
it
=
dataMapTmp
.
keySet
().
iterator
();
it
.
hasNext
();){
Integer
key
=
it
.
next
();
String
value
=
dataMapTmp
.
get
(
key
);
System
.
out
.
println
(
"序号:"
+
(
key
+
1
)
+
" 值: '"
+
value
+
"'"
);
tableSb
.
append
(
"<td>序号"
+(
key
+
1
)+
"</td>"
);
}
tableSb
.
append
(
"</tr>"
);
}
for
(
int
i
=
0
;
i
<
dataList
.
size
();
i
++){
System
.
out
.
println
(
"行数: "
+
(
i
+
1
));
Map
<
Integer
,
String
>
dataMapTmp
=
dataList
.
get
(
i
);
tableSb
.
append
(
"<tr>"
);
for
(
Iterator
<
Integer
>
it
=
dataMapTmp
.
keySet
().
iterator
();
it
.
hasNext
();){
Integer
key
=
it
.
next
();
String
value
=
dataMapTmp
.
get
(
key
);
System
.
out
.
println
(
"序号:"
+
(
key
+
1
)
+
" 值: '"
+
value
+
"'"
);
tableSb
.
append
(
"<td>"
+
value
+
"</td>"
);
}
tableSb
.
append
(
"</tr>"
);
}
tableSb
.
append
(
"</table>"
);
return
tableSb
.
toString
();
}
public
static
List
<
String
>
unzip
(
String
zipFilePath
,
String
outPutDirectory
){
List
<
String
>
fileList
=
new
ArrayList
<
String
>();
try
{
ZipInputStream
zin
=
new
ZipInputStream
(
new
FileInputStream
(
zipFilePath
));
//输入源zip路径
BufferedInputStream
bin
=
new
BufferedInputStream
(
zin
);
BufferedOutputStream
bout
=
null
;
File
file
=
null
;
ZipEntry
entry
;
try
{
while
((
entry
=
zin
.
getNextEntry
())!=
null
&&
!
entry
.
isDirectory
()){
file
=
new
File
(
outPutDirectory
,
entry
.
getName
());
if
(!
file
.
exists
()){
(
new
File
(
file
.
getParent
())).
mkdirs
();
}
bout
=
new
BufferedOutputStream
(
new
FileOutputStream
(
file
));
int
b
;
while
((
b
=
bin
.
read
())!=-
1
){
bout
.
write
(
b
);
}
bout
.
flush
();
fileList
.
add
(
file
.
getAbsolutePath
());
System
.
out
.
println
(
file
+
"解压成功"
);
}
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
finally
{
try
{
bin
.
close
();
zin
.
close
();
if
(
bout
!=
null
){
bout
.
close
();
}
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
}
}
catch
(
FileNotFoundException
e
)
{
e
.
printStackTrace
();
}
return
fileList
;
}
}
\ No newline at end of file
liquidnet-bus-service/liquidnet-service-dragon/liquidnet-service-dragon-impl/src/test/java/com/liquidnet/service/scpsdk/TestAcpService.java
0 → 100644
View file @
4bb7fbf3
package
com
.
liquidnet
.
service
.
scpsdk
;
import
com.liquidnet.commons.lang.util.DateUtil
;
import
com.liquidnet.commons.lang.util.IDGenerator
;
import
com.liquidnet.service.dragon.channel.unionpay.sdk.AcpService
;
import
com.liquidnet.service.dragon.channel.unionpay.sdk.SDKConfig
;
import
lombok.extern.slf4j.Slf4j
;
import
org.junit.Test
;
import
org.junit.runner.RunWith
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.boot.test.context.SpringBootTest
;
import
org.springframework.test.context.junit4.SpringJUnit4ClassRunner
;
import
javax.servlet.ServletException
;
import
javax.servlet.http.HttpServletRequest
;
import
javax.servlet.http.HttpServletResponse
;
import
java.io.IOException
;
import
java.time.LocalDateTime
;
import
java.util.HashMap
;
import
java.util.Map
;
/**
* @author AnJiabin <anjiabin@zhengzai.tv>
* @version V1.0
* @Description: TODO
* @class: TestAcpService
* @Package com.liquidnet.service
* @Copyright: LightNet @ Copyright (c) 2021
* @date 2021/11/9 12:11
*/
@Slf4j
@RunWith
(
SpringJUnit4ClassRunner
.
class
)
@SpringBootTest
public
class
TestAcpService
{
@Autowired
private
DemoBase
demoBase
;
@Autowired
private
AcpService
acpService
;
@Autowired
private
SDKConfig
sdkConfig
;
@Test
public
void
testAppTrans
()
throws
ServletException
,
IOException
{
String
merId
=
"821690048160PQY"
;
String
txnAmt
=
"1"
;
String
orderId
=
IDGenerator
.
payCode
();
//设置订单过期时间
String
txnTime
=
DateUtil
.
format
(
LocalDateTime
.
now
(),
DateUtil
.
Formatter
.
yyyyMMddHHmmss
);
Map
<
String
,
String
>
contentData
=
new
HashMap
<
String
,
String
>();
/***银联全渠道系统,产品参数,除了encoding自行选择外其他不需修改***/
contentData
.
put
(
"version"
,
sdkConfig
.
getVersion
());
//版本号 全渠道默认值
contentData
.
put
(
"encoding"
,
DemoBase
.
encoding
);
//字符集编码 可以使用UTF-8,GBK两种方式
contentData
.
put
(
"signMethod"
,
sdkConfig
.
getSignMethod
());
//签名方法
contentData
.
put
(
"txnType"
,
"01"
);
//交易类型 01:消费
contentData
.
put
(
"txnSubType"
,
"01"
);
//交易子类 01:消费
contentData
.
put
(
"bizType"
,
"000201"
);
//填写000201
contentData
.
put
(
"channelType"
,
"08"
);
//渠道类型 08手机
/***商户接入参数***/
contentData
.
put
(
"merId"
,
merId
);
//商户号码,请改成自己申请的商户号或者open上注册得来的777商户号测试
contentData
.
put
(
"accessType"
,
"0"
);
//接入类型,商户接入填0 ,不需修改(0:直连商户, 1: 收单机构 2:平台商户)
contentData
.
put
(
"orderId"
,
orderId
);
//商户订单号,8-40位数字字母,不能含“-”或“_”,可以自行定制规则
contentData
.
put
(
"txnTime"
,
txnTime
);
//订单发送时间,取系统时间,格式为yyyyMMddHHmmss,必须取当前时间,否则会报txnTime无效
contentData
.
put
(
"accType"
,
"01"
);
//账号类型 01:银行卡02:存折03:IC卡帐号类型(卡介质)
contentData
.
put
(
"txnAmt"
,
txnAmt
);
//交易金额 单位为分,不能带小数点
contentData
.
put
(
"currencyCode"
,
"156"
);
//境内商户固定 156 人民币
// 请求方保留域,
// 透传字段,查询、通知、对账文件中均会原样出现,如有需要请启用并修改自己希望透传的数据。
// 出现部分特殊字符时可能影响解析,请按下面建议的方式填写:
// 1. 如果能确定内容不会出现&={}[]"'等符号时,可以直接填写数据,建议的方法如下。
// contentData.put("reqReserved", "透传信息1|透传信息2|透传信息3");
// 2. 内容可能出现&={}[]"'符号时:
// 1) 如果需要对账文件里能显示,可将字符替换成全角&={}【】“‘字符(自己写代码,此处不演示);
// 2) 如果对账文件没有显示要求,可做一下base64(如下)。
// 注意控制数据长度,实际传输的数据长度不能超过1024位。
// 查询、通知等接口解析时使用new String(Base64.decodeBase64(reqReserved), DemoBase.encoding);解base64后再对数据做后续解析。
// contentData.put("reqReserved", Base64.encodeBase64String("任意格式的信息都可以".toString().getBytes(DemoBase.encoding)));
//后台通知地址(需设置为外网能访问 http https均可),支付成功后银联会自动将异步通知报文post到商户上送的该地址,【支付失败的交易银联不会发送后台通知】
//后台通知参数详见open.unionpay.com帮助中心 下载 产品接口规范 网关支付产品接口规范 消费交易 商户通知
//注意:1.需设置为外网能访问,否则收不到通知 2.http https均可 3.收单后台通知后需要10秒内返回http200或302状态码
// 4.如果银联通知服务器发送通知后10秒内未收到返回状态码或者应答码非http200或302,那么银联会间隔一段时间再次发送。总共发送5次,银联后续间隔1、2、4、5 分钟后会再次通知。
// 5.后台通知地址如果上送了带有?的参数,例如:http://abc/web?a=b&c=d 在后台通知处理程序验证签名之前需要编写逻辑将这些字段去掉再验签,否则将会验签失败
contentData
.
put
(
"backUrl"
,
sdkConfig
.
getBackUrl
());
/**对请求参数进行签名并发送http post请求,接收同步应答报文**/
Map
<
String
,
String
>
reqData
=
acpService
.
sign
(
contentData
,
DemoBase
.
encoding
);
//报文中certId,signature的值是在signData方法中获取并自动赋值的,只要证书配置正确即可。
String
requestAppUrl
=
sdkConfig
.
getAppTransUrl
();
//交易请求url从配置文件读取对应属性文件acp_sdk.properties中的 acpsdk.backTransUrl
Map
<
String
,
String
>
rspData
=
acpService
.
post
(
reqData
,
requestAppUrl
,
DemoBase
.
encoding
);
//发送请求报文并接受同步应答(默认连接超时时间30秒,读取返回结果超时时间30秒);这里调用signData之后,调用submitUrl之前不能对submitFromData中的键值对做任何修改,如果修改会导致验签不通过
/**对应答码的处理,请根据您的业务逻辑来编写程序,以下应答码处理逻辑仅供参考------------->**/
//应答码规范参考open.unionpay.com帮助中心 下载 产品接口规范 《平台接入接口规范-第5部分-附录》
if
(!
rspData
.
isEmpty
()){
if
(
acpService
.
validate
(
rspData
,
DemoBase
.
encoding
)){
log
.
info
(
"验证签名成功"
);
String
respCode
=
rspData
.
get
(
"respCode"
)
;
if
((
"00"
).
equals
(
respCode
)){
//成功,获取tn号
//String tn = resmap.get("tn");
//TODO
}
else
{
//其他应答码为失败请排查原因或做失败处理
//TODO
}
}
else
{
log
.
error
(
"验证签名失败"
);
//TODO 检查验证签名失败的原因
}
}
else
{
//未返回正确的http状态
log
.
error
(
"未获取到返回报文或返回http状态码非200"
);
}
String
reqMessage
=
DemoBase
.
genHtmlResult
(
reqData
);
String
rspMessage
=
DemoBase
.
genHtmlResult
(
rspData
);
log
.
info
(
"请求报文:<br/>"
+
reqMessage
+
"<br/>"
+
"应答报文:</br>"
+
rspMessage
+
""
);
}
}
Write
Preview
Markdown
is supported
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