no message

This commit is contained in:
2025-08-21 17:33:28 +08:00
commit 9d744548d1
27 changed files with 2880 additions and 0 deletions

View 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());
}
}

View 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;
}
}

View 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);
}
}