Java实现微信支付的签名算法示例

 更新时间:2023年12月04日 11:14:49   作者:Wen先森  
这篇文章主要为大家介绍了Java实现微信支付的签名算法实现示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

签名算法

签名生成的通用步骤如下:

第一步,设所有发送或者接收到的数据为集合M

将集合M内非空参数值的参数按照参数名ASCII码从小到大排序(字典序),使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串stringA。

特别注意重要规则

参数名ASCII码从小到大排序(字典序);

如果参数的值为空不参与签名;

参数名区分大小写;

验证调用返回或微信主动通知签名时,传送的sign参数不参与签名,将生成的签名与该sign值作校验。

微信接口可能增加字段,验证签名时必须支持增加的扩展字段

第二步,在stringA最后拼接上key得到stringSignTemp字符串

并对stringSignTemp进行MD5运算,再将得到的字符串所有字符转换为大写,得到sign值signValue。

注意:密钥的长度为32个字节

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.ObjectUtils;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;
/**
 * @author Wen先森
 * @version 1.0
 * @date 2022/8/25 11:07
 */
@Slf4j
public class SignatureUntils {
    public static final String  KEY="0de034fa56cf0ce676570d571de2705b";
    /**
     * 处理要签名的数据
     * 1. 获取参数content,content为json字符串
     * 2. 转换参数成URL 键值对的格式(即 key1=value1&key2=value2…)
     * 3. 返回整理好的待签名数据
     */
    private static String handleStr(Map<String,?> paramsMap){
        //转成map
        //获取参数名称转成List集合
        Set<String> keySet = paramsMap.keySet();
        List<String> paramNames = new ArrayList<String>(keySet);
        //对参数名称进行排序
        Collections.sort(paramNames);
        //把参数转化成url键值对格式并返回
        StringBuilder paramNameValue = new StringBuilder();
        for (String paramName : paramNames ) {
            if("sign".equals(paramName) || ObjectUtils.isEmpty(paramsMap.get(paramName))) {
                continue;
            }else{
                paramNameValue.append(paramName).append("=").append(paramsMap.get(paramName)).append("&");
            }
        }
       // paramNameValue.deleteCharAt(paramNameValue.length()-1);
        return paramNameValue.toString();
    }
    /**
     * 生成签名;
     *
     * @param params
     * @return
     */
    static public String signForInspiry(Map<String,?> params, String key) {
        //先排序
        String str = handleStr(params);
        StringBuffer sbkey = new StringBuffer(str);
        sbkey = sbkey.append("key=" + key);
        //MD5加密,结果转换为大写字符
        String sign = toMd5(sbkey.toString()).toUpperCase();
        return sign;
    }
    /**
     * 对字符串进行MD5加密
     *
     * @param str 需要加密的字符串
     * @return 小写MD5字符串 32位
     */
    public static String toMd5(String str) {
        String re = null;
        byte encrypt[];
        try {
            byte[] tem = str.getBytes();
            MessageDigest md5 = MessageDigest.getInstance("md5");
            md5.reset();
            md5.update(tem);
            encrypt = md5.digest();
            StringBuilder sb = new StringBuilder();
            for (byte t : encrypt) {
                String s = Integer.toHexString(t & 0xFF);
                if (s.length() == 1) {
                    s = "0" + s;
                }
                sb.append(s);
            }
            re = sb.toString();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return re;
    }
    public static boolean checkSign(String sign,Map<String,?> params,String key){
        try {
            String signValue = signForInspiry(params, key);
            if (StringUtils.endsWithIgnoreCase(signValue,sign)){
                log.info("验签成功");
                return true;
            }
        } catch (Exception e) {
            log.info("验签异常");
            e.printStackTrace();
        }
        log.info("验签失败");
        return false;
    }
    public static void main(String[] args) {
        String sign="81AA2B818EAD40FE2D8E7E3242C14577";
        String key="0de034fa56cf0ce676570d571de2705b";
        Map<String,Object> map = new HashMap<>();
        map.put("deviceSn","000SD50030180000001");
        map.put("timestamp","1661759090226");
        map.put("sign",sign);
        map.put("orderNo","HMP2208310000584428263559179");
        // 需要签名参数
        System.out.println("签名参数:"+map);
        String sortPram = handleStr(map);
        // 排序后和去掉sign参数之后
        System.out.println("排序后参数:"+sortPram);
        String signValue = signForInspiry(map, "0de034fa56cf0ce676570d571de2705b");
        // MD5加密并全部大写
        System.out.println("签名内容:"+signValue);
        // 验签
        checkSign(sign, map, key);
    }
}

以上就是Java实现微信支付的签名算法示例的详细内容,更多关于Java微信支付签名算法的资料请关注脚本之家其它相关文章!

相关文章

