com.core.util.wx.PayUtils.java Source code

Java tutorial

Introduction

Here is the source code for com.core.util.wx.PayUtils.java

Source

/**
 * $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, "");
    }
}