no message
This commit is contained in:
159
src/main/java/com/sczx/pay/utils/ComputerInfo.java
Normal file
159
src/main/java/com/sczx/pay/utils/ComputerInfo.java
Normal file
@ -0,0 +1,159 @@
|
||||
package com.sczx.pay.utils;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.InetAddress;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/*
|
||||
* <取网卡物理地址--
|
||||
* 1.在Windows,Linux系统下均可用;
|
||||
* 2.通过ipconifg,ifconfig获得计算机信息;
|
||||
* 3.再用模式匹配方式查找MAC地址,与操作系统的语言无关>
|
||||
*
|
||||
* //* Description: <取计算机名--从环境变量中取>
|
||||
* abstract 限制继承/创建实例
|
||||
*/
|
||||
public abstract class ComputerInfo {
|
||||
private static String macAddressStr = null;
|
||||
private static String computerName = System.getenv().get("COMPUTERNAME");
|
||||
|
||||
private static final String[] windowsCommand = { "ipconfig", "/all" };
|
||||
private static final String[] linuxCommand = { "/sbin/ifconfig", "-a" };
|
||||
private static final String[] macCommand = { "ifconfig", "-a" };
|
||||
private static final Pattern macPattern = Pattern.compile(".*((:?[0-9a-f]{2}[-:]){5}[0-9a-f]{2}).*",
|
||||
Pattern.CASE_INSENSITIVE);
|
||||
|
||||
/**
|
||||
* 获取多个网卡地址
|
||||
*
|
||||
* @return
|
||||
* @throws IOException
|
||||
*/
|
||||
private final static List<String> getMacAddressList() throws IOException {
|
||||
final ArrayList<String> macAddressList = new ArrayList<String>();
|
||||
final String os = System.getProperty("os.name");
|
||||
final String command[];
|
||||
|
||||
if (os.startsWith("Windows")) {
|
||||
command = windowsCommand;
|
||||
} else if (os.startsWith("Linux")) {
|
||||
command = linuxCommand;
|
||||
} else if (os.startsWith("Mac")){
|
||||
command = macCommand;
|
||||
}
|
||||
else {
|
||||
throw new IOException("Unknow operating system:" + os);
|
||||
}
|
||||
// 执行命令
|
||||
final Process process = Runtime.getRuntime().exec(command);
|
||||
|
||||
BufferedReader bufReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
|
||||
for (String line = null; (line = bufReader.readLine()) != null;) {
|
||||
Matcher matcher = macPattern.matcher(line);
|
||||
if (matcher.matches()) {
|
||||
macAddressList.add(matcher.group(1));
|
||||
// macAddressList.add(matcher.group(1).replaceAll("[-:]",
|
||||
// ""));//去掉MAC中的“-”
|
||||
}
|
||||
}
|
||||
|
||||
process.destroy();
|
||||
bufReader.close();
|
||||
return macAddressList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取一个网卡地址(多个网卡时从中获取一个)
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static String getMacAddress() {
|
||||
if (macAddressStr == null || macAddressStr.equals("")) {
|
||||
StringBuffer sb = new StringBuffer(); // 存放多个网卡地址用,目前只取一个非0000000000E0隧道的值
|
||||
try {
|
||||
List<String> macList = getMacAddressList();
|
||||
for (Iterator<String> iter = macList.iterator(); iter.hasNext();) {
|
||||
String amac = iter.next();
|
||||
if (!"0000000000E0".equals(amac)) {
|
||||
sb.append(amac);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
macAddressStr = sb.toString();
|
||||
|
||||
}
|
||||
|
||||
return macAddressStr;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取电脑名
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static String getComputerName() {
|
||||
if (computerName == null || computerName.equals("")) {
|
||||
computerName = System.getenv().get("COMPUTERNAME");
|
||||
}
|
||||
return computerName;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取客户端IP地址
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static String getIpAddrAndName() throws IOException {
|
||||
return InetAddress.getLocalHost().toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取客户端IP地址
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static String getIpAddr() throws IOException {
|
||||
return InetAddress.getLocalHost().getHostAddress().toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取电脑唯一标识
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static String getComputerID() {
|
||||
String id = getMacAddress();
|
||||
if (id == null || id.equals("")) {
|
||||
try {
|
||||
id = getIpAddrAndName();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return computerName;
|
||||
}
|
||||
|
||||
/**
|
||||
* 限制创建实例
|
||||
*/
|
||||
private ComputerInfo() {
|
||||
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
System.out.println(ComputerInfo.getMacAddress());
|
||||
System.out.println(ComputerInfo.getComputerName());
|
||||
System.out.println(ComputerInfo.getIpAddr());
|
||||
System.out.println(ComputerInfo.getIpAddrAndName());
|
||||
}
|
||||
}
|
||||
135
src/main/java/com/sczx/pay/utils/IPUtils.java
Normal file
135
src/main/java/com/sczx/pay/utils/IPUtils.java
Normal file
@ -0,0 +1,135 @@
|
||||
package com.sczx.pay.utils;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.InetAddress;
|
||||
import java.net.URL;
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
/**
|
||||
* IP地址工具类
|
||||
*/
|
||||
public class IPUtils {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(IPUtils.class);
|
||||
|
||||
// 多个IP查询服务,以防某个服务不可用
|
||||
private static final String[] IP_SERVICES = {
|
||||
"https://api.ipify.org",
|
||||
"https://icanhazip.com",
|
||||
"https://ident.me"
|
||||
};
|
||||
|
||||
private static String cachedPublicIP = null;
|
||||
private static long lastFetchTime = 0;
|
||||
private static final long CACHE_DURATION = 30 * 60 * 1000; // 30分钟缓存
|
||||
|
||||
/**
|
||||
* 获取服务器公网IP地址
|
||||
* @return 公网IP地址
|
||||
*/
|
||||
public static String getServerPublicIP() {
|
||||
// 检查缓存
|
||||
if (cachedPublicIP != null && (System.currentTimeMillis() - lastFetchTime) < CACHE_DURATION) {
|
||||
return cachedPublicIP;
|
||||
}
|
||||
|
||||
// 首先尝试从外部服务获取公网IP
|
||||
String publicIP = fetchPublicIPFromExternalService();
|
||||
if (publicIP != null && !publicIP.isEmpty()) {
|
||||
cachedPublicIP = publicIP;
|
||||
lastFetchTime = System.currentTimeMillis();
|
||||
return publicIP;
|
||||
}
|
||||
|
||||
// 如果外部服务不可用,则获取本地IP
|
||||
try {
|
||||
String localIP = InetAddress.getLocalHost().getHostAddress();
|
||||
logger.warn("无法获取公网IP,使用本地IP: {}", localIP);
|
||||
return localIP;
|
||||
} catch (UnknownHostException e) {
|
||||
logger.error("获取本地IP失败", e);
|
||||
return "127.0.0.1";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 从外部服务获取公网IP
|
||||
* @return 公网IP地址
|
||||
*/
|
||||
private static String fetchPublicIPFromExternalService() {
|
||||
for (String serviceUrl : IP_SERVICES) {
|
||||
try {
|
||||
String ip = fetchIPFromService(serviceUrl);
|
||||
if (isValidIP(ip)) {
|
||||
logger.info("成功从 {} 获取公网IP: {}", serviceUrl, ip);
|
||||
return ip;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.warn("从服务 {} 获取IP失败: {}", serviceUrl, e.getMessage());
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从指定服务获取IP
|
||||
* @param serviceUrl 服务URL
|
||||
* @return IP地址
|
||||
* @throws Exception 网络异常
|
||||
*/
|
||||
private static String fetchIPFromService(String serviceUrl) throws Exception {
|
||||
URL url = new URL(serviceUrl);
|
||||
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
||||
connection.setRequestMethod("GET");
|
||||
connection.setConnectTimeout(5000);
|
||||
connection.setReadTimeout(5000);
|
||||
|
||||
try (BufferedReader reader = new BufferedReader(
|
||||
new InputStreamReader(connection.getInputStream()))) {
|
||||
return reader.readLine().trim();
|
||||
} finally {
|
||||
connection.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证IP地址是否有效
|
||||
* @param ip IP地址
|
||||
* @return 是否有效
|
||||
*/
|
||||
private static boolean isValidIP(String ip) {
|
||||
if (ip == null || ip.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 简单的IP格式验证
|
||||
String[] parts = ip.split("\\.");
|
||||
if (parts.length != 4) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (String part : parts) {
|
||||
try {
|
||||
int num = Integer.parseInt(part);
|
||||
if (num < 0 || num > 255) {
|
||||
return false;
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// 排除私有IP和回环地址
|
||||
if (ip.startsWith("127.") || ip.startsWith("10.") ||
|
||||
ip.startsWith("192.168.") || ip.startsWith("172.")) {
|
||||
// 私有地址也可以接受,因为可能在内网环境中使用
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
167
src/main/java/com/sczx/pay/utils/WXPayUtil.java
Normal file
167
src/main/java/com/sczx/pay/utils/WXPayUtil.java
Normal file
@ -0,0 +1,167 @@
|
||||
package com.sczx.pay.utils;
|
||||
|
||||
import org.apache.commons.codec.digest.DigestUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
import javax.crypto.Mac;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.transform.OutputKeys;
|
||||
import javax.xml.transform.Transformer;
|
||||
import javax.xml.transform.TransformerFactory;
|
||||
import javax.xml.transform.dom.DOMSource;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.StringWriter;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.*;
|
||||
|
||||
public class WXPayUtil {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(WXPayUtil.class);
|
||||
private static final String CHARSET = "UTF-8";
|
||||
private static final SecureRandom random = new SecureRandom();
|
||||
|
||||
/**
|
||||
* 生成随机字符串
|
||||
*/
|
||||
public static String generateNonceStr() {
|
||||
return UUID.randomUUID().toString().replace("-", "").substring(0, 32);
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成签名
|
||||
*/
|
||||
public static String generateSignature(Map<String, String> data, String key) throws Exception {
|
||||
return generateSignature(data, key, "MD5");
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成签名
|
||||
*/
|
||||
public static String generateSignature(Map<String, String> data, String key, String signType) throws Exception {
|
||||
Set<String> keySet = data.keySet();
|
||||
String[] keyArray = keySet.toArray(new String[0]);
|
||||
Arrays.sort(keyArray);
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (String k : keyArray) {
|
||||
if (k.equals("sign")) {
|
||||
continue;
|
||||
}
|
||||
String value = data.get(k);
|
||||
if (value != null && value.trim().length() > 0) {
|
||||
sb.append(k).append("=").append(value.trim()).append("&");
|
||||
}
|
||||
}
|
||||
|
||||
sb.append("key=").append(key);
|
||||
|
||||
if ("MD5".equals(signType)) {
|
||||
return DigestUtils.md5Hex(sb.toString()).toUpperCase();
|
||||
} else if ("HMAC-SHA256".equals(signType)) {
|
||||
return HMACSHA256(sb.toString(), key);
|
||||
} else {
|
||||
throw new Exception("Invalid sign_type: " + signType);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* HMAC-SHA256签名
|
||||
*/
|
||||
private static String HMACSHA256(String data, String key) throws Exception {
|
||||
Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
|
||||
SecretKeySpec secret_key = new SecretKeySpec(key.getBytes(CHARSET), "HmacSHA256");
|
||||
sha256_HMAC.init(secret_key);
|
||||
byte[] array = sha256_HMAC.doFinal(data.getBytes(CHARSET));
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (byte item : array) {
|
||||
sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3));
|
||||
}
|
||||
return sb.toString().toUpperCase();
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证签名
|
||||
*/
|
||||
public static boolean isSignatureValid(Map<String, String> data, String key) throws Exception {
|
||||
if (!data.containsKey("sign")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
String sign = data.get("sign");
|
||||
String calculatedSign = generateSignature(data, key);
|
||||
return sign.equals(calculatedSign);
|
||||
}
|
||||
|
||||
/**
|
||||
* XML字符串转换为Map
|
||||
*/
|
||||
public static Map<String, String> xmlToMap(String strXML) throws Exception {
|
||||
Map<String, String> data = new HashMap<>();
|
||||
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
|
||||
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
|
||||
Document doc = documentBuilder.parse(new ByteArrayInputStream(strXML.getBytes(CHARSET)));
|
||||
|
||||
doc.getDocumentElement().normalize();
|
||||
NodeList nodeList = doc.getDocumentElement().getChildNodes();
|
||||
|
||||
for (int i = 0; i < nodeList.getLength(); i++) {
|
||||
Node node = nodeList.item(i);
|
||||
if (node.getNodeType() == Node.ELEMENT_NODE) {
|
||||
Element element = (Element) node;
|
||||
data.put(element.getNodeName(), element.getTextContent());
|
||||
}
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Map转换为XML字符串
|
||||
*/
|
||||
public static String mapToXml(Map<String, String> data) throws Exception {
|
||||
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
|
||||
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
|
||||
Document document = documentBuilder.newDocument();
|
||||
|
||||
Element root = document.createElement("xml");
|
||||
document.appendChild(root);
|
||||
|
||||
for (String key : data.keySet()) {
|
||||
String value = data.get(key);
|
||||
if (value == null) {
|
||||
value = "";
|
||||
}
|
||||
|
||||
Element filed = document.createElement(key);
|
||||
filed.appendChild(document.createTextNode(value));
|
||||
root.appendChild(filed);
|
||||
}
|
||||
|
||||
TransformerFactory tf = TransformerFactory.newInstance();
|
||||
Transformer transformer = tf.newTransformer();
|
||||
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
|
||||
DOMSource source = new DOMSource(document);
|
||||
StringWriter writer = new StringWriter();
|
||||
StreamResult result = new StreamResult(writer);
|
||||
transformer.transform(source, result);
|
||||
|
||||
return writer.getBuffer().toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证微信支付通知签名
|
||||
*/
|
||||
public static boolean isSignatureValid(String xmlString, String key) throws Exception {
|
||||
Map<String, String> data = xmlToMap(xmlString);
|
||||
return isSignatureValid(data, key);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user