Fixing .gitignore
This commit is contained in:
@@ -1,45 +1,45 @@
|
||||
package com.peanut.modules.pay.weChatPay.util;
|
||||
|
||||
import org.junit.rules.Verifier;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
|
||||
public class HttpUtils {
|
||||
|
||||
|
||||
/**
|
||||
* 将通知参数转化为字符串
|
||||
* @param request
|
||||
* @return
|
||||
*
|
||||
* WechatPayValidatorForRequest
|
||||
*/
|
||||
public static String readData(HttpServletRequest request) {
|
||||
BufferedReader br = null;
|
||||
try {
|
||||
StringBuilder result = new StringBuilder();
|
||||
br = request.getReader();
|
||||
for (String line; (line = br.readLine()) != null; ) {
|
||||
if (result.length() > 0) {
|
||||
result.append("\n");
|
||||
}
|
||||
result.append(line);
|
||||
}
|
||||
return result.toString();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
} finally {
|
||||
if (br != null) {
|
||||
try {
|
||||
br.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}}}}
|
||||
|
||||
|
||||
|
||||
package com.peanut.modules.pay.weChatPay.util;
|
||||
|
||||
import org.junit.rules.Verifier;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
|
||||
public class HttpUtils {
|
||||
|
||||
|
||||
/**
|
||||
* 将通知参数转化为字符串
|
||||
* @param request
|
||||
* @return
|
||||
*
|
||||
* WechatPayValidatorForRequest
|
||||
*/
|
||||
public static String readData(HttpServletRequest request) {
|
||||
BufferedReader br = null;
|
||||
try {
|
||||
StringBuilder result = new StringBuilder();
|
||||
br = request.getReader();
|
||||
for (String line; (line = br.readLine()) != null; ) {
|
||||
if (result.length() > 0) {
|
||||
result.append("\n");
|
||||
}
|
||||
result.append(line);
|
||||
}
|
||||
return result.toString();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
} finally {
|
||||
if (br != null) {
|
||||
try {
|
||||
br.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}}}}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,150 +1,150 @@
|
||||
package com.peanut.modules.pay.weChatPay.util;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.alibaba.fastjson.TypeReference;
|
||||
import com.wechat.pay.contrib.apache.httpclient.auth.Verifier;
|
||||
import com.wechat.pay.contrib.apache.httpclient.util.AesUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.http.HttpEntity;
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
import org.apache.http.util.EntityUtils;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.DateTimeException;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.Map;
|
||||
|
||||
import static com.wechat.pay.contrib.apache.httpclient.constant.WechatPayHttpHeaders.*;
|
||||
|
||||
/**
|
||||
* @Author:
|
||||
* @Description:
|
||||
**/
|
||||
@Slf4j
|
||||
public class WechatPayValidator {
|
||||
/**
|
||||
* 应答超时时间,单位为分钟
|
||||
*/
|
||||
private static final long RESPONSE_EXPIRED_MINUTES = 5;
|
||||
private final Verifier verifier;
|
||||
private final String requestId;
|
||||
private final String body;
|
||||
|
||||
|
||||
public WechatPayValidator(Verifier verifier, String requestId, String body) {
|
||||
this.verifier = verifier;
|
||||
this.requestId = requestId;
|
||||
this.body = body;
|
||||
}
|
||||
|
||||
protected static IllegalArgumentException parameterError(String message, Object... args) {
|
||||
message = String.format(message, args);
|
||||
return new IllegalArgumentException("parameter error: " + message);
|
||||
}
|
||||
|
||||
protected static IllegalArgumentException verifyFail(String message, Object... args) {
|
||||
message = String.format(message, args);
|
||||
return new IllegalArgumentException("signature verify fail: " + message);
|
||||
}
|
||||
|
||||
public final boolean validate(HttpServletRequest request) {
|
||||
try {
|
||||
//处理请求参数
|
||||
validateParameters(request);
|
||||
|
||||
//构造验签名串
|
||||
String message = buildMessage(request);
|
||||
|
||||
String serial = request.getHeader(WECHAT_PAY_SERIAL);
|
||||
String signature = request.getHeader(WECHAT_PAY_SIGNATURE);
|
||||
|
||||
//验签
|
||||
if (!verifier.verify(serial, message.getBytes(StandardCharsets.UTF_8), signature)) {
|
||||
throw verifyFail("serial=[%s] message=[%s] sign=[%s], request-id=[%s]",
|
||||
serial, message, signature, requestId);
|
||||
}
|
||||
} catch (IllegalArgumentException e) {
|
||||
log.warn(e.getMessage());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void validateParameters(HttpServletRequest request) {
|
||||
|
||||
// NOTE: ensure HEADER_WECHAT_PAY_TIMESTAMP at last
|
||||
String[] headers = {WECHAT_PAY_SERIAL, WECHAT_PAY_SIGNATURE, WECHAT_PAY_NONCE, WECHAT_PAY_TIMESTAMP};
|
||||
|
||||
String header = null;
|
||||
for (String headerName : headers) {
|
||||
header = request.getHeader(headerName);
|
||||
if (header == null) {
|
||||
throw parameterError("empty [%s], request-id=[%s]", headerName, requestId);
|
||||
}
|
||||
}
|
||||
|
||||
//判断请求是否过期
|
||||
String timestampStr = header;
|
||||
try {
|
||||
Instant responseTime = Instant.ofEpochSecond(Long.parseLong(timestampStr));
|
||||
// 拒绝过期请求
|
||||
if (Duration.between(responseTime, Instant.now()).abs().toMinutes() >= RESPONSE_EXPIRED_MINUTES) {
|
||||
throw parameterError("timestamp=[%s] expires, request-id=[%s]", timestampStr, requestId);
|
||||
}
|
||||
} catch (DateTimeException | NumberFormatException e) {
|
||||
throw parameterError("invalid timestamp=[%s], request-id=[%s]", timestampStr, requestId);
|
||||
}
|
||||
}
|
||||
|
||||
private String buildMessage(HttpServletRequest request) {
|
||||
String timestamp = request.getHeader(WECHAT_PAY_TIMESTAMP);
|
||||
String nonce = request.getHeader(WECHAT_PAY_NONCE);
|
||||
return timestamp + "\n"
|
||||
+ nonce + "\n"
|
||||
+ body + "\n";
|
||||
}
|
||||
|
||||
private String getResponseBody(CloseableHttpResponse response) throws IOException {
|
||||
HttpEntity entity = response.getEntity();
|
||||
return (entity != null && entity.isRepeatable()) ? EntityUtils.toString(entity) : "";
|
||||
}
|
||||
|
||||
/**
|
||||
* 对称解密,异步通知的加密数据
|
||||
* @param resource 加密数据
|
||||
* @param apiV3Key apiV3密钥
|
||||
* @param type 1-支付,2-退款
|
||||
* @return
|
||||
*/
|
||||
public static Map<String, Object> decryptFromResource(String resource,String apiV3Key,Integer type) {
|
||||
|
||||
String msg = type==1?"支付成功":"退款成功";
|
||||
log.info(msg+",回调通知,密文解密");
|
||||
try {
|
||||
//通知数据
|
||||
Map<String, Object> resourceMap = JSONObject.parseObject(resource, new TypeReference<Map<String, Object>>() {
|
||||
});
|
||||
//数据密文
|
||||
String ciphertext = resourceMap.get("ciphertext").toString();
|
||||
//随机串
|
||||
String nonce = resourceMap.get("nonce").toString();
|
||||
//附加数据
|
||||
String associatedData = resourceMap.get("associated_data").toString();
|
||||
|
||||
log.info("密文: {}", ciphertext);
|
||||
AesUtil aesUtil = new AesUtil(apiV3Key.getBytes(StandardCharsets.UTF_8));
|
||||
String resourceStr = aesUtil.decryptToString(associatedData.getBytes(StandardCharsets.UTF_8),
|
||||
nonce.getBytes(StandardCharsets.UTF_8),
|
||||
ciphertext);
|
||||
|
||||
log.info(msg+",回调通知,解密结果 明文: {}", resourceStr);
|
||||
return JSONObject.parseObject(resourceStr, new TypeReference<Map<String, Object>>(){});
|
||||
}catch (Exception e){
|
||||
throw new RuntimeException("回调参数,解密失败!");
|
||||
}
|
||||
}
|
||||
}
|
||||
package com.peanut.modules.pay.weChatPay.util;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.alibaba.fastjson.TypeReference;
|
||||
import com.wechat.pay.contrib.apache.httpclient.auth.Verifier;
|
||||
import com.wechat.pay.contrib.apache.httpclient.util.AesUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.http.HttpEntity;
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
import org.apache.http.util.EntityUtils;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.DateTimeException;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.Map;
|
||||
|
||||
import static com.wechat.pay.contrib.apache.httpclient.constant.WechatPayHttpHeaders.*;
|
||||
|
||||
/**
|
||||
* @Author:
|
||||
* @Description:
|
||||
**/
|
||||
@Slf4j
|
||||
public class WechatPayValidator {
|
||||
/**
|
||||
* 应答超时时间,单位为分钟
|
||||
*/
|
||||
private static final long RESPONSE_EXPIRED_MINUTES = 5;
|
||||
private final Verifier verifier;
|
||||
private final String requestId;
|
||||
private final String body;
|
||||
|
||||
|
||||
public WechatPayValidator(Verifier verifier, String requestId, String body) {
|
||||
this.verifier = verifier;
|
||||
this.requestId = requestId;
|
||||
this.body = body;
|
||||
}
|
||||
|
||||
protected static IllegalArgumentException parameterError(String message, Object... args) {
|
||||
message = String.format(message, args);
|
||||
return new IllegalArgumentException("parameter error: " + message);
|
||||
}
|
||||
|
||||
protected static IllegalArgumentException verifyFail(String message, Object... args) {
|
||||
message = String.format(message, args);
|
||||
return new IllegalArgumentException("signature verify fail: " + message);
|
||||
}
|
||||
|
||||
public final boolean validate(HttpServletRequest request) {
|
||||
try {
|
||||
//处理请求参数
|
||||
validateParameters(request);
|
||||
|
||||
//构造验签名串
|
||||
String message = buildMessage(request);
|
||||
|
||||
String serial = request.getHeader(WECHAT_PAY_SERIAL);
|
||||
String signature = request.getHeader(WECHAT_PAY_SIGNATURE);
|
||||
|
||||
//验签
|
||||
if (!verifier.verify(serial, message.getBytes(StandardCharsets.UTF_8), signature)) {
|
||||
throw verifyFail("serial=[%s] message=[%s] sign=[%s], request-id=[%s]",
|
||||
serial, message, signature, requestId);
|
||||
}
|
||||
} catch (IllegalArgumentException e) {
|
||||
log.warn(e.getMessage());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void validateParameters(HttpServletRequest request) {
|
||||
|
||||
// NOTE: ensure HEADER_WECHAT_PAY_TIMESTAMP at last
|
||||
String[] headers = {WECHAT_PAY_SERIAL, WECHAT_PAY_SIGNATURE, WECHAT_PAY_NONCE, WECHAT_PAY_TIMESTAMP};
|
||||
|
||||
String header = null;
|
||||
for (String headerName : headers) {
|
||||
header = request.getHeader(headerName);
|
||||
if (header == null) {
|
||||
throw parameterError("empty [%s], request-id=[%s]", headerName, requestId);
|
||||
}
|
||||
}
|
||||
|
||||
//判断请求是否过期
|
||||
String timestampStr = header;
|
||||
try {
|
||||
Instant responseTime = Instant.ofEpochSecond(Long.parseLong(timestampStr));
|
||||
// 拒绝过期请求
|
||||
if (Duration.between(responseTime, Instant.now()).abs().toMinutes() >= RESPONSE_EXPIRED_MINUTES) {
|
||||
throw parameterError("timestamp=[%s] expires, request-id=[%s]", timestampStr, requestId);
|
||||
}
|
||||
} catch (DateTimeException | NumberFormatException e) {
|
||||
throw parameterError("invalid timestamp=[%s], request-id=[%s]", timestampStr, requestId);
|
||||
}
|
||||
}
|
||||
|
||||
private String buildMessage(HttpServletRequest request) {
|
||||
String timestamp = request.getHeader(WECHAT_PAY_TIMESTAMP);
|
||||
String nonce = request.getHeader(WECHAT_PAY_NONCE);
|
||||
return timestamp + "\n"
|
||||
+ nonce + "\n"
|
||||
+ body + "\n";
|
||||
}
|
||||
|
||||
private String getResponseBody(CloseableHttpResponse response) throws IOException {
|
||||
HttpEntity entity = response.getEntity();
|
||||
return (entity != null && entity.isRepeatable()) ? EntityUtils.toString(entity) : "";
|
||||
}
|
||||
|
||||
/**
|
||||
* 对称解密,异步通知的加密数据
|
||||
* @param resource 加密数据
|
||||
* @param apiV3Key apiV3密钥
|
||||
* @param type 1-支付,2-退款
|
||||
* @return
|
||||
*/
|
||||
public static Map<String, Object> decryptFromResource(String resource,String apiV3Key,Integer type) {
|
||||
|
||||
String msg = type==1?"支付成功":"退款成功";
|
||||
log.info(msg+",回调通知,密文解密");
|
||||
try {
|
||||
//通知数据
|
||||
Map<String, Object> resourceMap = JSONObject.parseObject(resource, new TypeReference<Map<String, Object>>() {
|
||||
});
|
||||
//数据密文
|
||||
String ciphertext = resourceMap.get("ciphertext").toString();
|
||||
//随机串
|
||||
String nonce = resourceMap.get("nonce").toString();
|
||||
//附加数据
|
||||
String associatedData = resourceMap.get("associated_data").toString();
|
||||
|
||||
log.info("密文: {}", ciphertext);
|
||||
AesUtil aesUtil = new AesUtil(apiV3Key.getBytes(StandardCharsets.UTF_8));
|
||||
String resourceStr = aesUtil.decryptToString(associatedData.getBytes(StandardCharsets.UTF_8),
|
||||
nonce.getBytes(StandardCharsets.UTF_8),
|
||||
ciphertext);
|
||||
|
||||
log.info(msg+",回调通知,解密结果 明文: {}", resourceStr);
|
||||
return JSONObject.parseObject(resourceStr, new TypeReference<Map<String, Object>>(){});
|
||||
}catch (Exception e){
|
||||
throw new RuntimeException("回调参数,解密失败!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,97 +1,97 @@
|
||||
package com.peanut.modules.pay.weChatPay.util;
|
||||
|
||||
|
||||
import com.wechat.pay.contrib.apache.httpclient.auth.Verifier;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.DateTimeException;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
|
||||
import static com.wechat.pay.contrib.apache.httpclient.constant.WechatPayHttpHeaders.*;
|
||||
|
||||
public class WechatPayValidatorForRequest {
|
||||
protected static final Logger log = LoggerFactory.getLogger(WechatPayValidatorForRequest.class);
|
||||
/**
|
||||
* 应答超时时间,单位为分钟
|
||||
*/
|
||||
protected static final long RESPONSE_EXPIRED_MINUTES = 5;
|
||||
protected final Verifier verifier;
|
||||
protected final String body;
|
||||
protected final String requestId;
|
||||
|
||||
public WechatPayValidatorForRequest(Verifier verifier, String body, String requestId) {
|
||||
this.verifier = verifier;
|
||||
this.body = body;
|
||||
this.requestId = requestId;
|
||||
}
|
||||
|
||||
protected static IllegalArgumentException parameterError(String message, Object... args) {
|
||||
message = String.format(message, args);
|
||||
return new IllegalArgumentException("parameter error: " + message);
|
||||
}
|
||||
|
||||
protected static IllegalArgumentException verifyFail(String message, Object... args) {
|
||||
message = String.format(message, args);
|
||||
return new IllegalArgumentException("signature verify fail: " + message);
|
||||
}
|
||||
|
||||
public final boolean validate(HttpServletRequest request) throws IOException {
|
||||
try {
|
||||
validateParameters(request);
|
||||
|
||||
String message = buildMessage(request);
|
||||
String serial = request.getHeader(WECHAT_PAY_SERIAL);
|
||||
String signature = request.getHeader(WECHAT_PAY_SIGNATURE);
|
||||
|
||||
if (!verifier.verify(serial, message.getBytes(StandardCharsets.UTF_8), signature)) {
|
||||
|
||||
throw verifyFail("serial=[%s] message=[%s] sign=[%s], request-id=[%s]",
|
||||
serial, message, signature, request.getHeader(REQUEST_ID));
|
||||
}
|
||||
} catch (IllegalArgumentException e) {
|
||||
log.warn(e.getMessage());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected final void validateParameters(HttpServletRequest request) {
|
||||
|
||||
// NOTE: ensure HEADER_WECHAT_PAY_TIMESTAMP at last
|
||||
String[] headers = {WECHAT_PAY_SERIAL, WECHAT_PAY_SIGNATURE, WECHAT_PAY_NONCE, WECHAT_PAY_TIMESTAMP};
|
||||
|
||||
String header = null;
|
||||
for (String headerName : headers) {
|
||||
header = request.getHeader(headerName);
|
||||
if (header == null) {
|
||||
throw parameterError("empty [%s], request-id=[%s]", headerName, requestId);
|
||||
}
|
||||
}
|
||||
|
||||
String timestampStr = header;
|
||||
try {
|
||||
Instant responseTime = Instant.ofEpochSecond(Long.parseLong(timestampStr));
|
||||
// 拒绝过期应答
|
||||
if (Duration.between(responseTime, Instant.now()).abs().toMinutes() >= RESPONSE_EXPIRED_MINUTES) {
|
||||
throw parameterError("timestamp=[%s] expires, request-id=[%s]", timestampStr, requestId);
|
||||
}
|
||||
} catch (DateTimeException | NumberFormatException e) {
|
||||
throw parameterError("invalid timestamp=[%s], request-id=[%s]", timestampStr, requestId);
|
||||
}
|
||||
}
|
||||
|
||||
protected final String buildMessage(HttpServletRequest request) throws IOException {
|
||||
String timestamp = request.getHeader(WECHAT_PAY_TIMESTAMP);
|
||||
String nonce = request.getHeader(WECHAT_PAY_NONCE);
|
||||
return timestamp + "\n"
|
||||
+ nonce + "\n"
|
||||
+ body + "\n";
|
||||
}
|
||||
|
||||
}
|
||||
package com.peanut.modules.pay.weChatPay.util;
|
||||
|
||||
|
||||
import com.wechat.pay.contrib.apache.httpclient.auth.Verifier;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.DateTimeException;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
|
||||
import static com.wechat.pay.contrib.apache.httpclient.constant.WechatPayHttpHeaders.*;
|
||||
|
||||
public class WechatPayValidatorForRequest {
|
||||
protected static final Logger log = LoggerFactory.getLogger(WechatPayValidatorForRequest.class);
|
||||
/**
|
||||
* 应答超时时间,单位为分钟
|
||||
*/
|
||||
protected static final long RESPONSE_EXPIRED_MINUTES = 5;
|
||||
protected final Verifier verifier;
|
||||
protected final String body;
|
||||
protected final String requestId;
|
||||
|
||||
public WechatPayValidatorForRequest(Verifier verifier, String body, String requestId) {
|
||||
this.verifier = verifier;
|
||||
this.body = body;
|
||||
this.requestId = requestId;
|
||||
}
|
||||
|
||||
protected static IllegalArgumentException parameterError(String message, Object... args) {
|
||||
message = String.format(message, args);
|
||||
return new IllegalArgumentException("parameter error: " + message);
|
||||
}
|
||||
|
||||
protected static IllegalArgumentException verifyFail(String message, Object... args) {
|
||||
message = String.format(message, args);
|
||||
return new IllegalArgumentException("signature verify fail: " + message);
|
||||
}
|
||||
|
||||
public final boolean validate(HttpServletRequest request) throws IOException {
|
||||
try {
|
||||
validateParameters(request);
|
||||
|
||||
String message = buildMessage(request);
|
||||
String serial = request.getHeader(WECHAT_PAY_SERIAL);
|
||||
String signature = request.getHeader(WECHAT_PAY_SIGNATURE);
|
||||
|
||||
if (!verifier.verify(serial, message.getBytes(StandardCharsets.UTF_8), signature)) {
|
||||
|
||||
throw verifyFail("serial=[%s] message=[%s] sign=[%s], request-id=[%s]",
|
||||
serial, message, signature, request.getHeader(REQUEST_ID));
|
||||
}
|
||||
} catch (IllegalArgumentException e) {
|
||||
log.warn(e.getMessage());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected final void validateParameters(HttpServletRequest request) {
|
||||
|
||||
// NOTE: ensure HEADER_WECHAT_PAY_TIMESTAMP at last
|
||||
String[] headers = {WECHAT_PAY_SERIAL, WECHAT_PAY_SIGNATURE, WECHAT_PAY_NONCE, WECHAT_PAY_TIMESTAMP};
|
||||
|
||||
String header = null;
|
||||
for (String headerName : headers) {
|
||||
header = request.getHeader(headerName);
|
||||
if (header == null) {
|
||||
throw parameterError("empty [%s], request-id=[%s]", headerName, requestId);
|
||||
}
|
||||
}
|
||||
|
||||
String timestampStr = header;
|
||||
try {
|
||||
Instant responseTime = Instant.ofEpochSecond(Long.parseLong(timestampStr));
|
||||
// 拒绝过期应答
|
||||
if (Duration.between(responseTime, Instant.now()).abs().toMinutes() >= RESPONSE_EXPIRED_MINUTES) {
|
||||
throw parameterError("timestamp=[%s] expires, request-id=[%s]", timestampStr, requestId);
|
||||
}
|
||||
} catch (DateTimeException | NumberFormatException e) {
|
||||
throw parameterError("invalid timestamp=[%s], request-id=[%s]", timestampStr, requestId);
|
||||
}
|
||||
}
|
||||
|
||||
protected final String buildMessage(HttpServletRequest request) throws IOException {
|
||||
String timestamp = request.getHeader(WECHAT_PAY_TIMESTAMP);
|
||||
String nonce = request.getHeader(WECHAT_PAY_NONCE);
|
||||
return timestamp + "\n"
|
||||
+ nonce + "\n"
|
||||
+ body + "\n";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,148 +1,148 @@
|
||||
package com.peanut.modules.pay.weChatPay.util;
|
||||
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder;
|
||||
import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;
|
||||
import lombok.Data;
|
||||
import org.apache.http.HttpEntity;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.entity.StringEntity;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.util.EntityUtils;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.Signature;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Base64;
|
||||
|
||||
@Component
|
||||
@Data
|
||||
public class WxPayUtil {
|
||||
|
||||
public static final String mchId = "1612860909"; // 商户号
|
||||
|
||||
public static final String appId = "wx47134a8f15083734"; // appId
|
||||
|
||||
public static final String apiV3Key = "4aYFklzaULeGlr7oJPZ6rHWKcxjihZUF"; // apiV3秘钥
|
||||
//商户私钥路径
|
||||
public static final String privateKeyUrl = "/usr/local/hs/peanut_book/target/classes/cent/apiclient_key.pem";
|
||||
// public static final String privateKeyUrl = "C:/Users/Administrator/IdeaProjects/peanut_book/src/main/resources/cent/apiclient_key.pem";
|
||||
|
||||
//平台证书路径
|
||||
public static final String wechatPayCertificateUrl = "/usr/local/hs/peanut_book/target/classes/cent/wechatpay_7B5676E3CDF56680D0414A009CE501C844DBE2D6.pem";
|
||||
// public static final String wechatPayCertificateUrl = "C:/Users/Administrator/IdeaProjects/peanut_book/src/main/resources/cent/wechatpay_7B5676E3CDF56680D0414A009CE501C844DBE2D6.pem";
|
||||
//第一步申请完证书后,在API证书哪里点击管理证书就能看到
|
||||
public static final String mchSerialNo = "679AECB2F7AC4183033F713828892BA640E4EEE3"; // 商户证书序列号
|
||||
|
||||
private CloseableHttpClient httpClient;
|
||||
|
||||
public void setup() {
|
||||
PrivateKey merchantPrivateKey = null;
|
||||
X509Certificate wechatPayCertificate = null;
|
||||
|
||||
try {
|
||||
merchantPrivateKey = PemUtil.loadPrivateKey(
|
||||
new FileInputStream(privateKeyUrl));
|
||||
wechatPayCertificate = PemUtil.loadCertificate(
|
||||
new FileInputStream(wechatPayCertificateUrl));
|
||||
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
ArrayList<X509Certificate> listCertificates = new ArrayList<>();
|
||||
listCertificates.add(wechatPayCertificate);
|
||||
|
||||
WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create()
|
||||
.withMerchant(mchId, mchSerialNo, merchantPrivateKey)
|
||||
.withWechatPay(listCertificates);
|
||||
httpClient = builder.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* wxMchid商户号
|
||||
* wxCertno证书编号
|
||||
* wxCertPath证书地址
|
||||
* wxPaternerKey v3秘钥
|
||||
* url 下单地址
|
||||
* body 构造好的消息体
|
||||
*/
|
||||
public JSONObject doPostWexinV3(String url, String body) {
|
||||
if (httpClient == null) {
|
||||
setup();
|
||||
}
|
||||
|
||||
HttpPost httpPost = new HttpPost(url);
|
||||
httpPost.addHeader("Content-Type", "application/json;chartset=utf-8");
|
||||
httpPost.addHeader("Accept", "application/json");
|
||||
try {
|
||||
if (body == null) {
|
||||
throw new IllegalArgumentException("data参数不能为空");
|
||||
}
|
||||
StringEntity stringEntity = new StringEntity(body, "utf-8");
|
||||
httpPost.setEntity(stringEntity);
|
||||
// 直接执行execute方法,官方会自动处理签名和验签,并进行证书自动更新
|
||||
HttpResponse httpResponse = httpClient.execute(httpPost);
|
||||
HttpEntity httpEntity = httpResponse.getEntity();
|
||||
|
||||
if (httpResponse.getStatusLine().getStatusCode() == 200) {
|
||||
String jsonResult = EntityUtils.toString(httpEntity);
|
||||
|
||||
return JSONObject.parseObject(jsonResult);
|
||||
} else {
|
||||
System.err.println("微信支付错误信息" + EntityUtils.toString(httpEntity));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
//获取签名
|
||||
public String getSign(String appId, long timestamp, String nonceStr, String pack){
|
||||
String message = buildMessage(appId, timestamp, nonceStr, pack);
|
||||
String paySign= null;
|
||||
try {
|
||||
paySign = sign(message.getBytes("utf-8"));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return paySign;
|
||||
}
|
||||
|
||||
private String buildMessage(String appId, long timestamp, String nonceStr, String pack) {
|
||||
return appId + "\n"
|
||||
+ timestamp + "\n"
|
||||
+ nonceStr + "\n"
|
||||
+ pack + "\n";
|
||||
}
|
||||
private String sign(byte[] message) throws Exception{
|
||||
PrivateKey merchantPrivateKey = null;
|
||||
X509Certificate wechatPayCertificate = null;
|
||||
|
||||
try {
|
||||
merchantPrivateKey = PemUtil.loadPrivateKey(
|
||||
new FileInputStream(privateKeyUrl));
|
||||
wechatPayCertificate = PemUtil.loadCertificate(
|
||||
new FileInputStream(wechatPayCertificateUrl));
|
||||
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
Signature sign = Signature.getInstance("SHA256withRSA");
|
||||
|
||||
sign.initSign(merchantPrivateKey);
|
||||
sign.update(message);
|
||||
return Base64.getEncoder().encodeToString(sign.sign());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
package com.peanut.modules.pay.weChatPay.util;
|
||||
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder;
|
||||
import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;
|
||||
import lombok.Data;
|
||||
import org.apache.http.HttpEntity;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.entity.StringEntity;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.util.EntityUtils;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.Signature;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Base64;
|
||||
|
||||
@Component
|
||||
@Data
|
||||
public class WxPayUtil {
|
||||
|
||||
public static final String mchId = "1612860909"; // 商户号
|
||||
|
||||
public static final String appId = "wx47134a8f15083734"; // appId
|
||||
|
||||
public static final String apiV3Key = "4aYFklzaULeGlr7oJPZ6rHWKcxjihZUF"; // apiV3秘钥
|
||||
//商户私钥路径
|
||||
public static final String privateKeyUrl = "/usr/local/hs/peanut_book/target/classes/cent/apiclient_key.pem";
|
||||
// public static final String privateKeyUrl = "C:/Users/Administrator/IdeaProjects/peanut_book/src/main/resources/cent/apiclient_key.pem";
|
||||
|
||||
//平台证书路径
|
||||
public static final String wechatPayCertificateUrl = "/usr/local/hs/peanut_book/target/classes/cent/wechatpay_7B5676E3CDF56680D0414A009CE501C844DBE2D6.pem";
|
||||
// public static final String wechatPayCertificateUrl = "C:/Users/Administrator/IdeaProjects/peanut_book/src/main/resources/cent/wechatpay_7B5676E3CDF56680D0414A009CE501C844DBE2D6.pem";
|
||||
//第一步申请完证书后,在API证书哪里点击管理证书就能看到
|
||||
public static final String mchSerialNo = "679AECB2F7AC4183033F713828892BA640E4EEE3"; // 商户证书序列号
|
||||
|
||||
private CloseableHttpClient httpClient;
|
||||
|
||||
public void setup() {
|
||||
PrivateKey merchantPrivateKey = null;
|
||||
X509Certificate wechatPayCertificate = null;
|
||||
|
||||
try {
|
||||
merchantPrivateKey = PemUtil.loadPrivateKey(
|
||||
new FileInputStream(privateKeyUrl));
|
||||
wechatPayCertificate = PemUtil.loadCertificate(
|
||||
new FileInputStream(wechatPayCertificateUrl));
|
||||
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
ArrayList<X509Certificate> listCertificates = new ArrayList<>();
|
||||
listCertificates.add(wechatPayCertificate);
|
||||
|
||||
WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create()
|
||||
.withMerchant(mchId, mchSerialNo, merchantPrivateKey)
|
||||
.withWechatPay(listCertificates);
|
||||
httpClient = builder.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* wxMchid商户号
|
||||
* wxCertno证书编号
|
||||
* wxCertPath证书地址
|
||||
* wxPaternerKey v3秘钥
|
||||
* url 下单地址
|
||||
* body 构造好的消息体
|
||||
*/
|
||||
public JSONObject doPostWexinV3(String url, String body) {
|
||||
if (httpClient == null) {
|
||||
setup();
|
||||
}
|
||||
|
||||
HttpPost httpPost = new HttpPost(url);
|
||||
httpPost.addHeader("Content-Type", "application/json;chartset=utf-8");
|
||||
httpPost.addHeader("Accept", "application/json");
|
||||
try {
|
||||
if (body == null) {
|
||||
throw new IllegalArgumentException("data参数不能为空");
|
||||
}
|
||||
StringEntity stringEntity = new StringEntity(body, "utf-8");
|
||||
httpPost.setEntity(stringEntity);
|
||||
// 直接执行execute方法,官方会自动处理签名和验签,并进行证书自动更新
|
||||
HttpResponse httpResponse = httpClient.execute(httpPost);
|
||||
HttpEntity httpEntity = httpResponse.getEntity();
|
||||
|
||||
if (httpResponse.getStatusLine().getStatusCode() == 200) {
|
||||
String jsonResult = EntityUtils.toString(httpEntity);
|
||||
|
||||
return JSONObject.parseObject(jsonResult);
|
||||
} else {
|
||||
System.err.println("微信支付错误信息" + EntityUtils.toString(httpEntity));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
//获取签名
|
||||
public String getSign(String appId, long timestamp, String nonceStr, String pack){
|
||||
String message = buildMessage(appId, timestamp, nonceStr, pack);
|
||||
String paySign= null;
|
||||
try {
|
||||
paySign = sign(message.getBytes("utf-8"));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return paySign;
|
||||
}
|
||||
|
||||
private String buildMessage(String appId, long timestamp, String nonceStr, String pack) {
|
||||
return appId + "\n"
|
||||
+ timestamp + "\n"
|
||||
+ nonceStr + "\n"
|
||||
+ pack + "\n";
|
||||
}
|
||||
private String sign(byte[] message) throws Exception{
|
||||
PrivateKey merchantPrivateKey = null;
|
||||
X509Certificate wechatPayCertificate = null;
|
||||
|
||||
try {
|
||||
merchantPrivateKey = PemUtil.loadPrivateKey(
|
||||
new FileInputStream(privateKeyUrl));
|
||||
wechatPayCertificate = PemUtil.loadCertificate(
|
||||
new FileInputStream(wechatPayCertificateUrl));
|
||||
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
Signature sign = Signature.getInstance("SHA256withRSA");
|
||||
|
||||
sign.initSign(merchantPrivateKey);
|
||||
sign.update(message);
|
||||
return Base64.getEncoder().encodeToString(sign.sign());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user