Java tutorial
/** * $Id: PayUtils.java Nov 20, 2014 2:25:53 PM hdp * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.core.util.wx; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.math.BigDecimal; import java.net.URLEncoder; import java.security.NoSuchAlgorithmException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; import java.util.Random; import java.util.TreeMap; import java.util.UUID; import javax.servlet.http.HttpServletRequest; import org.apache.commons.lang3.StringUtils; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.HttpClients; import org.apache.http.util.EntityUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; //import com.tentcoo.base.enums.RefundStatus; import com.base.util.HTTPSRequest; /** * * <p> * : Nov 20, 2014 2:25:53 PM * </p> * * @author * @version V1.0 * @since V1.0 */ public final class PayUtils { /** * */ private static Logger LOG = LoggerFactory.getLogger(PayUtils.class); public static final String JSAPI = "JSAPI"; public static final String NATIVE = "NATIVE"; private PayUtils() { throw new RuntimeException("can't init"); } /** * ??32? */ public static String createNoncestr() { return UUID.randomUUID().toString().replaceAll("\\-", ""); } /** * ????? */ public static String formatBizQueryParaMap(Map<String, String> paraMap, boolean urlencode) { StringBuilder sb = new StringBuilder(); TreeMap<String, String> sortMap = new TreeMap<String, String>(paraMap); if (urlencode) { try { for (String key : sortMap.keySet()) { sb.append(key).append("=").append(URLEncoder.encode(sortMap.get(key), "UTF-8")).append("&"); } } catch (UnsupportedEncodingException e) { LOG.error(e.getMessage(), e); } } else { for (String key : sortMap.keySet()) { sb.append(key).append("=").append(sortMap.get(key)).append("&"); } } if (sb.length() > 0) { sb.deleteCharAt(sb.length() - 1); } return sb.toString(); } /** * ??? */ public static String getSign(Map<String, String> params, String mchKey) { StringBuilder sb = new StringBuilder(); sb.append(formatBizQueryParaMap(params, false)); // ??string?KEY // sb.append("&key=").append(WxConfigUtil.KEY); sb.append("&key=").append(mchKey); // ??MD5 String result = null; try { result = MD5.getMD5(sb.toString()); } catch (NoSuchAlgorithmException e) { LOG.error(e.getMessage(), e); return result; } // ?? return result.toUpperCase(); } public static String getSign(String nonceStr, String outTradeNo, String body, String totalFee, String notifyUrl, String tradeType, String openid, String ip, String appid, String mchId, String mchKey) { Map<String, String> params = new HashMap<String, String>(); if (outTradeNo != null && !outTradeNo.isEmpty()) { params.put("out_trade_no", outTradeNo); } if (body != null && !body.isEmpty()) { params.put("body", body); } if (totalFee != null && !totalFee.isEmpty()) { params.put("total_fee", totalFee); } if (notifyUrl != null && !notifyUrl.isEmpty()) { params.put("notify_url", notifyUrl); } if (tradeType != null && !tradeType.isEmpty()) { params.put("trade_type", tradeType); } if (openid != null && !openid.isEmpty()) { params.put("openid", openid); } if (appid != null && !appid.isEmpty()) { params.put("appid", appid);// ?ID } if (nonceStr != null && !nonceStr.isEmpty()) { params.put("nonce_str", nonceStr);// ? } // params.put("mch_id", WxConfigUtil.MCHID);// ? params.put("mch_id", mchId); return getSign(params, mchKey); } // /** // * ???? // * // * @param param // * @return // */ // public String getAliSign(Map<String, String> param) { // String sign = formatBizQueryParaMap(param, true); // return RSA.sign(sign, AliWxConfigUtil.private_key, // AliWxConfigUtil.input_charset); // // } /** * post???xml?url * * @param xml * @param url * @return */ public static String postXmlCurl(String xml, String url) { HttpClient client = HttpClients.createSystem(); HttpPost post = new HttpPost(url); String result = null; try { post.setEntity(new StringEntity(xml)); HttpResponse httpResponse = client.execute(post); if (httpResponse.getStatusLine().getStatusCode() == 200) { HttpEntity httpEntity = httpResponse.getEntity(); result = EntityUtils.toString(httpEntity);// ? } } catch (UnsupportedEncodingException e) { LOG.error(e.getMessage(), e); } catch (ClientProtocolException e) { LOG.error(e.getMessage(), e); } catch (IOException e) { LOG.error(e.getMessage(), e); } return result; } /** * ?post???xml?url * * @param xml * @param url * @return */ private static String postXmlSSLCurl(String xml, String url) { try { return HTTPSRequest.httpsRequestSec(url, "POST", xml); } catch (Exception e) { LOG.error(e.getMessage(), e); return null; } } /** * xml * * @param outTradeNo * @param body * @param totalFee * @param notifyUrl * @param tradeType * @param openid * @param ip * @return */ private static String createXml(String nonceStr, String outTradeNo, String body, String totalFee, String notifyUrl, String tradeType, String openid, String ip, String sign, String appid) { Map<String, String> params = new HashMap<String, String>(); // params.put("out_trade_no", outTradeNo); // params.put("body", body); // params.put("total_fee", totalFee); // params.put("notify_url", notifyUrl); // params.put("trade_type", tradeType); // params.put("openid", openid); // params.put("appid", appid);// ?ID // params.put("mch_id", WxConfigUtil.MCHID);// ? // params.put("nonce_str", nonceStr);// ? if (outTradeNo != null && !outTradeNo.isEmpty()) { params.put("out_trade_no", outTradeNo); } if (body != null && !body.isEmpty()) { params.put("body", body); } if (totalFee != null && !totalFee.isEmpty()) { params.put("total_fee", totalFee); } if (notifyUrl != null && !notifyUrl.isEmpty()) { params.put("notify_url", notifyUrl); } if (tradeType != null && !tradeType.isEmpty()) { params.put("trade_type", tradeType); } if (openid != null && !openid.isEmpty()) { params.put("openid", openid); } if (appid != null && !appid.isEmpty()) { params.put("appid", appid);// ?ID } if (nonceStr != null && !nonceStr.isEmpty()) { params.put("nonce_str", nonceStr);// ? } if (sign != null && !sign.isEmpty()) { params.put("sign", sign);// ?? } params.put("mch_id", WxConfigUtil.MCHID);// ? return XmlUtils.mapToXml(params); } /** * ?postxml */ private static String postXmlSSL(String nonceStr, String url, String outTradeNo, String body, String totalFee, String notifyUrl, String tradeType, String openid, String ip, String sign, String appid) { String xml = createXml(nonceStr, outTradeNo, body, totalFee, notifyUrl, tradeType, openid, ip, sign, appid); return postXmlSSLCurl(xml, url); } /** * ?id * * @param outTradeNo * ?? * @param body * ? * @param totalFee * ? * @param tradeType * JSAPI * @param openid * openid * @param ip * ip * @return */ public static String getPrepayId(String nonceStr, String outTradeNo, String body, String totalFee, String tradeType, String openid, String ip, String sign, String appid, String mchId, String mchKey) { Map<String, String> resultMap = prepay(nonceStr, outTradeNo, body, totalFee, tradeType, openid, ip, sign, appid, mchId, mchKey); if (resultMap != null) { return resultMap.get("prepay_id"); } return null; } /** * ?? * * @param nonceStr * @param outTradeNo * @return */ public static Map<String, String> queryOrder(String nonceStr, String outTradeNo) { Map<String, String> param = new HashMap<String, String>(); param.put("appid", WxConfigUtil.WX_APPID); param.put("mch_id", WxConfigUtil.MCHID); param.put("out_trade_no", outTradeNo); param.put("nonce_str", nonceStr); return wxPayInterface(param, WxConfigUtil.ORDER_QUERY_URL, ""); } /** * @param outTradeNo ?? * @param openId id * @param cash * @param appId APPID * @param mchId ID * @param mchKey KEY * @param body ?? * @return ??? */ public static Map<String, Object> payOrder(String outTradeNo, String openId, BigDecimal cash, String appId, String mchId, String mchKey, String body) { String propertiesUtil = "";//-PropertiesUtil.notifyUrl String nonceStr = createNoncestr(); String total = String.valueOf(cash.multiply(new BigDecimal(100)).intValue()); // HTTPSRequest.setSslsf(mchId);???mchId.p12?? String signFirst = getSign(nonceStr, outTradeNo, body, total, propertiesUtil, "JSAPI", openId, "127.0.0.1", appId, mchId, mchKey); Map<String, String> prepay = prepay(nonceStr, outTradeNo, body, total, "JSAPI", openId, "127.0.0.1", signFirst, appId, mchId, mchKey); String retCd = prepay.get("return_code"); String prepayId = ""; if (retCd.equals("SUCCESS")) { String resultCd = prepay.get("result_code"); if (resultCd.equals("SUCCESS")) { prepayId = prepay.get("prepay_id"); } } String packages = "prepay_id=" + prepayId; String timeStamp = String.valueOf(System.currentTimeMillis() / 1000L); String signType = "MD5"; Map<String, String> parameters = new HashMap<String, String>(); parameters.put("appId", appId); parameters.put("timeStamp", timeStamp); parameters.put("nonceStr", nonceStr); parameters.put("package", packages); parameters.put("signType", signType); String sign = getSign(parameters, mchKey); Map<String, Object> jsonMap = new LinkedHashMap<String, Object>(); jsonMap.put("appId", appId); jsonMap.put("timeStamp", timeStamp); jsonMap.put("nonceStr", nonceStr); jsonMap.put("package", packages); jsonMap.put("signType", signType); jsonMap.put("paySign", sign); // String totalFee = String.valueOf(chargeOrderCash.multiply(new BigDecimal(100)).intValue()); return jsonMap; } /** * * * @param nonceStr * @param outTradeNo * @param total * @param refund * @param uid * @return */ public static Map<String, String> refund(String nonceStr, String outTradeNo, int total, int refund, String uid) { Map<String, String> param = new HashMap<String, String>(); if (uid != null) { param.put("op_user_id", uid); } else { param.put("op_user_id", "system"); } param.put("appid", WxConfigUtil.WX_APPID); param.put("mch_id", WxConfigUtil.MCHID); param.put("out_trade_no", outTradeNo); param.put("nonce_str", nonceStr); param.put("out_refund_no", nonceStr); param.put("total_fee", total + ""); param.put("refund_fee", refund + ""); return wxPayInterface(param, WxConfigUtil.REFUND_URL, ""); } /** * ? * * @param param * @param url * @return */ public static Map<String, String> wxPayInterface(Map<String, String> param, String url, String mchKey) { String sign = getSign(param, mchKey); param.put("sign", sign); String xml = XmlUtils.mapToXml(param); String response = postXmlSSLCurl(xml, url); System.out.println("response:" + response); Map<String, String> respMap = XmlUtils.xmlToMap(response); return respMap; } /** * ?? * * @param nonceStr * @param outTradeNo * @param body * @param totalFee * @param tradeType * @param openid * @param ip * @param sign * @param appid * @return */ public static Map<String, String> prepay(String nonceStr, String outTradeNo, String body, String totalFee, String tradeType, String openid, String ip, String sign, String appid, String mchId, String mchKey) { if (StringUtils.isBlank(tradeType)) { tradeType = JSAPI; } String xml = postXmlSSL(nonceStr, WxConfigUtil.CURL_URL, outTradeNo, body, totalFee, WxConfigUtil.NOTIFY_URL, tradeType, openid, ip, sign, appid); System.out.println("xml:" + xml); if (null != xml) { Map<String, String> resultMap = XmlUtils.xmlToMap(xml); if (null != resultMap) return resultMap; } return null; } // /** // * ? // * <p> // * ,20 ? 3 ??? // * </p> // * // * @param outTradeNo // * ?? // * @param outRefundNo // * ?? ?? // * @param totalFee // * ? // * @param refundFee // * ? // * @return ???true??false // */ // public static boolean refund2(String outTradeNo, String outRefundNo, // int totalFee, int refundFee, String appid) { // Map<String, String> params = new HashMap<String, String>(); // params.put("out_trade_no", outTradeNo); // params.put("out_refund_no", outRefundNo); // params.put("total_fee", String.valueOf(totalFee)); // params.put("refund_fee", String.valueOf(refundFee)); // params.put("appid", appid); // params.put("mch_id", WxConfigUtil.MCHID); // params.put("op_user_id", WxConfigUtil.MCHID); // params.put("nonce_str", PayUtils.createNoncestr()); // params.put("sign", PayUtils.getSign(params)); // // String xml = XmlUtils.mapToXml(params); // String result = PayUtils.postXmlSSLCurl(xml, WxConfigUtil.REFUND_URL); // Map<String, String> resultMap = XmlUtils.xmlToMap(result); // return "SUCCESS".equals(resultMap.get("return_code")); // } // /** // * ? // * // * @param outTradeNo // * ?? // * @return // */ // public static RefundStatus refundQuery(String outTradeNo, String appid) { // Map<String, String> params = new HashMap<String, String>(); // params.put("out_trade_no", outTradeNo); // params.put("appid", appid); // params.put("mch_id", WxConfigUtil.MCHID); // params.put("nonce_str", PayUtils.createNoncestr()); // params.put("sign", PayUtils.getSign(params)); // // String xml = XmlUtils.mapToXml(params); // String result = PayUtils // .postXmlSSLCurl(xml, WxConfigUtil.REFUND_QUERY_URL); // Map<String, String> resultMap = XmlUtils.xmlToMap(result); // if (null == resultMap.get("return_code")) // return RefundStatus.ERROR; // if (!"SUCCESS".equals(resultMap.get("return_code"))) // return RefundStatus.ERROR; // String status = resultMap.get("refund_status_" + 0); // return RefundStatus.valueOf(status); // } /** * * * @param xml * @return */ public static boolean checkSign(Map<String, String> params) { Map<String, String> map = new HashMap<String, String>(params); String key = "sign"; String sign = map.get(key); if (StringUtils.isBlank(sign)) return false; map.remove(key); return sign.equals(getSign(map, "")); } /** * ?? * * @param success * @param msg * @return */ public static String returnXml(boolean success, String msg) { Map<String, String> map = new HashMap<String, String>(); map.put("return_code", success ? "SUCCESS" : "FAIL"); if (StringUtils.isNotBlank(msg)) map.put("return_msg", msg); return XmlUtils.mapToXml(map); } public static String getIpAddr(HttpServletRequest request) { String ip = request.getHeader("x-forwarded-for"); if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("Proxy-Client-IP"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("WL-Proxy-Client-IP"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getRemoteAddr(); } return ip; } // public static void main(String[] args) { // String openid = "op7X8tz1Ug0J2khfm8jP-UiDKacw"; // BigDecimal totalFee = new BigDecimal(0.01); // String body = ""; // WeixinOrder weixinOrder = new WeixinOrder(); // // weixinOrder.setIp("116.21.163.170"); // weixinOrder.setCreateTime(new Date()); // weixinOrder.setOpenid(openid); // weixinOrder.setOutTradeNo(UUID.randomUUID().toString() // .replaceAll("\\-", "")); // weixinOrder.setTotalFee(totalFee); // weixinOrder.setTradeStatus(TradeStatus.PRAPARE); // weixinOrder.setTradeType(PayUtils.JSAPI); // weixinOrder.setBody(body); // // String nonceStr = PayUtils.createNoncestr(); // if (LOG.isInfoEnabled()) // LOG.info("nonceStr:" + nonceStr); // if (LOG.isInfoEnabled()) // LOG.info("OutTradeNo:" + weixinOrder.getOutTradeNo() + ",body:" // + weixinOrder.getBody() + ",totalFee" // + weixinOrder.getTotalFee().floatValue() // + ", WxConfigUtil.NOTIFY_URL:" + WxConfigUtil.NOTIFY_URL // + ",tradeType:" + weixinOrder.getTradeType() + ", openid:" // + openid + ", Ip:" + weixinOrder.getIp()); // String sign = PayUtils.getSign( // nonceStr, // weixinOrder.getOutTradeNo(), // weixinOrder.getBody(), // String.valueOf(weixinOrder.getTotalFee() // .multiply(new BigDecimal(100)).intValue()), // WxConfigUtil.NOTIFY_URL, weixinOrder.getTradeType(), openid, // weixinOrder.getIp()); // if (LOG.isInfoEnabled()) // LOG.info("sign:" + sign); // String prepayId = PayUtils.getPrepayId( // nonceStr, // weixinOrder.getOutTradeNo(), // weixinOrder.getBody(), // String.valueOf(weixinOrder.getTotalFee() // .multiply(new BigDecimal(100)).intValue()), // weixinOrder.getTradeType(), weixinOrder.getOpenid(), // weixinOrder.getIp(), sign); // if (LOG.isInfoEnabled()) // LOG.info("prepayId:" + prepayId); // weixinOrder.setPrepayId(prepayId); // } /** * ?? * */ public static String getMchNo() { String order = WxConfigUtil.MCHID + new SimpleDateFormat("yyyyMMddss").format(new Date()); Random r = new Random(); for (int i = 0; i < 2; i++) { order += r.nextInt(9000) + 1000; } return order; } public static final String getXmlSend(String nonce_str, String mch_billno, String mch_id, String wxappid, String send_name, String re_openid, String total_amount, String total_num, String wishing, String client_ip, String act_name, String remark) { String sign = getSignSend(nonce_str, mch_billno, mch_id, wxappid, send_name, re_openid, total_amount, total_num, wishing, client_ip, act_name, remark); String xml = ""; xml += "<xml>"; xml += " <sign>" + sign + "</sign>"; xml += " <mch_billno>" + mch_billno + "</mch_billno>"; xml += " <mch_id>" + mch_id + "</mch_id>"; xml += " <wxappid>" + wxappid + "</wxappid>"; xml += " <send_name>" + send_name + "</send_name>"; xml += " <re_openid>" + re_openid + "</re_openid>"; xml += " <total_amount>" + total_amount + "</total_amount>"; xml += " <total_num>" + total_num + "</total_num>"; xml += " <wishing>" + wishing + "</wishing>"; xml += " <client_ip>" + client_ip + "</client_ip>"; xml += " <act_name>" + act_name + "</act_name>"; // " <act_id>"+act_id+"</act_id>" + xml += " <remark>" + remark + "</remark>"; xml += " <nonce_str>" + nonce_str + "</nonce_str>"; xml += "</xml>"; return xml; } private static String getSignSend(String nonce_str, String mch_billno, String mch_id, String wxappid, String send_name, String re_openid, String total_amount, String total_num, String wishing, String client_ip, String act_name, String remark) { Map<String, String> params = new HashMap<String, String>(); params.put("nonce_str", nonce_str); params.put("mch_billno", mch_billno); params.put("mch_id", mch_id); params.put("wxappid", wxappid); params.put("send_name", send_name); params.put("re_openid", re_openid); params.put("total_amount", total_amount); params.put("total_num", total_num); params.put("wishing", wishing); params.put("client_ip", client_ip); params.put("act_name", act_name); params.put("remark", remark); return getSign(params, ""); } }