计算微信下载回单文件的哈希值,以确认下载账单数据的完整性

简介: 微信回单文件的哈希值,是微信支付为商户下载的电子回单文件生成的一个固定长度且唯一的字符串,也常被称为“数字指纹”。它主要用于验证回单文件的完整性和真实性。

大家好,我是小悟。


微信回单文件的哈希值,是微信支付为商户下载的电子回单文件生成的一个固定长度且唯一的字符串,也常被称为“数字指纹”。它主要用于验证回单文件的完整性和真实性。


可靠的哈希函数具有“雪崩效应”,即原始数据哪怕只发生一个比特的改变,计算出的哈希值也会截然不同。这使得它极其灵敏,能够有效发现文件的任何改动。


处理微信的回单文件并计算其哈希值,通常涉及获取文件、选择算法和实际计算几个步骤。


1. 基础版本 - 计算文件MD5SHA-256

import java.io.FileInputStream;
import java.security.MessageDigest;
import java.util.HexFormat;
public class WechatBillDigest {
    /**
     * 计算文件的MD5摘要值
     */
    public static String calculateMD5(String filePath) throws Exception {
        return calculateDigest(filePath, "MD5");
    }
    /**
     * 计算文件的SHA-256摘要值
     */
    public static String calculateSHA256(String filePath) throws Exception {
        return calculateDigest(filePath, "SHA-256");
    }
    /**
     * 通用摘要计算方法
     */
    private static String calculateDigest(String filePath, String algorithm) throws Exception {
        MessageDigest digest = MessageDigest.getInstance(algorithm);
        try (FileInputStream fis = new FileInputStream(filePath)) {
            byte[] buffer = new byte[8192];
            int bytesRead;
            while ((bytesRead = fis.read(buffer)) != -1) {
                digest.update(buffer, 0, bytesRead);
            }
        }
        byte[] hashBytes = digest.digest();
        return HexFormat.of().formatHex(hashBytes);
    }
}

2. 完整工具类(支持多种算法)

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.HexFormat;
public class WechatBillDigestUtil {
    public enum DigestAlgorithm {
        MD5("MD5"),
        SHA1("SHA-1"),
        SHA256("SHA-256"),
        SHA512("SHA-512");
        private final String algorithm;
        DigestAlgorithm(String algorithm) {
            this.algorithm = algorithm;
        }
        public String getAlgorithm() {
            return algorithm;
        }
    }
    /**
     * 计算微信回单文件的摘要值
     */
    public static String calculateDigest(File file, DigestAlgorithm algorithm) 
            throws NoSuchAlgorithmException, IOException {
        if (!file.exists()) {
            throw new IOException("文件不存在: " + file.getAbsolutePath());
        }
        if (!file.isFile()) {
            throw new IOException("路径不是文件: " + file.getAbsolutePath());
        }
        MessageDigest digest = MessageDigest.getInstance(algorithm.getAlgorithm());
        try (FileInputStream fis = new FileInputStream(file)) {
            byte[] buffer = new byte[8192];
            int bytesRead;
            while ((bytesRead = fis.read(buffer)) != -1) {
                digest.update(buffer, 0, bytesRead);
            }
        }
        byte[] hashBytes = digest.digest();
        return HexFormat.of().formatHex(hashBytes);
    }
    /**
     * 批量计算多种摘要值
     */
    public static void calculateAllDigests(String filePath) {
        File file = new File(filePath);
        if (!file.exists()) {
            System.out.println("文件不存在: " + filePath);
            return;
        }
        System.out.println("文件: " + file.getName());
        System.out.println("大小: " + file.length() + " 字节");
        System.out.println("最后修改: " + new java.util.Date(file.lastModified()));
        System.out.println("----------------------------------------");
        for (DigestAlgorithm algorithm : DigestAlgorithm.values()) {
            try {
                String digest = calculateDigest(file, algorithm);
                System.out.printf("%-8s: %s%n", algorithm.name(), digest);
            } catch (Exception e) {
                System.out.printf("%-8s: 计算失败 - %s%n", algorithm.name(), e.getMessage());
            }
        }
    }
}

