Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
V
volunteer_service
Project
Project
Details
Activity
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
licc
volunteer_service
Commits
b95df660
Commit
b95df660
authored
Feb 07, 2021
by
licc
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
微信支付
parent
588bd17d
Hide whitespace changes
Inline
Side-by-side
Showing
23 changed files
with
1382 additions
and
122 deletions
+1382
-122
pom.xml
wisenergy-service/pom.xml
+6
-7
WxPayService.java
.../src/main/java/cn/wisenergy/service/app/WxPayService.java
+16
-1
PayServiceImpl.java
...in/java/cn/wisenergy/service/app/impl/PayServiceImpl.java
+0
-79
WxPayServiceImpl.java
.../java/cn/wisenergy/service/app/impl/WxPayServiceImpl.java
+243
-0
Credentials.java
...ain/java/cn/wisenergy/service/httpClient/Credentials.java
+12
-0
SignatureExec.java
...n/java/cn/wisenergy/service/httpClient/SignatureExec.java
+78
-0
Validator.java
.../main/java/cn/wisenergy/service/httpClient/Validator.java
+9
-0
WechatPayHttpClientBuilder.java
...energy/service/httpClient/WechatPayHttpClientBuilder.java
+75
-0
WechatPayUploadHttpPost.java
...wisenergy/service/httpClient/WechatPayUploadHttpPost.java
+78
-0
AutoUpdateCertificatesVerifier.java
...rvice/httpClient/auth/AutoUpdateCertificatesVerifier.java
+181
-0
CertificatesVerifier.java
...senergy/service/httpClient/auth/CertificatesVerifier.java
+65
-0
PrivateKeySigner.java
...n/wisenergy/service/httpClient/auth/PrivateKeySigner.java
+36
-0
Signer.java
...ain/java/cn/wisenergy/service/httpClient/auth/Signer.java
+15
-0
Verifier.java
...n/java/cn/wisenergy/service/httpClient/auth/Verifier.java
+13
-0
WechatPay2Credentials.java
...energy/service/httpClient/auth/WechatPay2Credentials.java
+94
-0
WechatPay2Validator.java
...isenergy/service/httpClient/auth/WechatPay2Validator.java
+108
-0
AesUtil.java
...in/java/cn/wisenergy/service/httpClient/util/AesUtil.java
+45
-0
PemUtil.java
...in/java/cn/wisenergy/service/httpClient/util/PemUtil.java
+56
-0
RsaCryptoUtil.java
...a/cn/wisenergy/service/httpClient/util/RsaCryptoUtil.java
+50
-0
SignUtil.java
...ice/src/main/java/cn/wisenergy/service/util/SignUtil.java
+0
-32
WxPayUtil.java
...ce/src/main/java/cn/wisenergy/service/util/WxPayUtil.java
+173
-0
WxCommon.java
...ce/src/main/java/cn/wisenergy/service/wxpay/WxCommon.java
+6
-0
PayController.java
.../cn/wisenergy/web/admin/controller/app/PayController.java
+23
-3
No files found.
wisenergy-service/pom.xml
View file @
b95df660
...
...
@@ -48,19 +48,18 @@
</dependency>
<!--微信支付-->
<!-- IJPay -->
<dependency>
<groupId>
com.github.javen205
</groupId>
<artifactId>
IJPay-All
</artifactId>
<version>
2.2.0
</version>
</dependency>
<dependency>
<groupId>
com.squareup.okhttp3
</groupId>
<artifactId>
okhttp
</artifactId>
<version>
3.6.0
</version>
</dependency>
<dependency>
<groupId>
com.github.wechatpay-apiv3
</groupId>
<artifactId>
wechatpay-apache-httpclient
</artifactId>
<version>
0.2.1
</version>
</dependency>
<!--pdf导出 -->
<dependency>
<groupId>
com.itextpdf
</groupId>
...
...
wisenergy-service/src/main/java/cn/wisenergy/service/app/PayService.java
→
wisenergy-service/src/main/java/cn/wisenergy/service/app/
Wx
PayService.java
View file @
b95df660
...
...
@@ -2,7 +2,10 @@ package cn.wisenergy.service.app;
import
cn.wisenergy.common.utils.R
;
import
cn.wisenergy.model.dto.PayPageDto
;
import
cn.wisenergy.model.dto.PayQueryDto
;
import
javax.crypto.IllegalBlockSizeException
;
import
java.io.IOException
;
import
java.io.UnsupportedEncodingException
;
import
java.security.InvalidKeyException
;
import
java.security.NoSuchAlgorithmException
;
...
...
@@ -12,7 +15,7 @@ import java.security.spec.InvalidKeySpecException;
/**
* @author 86187
*/
public
interface
PayService
{
public
interface
Wx
PayService
{
/**
* 微行支付接口
...
...
@@ -20,4 +23,16 @@ public interface PayService {
* @return
*/
R
<
String
>
wxPay
(
PayPageDto
payPageDto
)
throws
UnsupportedEncodingException
,
NoSuchAlgorithmException
,
SignatureException
,
InvalidKeySpecException
,
InvalidKeyException
;
/**
* 微信支付-交易查询
* @param payQueryDto 入参
* @return
*/
R
<
String
>
queryWx
(
PayQueryDto
payQueryDto
)
throws
UnsupportedEncodingException
,
NoSuchAlgorithmException
,
SignatureException
,
InvalidKeySpecException
,
InvalidKeyException
;
R
<
String
>
wx_Pay
(
PayPageDto
payPageDto
)
throws
IOException
,
NoSuchAlgorithmException
,
SignatureException
,
InvalidKeySpecException
,
InvalidKeyException
,
IllegalBlockSizeException
;
}
wisenergy-service/src/main/java/cn/wisenergy/service/app/impl/PayServiceImpl.java
deleted
100644 → 0
View file @
588bd17d
package
cn
.
wisenergy
.
service
.
app
.
impl
;
import
cn.wisenergy.common.utils.R
;
import
cn.wisenergy.model.dto.PayPageDto
;
import
cn.wisenergy.service.app.PayService
;
import
cn.wisenergy.service.util.SignDemo
;
import
cn.wisenergy.service.util.SignUtil
;
import
cn.wisenergy.service.wxpay.WxCommon
;
import
com.alibaba.fastjson.JSONObject
;
import
lombok.extern.slf4j.Slf4j
;
import
okhttp3.HttpUrl
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.http.HttpEntity
;
import
org.springframework.http.HttpHeaders
;
import
org.springframework.http.MediaType
;
import
org.springframework.http.ResponseEntity
;
import
org.springframework.stereotype.Service
;
import
org.springframework.web.client.RestTemplate
;
import
java.io.UnsupportedEncodingException
;
import
java.security.InvalidKeyException
;
import
java.security.NoSuchAlgorithmException
;
import
java.security.SignatureException
;
import
java.security.spec.InvalidKeySpecException
;
import
java.util.HashMap
;
import
java.util.Map
;
import
java.util.Objects
;
import
java.util.UUID
;
/**
* @author 86187
*/
@Service
@Slf4j
public
class
PayServiceImpl
implements
PayService
{
@Autowired
private
RestTemplate
restTemplate
;
@Override
public
R
<
String
>
wxPay
(
PayPageDto
payPageDto
)
throws
UnsupportedEncodingException
,
NoSuchAlgorithmException
,
SignatureException
,
InvalidKeySpecException
,
InvalidKeyException
{
if
(
null
==
payPageDto
||
null
==
payPageDto
.
getTotal
())
{
return
R
.
error
(
"入参不能为空!"
);
}
final
HttpHeaders
headers
=
new
HttpHeaders
();
MediaType
type
=
MediaType
.
parseMediaType
(
"application/json; charset=UTF-8"
);
headers
.
setContentType
(
type
);
long
timestamp
=
System
.
currentTimeMillis
()
/
1000
;
String
nonceStr
=
UUID
.
randomUUID
().
toString
().
replace
(
"-"
,
""
);
String
url
=
"v3/pay/transactions/native"
;
String
method
=
"POST"
;
String
tradeNo
=
"21"
+
System
.
currentTimeMillis
();
HttpUrl
httpurl
=
HttpUrl
.
parse
(
WxCommon
.
WX_PAY_URL
);
//构造签名参数
JSONObject
jsonObject
=
new
JSONObject
();
jsonObject
.
put
(
"appid"
,
WxCommon
.
APP_ID
);
jsonObject
.
put
(
"mchid"
,
WxCommon
.
MCHID
);
jsonObject
.
put
(
"timestamp"
,
timestamp
);
jsonObject
.
put
(
"nonce_str"
,
nonceStr
);
jsonObject
.
put
(
"url"
,
url
);
jsonObject
.
put
(
"method"
,
method
);
jsonObject
.
put
(
"description"
,
"充值"
);
jsonObject
.
put
(
"out_trade_no"
,
tradeNo
);
jsonObject
.
put
(
"notify_url"
,
WxCommon
.
NOTIFY_URL
);
jsonObject
.
put
(
"amount"
,
payPageDto
);
String
sign
=
SignDemo
.
getToken
(
method
,
httpurl
,
jsonObject
.
toJSONString
(),
nonceStr
,
timestamp
);
headers
.
add
(
"Wechatpay-Signature"
,
sign
);
HttpEntity
<
JSONObject
>
formEntity
=
new
HttpEntity
<>(
jsonObject
,
headers
);
ResponseEntity
<
JSONObject
>
responseEntity
=
this
.
restTemplate
.
postForEntity
(
WxCommon
.
WX_PAY_URL
,
formEntity
,
JSONObject
.
class
);
return
R
.
ok
(
Objects
.
requireNonNull
(
responseEntity
.
getBody
()).
toJSONString
());
}
}
wisenergy-service/src/main/java/cn/wisenergy/service/app/impl/WxPayServiceImpl.java
0 → 100644
View file @
b95df660
package
cn
.
wisenergy
.
service
.
app
.
impl
;
import
cn.wisenergy.common.utils.R
;
import
cn.wisenergy.model.dto.PayPageDto
;
import
cn.wisenergy.model.dto.PayQueryDto
;
import
cn.wisenergy.service.app.WxPayService
;
import
cn.wisenergy.service.httpClient.Credentials
;
import
cn.wisenergy.service.httpClient.WechatPayHttpClientBuilder
;
import
cn.wisenergy.service.httpClient.auth.AutoUpdateCertificatesVerifier
;
import
cn.wisenergy.service.httpClient.auth.PrivateKeySigner
;
import
cn.wisenergy.service.httpClient.auth.WechatPay2Credentials
;
import
cn.wisenergy.service.httpClient.auth.WechatPay2Validator
;
import
cn.wisenergy.service.httpClient.util.PemUtil
;
import
cn.wisenergy.service.httpClient.util.RsaCryptoUtil
;
import
cn.wisenergy.service.util.SignDemo
;
import
cn.wisenergy.service.wxpay.WxCommon
;
import
com.alibaba.fastjson.JSONObject
;
import
lombok.extern.slf4j.Slf4j
;
import
okhttp3.HttpUrl
;
import
org.apache.commons.lang.StringUtils
;
import
org.apache.http.HttpEntity
;
import
org.apache.http.HttpRequest
;
import
org.apache.http.client.methods.CloseableHttpResponse
;
import
org.apache.http.client.methods.HttpGet
;
import
org.apache.http.client.methods.HttpPost
;
import
org.apache.http.client.methods.HttpRequestWrapper
;
import
org.apache.http.entity.ContentType
;
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.junit.After
;
import
org.junit.Before
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.http.HttpHeaders
;
import
org.springframework.http.MediaType
;
import
org.springframework.http.ResponseEntity
;
import
org.springframework.stereotype.Service
;
import
org.springframework.web.client.RestTemplate
;
import
javax.crypto.IllegalBlockSizeException
;
import
java.io.ByteArrayInputStream
;
import
java.io.IOException
;
import
java.io.UnsupportedEncodingException
;
import
java.security.InvalidKeyException
;
import
java.security.NoSuchAlgorithmException
;
import
java.security.PrivateKey
;
import
java.security.SignatureException
;
import
java.security.spec.InvalidKeySpecException
;
import
java.util.UUID
;
/**
* @author 86187
*/
@Service
@Slf4j
public
class
WxPayServiceImpl
implements
WxPayService
{
/**
* 商户号
*/
private
static
String
mchId
=
WxCommon
.
MCHID
;
// 商户证书序列号
private
static
String
mchSerialNo
=
WxCommon
.
SERIAL_NO
;
// api密钥
private
static
String
apiV3Key
=
WxCommon
.
SECRET_KEY
;
// 你的商户私钥
private
static
String
privateKey
=
"-----BEGIN PRIVATE KEY-----\n"
+
WxCommon
.
PRIVATE_KEY
+
"-----END PRIVATE KEY-----\n"
;
private
CloseableHttpClient
httpClient
;
private
AutoUpdateCertificatesVerifier
verifier
;
@Before
public
void
setup
()
throws
IOException
{
PrivateKey
merchantPrivateKey
=
PemUtil
.
loadPrivateKey
(
new
ByteArrayInputStream
(
privateKey
.
getBytes
(
"utf-8"
)));
//使用自动更新的签名验证器,不需要传入证书
verifier
=
new
AutoUpdateCertificatesVerifier
(
new
WechatPay2Credentials
(
mchId
,
new
PrivateKeySigner
(
mchSerialNo
,
merchantPrivateKey
)),
apiV3Key
.
getBytes
(
"utf-8"
));
httpClient
=
WechatPayHttpClientBuilder
.
create
()
.
withMerchant
(
mchId
,
mchSerialNo
,
merchantPrivateKey
)
.
withValidator
(
new
WechatPay2Validator
(
verifier
))
.
build
();
}
@After
public
void
after
()
throws
IOException
{
httpClient
.
close
();
}
@Override
public
R
<
String
>
wxPay
(
PayPageDto
payPageDto
)
throws
UnsupportedEncodingException
,
NoSuchAlgorithmException
,
SignatureException
,
InvalidKeySpecException
,
InvalidKeyException
{
if
(
null
==
payPageDto
||
null
==
payPageDto
.
getTotal
())
{
return
R
.
error
(
"入参不能为空!"
);
}
HttpPost
httpPost
=
new
HttpPost
();
httpPost
.
addHeader
(
"Content-Type"
,
"application/json"
);
httpPost
.
addHeader
(
"Accept"
,
"application/json"
);
long
timestamp
=
System
.
currentTimeMillis
()
/
1000
;
String
nonceStr
=
UUID
.
randomUUID
().
toString
().
replace
(
"-"
,
""
);
String
method
=
"POST"
;
String
tradeNo
=
"21"
+
System
.
currentTimeMillis
();
HttpUrl
httpurl
=
HttpUrl
.
parse
(
WxCommon
.
WX_PAY_URL
);
//构造签名参数
JSONObject
jsonObject
=
new
JSONObject
();
jsonObject
.
put
(
"appid"
,
WxCommon
.
APP_ID
);
jsonObject
.
put
(
"mchid"
,
WxCommon
.
MCHID
);
jsonObject
.
put
(
"description"
,
"充值"
);
jsonObject
.
put
(
"out_trade_no"
,
tradeNo
);
jsonObject
.
put
(
"notify_url"
,
WxCommon
.
NOTIFY_URL
);
jsonObject
.
put
(
"amount"
,
payPageDto
);
String
sign
=
SignDemo
.
getToken
(
method
,
httpurl
,
jsonObject
.
toJSONString
(),
nonceStr
,
timestamp
);
httpPost
.
setHeader
(
"Authorization"
,
"WECHATPAY2-SHA256-RSA2048"
+
" "
+
sign
);
return
null
;
}
@Override
public
R
<
String
>
queryWx
(
PayQueryDto
payQueryDto
)
throws
UnsupportedEncodingException
,
NoSuchAlgorithmException
,
SignatureException
,
InvalidKeySpecException
,
InvalidKeyException
{
if
(
null
==
payQueryDto
||
StringUtils
.
isBlank
(
payQueryDto
.
getOutTradeNo
()))
{
return
R
.
error
(
"入参不能为空!"
);
}
long
timestamp
=
System
.
currentTimeMillis
()
/
1000
;
String
nonceStr
=
UUID
.
randomUUID
().
toString
().
replace
(
"-"
,
""
);
String
method
=
"GET"
;
String
url
=
WxCommon
.
WX_PAY_QUERY
+
payQueryDto
.
getOutTradeNo
()
+
"?mchid="
+
WxCommon
.
MCHID
;
HttpUrl
httpurl
=
HttpUrl
.
parse
(
url
);
//构造签名参数
String
sign
=
SignDemo
.
getToken
(
method
,
httpurl
,
null
,
nonceStr
,
timestamp
);
HttpGet
httpGet
=
new
HttpGet
();
httpGet
.
addHeader
(
"Content-Type"
,
"application/json"
);
httpGet
.
addHeader
(
"Accept"
,
"application/json"
);
//设置认证信息
httpGet
.
setHeader
(
"Authorization"
,
"WECHATPAY2-SHA256-RSA2048"
+
" "
+
sign
);
return
null
;
}
@Override
public
R
<
String
>
wx_Pay
(
PayPageDto
payPageDto
)
throws
IOException
,
NoSuchAlgorithmException
,
SignatureException
,
InvalidKeySpecException
,
InvalidKeyException
,
IllegalBlockSizeException
{
HttpPost
httpPost
=
new
HttpPost
(
WxCommon
.
WX_PAY_URL
);
long
timestamp
=
System
.
currentTimeMillis
()
/
1000
;
String
nonceStr
=
UUID
.
randomUUID
().
toString
().
replace
(
"-"
,
""
);
String
method
=
"POST"
;
String
tradeNo
=
"21"
+
System
.
currentTimeMillis
();
HttpUrl
httpurl
=
HttpUrl
.
parse
(
WxCommon
.
WX_PAY_URL
);
// 请求body参数
String
reqdata
=
"{"
+
"\"time_expire\":\"2021-02-07T10:34:56+08:00\","
+
"\"amount\": {"
+
"\"total\":"
+
payPageDto
.
getTotal
()
+
","
+
"\"currency\":\"CNY\""
+
"},"
+
"\"mchid\":\""
+
WxCommon
.
MCHID
+
"\","
+
"\"description\":\"Image形象店-深圳腾大-QQ公仔\","
+
"\"notify_url\":\""
+
WxCommon
.
NOTIFY_URL
+
"\","
+
"\"out_trade_no\":\""
+
tradeNo
+
"\","
+
"\"goods_tag\":\"WXG\","
+
"\"appid\":\""
+
WxCommon
.
APP_ID
+
"\","
+
"\"attach\":\"自定义数据说明\","
+
"\"detail\": {"
+
"\"invoice_id\":\"wx123\","
+
"\"goods_detail\": ["
+
"{"
+
"\"goods_name\":\"iPhoneX 256G\","
+
"\"wechatpay_goods_id\":\"1001\","
+
"\"quantity\":1,"
+
"\"merchant_goods_id\":\"商品编码\","
+
"\"unit_price\":828800"
+
"},"
+
"{"
+
"\"goods_name\":\"iPhoneX 256G\","
+
"\"wechatpay_goods_id\":\"1001\","
+
"\"quantity\":1,"
+
"\"merchant_goods_id\":\"商品编码\","
+
"\"unit_price\":828800"
+
"}"
+
"],"
+
"\"cost_price\":608800"
+
"},"
+
"\"scene_info\": {"
+
"\"store_info\": {"
+
"\"address\":\"广东省深圳市南山区科技中一道10000号\","
+
"\"area_code\":\"440305\","
+
"\"name\":\"腾讯大厦分店\","
+
"\"id\":\"0001\""
+
"},"
+
"\"device_id\":\"013467007045764\","
+
"\"payer_client_ip\":\"14.23.150.211\""
+
"}"
+
"}"
;
StringEntity
reqEntity
=
new
StringEntity
(
reqdata
,
ContentType
.
create
(
"application/json"
,
"utf-8"
));
httpPost
.
setEntity
(
reqEntity
);
httpPost
.
addHeader
(
"Accept"
,
"application/json"
);
//构造签名参数
//构造签名参数
JSONObject
jsonObject
=
new
JSONObject
();
jsonObject
.
put
(
"appid"
,
WxCommon
.
APP_ID
);
jsonObject
.
put
(
"mchid"
,
WxCommon
.
MCHID
);
jsonObject
.
put
(
"description"
,
"充值"
);
jsonObject
.
put
(
"out_trade_no"
,
tradeNo
);
jsonObject
.
put
(
"notify_url"
,
WxCommon
.
NOTIFY_URL
);
jsonObject
.
put
(
"amount"
,
payPageDto
);
String
token
=
SignDemo
.
getToken
(
method
,
httpurl
,
jsonObject
.
toJSONString
(),
nonceStr
,
timestamp
);
httpPost
.
setHeader
(
"Authorization"
,
"WECHATPAY2-SHA256-RSA2048"
+
" "
+
token
);
//1.创建HttpClient对象
CloseableHttpClient
httpClient
=
HttpClients
.
createDefault
();
//完成签名并执行请求
CloseableHttpResponse
response
=
httpClient
.
execute
(
httpPost
);
try
{
if
(
response
.
getStatusLine
().
getStatusCode
()
==
200
)
{
HttpEntity
httpEntity
=
response
.
getEntity
();
String
content
=
EntityUtils
.
toString
(
httpEntity
,
"utf8"
);
System
.
out
.
println
(
content
.
length
());
return
R
.
ok
(
response
.
toString
());
}
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
finally
{
response
.
close
();
}
return
null
;
}
}
wisenergy-service/src/main/java/cn/wisenergy/service/httpClient/Credentials.java
0 → 100644
View file @
b95df660
package
cn
.
wisenergy
.
service
.
httpClient
;
import
org.apache.http.client.methods.HttpRequestWrapper
;
import
java.io.IOException
;
public
interface
Credentials
{
String
getSchema
();
String
getToken
(
HttpRequestWrapper
request
)
throws
IOException
;
}
wisenergy-service/src/main/java/cn/wisenergy/service/httpClient/SignatureExec.java
0 → 100644
View file @
b95df660
package
cn
.
wisenergy
.
service
.
httpClient
;
import
org.apache.http.HttpEntity
;
import
org.apache.http.HttpEntityEnclosingRequest
;
import
org.apache.http.HttpException
;
import
org.apache.http.StatusLine
;
import
org.apache.http.client.methods.CloseableHttpResponse
;
import
org.apache.http.client.methods.HttpExecutionAware
;
import
org.apache.http.client.methods.HttpRequestWrapper
;
import
org.apache.http.client.protocol.HttpClientContext
;
import
org.apache.http.conn.routing.HttpRoute
;
import
org.apache.http.entity.BufferedHttpEntity
;
import
org.apache.http.impl.execchain.ClientExecChain
;
import
java.io.IOException
;
public
class
SignatureExec
implements
ClientExecChain
{
final
ClientExecChain
mainExec
;
final
Credentials
credentials
;
final
Validator
validator
;
SignatureExec
(
Credentials
credentials
,
Validator
validator
,
ClientExecChain
mainExec
)
{
this
.
credentials
=
credentials
;
this
.
validator
=
validator
;
this
.
mainExec
=
mainExec
;
}
protected
void
convertToRepeatableResponseEntity
(
CloseableHttpResponse
response
)
throws
IOException
{
HttpEntity
entity
=
response
.
getEntity
();
if
(
entity
!=
null
)
{
response
.
setEntity
(
new
BufferedHttpEntity
(
entity
));
}
}
protected
void
convertToRepeatableRequestEntity
(
HttpRequestWrapper
request
)
throws
IOException
{
if
(
request
instanceof
HttpEntityEnclosingRequest
)
{
HttpEntity
entity
=
((
HttpEntityEnclosingRequest
)
request
).
getEntity
();
if
(
entity
!=
null
)
{
((
HttpEntityEnclosingRequest
)
request
).
setEntity
(
new
BufferedHttpEntity
(
entity
));
}
}
}
@Override
public
CloseableHttpResponse
execute
(
HttpRoute
route
,
HttpRequestWrapper
request
,
HttpClientContext
context
,
HttpExecutionAware
execAware
)
throws
IOException
,
HttpException
{
if
(
request
.
getURI
().
getHost
().
endsWith
(
".mch.weixin.qq.com"
))
{
return
executeWithSignature
(
route
,
request
,
context
,
execAware
);
}
else
{
return
mainExec
.
execute
(
route
,
request
,
context
,
execAware
);
}
}
private
CloseableHttpResponse
executeWithSignature
(
HttpRoute
route
,
HttpRequestWrapper
request
,
HttpClientContext
context
,
HttpExecutionAware
execAware
)
throws
IOException
,
HttpException
{
// 上传类不需要消耗两次故不做转换
if
(!(
request
.
getOriginal
()
instanceof
WechatPayUploadHttpPost
))
{
convertToRepeatableRequestEntity
(
request
);
}
// 添加认证信息
request
.
addHeader
(
"Authorization"
,
credentials
.
getSchema
()
+
" "
+
credentials
.
getToken
(
request
));
// 执行
CloseableHttpResponse
response
=
mainExec
.
execute
(
route
,
request
,
context
,
execAware
);
// 对成功应答验签
StatusLine
statusLine
=
response
.
getStatusLine
();
if
(
statusLine
.
getStatusCode
()
>=
200
&&
statusLine
.
getStatusCode
()
<
300
)
{
convertToRepeatableResponseEntity
(
response
);
if
(!
validator
.
validate
(
response
))
{
throw
new
HttpException
(
"应答的微信支付签名验证失败"
);
}
}
return
response
;
}
}
wisenergy-service/src/main/java/cn/wisenergy/service/httpClient/Validator.java
0 → 100644
View file @
b95df660
package
cn
.
wisenergy
.
service
.
httpClient
;
import
org.apache.http.client.methods.CloseableHttpResponse
;
import
java.io.IOException
;
public
interface
Validator
{
boolean
validate
(
CloseableHttpResponse
response
)
throws
IOException
;
}
wisenergy-service/src/main/java/cn/wisenergy/service/httpClient/WechatPayHttpClientBuilder.java
0 → 100644
View file @
b95df660
package
cn
.
wisenergy
.
service
.
httpClient
;
import
cn.wisenergy.service.httpClient.auth.CertificatesVerifier
;
import
cn.wisenergy.service.httpClient.auth.PrivateKeySigner
;
import
cn.wisenergy.service.httpClient.auth.WechatPay2Credentials
;
import
cn.wisenergy.service.httpClient.auth.WechatPay2Validator
;
import
org.apache.http.impl.client.CloseableHttpClient
;
import
org.apache.http.impl.client.HttpClientBuilder
;
import
org.apache.http.impl.execchain.ClientExecChain
;
import
java.security.PrivateKey
;
import
java.security.cert.X509Certificate
;
import
java.util.List
;
public
class
WechatPayHttpClientBuilder
extends
HttpClientBuilder
{
private
Credentials
credentials
;
private
Validator
validator
;
static
final
String
os
=
System
.
getProperty
(
"os.name"
)
+
"/"
+
System
.
getProperty
(
"os.version"
);
static
final
String
version
=
System
.
getProperty
(
"java.version"
);
private
WechatPayHttpClientBuilder
()
{
super
();
String
userAgent
=
String
.
format
(
"WechatPay-Apache-HttpClient/%s (%s) Java/%s"
,
getClass
().
getPackage
().
getImplementationVersion
(),
os
,
version
==
null
?
"Unknown"
:
version
);
setUserAgent
(
userAgent
);
}
public
static
WechatPayHttpClientBuilder
create
()
{
return
new
WechatPayHttpClientBuilder
();
}
public
WechatPayHttpClientBuilder
withMerchant
(
String
merchantId
,
String
serialNo
,
PrivateKey
privateKey
)
{
this
.
credentials
=
new
WechatPay2Credentials
(
merchantId
,
new
PrivateKeySigner
(
serialNo
,
privateKey
));
return
this
;
}
public
WechatPayHttpClientBuilder
withCredentials
(
Credentials
credentials
)
{
this
.
credentials
=
credentials
;
return
this
;
}
public
WechatPayHttpClientBuilder
withWechatpay
(
List
<
X509Certificate
>
certificates
)
{
this
.
validator
=
new
WechatPay2Validator
(
new
CertificatesVerifier
(
certificates
));
return
this
;
}
public
WechatPayHttpClientBuilder
withValidator
(
Validator
validator
)
{
this
.
validator
=
validator
;
return
this
;
}
@Override
public
CloseableHttpClient
build
()
{
if
(
credentials
==
null
)
{
throw
new
IllegalArgumentException
(
"缺少身份认证信息"
);
}
if
(
validator
==
null
)
{
throw
new
IllegalArgumentException
(
"缺少签名验证信息"
);
}
return
super
.
build
();
}
@Override
protected
ClientExecChain
decorateProtocolExec
(
final
ClientExecChain
requestExecutor
)
{
return
new
SignatureExec
(
this
.
credentials
,
this
.
validator
,
requestExecutor
);
}
}
wisenergy-service/src/main/java/cn/wisenergy/service/httpClient/WechatPayUploadHttpPost.java
0 → 100644
View file @
b95df660
package
cn
.
wisenergy
.
service
.
httpClient
;
import
org.apache.http.client.methods.HttpPost
;
import
org.apache.http.entity.ContentType
;
import
java.io.InputStream
;
import
java.net.URI
;
import
java.net.URLConnection
;
/**
* @author 86187
*/
public
class
WechatPayUploadHttpPost
extends
HttpPost
{
private
String
meta
;
private
WechatPayUploadHttpPost
(
URI
uri
,
String
meta
)
{
super
(
uri
);
this
.
meta
=
meta
;
}
public
String
getMeta
()
{
return
meta
;
}
public
static
class
Builder
{
private
String
fileName
;
private
String
fileSha256
;
private
InputStream
fileInputStream
;
private
org
.
apache
.
http
.
entity
.
ContentType
fileContentType
;
private
URI
uri
;
public
Builder
(
URI
uri
)
{
this
.
uri
=
uri
;
}
public
Builder
withImage
(
String
fileName
,
String
fileSha256
,
InputStream
inputStream
)
{
this
.
fileName
=
fileName
;
this
.
fileSha256
=
fileSha256
;
this
.
fileInputStream
=
inputStream
;
String
mimeType
=
URLConnection
.
guessContentTypeFromName
(
fileName
);
if
(
mimeType
==
null
)
{
// guess this is a video uploading
this
.
fileContentType
=
ContentType
.
APPLICATION_OCTET_STREAM
;
}
else
{
this
.
fileContentType
=
ContentType
.
create
(
mimeType
);
}
return
this
;
}
public
WechatPayUploadHttpPost
build
()
{
if
(
fileName
==
null
||
fileSha256
==
null
||
fileInputStream
==
null
)
{
throw
new
IllegalArgumentException
(
"缺少待上传图片文件信息"
);
}
if
(
uri
==
null
)
{
throw
new
IllegalArgumentException
(
"缺少上传图片接口URL"
);
}
String
meta
=
String
.
format
(
"{\"filename\":\"%s\",\"sha256\":\"%s\"}"
,
fileName
,
fileSha256
);
WechatPayUploadHttpPost
request
=
new
WechatPayUploadHttpPost
(
uri
,
meta
);
// MultipartEntityBuilder entityBuilder = MultipartEntityBuilder.create();
// entityBuilder.setMode(HttpMultipartMode.RFC6532)
// .addBinaryBody("file", fileInputStream, fileContentType, fileName)
// .addTextBody("meta", meta, org.apache.http.entity.ContentType.APPLICATION_JSON);
//
// request.setEntity(entityBuilder.build());
// request.addHeader("Accept", org.apache.http.entity.ContentType.APPLICATION_JSON.toString());
return
request
;
}
}
}
wisenergy-service/src/main/java/cn/wisenergy/service/httpClient/auth/AutoUpdateCertificatesVerifier.java
0 → 100644
View file @
b95df660
package
cn
.
wisenergy
.
service
.
httpClient
.
auth
;
import
cn.wisenergy.service.httpClient.Credentials
;
import
cn.wisenergy.service.httpClient.WechatPayHttpClientBuilder
;
import
cn.wisenergy.service.httpClient.util.AesUtil
;
import
com.fasterxml.jackson.databind.JsonNode
;
import
com.fasterxml.jackson.databind.ObjectMapper
;
import
org.apache.http.client.methods.CloseableHttpResponse
;
import
org.apache.http.client.methods.HttpGet
;
import
org.apache.http.impl.client.CloseableHttpClient
;
import
org.apache.http.util.EntityUtils
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
java.io.ByteArrayInputStream
;
import
java.io.IOException
;
import
java.security.GeneralSecurityException
;
import
java.security.cert.CertificateExpiredException
;
import
java.security.cert.CertificateFactory
;
import
java.security.cert.CertificateNotYetValidException
;
import
java.security.cert.X509Certificate
;
import
java.time.Duration
;
import
java.time.Instant
;
import
java.util.ArrayList
;
import
java.util.List
;
import
java.util.concurrent.locks.ReentrantLock
;
/**
* 在原有CertificatesVerifier基础上,增加自动更新证书功能
*/
public
class
AutoUpdateCertificatesVerifier
implements
Verifier
{
private
static
final
Logger
log
=
LoggerFactory
.
getLogger
(
AutoUpdateCertificatesVerifier
.
class
);
//证书下载地址
private
static
final
String
CertDownloadPath
=
"https://api.mch.weixin.qq.com/v3/certificates"
;
//上次更新时间
private
volatile
Instant
instant
;
//证书更新间隔时间,单位为分钟
private
int
minutesInterval
;
private
CertificatesVerifier
verifier
;
private
Credentials
credentials
;
private
byte
[]
apiV3Key
;
private
ReentrantLock
lock
=
new
ReentrantLock
();
public
AutoUpdateCertificatesVerifier
(
Credentials
credentials
,
byte
[]
apiV3Key
)
{
this
(
credentials
,
apiV3Key
,
TimeInterval
.
OneHour
.
getMinutes
());
}
public
AutoUpdateCertificatesVerifier
(
Credentials
credentials
,
byte
[]
apiV3Key
,
int
minutesInterval
)
{
this
.
credentials
=
credentials
;
this
.
apiV3Key
=
apiV3Key
;
this
.
minutesInterval
=
minutesInterval
;
//构造时更新证书
try
{
autoUpdateCert
();
instant
=
Instant
.
now
();
}
catch
(
IOException
|
GeneralSecurityException
e
)
{
throw
new
RuntimeException
(
e
);
}
}
public
AutoUpdateCertificatesVerifier
(
WechatPay2Credentials
wechatPay2Credentials
,
byte
[]
bytes
)
{
}
@Override
public
X509Certificate
getValidCertificate
()
{
return
verifier
.
getValidCertificate
();
}
@Override
public
boolean
verify
(
String
serialNumber
,
byte
[]
message
,
String
signature
)
{
if
(
instant
==
null
||
Duration
.
between
(
instant
,
Instant
.
now
()).
toMinutes
()
>=
minutesInterval
)
{
if
(
lock
.
tryLock
())
{
try
{
autoUpdateCert
();
//更新时间
instant
=
Instant
.
now
();
}
catch
(
GeneralSecurityException
|
IOException
e
)
{
log
.
warn
(
"Auto update cert failed, exception = "
+
e
);
}
finally
{
lock
.
unlock
();
}
}
}
return
verifier
.
verify
(
serialNumber
,
message
,
signature
);
}
private
void
autoUpdateCert
()
throws
IOException
,
GeneralSecurityException
{
CloseableHttpClient
httpClient
=
WechatPayHttpClientBuilder
.
create
()
.
withCredentials
(
credentials
)
.
withValidator
(
verifier
==
null
?
(
response
)
->
true
:
new
WechatPay2Validator
(
verifier
))
.
build
();
try
{
HttpGet
httpGet
=
new
HttpGet
(
CertDownloadPath
);
httpGet
.
addHeader
(
"Accept"
,
"application/json"
);
CloseableHttpResponse
response
=
httpClient
.
execute
(
httpGet
);
try
{
int
statusCode
=
response
.
getStatusLine
().
getStatusCode
();
String
body
=
EntityUtils
.
toString
(
response
.
getEntity
());
if
(
statusCode
==
200
)
{
List
<
X509Certificate
>
newCertList
=
deserializeToCerts
(
apiV3Key
,
body
);
if
(
newCertList
.
isEmpty
())
{
log
.
warn
(
"Cert list is empty"
);
return
;
}
this
.
verifier
=
new
CertificatesVerifier
(
newCertList
);
}
else
{
log
.
warn
(
"Auto update cert failed, statusCode = "
+
statusCode
+
",body = "
+
body
);
}
}
finally
{
response
.
close
();
}
}
finally
{
httpClient
.
close
();
}
}
/**
* 反序列化证书并解密
*/
private
List
<
X509Certificate
>
deserializeToCerts
(
byte
[]
apiV3Key
,
String
body
)
throws
GeneralSecurityException
,
IOException
{
AesUtil
decryptor
=
new
AesUtil
(
apiV3Key
);
ObjectMapper
mapper
=
new
ObjectMapper
();
JsonNode
dataNode
=
mapper
.
readTree
(
body
).
get
(
"data"
);
List
<
X509Certificate
>
newCertList
=
new
ArrayList
<>();
if
(
dataNode
!=
null
)
{
for
(
int
i
=
0
,
count
=
dataNode
.
size
();
i
<
count
;
i
++)
{
JsonNode
encryptCertificateNode
=
dataNode
.
get
(
i
).
get
(
"encrypt_certificate"
);
//解密
String
cert
=
decryptor
.
decryptToString
(
encryptCertificateNode
.
get
(
"associated_data"
).
toString
().
replaceAll
(
"\""
,
""
)
.
getBytes
(
"utf-8"
),
encryptCertificateNode
.
get
(
"nonce"
).
toString
().
replaceAll
(
"\""
,
""
)
.
getBytes
(
"utf-8"
),
encryptCertificateNode
.
get
(
"ciphertext"
).
toString
().
replaceAll
(
"\""
,
""
));
CertificateFactory
cf
=
CertificateFactory
.
getInstance
(
"X509"
);
X509Certificate
x509Cert
=
(
X509Certificate
)
cf
.
generateCertificate
(
new
ByteArrayInputStream
(
cert
.
getBytes
(
"utf-8"
))
);
try
{
x509Cert
.
checkValidity
();
}
catch
(
CertificateExpiredException
|
CertificateNotYetValidException
e
)
{
continue
;
}
newCertList
.
add
(
x509Cert
);
}
}
return
newCertList
;
}
/**
* 时间间隔枚举,支持一小时、六小时以及十二小时
*/
public
enum
TimeInterval
{
OneHour
(
60
),
SixHours
(
60
*
6
),
TwelveHours
(
60
*
12
);
private
int
minutes
;
TimeInterval
(
int
minutes
)
{
this
.
minutes
=
minutes
;
}
public
int
getMinutes
()
{
return
minutes
;
}
}
}
wisenergy-service/src/main/java/cn/wisenergy/service/httpClient/auth/CertificatesVerifier.java
0 → 100644
View file @
b95df660
package
cn
.
wisenergy
.
service
.
httpClient
.
auth
;
import
java.math.BigInteger
;
import
java.security.InvalidKeyException
;
import
java.security.NoSuchAlgorithmException
;
import
java.security.Signature
;
import
java.security.SignatureException
;
import
java.security.cert.CertificateExpiredException
;
import
java.security.cert.CertificateNotYetValidException
;
import
java.security.cert.X509Certificate
;
import
java.util.Base64
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.NoSuchElementException
;
/**
* @author 86187
*/
public
class
CertificatesVerifier
implements
Verifier
{
private
final
HashMap
<
BigInteger
,
X509Certificate
>
certificates
=
new
HashMap
<>();
public
CertificatesVerifier
(
List
<
X509Certificate
>
list
)
{
for
(
X509Certificate
item
:
list
)
{
certificates
.
put
(
item
.
getSerialNumber
(),
item
);
}
}
private
boolean
verify
(
X509Certificate
certificate
,
byte
[]
message
,
String
signature
)
{
try
{
Signature
sign
=
Signature
.
getInstance
(
"SHA256withRSA"
);
sign
.
initVerify
(
certificate
);
sign
.
update
(
message
);
return
sign
.
verify
(
Base64
.
getDecoder
().
decode
(
signature
));
}
catch
(
NoSuchAlgorithmException
e
)
{
throw
new
RuntimeException
(
"当前Java环境不支持SHA256withRSA"
,
e
);
}
catch
(
SignatureException
e
)
{
throw
new
RuntimeException
(
"签名验证过程发生了错误"
,
e
);
}
catch
(
InvalidKeyException
e
)
{
throw
new
RuntimeException
(
"无效的证书"
,
e
);
}
}
@Override
public
boolean
verify
(
String
serialNumber
,
byte
[]
message
,
String
signature
)
{
BigInteger
val
=
new
BigInteger
(
serialNumber
,
16
);
return
certificates
.
containsKey
(
val
)
&&
verify
(
certificates
.
get
(
val
),
message
,
signature
);
}
@Override
public
X509Certificate
getValidCertificate
()
{
for
(
X509Certificate
x509Cert
:
certificates
.
values
())
{
try
{
x509Cert
.
checkValidity
();
return
x509Cert
;
}
catch
(
CertificateExpiredException
|
CertificateNotYetValidException
e
)
{
continue
;
}
}
throw
new
NoSuchElementException
(
"没有有效的微信支付平台证书"
);
}
}
wisenergy-service/src/main/java/cn/wisenergy/service/httpClient/auth/PrivateKeySigner.java
0 → 100644
View file @
b95df660
package
cn
.
wisenergy
.
service
.
httpClient
.
auth
;
import
java.security.*
;
import
java.util.Base64
;
/**
* @author 86187
*/
public
class
PrivateKeySigner
implements
Signer
{
private
String
certificateSerialNumber
;
private
PrivateKey
privateKey
;
public
PrivateKeySigner
(
String
serialNumber
,
PrivateKey
privateKey
)
{
this
.
certificateSerialNumber
=
serialNumber
;
this
.
privateKey
=
privateKey
;
}
@Override
public
SignatureResult
sign
(
byte
[]
message
)
{
try
{
Signature
sign
=
Signature
.
getInstance
(
"SHA256withRSA"
);
sign
.
initSign
(
privateKey
);
sign
.
update
(
message
);
return
new
SignatureResult
(
Base64
.
getEncoder
().
encodeToString
(
sign
.
sign
()),
certificateSerialNumber
);
}
catch
(
NoSuchAlgorithmException
e
)
{
throw
new
RuntimeException
(
"当前Java环境不支持SHA256withRSA"
,
e
);
}
catch
(
SignatureException
e
)
{
throw
new
RuntimeException
(
"签名计算失败"
,
e
);
}
catch
(
InvalidKeyException
e
)
{
throw
new
RuntimeException
(
"无效的私钥"
,
e
);
}
}
}
wisenergy-service/src/main/java/cn/wisenergy/service/httpClient/auth/Signer.java
0 → 100644
View file @
b95df660
package
cn
.
wisenergy
.
service
.
httpClient
.
auth
;
public
interface
Signer
{
SignatureResult
sign
(
byte
[]
message
);
class
SignatureResult
{
String
sign
;
String
certificateSerialNumber
;
public
SignatureResult
(
String
sign
,
String
serialNumber
)
{
this
.
sign
=
sign
;
this
.
certificateSerialNumber
=
serialNumber
;
}
}
}
wisenergy-service/src/main/java/cn/wisenergy/service/httpClient/auth/Verifier.java
0 → 100644
View file @
b95df660
package
cn
.
wisenergy
.
service
.
httpClient
.
auth
;
import
java.security.cert.X509Certificate
;
/**
* @author 86187
*/
public
interface
Verifier
{
boolean
verify
(
String
serialNumber
,
byte
[]
message
,
String
signature
);
X509Certificate
getValidCertificate
();
}
wisenergy-service/src/main/java/cn/wisenergy/service/httpClient/auth/WechatPay2Credentials.java
0 → 100644
View file @
b95df660
package
cn
.
wisenergy
.
service
.
httpClient
.
auth
;
import
cn.wisenergy.service.httpClient.Credentials
;
import
cn.wisenergy.service.httpClient.WechatPayUploadHttpPost
;
import
org.apache.http.HttpEntityEnclosingRequest
;
import
org.apache.http.client.methods.HttpRequestWrapper
;
import
org.apache.http.util.EntityUtils
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
java.io.IOException
;
import
java.net.URI
;
import
java.nio.charset.StandardCharsets
;
import
java.security.SecureRandom
;
public
class
WechatPay2Credentials
implements
Credentials
{
private
static
final
Logger
log
=
LoggerFactory
.
getLogger
(
WechatPay2Credentials
.
class
);
private
static
final
String
SYMBOLS
=
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
;
private
static
final
SecureRandom
RANDOM
=
new
SecureRandom
();
protected
String
merchantId
;
protected
Signer
signer
;
public
WechatPay2Credentials
(
String
merchantId
,
Signer
signer
)
{
this
.
merchantId
=
merchantId
;
this
.
signer
=
signer
;
}
public
String
getMerchantId
()
{
return
merchantId
;
}
protected
long
generateTimestamp
()
{
return
System
.
currentTimeMillis
()
/
1000
;
}
protected
String
generateNonceStr
()
{
char
[]
nonceChars
=
new
char
[
32
];
for
(
int
index
=
0
;
index
<
nonceChars
.
length
;
++
index
)
{
nonceChars
[
index
]
=
SYMBOLS
.
charAt
(
RANDOM
.
nextInt
(
SYMBOLS
.
length
()));
}
return
new
String
(
nonceChars
);
}
@Override
public
final
String
getSchema
()
{
return
"WECHATPAY2-SHA256-RSA2048"
;
}
@Override
public
final
String
getToken
(
HttpRequestWrapper
request
)
throws
IOException
{
String
nonceStr
=
generateNonceStr
();
long
timestamp
=
generateTimestamp
();
String
message
=
buildMessage
(
nonceStr
,
timestamp
,
request
);
log
.
debug
(
"authorization message=[{}]"
,
message
);
Signer
.
SignatureResult
signature
=
signer
.
sign
(
message
.
getBytes
(
StandardCharsets
.
UTF_8
));
String
token
=
"mchid=\""
+
getMerchantId
()
+
"\","
+
"nonce_str=\""
+
nonceStr
+
"\","
+
"timestamp=\""
+
timestamp
+
"\","
+
"serial_no=\""
+
signature
.
certificateSerialNumber
+
"\","
+
"signature=\""
+
signature
.
sign
+
"\""
;
log
.
debug
(
"authorization token=[{}]"
,
token
);
return
token
;
}
protected
final
String
buildMessage
(
String
nonce
,
long
timestamp
,
HttpRequestWrapper
request
)
throws
IOException
{
URI
uri
=
request
.
getURI
();
String
canonicalUrl
=
uri
.
getRawPath
();
if
(
uri
.
getQuery
()
!=
null
)
{
canonicalUrl
+=
"?"
+
uri
.
getRawQuery
();
}
String
body
=
""
;
// PATCH,POST,PUT
if
(
request
.
getOriginal
()
instanceof
WechatPayUploadHttpPost
)
{
body
=
((
WechatPayUploadHttpPost
)
request
.
getOriginal
()).
getMeta
();
}
else
if
(
request
instanceof
HttpEntityEnclosingRequest
)
{
body
=
EntityUtils
.
toString
(((
HttpEntityEnclosingRequest
)
request
).
getEntity
());
}
return
request
.
getRequestLine
().
getMethod
()
+
"\n"
+
canonicalUrl
+
"\n"
+
timestamp
+
"\n"
+
nonce
+
"\n"
+
body
+
"\n"
;
}
}
wisenergy-service/src/main/java/cn/wisenergy/service/httpClient/auth/WechatPay2Validator.java
0 → 100644
View file @
b95df660
package
cn
.
wisenergy
.
service
.
httpClient
.
auth
;
import
cn.wisenergy.service.httpClient.Validator
;
import
org.apache.http.Header
;
import
org.apache.http.HttpEntity
;
import
org.apache.http.client.methods.CloseableHttpResponse
;
import
org.apache.http.util.EntityUtils
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
java.io.IOException
;
import
java.time.DateTimeException
;
import
java.time.Duration
;
import
java.time.Instant
;
/**
* @author 86187
*/
public
class
WechatPay2Validator
implements
Validator
{
private
static
final
Logger
log
=
LoggerFactory
.
getLogger
(
WechatPay2Validator
.
class
);
private
Verifier
verifier
;
public
WechatPay2Validator
(
Verifier
verifier
)
{
this
.
verifier
=
verifier
;
}
static
RuntimeException
parameterError
(
String
message
,
Object
...
args
)
{
message
=
String
.
format
(
message
,
args
);
return
new
IllegalArgumentException
(
"parameter error: "
+
message
);
}
static
RuntimeException
verifyFail
(
String
message
,
Object
...
args
)
{
message
=
String
.
format
(
message
,
args
);
return
new
IllegalArgumentException
(
"signature verify fail: "
+
message
);
}
@Override
public
final
boolean
validate
(
CloseableHttpResponse
response
)
throws
IOException
{
try
{
validateParameters
(
response
);
String
message
=
buildMessage
(
response
);
String
serial
=
response
.
getFirstHeader
(
"Wechatpay-Serial"
).
getValue
();
String
signature
=
response
.
getFirstHeader
(
"Wechatpay-Signature"
).
getValue
();
if
(!
verifier
.
verify
(
serial
,
message
.
getBytes
(
"utf-8"
),
signature
))
{
throw
verifyFail
(
"serial=[%s] message=[%s] sign=[%s], request-id=[%s]"
,
serial
,
message
,
signature
,
response
.
getFirstHeader
(
"Request-ID"
).
getValue
());
}
}
catch
(
IllegalArgumentException
e
)
{
log
.
warn
(
e
.
getMessage
());
return
false
;
}
return
true
;
}
protected
final
void
validateParameters
(
CloseableHttpResponse
response
)
{
String
requestId
;
if
(!
response
.
containsHeader
(
"Request-ID"
))
{
throw
parameterError
(
"empty Request-ID"
);
}
else
{
requestId
=
response
.
getFirstHeader
(
"Request-ID"
).
getValue
();
}
if
(!
response
.
containsHeader
(
"Wechatpay-Serial"
))
{
throw
parameterError
(
"empty Wechatpay-Serial, request-id=[%s]"
,
requestId
);
}
else
if
(!
response
.
containsHeader
(
"Wechatpay-Signature"
)){
throw
parameterError
(
"empty Wechatpay-Signature, request-id=[%s]"
,
requestId
);
}
else
if
(!
response
.
containsHeader
(
"Wechatpay-Timestamp"
))
{
throw
parameterError
(
"empty Wechatpay-Timestamp, request-id=[%s]"
,
requestId
);
}
else
if
(!
response
.
containsHeader
(
"Wechatpay-Nonce"
))
{
throw
parameterError
(
"empty Wechatpay-Nonce, request-id=[%s]"
,
requestId
);
}
else
{
Header
timestamp
=
response
.
getFirstHeader
(
"Wechatpay-Timestamp"
);
try
{
Instant
instant
=
Instant
.
ofEpochSecond
(
Long
.
parseLong
(
timestamp
.
getValue
()));
// 拒绝5分钟之外的应答
if
(
Duration
.
between
(
instant
,
Instant
.
now
()).
abs
().
toMinutes
()
>=
5
)
{
throw
parameterError
(
"timestamp=[%s] expires, request-id=[%s]"
,
timestamp
.
getValue
(),
requestId
);
}
}
catch
(
DateTimeException
|
NumberFormatException
e
)
{
throw
parameterError
(
"invalid timestamp=[%s], request-id=[%s]"
,
timestamp
.
getValue
(),
requestId
);
}
}
}
protected
final
String
buildMessage
(
CloseableHttpResponse
response
)
throws
IOException
{
String
timestamp
=
response
.
getFirstHeader
(
"Wechatpay-Timestamp"
).
getValue
();
String
nonce
=
response
.
getFirstHeader
(
"Wechatpay-Nonce"
).
getValue
();
String
body
=
getResponseBody
(
response
);
return
timestamp
+
"\n"
+
nonce
+
"\n"
+
body
+
"\n"
;
}
protected
final
String
getResponseBody
(
CloseableHttpResponse
response
)
throws
IOException
{
HttpEntity
entity
=
response
.
getEntity
();
return
(
entity
!=
null
&&
entity
.
isRepeatable
())
?
EntityUtils
.
toString
(
entity
)
:
""
;
}
}
wisenergy-service/src/main/java/cn/wisenergy/service/httpClient/util/AesUtil.java
0 → 100644
View file @
b95df660
package
cn
.
wisenergy
.
service
.
httpClient
.
util
;
import
javax.crypto.Cipher
;
import
javax.crypto.NoSuchPaddingException
;
import
javax.crypto.spec.GCMParameterSpec
;
import
javax.crypto.spec.SecretKeySpec
;
import
java.io.IOException
;
import
java.security.GeneralSecurityException
;
import
java.security.InvalidAlgorithmParameterException
;
import
java.security.InvalidKeyException
;
import
java.security.NoSuchAlgorithmException
;
import
java.util.Base64
;
public
class
AesUtil
{
static
final
int
KEY_LENGTH_BYTE
=
32
;
static
final
int
TAG_LENGTH_BIT
=
128
;
private
final
byte
[]
aesKey
;
public
AesUtil
(
byte
[]
key
)
{
if
(
key
.
length
!=
KEY_LENGTH_BYTE
)
{
throw
new
IllegalArgumentException
(
"无效的ApiV3Key,长度必须为32个字节"
);
}
this
.
aesKey
=
key
;
}
public
String
decryptToString
(
byte
[]
associatedData
,
byte
[]
nonce
,
String
ciphertext
)
throws
GeneralSecurityException
,
IOException
{
try
{
Cipher
cipher
=
Cipher
.
getInstance
(
"AES/GCM/NoPadding"
);
SecretKeySpec
key
=
new
SecretKeySpec
(
aesKey
,
"AES"
);
GCMParameterSpec
spec
=
new
GCMParameterSpec
(
TAG_LENGTH_BIT
,
nonce
);
cipher
.
init
(
Cipher
.
DECRYPT_MODE
,
key
,
spec
);
cipher
.
updateAAD
(
associatedData
);
return
new
String
(
cipher
.
doFinal
(
Base64
.
getDecoder
().
decode
(
ciphertext
)),
"utf-8"
);
}
catch
(
NoSuchAlgorithmException
|
NoSuchPaddingException
e
)
{
throw
new
IllegalStateException
(
e
);
}
catch
(
InvalidKeyException
|
InvalidAlgorithmParameterException
e
)
{
throw
new
IllegalArgumentException
(
e
);
}
}
}
wisenergy-service/src/main/java/cn/wisenergy/service/httpClient/util/PemUtil.java
0 → 100644
View file @
b95df660
package
cn
.
wisenergy
.
service
.
httpClient
.
util
;
import
java.io.ByteArrayOutputStream
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.security.KeyFactory
;
import
java.security.NoSuchAlgorithmException
;
import
java.security.PrivateKey
;
import
java.security.cert.*
;
import
java.security.spec.InvalidKeySpecException
;
import
java.security.spec.PKCS8EncodedKeySpec
;
import
java.util.Base64
;
public
class
PemUtil
{
public
static
PrivateKey
loadPrivateKey
(
InputStream
inputStream
)
{
try
{
ByteArrayOutputStream
array
=
new
ByteArrayOutputStream
();
byte
[]
buffer
=
new
byte
[
1024
];
int
length
;
while
((
length
=
inputStream
.
read
(
buffer
))
!=
-
1
)
{
array
.
write
(
buffer
,
0
,
length
);
}
String
privateKey
=
array
.
toString
(
"utf-8"
)
.
replace
(
"-----BEGIN PRIVATE KEY-----"
,
""
)
.
replace
(
"-----END PRIVATE KEY-----"
,
""
)
.
replaceAll
(
"\\s+"
,
""
);
KeyFactory
kf
=
KeyFactory
.
getInstance
(
"RSA"
);
return
kf
.
generatePrivate
(
new
PKCS8EncodedKeySpec
(
Base64
.
getDecoder
().
decode
(
privateKey
)));
}
catch
(
NoSuchAlgorithmException
e
)
{
throw
new
RuntimeException
(
"当前Java环境不支持RSA"
,
e
);
}
catch
(
InvalidKeySpecException
e
)
{
throw
new
RuntimeException
(
"无效的密钥格式"
);
}
catch
(
IOException
e
)
{
throw
new
RuntimeException
(
"无效的密钥"
);
}
}
public
static
X509Certificate
loadCertificate
(
InputStream
inputStream
)
{
try
{
CertificateFactory
cf
=
CertificateFactory
.
getInstance
(
"X509"
);
X509Certificate
cert
=
(
X509Certificate
)
cf
.
generateCertificate
(
inputStream
);
cert
.
checkValidity
();
return
cert
;
}
catch
(
CertificateExpiredException
e
)
{
throw
new
RuntimeException
(
"证书已过期"
,
e
);
}
catch
(
CertificateNotYetValidException
e
)
{
throw
new
RuntimeException
(
"证书尚未生效"
,
e
);
}
catch
(
CertificateException
e
)
{
throw
new
RuntimeException
(
"无效的证书"
,
e
);
}
}
}
wisenergy-service/src/main/java/cn/wisenergy/service/httpClient/util/RsaCryptoUtil.java
0 → 100644
View file @
b95df660
package
cn
.
wisenergy
.
service
.
httpClient
.
util
;
import
javax.crypto.BadPaddingException
;
import
javax.crypto.Cipher
;
import
javax.crypto.IllegalBlockSizeException
;
import
javax.crypto.NoSuchPaddingException
;
import
java.nio.charset.StandardCharsets
;
import
java.security.InvalidKeyException
;
import
java.security.NoSuchAlgorithmException
;
import
java.security.PrivateKey
;
import
java.security.cert.X509Certificate
;
import
java.util.Base64
;
public
class
RsaCryptoUtil
{
public
static
String
encryptOAEP
(
String
message
,
X509Certificate
certificate
)
throws
IllegalBlockSizeException
{
try
{
Cipher
cipher
=
Cipher
.
getInstance
(
"RSA/ECB/OAEPWithSHA-1AndMGF1Padding"
);
cipher
.
init
(
Cipher
.
ENCRYPT_MODE
,
certificate
.
getPublicKey
());
byte
[]
data
=
message
.
getBytes
(
StandardCharsets
.
UTF_8
);
byte
[]
ciphertext
=
cipher
.
doFinal
(
data
);
return
Base64
.
getEncoder
().
encodeToString
(
ciphertext
);
}
catch
(
NoSuchAlgorithmException
|
NoSuchPaddingException
e
)
{
throw
new
RuntimeException
(
"当前Java环境不支持RSA v1.5/OAEP"
,
e
);
}
catch
(
InvalidKeyException
e
)
{
throw
new
IllegalArgumentException
(
"无效的证书"
,
e
);
}
catch
(
IllegalBlockSizeException
|
BadPaddingException
e
)
{
throw
new
IllegalBlockSizeException
(
"加密原串的长度不能超过214字节"
);
}
}
public
static
String
decryptOAEP
(
String
ciphertext
,
PrivateKey
privateKey
)
throws
BadPaddingException
{
try
{
Cipher
cipher
=
Cipher
.
getInstance
(
"RSA/ECB/OAEPWithSHA-1AndMGF1Padding"
);
cipher
.
init
(
Cipher
.
DECRYPT_MODE
,
privateKey
);
byte
[]
data
=
Base64
.
getDecoder
().
decode
(
ciphertext
);
return
new
String
(
cipher
.
doFinal
(
data
),
StandardCharsets
.
UTF_8
);
}
catch
(
NoSuchPaddingException
|
NoSuchAlgorithmException
e
)
{
throw
new
RuntimeException
(
"当前Java环境不支持RSA v1.5/OAEP"
,
e
);
}
catch
(
InvalidKeyException
e
)
{
throw
new
IllegalArgumentException
(
"无效的私钥"
,
e
);
}
catch
(
BadPaddingException
|
IllegalBlockSizeException
e
)
{
throw
new
BadPaddingException
(
"解密失败"
);
}
}
}
wisenergy-service/src/main/java/cn/wisenergy/service/util/SignUtil.java
deleted
100644 → 0
View file @
588bd17d
package
cn
.
wisenergy
.
service
.
util
;
import
org.apache.commons.codec.digest.DigestUtils
;
import
java.io.UnsupportedEncodingException
;
import
java.util.Arrays
;
import
java.util.Map
;
/**
* @author 86187
*/
public
class
SignUtil
{
public
static
String
genSignature
(
String
secretKey
,
Map
<
String
,
Object
>
params
)
throws
UnsupportedEncodingException
{
//secretKey为商户平台设置的密钥key
if
(
secretKey
==
null
||
params
==
null
||
params
.
size
()
==
0
)
{
return
""
;
}
// 1. 参数名按照ASCII码表升序排序
String
[]
keys
=
params
.
keySet
().
toArray
(
new
String
[
0
]);
Arrays
.
sort
(
keys
);
// 2. 按照排序拼接参数名与参数值
StringBuffer
paramBuffer
=
new
StringBuffer
();
for
(
String
key
:
keys
)
{
paramBuffer
.
append
(
"&"
+
key
).
append
(
params
.
get
(
key
)
==
null
?
""
:
"="
+
params
.
get
(
key
));
}
// 3. 将secretKey拼接到最后
paramBuffer
=
paramBuffer
.
append
(
"&key="
+
secretKey
);
String
pa
=
paramBuffer
.
substring
(
1
);
// 4. MD5是128位长度的摘要算法,用16进制表示,一个十六进制的字符能表示4个位,所以签名后的字符串长度固定为32个十六进制字符。
return
DigestUtils
.
md5Hex
(
pa
.
getBytes
(
"UTF-8"
)).
toUpperCase
();
}
}
wisenergy-service/src/main/java/cn/wisenergy/service/util/WxPayUtil.java
0 → 100644
View file @
b95df660
package
cn
.
wisenergy
.
service
.
util
;
import
cn.wisenergy.common.utils.R
;
import
cn.wisenergy.model.dto.PayPageDto
;
import
cn.wisenergy.service.httpClient.WechatPayHttpClientBuilder
;
import
cn.wisenergy.service.httpClient.auth.AutoUpdateCertificatesVerifier
;
import
cn.wisenergy.service.httpClient.auth.PrivateKeySigner
;
import
cn.wisenergy.service.httpClient.auth.WechatPay2Credentials
;
import
cn.wisenergy.service.httpClient.auth.WechatPay2Validator
;
import
cn.wisenergy.service.httpClient.util.PemUtil
;
import
cn.wisenergy.service.wxpay.WxCommon
;
import
com.alibaba.fastjson.JSONObject
;
import
okhttp3.HttpUrl
;
import
org.apache.http.HttpEntity
;
import
org.apache.http.client.methods.CloseableHttpResponse
;
import
org.apache.http.client.methods.HttpPost
;
import
org.apache.http.entity.ContentType
;
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.junit.After
;
import
org.junit.Before
;
import
java.io.ByteArrayInputStream
;
import
java.io.IOException
;
import
java.io.UnsupportedEncodingException
;
import
java.security.InvalidKeyException
;
import
java.security.NoSuchAlgorithmException
;
import
java.security.PrivateKey
;
import
java.security.SignatureException
;
import
java.security.spec.InvalidKeySpecException
;
import
java.util.UUID
;
public
class
WxPayUtil
{
/**
* 商户号
*/
private
static
String
mchId
=
WxCommon
.
MCHID
;
// 商户证书序列号
private
static
String
mchSerialNo
=
WxCommon
.
SERIAL_NO
;
// api密钥
private
static
String
apiV3Key
=
WxCommon
.
SECRET_KEY
;
// 你的商户私钥
private
static
String
privateKey
=
"-----BEGIN PRIVATE KEY-----\n"
+
WxCommon
.
PRIVATE_KEY
+
"-----END PRIVATE KEY-----\n"
;
private
static
CloseableHttpClient
httpClient
;
private
static
AutoUpdateCertificatesVerifier
verifier
;
static
{
PrivateKey
merchantPrivateKey
=
null
;
try
{
merchantPrivateKey
=
PemUtil
.
loadPrivateKey
(
new
ByteArrayInputStream
(
privateKey
.
getBytes
(
"utf-8"
)));
}
catch
(
UnsupportedEncodingException
e
)
{
e
.
printStackTrace
();
}
//使用自动更新的签名验证器,不需要传入证书
try
{
verifier
=
new
AutoUpdateCertificatesVerifier
(
new
WechatPay2Credentials
(
mchId
,
new
PrivateKeySigner
(
mchSerialNo
,
merchantPrivateKey
)),
apiV3Key
.
getBytes
(
"utf-8"
));
}
catch
(
UnsupportedEncodingException
e
)
{
e
.
printStackTrace
();
}
httpClient
=
WechatPayHttpClientBuilder
.
create
()
.
withMerchant
(
mchId
,
mchSerialNo
,
merchantPrivateKey
)
.
withValidator
(
new
WechatPay2Validator
(
verifier
))
.
build
();
}
@After
public
void
after
()
throws
IOException
{
httpClient
.
close
();
}
public
static
void
main
(
String
[]
args
)
throws
IOException
,
NoSuchAlgorithmException
,
SignatureException
,
InvalidKeySpecException
,
InvalidKeyException
{
HttpPost
httpPost
=
new
HttpPost
(
WxCommon
.
WX_PAY_URL
);
long
timestamp
=
System
.
currentTimeMillis
()
/
1000
;
String
nonceStr
=
UUID
.
randomUUID
().
toString
().
replace
(
"-"
,
""
);
String
method
=
"POST"
;
String
tradeNo
=
"21"
+
System
.
currentTimeMillis
();
HttpUrl
httpurl
=
HttpUrl
.
parse
(
WxCommon
.
WX_PAY_URL
);
// 请求body参数
String
reqdata
=
"{"
+
"\"time_expire\":\"2021-02-07T10:34:56+08:00\","
+
"\"amount\": {"
+
"\"total\":100,"
+
"\"currency\":\"CNY\""
+
"},"
+
"\"mchid\":\""
+
WxCommon
.
MCHID
+
"\","
+
"\"description\":\"Image形象店-深圳腾大-QQ公仔\","
+
"\"notify_url\":\""
+
WxCommon
.
NOTIFY_URL
+
"\","
+
"\"out_trade_no\":\""
+
tradeNo
+
"\","
+
"\"goods_tag\":\"WXG\","
+
"\"appid\":\""
+
WxCommon
.
APP_ID
+
"\","
+
"\"attach\":\"自定义数据说明\","
+
"\"detail\": {"
+
"\"invoice_id\":\"wx123\","
+
"\"goods_detail\": ["
+
"{"
+
"\"goods_name\":\"iPhoneX 256G\","
+
"\"wechatpay_goods_id\":\"1001\","
+
"\"quantity\":1,"
+
"\"merchant_goods_id\":\"商品编码\","
+
"\"unit_price\":828800"
+
"},"
+
"{"
+
"\"goods_name\":\"iPhoneX 256G\","
+
"\"wechatpay_goods_id\":\"1001\","
+
"\"quantity\":1,"
+
"\"merchant_goods_id\":\"商品编码\","
+
"\"unit_price\":828800"
+
"}"
+
"],"
+
"\"cost_price\":608800"
+
"},"
+
"\"scene_info\": {"
+
"\"store_info\": {"
+
"\"address\":\"广东省深圳市南山区科技中一道10000号\","
+
"\"area_code\":\"440305\","
+
"\"name\":\"腾讯大厦分店\","
+
"\"id\":\"0001\""
+
"},"
+
"\"device_id\":\"013467007045764\","
+
"\"payer_client_ip\":\"14.23.150.211\""
+
"}"
+
"}"
;
StringEntity
reqEntity
=
new
StringEntity
(
reqdata
,
ContentType
.
create
(
"application/json"
,
"utf-8"
));
httpPost
.
setEntity
(
reqEntity
);
httpPost
.
addHeader
(
"Accept"
,
"application/json"
);
// //构造签名参数
// //构造签名参数
// JSONObject jsonObject = new JSONObject();
// jsonObject.put("appid", WxCommon.APP_ID);
// jsonObject.put("mchid", WxCommon.MCHID);
// jsonObject.put("description", "充值");
// jsonObject.put("out_trade_no", tradeNo);
// jsonObject.put("notify_url", WxCommon.NOTIFY_URL);
// PayPageDto payPageDto=new PayPageDto();
// payPageDto.setTotal(100);
// jsonObject.put("amount", payPageDto);
// String token = SignDemo.getToken(method, httpurl, jsonObject.toJSONString(), nonceStr, timestamp);
// httpPost.setHeader("Authorization", "WECHATPAY2-SHA256-RSA2048" + " " + token);
//完成签名并执行请求
CloseableHttpResponse
response
=
httpClient
.
execute
(
httpPost
);
try
{
if
(
response
.
getStatusLine
().
getStatusCode
()
==
200
)
{
HttpEntity
httpEntity
=
response
.
getEntity
();
String
content
=
EntityUtils
.
toString
(
httpEntity
,
"utf8"
);
System
.
out
.
println
(
content
.
length
());
}
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
finally
{
response
.
close
();
}
}
}
wisenergy-service/src/main/java/cn/wisenergy/service/wxpay/WxCommon.java
View file @
b95df660
...
...
@@ -16,6 +16,7 @@ public class WxCommon {
public
static
final
String
WX_PAY_URL
=
"https://api.mch.weixin.qq.com/v3/pay/transactions/native"
;
public
static
final
String
WX_PAY_QUERY
=
" https://api.mch.weixin.qq.com/v3/pay/transactions/out-trade-no/"
;
public
static
final
String
SECRET_KEY
=
"MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDhGq+iGQueP8EU"
+
"3qj0T0Otnha0XboVcgmeDkgbe08H54WiF9d3R4aLAo+wAkAj/R7nRw2yWeaaMEgb"
+
"ZvUz03IioVKwLhaMVEtwE5sNFCMGDDh9jGjm66j+BYgVk02P5hUAcYLcJYeo9iHA"
+
...
...
@@ -52,4 +53,9 @@ public class WxCommon {
* 认证类型
*/
public
static
final
String
SCHEMA
=
"WECHATPAY2-SHA256-RSA2048"
;
/**
* 认证类型
*/
public
static
final
String
PRIVATE_KEY
=
"efef4a06a1654e0f78d113377ea37aed"
;
}
wisenergy-web-admin/src/main/java/cn/wisenergy/web/admin/controller/app/PayController.java
View file @
b95df660
...
...
@@ -3,7 +3,7 @@ package cn.wisenergy.web.admin.controller.app;
import
cn.wisenergy.common.utils.R
;
import
cn.wisenergy.model.dto.PayPageDto
;
import
cn.wisenergy.model.dto.PayQueryDto
;
import
cn.wisenergy.service.app.PayService
;
import
cn.wisenergy.service.app.
Wx
PayService
;
import
cn.wisenergy.service.common.Common
;
import
com.alipay.api.AlipayApiException
;
import
com.alipay.api.AlipayClient
;
...
...
@@ -22,6 +22,7 @@ import org.springframework.web.bind.annotation.RequestBody;
import
org.springframework.web.bind.annotation.RequestMapping
;
import
org.springframework.web.bind.annotation.RestController
;
import
javax.crypto.IllegalBlockSizeException
;
import
javax.servlet.http.HttpServletRequest
;
import
javax.servlet.http.HttpServletResponse
;
import
java.io.IOException
;
...
...
@@ -45,7 +46,7 @@ public class PayController {
private
static
final
String
CHARSET
=
"UTF-8"
;
@Autowired
private
PayService
p
ayService
;
private
WxPayService
wxP
ayService
;
@ApiOperation
(
value
=
"PC支付宝-支付接口"
,
notes
=
"PC支付宝-支付接口"
,
httpMethod
=
"POST"
)
@ApiImplicitParam
(
name
=
"payPageDto"
,
value
=
"参数"
,
dataType
=
"PayPageDto"
)
...
...
@@ -193,6 +194,25 @@ public class PayController {
@ApiImplicitParam
(
name
=
"payPageDto"
,
value
=
"支付入参"
,
dataType
=
"PayPageDto"
)
@PostMapping
(
"/wxPay"
)
public
R
<
String
>
wxPay
(
@RequestBody
PayPageDto
payPageDto
)
throws
AlipayApiException
,
UnsupportedEncodingException
,
InvalidKeySpecException
,
NoSuchAlgorithmException
,
InvalidKeyException
,
SignatureException
{
return
payService
.
wxPay
(
payPageDto
);
return
wxPayService
.
wxPay
(
payPageDto
);
}
@ApiOperation
(
value
=
"微信支付-交易查询"
,
notes
=
"微信支付-交易查询"
,
httpMethod
=
"POST"
)
@ApiImplicitParam
(
name
=
"payQueryDto"
,
value
=
"查询参数"
,
dataType
=
"PayQueryDto"
)
@PostMapping
(
"/queryWx"
)
public
R
<
String
>
queryWx
(
@RequestBody
PayQueryDto
payQueryDto
)
throws
AlipayApiException
,
InvalidKeySpecException
,
SignatureException
,
NoSuchAlgorithmException
,
InvalidKeyException
,
UnsupportedEncodingException
{
if
(
null
==
payQueryDto
||
StringUtils
.
isBlank
(
payQueryDto
.
getOutTradeNo
()))
{
return
R
.
error
(
"操作错误!"
);
}
return
wxPayService
.
queryWx
(
payQueryDto
);
}
@ApiOperation
(
value
=
"测试-微行支付-统一下单"
,
notes
=
"测试-微行支付-统一下单"
,
httpMethod
=
"POST"
)
@ApiImplicitParam
(
name
=
"payPageDto"
,
value
=
"支付入参"
,
dataType
=
"PayPageDto"
)
@PostMapping
(
"/wx_Pay"
)
public
R
<
String
>
wx_Pay
(
@RequestBody
PayPageDto
payPageDto
)
throws
AlipayApiException
,
IOException
,
InvalidKeySpecException
,
NoSuchAlgorithmException
,
InvalidKeyException
,
SignatureException
,
IllegalBlockSizeException
{
return
wxPayService
.
wx_Pay
(
payPageDto
);
}
}
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