2
2
3
3
import com .wechat .pay .contrib .apache .httpclient .Validator ;
4
4
import java .io .IOException ;
5
+ import java .time .DateTimeException ;
6
+ import java .time .Duration ;
7
+ import java .time .Instant ;
5
8
import org .apache .http .Header ;
6
9
import org .apache .http .HttpEntity ;
7
10
import org .apache .http .client .methods .CloseableHttpResponse ;
@@ -19,24 +22,72 @@ public WechatPay2Validator(Verifier verifier) {
19
22
this .verifier = verifier ;
20
23
}
21
24
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
+
22
35
@ Override
23
36
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 ();
28
43
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 ());
31
51
return false ;
32
52
}
33
53
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 (Long .parseLong (timestamp .getValue ()));
77
+ // 拒绝5分钟之外的应答
78
+ if (Duration .between (instant , Instant .now ()).abs ().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
+ }
36
87
}
37
88
38
89
protected final String buildMessage (CloseableHttpResponse response ) throws IOException {
39
- String timestamp = response .getFirstHeader ("Wechatpay-TimeStamp " ).getValue ();
90
+ String timestamp = response .getFirstHeader ("Wechatpay-Timestamp " ).getValue ();
40
91
String nonce = response .getFirstHeader ("Wechatpay-Nonce" ).getValue ();
41
92
42
93
String body = getResponseBody (response );
0 commit comments