3. 带进度显示的高级版本

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.MessageDigest;
import java.text.DecimalFormat;
public class WechatBillDigestWithProgress {
    /**
     * 带进度显示的文件摘要计算
     */
    public static String calculateDigestWithProgress(String filePath, String algorithm) 
            throws Exception {
        File file = new File(filePath);
        if (!file.exists()) {
            throw new IOException("文件不存在: " + filePath);
        }
        long fileSize = file.length();
        MessageDigest digest = MessageDigest.getInstance(algorithm);
        try (FileInputStream fis = new FileInputStream(file)) {
            byte[] buffer = new byte[8192];
            int bytesRead;
            long totalRead = 0;
            long lastProgress = -1;
            System.out.println("开始计算文件摘要...");
            System.out.println("文件大小: " + formatFileSize(fileSize));
            while ((bytesRead = fis.read(buffer)) != -1) {
                digest.update(buffer, 0, bytesRead);
                totalRead += bytesRead;
                // 显示进度(每10%更新一次)
                int progress = (int) ((totalRead * 100) / fileSize);
                if (progress != lastProgress && progress % 10 == 0) {
                    System.out.printf("计算进度: %d%%%n", progress);
                    lastProgress = progress;
                }
            }
            System.out.println("计算完成: 100%");
        }
        byte[] hashBytes = digest.digest();
        return bytesToHex(hashBytes);
    }
    /**
     * 字节数组转十六进制字符串
     */
    private static String bytesToHex(byte[] bytes) {
        StringBuilder hexString = new StringBuilder();
        for (byte b : bytes) {
            String hex = Integer.toHexString(0xff & b);
            if (hex.length() == 1) {
                hexString.append('0');
            }
            hexString.append(hex);
        }
        return hexString.toString();
    }
    /**
     * 格式化文件大小
     */
    private static String formatFileSize(long size) {
        if (size <= 0) return "0 B";
        final String[] units = new String[]{"B", "KB", "MB", "GB", "TB"};
        int digitGroups = (int) (Math.log10(size) / Math.log10(1024));
        return new DecimalFormat("#,##0.#").format(size / Math.pow(1024, digitGroups)) 
                + " " + units[digitGroups];
    }
}

4. 使用示例

public class WechatBillDigestExample {
    public static void main(String[] args) {
        String filePath = "path/to/wechat/bill.csv"; // 替换为实际文件路径
        try {
            // 方法1: 基础使用
            String md5 = WechatBillDigest.calculateMD5(filePath);
            String sha256 = WechatBillDigest.calculateSHA256(filePath);
            System.out.println("MD5: " + md5);
            System.out.println("SHA-256: " + sha256);
            System.out.println();
            // 方法2: 使用工具类计算所有摘要
            WechatBillDigestUtil.calculateAllDigests(filePath);
            System.out.println();
            // 方法3: 带进度显示
            String digestWithProgress = WechatBillDigestWithProgress
                    .calculateDigestWithProgress(filePath, "SHA-256");
            System.out.println("最终摘要值: " + digestWithProgress);
        } catch (Exception e) {
            System.err.println("计算摘要时出错: " + e.getMessage());
            e.printStackTrace();
        }
    }
}

5. Maven依赖(如果需要第三方库)

<dependencies>
    <!-- Apache Commons Codec 提供更多摘要算法支持 -->
    <dependency>
        <groupId>commons-codec</groupId>
        <artifactId>commons-codec</artifactId>
        <version>1.16.0</version>
    </dependency>
</dependencies>

多种算法支持:MD5、SHA-1、SHA-256、SHA-512


大文件优化:使用缓冲区读取,避免内存溢出


