package com.stylefeng.guns.core.util; import ch.qos.logback.core.encoder.Encoder; import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.lang.StringUtils; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.PrintWriter; import java.io.UnsupportedEncodingException; import java.util.*; public class NotifyDemo { /** * md5秘钥 */ static final String md5key = "impARTxrQcfwmRijpDNCw6hPxaWCddKEpYxjaKXDhCaTCXJ6"; /** * 支付通知模块,用于:在支付成功后 接受银商平台发送的支付结果通知 */ // @RequestMapping(value = "/notify.do", method = RequestMethod.POST) public String getNotify(HttpServletRequest request, HttpServletResponse response) throws Exception { /*接收参数*/ Map params = getRequestParams(request); System.out.println("params:" + params); String sign = params.get("sign"); System.out.println(sign); /*验签*/ //对通知内容生成sign String strSign = makeSign(md5key, params); //System.out.println("strSign="+strSign); //判断签名是否相等 if (sign.equals(strSign)) { // 收到通知后记得返回SUCCESS System.out.println("验签通过"); PrintWriter writer = response.getWriter(); writer.print("SUCCESS"); writer.flush(); } else { System.out.println("验签未通过"); } //更新商户系统的订单 //跳转支付完成页面 return "/WEB-INF/views/jsp/payResult.jsp"; } // 获取HttpServletRequest里面的参数 public static Map getRequestParams(HttpServletRequest request) { Map params = request.getParameterMap(); Map params2 = new HashMap<>(); for (String key : params.keySet()) { String[] values = params.get(key); if (values.length > 0) { params2.put(key, request.getParameter(key)); } } return params2; } public static String makeSign(String md5Key, Map params) { String preStr = buildSignString(params); // 把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串 String text = preStr + md5Key; System.out.println("待签名字符串:" + text); return DigestUtils.sha256Hex(getContentBytes(text)).toUpperCase(); } /** * 生成签名. 注意,若含有sign_type字段,必须和signType参数保持一致。 * * @param data 待签名数据 * @param key API密钥 * @param signType 签名方式 * @return 签名 */ public static String generateSignature(final Map data, String key, String signType) throws Exception { Set keySet = data.keySet(); String[] keyArray = keySet.toArray(new String[keySet.size()]); Arrays.sort(keyArray); StringBuilder sb = new StringBuilder(); for (String k : keyArray) { if (k.equals("sign")) { continue; } if (data.get(k).trim().length() > 0) { // 参数值为空,则不参与签名 sb.append(k).append("=").append(data.get(k).trim()).append("&"); } } sb.append("key=").append(key); if ("HMAC-SHA256".equals(signType)) { return HMACSHA256(sb.toString(), key); } else { throw new Exception(String.format("Invalid sign_type: %s", signType)); } } /** * 生成 HMACSHA256 * * @param data 待处理数据 * @param key 密钥 * @return 加密结果 * @throws Exception */ public static String HMACSHA256(String data, String key) throws Exception { Mac sha256_HMAC = Mac.getInstance("HmacSHA256"); SecretKeySpec secret_key = new SecretKeySpec(key.getBytes("UTF-8"), "HmacSHA256"); sha256_HMAC.init(secret_key); byte[] array = sha256_HMAC.doFinal(data.getBytes("UTF-8")); StringBuilder sb = new StringBuilder(); for (byte item : array) { sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3)); } return sb.toString().toUpperCase(); } // 构建签名字符串 public static String buildSignString(Map params) { // params.put("Zm","test_test"); if (params == null || params.size() == 0) { return ""; } List keys = new ArrayList<>(params.size()); for (String key : params.keySet()) { if ("sign".equals(key)) continue; if (StringUtils.isEmpty(params.get(key))) continue; keys.add(key); } //System.out.println(listToString(keys)); Collections.sort(keys); StringBuilder buf = new StringBuilder(); for (int i = 0; i < keys.size(); i++) { String key = keys.get(i); String value = params.get(key); if (i == keys.size() - 1) {// 拼接时,不包括最后一个&字符 buf.append(key + "=" + value); } else { buf.append(key + "=" + value + "&"); } } return buf.toString(); } // 根据编码类型获得签名内容byte[] public static byte[] getContentBytes(String content) { try { return content.getBytes("UTF-8"); } catch (UnsupportedEncodingException e) { throw new RuntimeException("签名过程中出现错误"); } } }