/** * 是否簽名正確,規則是:按參數名稱a-z排序,遇到空值的參數不參加簽名。 * @return boolean */ public static boolean isTenpaySign(String characterEncoding, SortedMap<Object, Object> packageParams, String API_KEY) { StringBuffer sb = new StringBuffer(); @SuppressWarnings("rawtypes") Set es = packageParams.entrySet(); @SuppressWarnings("rawtypes") Iterator it = es.iterator(); while(it.hasNext()) { @SuppressWarnings("rawtypes") Map.Entry entry = (Map.Entry)it.next(); String k = (String)entry.getKey(); String v = (String)entry.getValue(); if(!"sign".equals(k) && null != v && !"".equals(v)) { sb.append(k + "=" + v + "&"); } } sb.append("key=" + API_KEY); //算出摘要 String mysign = CommonUtils.MD5Encode(sb.toString(), characterEncoding).toLowerCase(); String tenpaySign = ((String)packageParams.get("sign")).toLowerCase(); return tenpaySign.equals(mysign); }
/** * @author chenp * @Description:sign簽名 * @param characterEncoding * 編碼格式 * @param parameters * 請求參數 * @return */ @SuppressWarnings("rawtypes") public static String createSign(String characterEncoding, SortedMap<Object, Object> packageParams, String API_KEY) { StringBuffer sb = new StringBuffer(); Set es = packageParams.entrySet(); Iterator it = es.iterator(); while (it.hasNext()) { Map.Entry entry = (Map.Entry) it.next(); String k = (String) entry.getKey(); String v = (String) entry.getValue(); if (null != v && !"".equals(v) && !"sign".equals(k) && !"key".equals(k)) { sb.append(k + "=" + v + "&"); } } sb.append("key=" + API_KEY); String sign = CommonUtils.MD5Encode(sb.toString(), characterEncoding).toUpperCase(); return sign; }
/** * @author chenp * @Description:將請求參數轉換爲xml格式的string * @param parameters * 請求參數 * @return */ @SuppressWarnings("rawtypes") public static String getRequestXml(SortedMap<Object, Object> parameters) { StringBuffer sb = new StringBuffer(); sb.append("<xml>"); Set es = parameters.entrySet(); Iterator it = es.iterator(); while (it.hasNext()) { Map.Entry entry = (Map.Entry) it.next(); String k = (String) entry.getKey(); String v = (String) entry.getValue(); if ("attach".equalsIgnoreCase(k) || "body".equalsIgnoreCase(k) || "sign".equalsIgnoreCase(k)) { sb.append("<" + k + ">" + "<![CDATA[" + v + "]]></" + k + ">"); } else { sb.append("<" + k + ">" + v + "</" + k + ">"); } } sb.append("</xml>"); return sb.toString(); } /** * 取出一個指定長度大小的隨機正整數. * * @param length * int 設定所取出隨機數的長度。length小於11 * @return int 返回生成的隨機數。 */ public static int buildRandom(int length) { int num = 1; double random = Math.random(); if (random < 0.1) { random = random + 0.1; } for (int i = 0; i < length; i++) { num = num * 10; } return (int) ((random * num)); } /** * 獲取當前時間 yyyyMMddHHmmss * @author chenp * @return String */ public static String getCurrTime() { Date now = new Date(); SimpleDateFormat outFormat = new SimpleDateFormat("yyyyMMddHHmmss"); String s = outFormat.format(now); return s; } /** * 獲取本機IP地址 * @author chenp * @return */ @SuppressWarnings("rawtypes") public static String localIp(){ String ip = null; Enumeration allNetInterfaces; try { allNetInterfaces = NetworkInterface.getNetworkInterfaces(); while (allNetInterfaces.hasMoreElements()) { NetworkInterface netInterface = (NetworkInterface) allNetInterfaces.nextElement(); List<InterfaceAddress> InterfaceAddress = netInterface.getInterfaceAddresses(); for (InterfaceAddress add : InterfaceAddress) { InetAddress Ip = add.getAddress(); if (Ip != null && Ip instanceof Inet4Address) { ip = Ip.getHostAddress(); } } } } catch (SocketException e) { lg.warn("獲取本機Ip失敗:異常信息:"+e.getMessage()); } return ip; }
** * 微信H5支付 * @return * @author chenp * @throws Exception */ public static Map<String, String> getH5CodeUrl(PayParams ps,HttpServletRequest request) throws Exception { String trade_type = "MWEB"; //類型【H5支付】 String scene_info = "{\"h5_info\": {\"type\":\"Wap\",\"wap_url\": \"http://localhost:8080/cggl/f/purchase/supplier/setting/account/beforeRecharge\",\"wap_name\": \"帳戶充值\"}}";//場景信息 /** * 參數封裝 */ SortedMap<Object,Object> packageParams = new TreeMap<Object,Object>(); packageParams.put("spbill_create_ip", getClientIp(request));//客戶端主機 packageParams.put("trade_type", trade_type); packageParams.put("scene_info", scene_info); Map<String,String> map = commPay(ps,request,packageParams); return map; } /** * JSAPI支付 * @param ps * @param request * @return * @throws Exception */ public static Map<String, String> getJSPay(PayParams ps,HttpServletRequest request) throws Exception { String trade_type = "JSAPI"; //類型【JSAPI】 SortedMap<Object,Object> packageParams = new TreeMap<Object,Object>(); packageParams.put("spbill_create_ip", getClientIp(request));//客戶端主機 packageParams.put("trade_type", trade_type); packageParams.put("openid", ps.getOpenId()); Map<String, String> map = commPay(ps, request, packageParams); return map; } /** * 支付接口 * @param ps * @param request * @param paramMap * @return * @throws JDOMException * @throws IOException */ public static Map<String,String> commPay(PayParams ps,HttpServletRequest request,SortedMap<Object,Object> paramMap) throws JDOMException, IOException{ //公共參數 String appid = Constants.APP_ID;//微信服務號的appid String mch_id = Constants.MCHID; //微信支付商戶號 String key = Constants.APIKEY; // 微信支付的API密鑰 String notify_url =Constants.DOMAIN+request.getContextPath()+WECHAT_NOTIFY_URL_PC;//回調地址【注意,這裏必需要使用外網的地址】 String ufdoder_url=UFDODER_URL;//微信下單API地址 //隨機數 String nonce_str = createRadomNum(4); /** * 參數封裝 */ SortedMap<Object,Object> packageParams = new TreeMap<Object,Object>(); packageParams.put("appid", appid); packageParams.put("mch_id", mch_id); packageParams.put("nonce_str", nonce_str);//隨機字符串 packageParams.put("body", ps.body);//支付的商品名稱 packageParams.put("out_trade_no", ps.out_trade_no+nonce_str);//商戶訂單號【備註:每次發起請求都須要隨機的字符串,不然失敗。】 packageParams.put("total_fee", ps.total_fee);//支付金額 packageParams.put("notify_url", notify_url); packageParams.put("attach", ps.attach);//額外的參數【業務類型+會員ID+支付類型】 packageParams.putAll(paramMap);//特定參數 @SuppressWarnings("static-access") String sign = new PayUtil().createSign("UTF-8", packageParams,key); packageParams.put("sign", sign); String requestXML = PayUtil.getRequestXml(packageParams);//將請求參數轉換成String類型 String resXml = HttpUtil.postData(ufdoder_url,requestXML); //解析請求以後的xml參數而且轉換成String類型 @SuppressWarnings("unchecked") Map<String,String> map = XMLUtil.doXMLParse(resXml); String result_code = (String) map.get("result_code"); lg.info("下單結果-result_code--》"+(String) map.get("result_code")); Map<String,String> nMap = new HashMap<String, String>(); String prepayId = (String) map.get("prepay_id"); String mweb_url = (String) map.get("mweb_url"); nMap.put("outTradeNo", ps.out_trade_no+nonce_str); nMap.put("prepayId", prepayId); nMap.put("outTradeNoZS", ps.out_trade_no); nMap.put("mweb_url", mweb_url); nMap.put("result_code", result_code); return nMap; } /** * 隨機數生成 * @return */ public static String createRadomNum(int lenth){ String currTime = PayUtil.getCurrTime(); String strTime = currTime.substring(8, currTime.length()); String strRandom = PayUtil.buildRandom(lenth) + ""; String nonce_str = strTime + strRandom; return nonce_str; }
/** * 根據code獲取用戶的openid * @param httpClient * @param appid * @param ky * @param code * @return */ public static String getOpenId(String appId, String appSecret, String code) { String url = MicroMsgDomain + "/sns/oauth2/access_token?" + "appid="+appId + "&secret="+appSecret + "&code="+code + "&grant_type=authorization_code"; GetMethod method = new GetMethod(url); method.getParams().setParameter(HttpMethodParams.HTTP_CONTENT_CHARSET,"UTF-8"); String openId=null; try { new HttpClient().executeMethod(method); String str = method.getResponseBodyAsString(); JSONObject json = JSONObject.fromObject(str); openId = json.getString("openid"); } catch (HttpException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (JSONException e) { e.printStackTrace(); } finally { method.releaseConnection(); } return openId; }