package cn.jeesoft.mvc.outapi; import java.io.BufferedInputStream; import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import javax.servlet.http.HttpServletRequest; import cn.jeesoft.core.utils.Sec; import cn.jeesoft.core.utils.StringUtils; import com.alibaba.fastjson.JSONObject; /** * 卡卡联支付 * @author king */ public class KklPayHelper { /** packet */ private static String PACKET = "PACKET"; /** 编码 */ private static String ENCODE = "UTF-8"; /** 分隔符 */ private static String EQUAL = "="; /** * 验证响应 * @param packet * @param md5Key * @return true:成功,false:失败,null:异常 */ public static Boolean verify(JSONObject packet, String md5Key) { String[] signFields = {"merchantCode", "instructCode", "transType", "outOrderId", "transTime","totalAmount"}; return KklPayHelper.verifySignMd5(md5Key, signFields, packet); } /** * 获取请求中的通知信息 * @param request * @return */ public static JSONObject getPacket(HttpServletRequest request) { String packetStr = getPacketStr(request); if (StringUtils.isEmpty(packetStr)) { return null; } try { return JSONObject.parseObject(packetStr); } catch (Exception e) { return null; } } /** * 获取请求中的通知信息 * @param request * @return */ private static String getPacketStr(HttpServletRequest request) { String packet = request.getParameter(PACKET); if (packet == null) { try { InputStream is = request.getInputStream(); BufferedInputStream bis = new BufferedInputStream(is); // 最大读取b长度数据,如果数据流不足b长度,则当读到流截止符时,停止读取数据 List<Byte> byteList = new ArrayList<Byte>(); byte[] temp = new byte[1]; while (bis.read(temp) != -1) { byteList.add(temp[0]); } int size = byteList.size(); if (size > 0) { byte[] b = new byte[size]; for (int i = 0; i < size; i++) { b[i] = byteList.get(i); } packet = new String(b, ENCODE); } else { // System.err.println(" 从request中获取请求数据流中获取为空 "); } } catch (Exception e) { // System.err.println("从request中获取请求数据流异常: " + e.toString()); } } // System.out.println("packet="+ packet+""); return packet; } /** * 验证签名 * @param md5Key * @param signFields * @param json * @return true:成功,false:失败,null:异常 */ public static Boolean verifySignMd5(String md5Key, String[] signFields, JSONObject json) { try { String sign = json.getString("sign"); String countSign = countSignMd5(md5Key, signFields, json); // System.out.println("sign["+sign+"]"); // System.out.println("countSign["+countSign+"]"); return countSign.equals(sign); } catch (Exception e) { return null; } } /** * 构建签名原文 * @param signFilds * @param packet * @return */ private static String orgSignSrc(String[] signFields, JSONObject packet) { if (signFields != null) { Arrays.sort(signFields); // 对key按照 字典顺序排序 } StringBuffer signSrc = new StringBuffer(""); int i = 0; for (String key : signFields) { signSrc.append(key); signSrc.append(EQUAL); signSrc.append((StringUtils.isEmpty(packet.getString(key)) ? "" : packet.getString(key))); // 最后一个元素后面不加& if (i < (signFields.length - 1)) { signSrc.append("&"); } i++; } return signSrc.toString(); } /** * 计算MD5签名 * @Description 按照支付规范计算MD5签名 * @param md5Key * @param signFields * @param json * @return * @throws NoSuchAlgorithmException * @throws UnsupportedEncodingException * * @since 1.0 */ private static String countSignMd5(String md5Key, String[] signFields, JSONObject json) throws NoSuchAlgorithmException, UnsupportedEncodingException { String signSrc = orgSignSrc(signFields, json); signSrc += "&KEY=" + md5Key; String signMd5 = Sec.MD5Encrypt(signSrc, 32); // System.out.println("生成的MD5="+signMd5); return signMd5; } }