Java实现微信支付的签名算法示例
作者: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微信支付签名算法的资料请关注脚本之家其它相关文章!