进度显示:可显示计算进度


异常处理:完善的错误处理机制


格式规范:输出标准的十六进制字符串


计算微信下载回单文件的哈希值,以确认下载账单数据的完整性.jpg


谢谢你看我的文章,既然看到这里了,如果觉得不错,随手点个赞、转发、在看三连吧,感谢感谢。那我们,下次再见。


您的一键三连,是我更新的最大动力,谢谢


山水有相逢,来日皆可期,谢谢阅读,我们再会


我手中的金箍棒,上能通天,下能探海

相关文章
|
消息中间件 人工智能 移动开发
阿里云Rocket MQ PHP Http SDK发送消息示例Demo
消息队列 RocketMQ 版支持 RESTful 风格的 HTTP 协议通信,并提供了以下 7 种语言的 SDK,下面以最新的PHP Http SDK为范例介绍RocketMQ消息的发送。
3249 0
阿里云Rocket MQ PHP Http SDK发送消息示例Demo
|
2月前
|
机器学习/深度学习 人工智能 自然语言处理
视觉语言模型(VLM)实战:让 AI 真正“看懂”图像
在多模态人工智能的浪潮中,视觉语言模型(Vision-Language Models, VLMs) 正迅速成为连接图像与文本理解的核心技术。从为视障人士描述场景,到电商智能客服识别用户上传的商品图,再到自动驾驶系统理解交通标志语义——VLM 正在模糊“看”与“说”的边界。本文将带你深入 VLM 的工作原理、典型架构,并通过一个实际案例展示如何构建一个简单的图像问答系统。
|
1月前
|
移动开发 前端开发 Java
微信直连商户公众号 JSAPI 支付,详细教程+源码
JSAPI 支付用于微信公众号内的网页调起微信收银台,常见于在公众号菜单、文章页或 H5 活动页中完成支付。该方式依赖微信内置浏览器环境,非微信浏览器无法调起。
312 1
|
2月前
|
监控 Java Nacos
手把手搭建Java微服务:从技术选型到生产部署
每个服务边界的确立,都是在回答一个基本问题:"什么应该在一起,什么应该分离?"这与我们人生中关于人际关系、职业发展的决策何其相似。
118 0
|
2月前
|
安全 关系型数据库 网络安全
Navicat通过SSH隧道连接数据库,详细步骤
通过SSH隧道连接数据库的本质是建立一个加密的安全通道。你的Navicat会先通过SSH协议登录到你的远程服务器,然后再通过这个加密的隧道连接服务器上的数据库服务。
220 1
|
2月前
|
监控 数据可视化 Java
Spring Boot 整合 Elasticsearch 及实战应用
这次内容详细介绍如何使用 Spring Boot 整合 Elasticsearch,并提供几个实际应用案例。内容涵盖 Elasticsearch 的基本概念、Spring Boot 整合步骤、实战应用示例以及优化建议。
304 0
|
2月前
|
Java 关系型数据库 Docker
Docker + Spring Boot:天生一对的完美部署
使用Docker部署Spring Boot项目能极大简化环境配置和应用分发。要将Spring Boot项目部署到Docker,主要流程是:准备项目、创建Docker镜像、运行Docker容器。
170 0
|
2月前
|
监控 Java Linux
部署Spring Boot项目到Linux服务器数据盘
将Spring Boot项目部署到Linux服务器数据盘是一个常见的操作。首先是如何挂载数据盘,然后是如何部署Spring Boot项目。
148 0
|
弹性计算 数据中心
便宜香港服务器推荐,阿里云24元1个月,288元一年
便宜香港服务器推荐,阿里云24元1个月,288元一年,阿里云香港服务器中国香港数据中心网络线路类型BGP多线精品,中国电信CN2高速网络高质量、大规格BGP带宽,运营商精品公网直连中国内地,时延更低,优化海外回中国内地流量的公网线路,可以提高国际业务访问质量