  • Java基础之Unsafe内存操作不安全类详解

    Java基础之Unsafe内存操作不安全类详解

    Java是面向对象语言,在使用Java编程时,大多数情况下都不会直接操作内存,而且Java也不提倡直接操作内存,但是Java中到底有没有可以直接操作内存的工具类呢?有!Java中提供Unsafe类可以用来来直接操作内存,文中详细介绍了Unsafe内存操作不安全类,需要的朋友可以参考下
    2021-06-06
  • Java中的CAS(Compare-And-Swap)操作示例详解

    Java中的CAS(Compare-And-Swap)操作示例详解

    CAS是一种原子操作,用于在多线程环境中实现无锁(lock-free)的线程安全编程,下面通过本文给大家介绍Java中的CAS(Compare-And-Swap)操作示例详解,感兴趣的朋友一起看看吧
    2025-06-06
  • java如何获取用户登录ip、浏览器信息、SessionId

    java如何获取用户登录ip、浏览器信息、SessionId

    这篇文章主要介绍了java如何获取用户登录ip、浏览器信息、SessionId,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-11-11
  • java -jar/-cp启动添加外部的依赖包方式

    java -jar/-cp启动添加外部的依赖包方式

    这篇文章主要介绍了java -jar/-cp启动添加外部的依赖包方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-01-01
  • Java函数式编程(八):字符串及方法引用

    Java函数式编程(八):字符串及方法引用

    这篇文章主要介绍了Java函数式编程(八):字符串及方法引用,本文是系列文章的第8篇,其它文章请参阅本文底部的相关文章,需要的朋友可以参考下
    2014-09-09
  • SpringBoot中@RestControllerAdvice @ExceptionHandler异常统一处理类失效原因分析

    SpringBoot中@RestControllerAdvice @ExceptionHandler异常统一处

    这篇文章主要介绍了SpringBoot中@RestControllerAdvice @ExceptionHandler异常统一处理类失效原因,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-01-01
  • Java详细分析梳理垃圾回收机制

    Java详细分析梳理垃圾回收机制

    垃圾回收,顾名思义,便是将已经分配出去的,但却不再使用的内存回收回来,以便能够再次分配。在 Java 虚拟机的语境下,垃圾指的是死亡的对象所占据的堆空间
    2022-04-04
  • 详解SpringBoot接收参数的五种形式

    详解SpringBoot接收参数的五种形式

    在Spring Boot中,接收参数可以通过多种方式实现,本文给大家介绍了SpringBoot接收参数的五种形式,并通过代码和图文给大家介绍的非常详细,需要的朋友可以参考下
    2024-03-03
  • Feign 请求动态URL方式

    Feign 请求动态URL方式

    这篇文章主要介绍了Feign 请求动态URL方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-07-07
  • 解析探秘fescar分布式事务实现原理

    解析探秘fescar分布式事务实现原理

    这篇文章主要为大家解析探秘fescar分布式事务的实现原理,fescar的txc模型实现非常有研究的价值,所以今天我们来好好翻一翻fescar项目的代码
    2022-02-02

最新评论