Skip to content

Commit e87f476

Browse files
committed
feat: 验签增加log, 增加时间戳5分钟过期拒绝
1 parent 0865ea9 commit e87f476

File tree

1 file changed

+59
-8
lines changed

1 file changed

+59
-8
lines changed

src/main/java/com/wechat/pay/contrib/apache/httpclient/auth/WechatPay2Validator.java

Lines changed: 59 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
import com.wechat.pay.contrib.apache.httpclient.Validator;
44
import java.io.IOException;
5+
import java.time.DateTimeException;
6+
import java.time.Duration;
7+
import java.time.Instant;
58
import org.apache.http.Header;
69
import org.apache.http.HttpEntity;
710
import org.apache.http.client.methods.CloseableHttpResponse;
@@ -19,20 +22,68 @@ public WechatPay2Validator(Verifier verifier) {
1922
this.verifier = verifier;
2023
}
2124

25+
static RuntimeException parameterError(String message, Object... args) {
26+
message = String.format(message, args);
27+
return new IllegalArgumentException("parameter error: " + message);
28+
}
29+
30+
static RuntimeException verifyFail(String message, Object... args) {
31+
message = String.format(message, args);
32+
return new IllegalArgumentException("signature verify fail: " + message);
33+
}
34+
2235
@Override
2336
public final boolean validate(CloseableHttpResponse response) throws IOException {
24-
Header serialNo = response.getFirstHeader("Wechatpay-Serial");
25-
Header sign = response.getFirstHeader("Wechatpay-Signature");
26-
Header timestamp = response.getFirstHeader("Wechatpay-TimeStamp");
27-
Header nonce = response.getFirstHeader("Wechatpay-Nonce");
37+
try {
38+
validateParameters(response);
39+
40+
String message = buildMessage(response);
41+
String serial = response.getFirstHeader("Wechatpay-Serial").getValue();
42+
String signature = response.getFirstHeader("Wechatpay-Signature").getValue();
2843

29-
// todo: check timestamp
30-
if (timestamp == null || nonce == null || serialNo == null || sign == null) {
44+
if (!verifier.verify(serial, message.getBytes("utf-8"), signature)) {
45+
throw verifyFail("serial=[%s] message=[%s] sign=[%s], request-id=[%s]",
46+
serial, message, signature,
47+
response.getFirstHeader("Request-ID").getValue());
48+
}
49+
} catch (IllegalArgumentException e) {
50+
log.warn(e.getMessage());
3151
return false;
3252
}
3353

34-
String message = buildMessage(response);
35-
return verifier.verify(serialNo.getValue(), message.getBytes("utf-8"), sign.getValue());
54+
return true;
55+
}
56+
57+
protected final void validateParameters(CloseableHttpResponse response) {
58+
String requestId;
59+
if (!response.containsHeader("Request-ID")) {
60+
throw parameterError("empty Request-ID");
61+
} else {
62+
requestId = response.getFirstHeader("Request-ID").getValue();
63+
}
64+
65+
if (!response.containsHeader("Wechatpay-Serial")) {
66+
throw parameterError("empty Wechatpay-Serial, request-id=[%s]", requestId);
67+
} else if (!response.containsHeader("Wechatpay-Signature")){
68+
throw parameterError("empty Wechatpay-Signature, request-id=[%s]", requestId);
69+
} else if (!response.containsHeader("Wechatpay-Timestamp")) {
70+
throw parameterError("empty Wechatpay-Timestamp, request-id=[%s]", requestId);
71+
} else if (!response.containsHeader("Wechatpay-Nonce")) {
72+
throw parameterError("empty Wechatpay-Nonce, request-id=[%s]", requestId);
73+
} else {
74+
Header timestamp = response.getFirstHeader("Wechatpay-Timestamp");
75+
try {
76+
Instant instant = Instant.ofEpochSecond(Integer.parseInt(timestamp.getValue()));
77+
// 拒绝5分钟之前的应答
78+
if (Duration.between(instant, Instant.now()).toMinutes() >= 5) {
79+
throw parameterError("timestamp=[%s] expires, request-id=[%s]",
80+
timestamp.getValue(), requestId);
81+
}
82+
} catch (DateTimeException | NumberFormatException e) {
83+
throw parameterError("invalid timestamp=[%s], request-id=[%s]",
84+
timestamp.getValue(), requestId);
85+
}
86+
}
3687
}
3788

3889
protected final String buildMessage(CloseableHttpResponse response) throws IOException {

0 commit comments

Comments
 (0)