com.mobile.blue.util.payyl.SDKUtil.java Source code

Java tutorial

Introduction

Here is the source code for com.mobile.blue.util.payyl.SDKUtil.java

Source

/**
 *
 * Licensed Property to China UnionPay Co., Ltd.
 * 
 * (C) Copyright of China UnionPay Co., Ltd. 2010
 *     All Rights Reserved.
 *
 * 
 * Modification History:
 * =============================================================================
 *   Author         Date          Description
 *   ------------ ---------- ---------------------------------------------------
 *   xshu       2014-05-28      MPI
 * =============================================================================
 */
package com.mobile.blue.util.payyl;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;

import org.apache.commons.lang.StringUtils;

public class SDKUtil {

    // ?UTF-8
    public static String encoding_UTF8 = "UTF-8";

    public static String encoding_GBK = "GBK";
    // ?
    public static String version = "5.0.0";

    /**
     * ??
     * 
     * @param contentData
     *            map
     * @param encoding
     *            ?encoding
     * @return ???map
     */
    @SuppressWarnings("unchecked")
    public static Map<String, String> signData(Map<String, ?> contentData, String encoding) {
        Entry<String, String> obj = null;
        Map<String, String> submitFromData = new HashMap<String, String>();
        for (Iterator<?> it = contentData.entrySet().iterator(); it.hasNext();) {
            obj = (Entry<String, String>) it.next();
            String value = obj.getValue();
            if (StringUtils.isNotBlank(value)) {
                // value???
                submitFromData.put(obj.getKey(), value.trim());
            }
        }

        SDKUtil.sign(submitFromData, encoding);
        return submitFromData;
    }

    /**
     * ??? ??,??????:???(acp_sdk.properties
     * ? acpsdk.singleMode=false)
     * 
     * @param contentData
     *            map
     * @param certPath
     *            ???
     * @param certPwd
     *            ????
     * @param encoding
     *            ?encoding
     * @return ???map
     */
    @SuppressWarnings("unchecked")
    public static Map<String, String> signData(Map<String, ?> contentData, String certPath, String certPwd,
            String encoding) {
        Entry<String, String> obj = null;
        Map<String, String> submitFromData = new HashMap<String, String>();
        System.out.println("? :");
        for (Iterator<?> it = contentData.entrySet().iterator(); it.hasNext();) {
            obj = (Entry<String, String>) it.next();
            String value = obj.getValue();
            if (StringUtils.isNotBlank(value)) {
                // value???
                submitFromData.put(obj.getKey(), value.trim());
                System.out.println(obj.getKey() + "-->" + String.valueOf(value));
            }
        }
        /**
         * ??
         */
        SDKUtil.signByCertInfo(submitFromData, encoding, certPath, certPwd);

        return submitFromData;
    }

    /**
     * ?????
     * 
     * @param contentData
     *            map
     * @param encoding
     *            ?encoding
     * @return  map
     */
    public static Map<String, String> submitUrl(Map<String, String> submitFromData, String requestUrl,
            String encoding) {
        String resultString = "";
        /**
         * ?????
         */
        HttpClient hc = new HttpClient(requestUrl, 30000, 30000);
        try {
            int status = hc.send(submitFromData, encoding);
            if (200 == status) {
                resultString = hc.getResult();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        Map<String, String> resData = new HashMap<String, String>();
        /**
         * ???
         */
        if (null != resultString && !"".equals(resultString)) {
            // ?map
            resData = SDKUtil.convertResultStringToMap(resultString);
            if (SDKUtil.validate(resData, encoding)) {
                LogUtil.writeLog("????,???");
            } else {
                LogUtil.writeLog("???,????...");
            }
        }
        return resData;
    }

    /**
     * ?????
     * 
     * @param contentData
     * @return  map
     */
    public static Map<String, String> submitDate(Map<String, ?> contentData, String requestUrl, String encoding) {
        Map<String, String> submitFromData = (Map<String, String>) signData(contentData, encoding);
        return submitUrl(submitFromData, requestUrl, encoding);
    }

    /**
     * ???(SHA-1?)<br>
     * 
     * @param resData
     *            ?<br>
     * @param encoding
     *            ?encoding<br>
     * @return
     */
    public static boolean validate(Map<String, String> resData, String encoding) {
        LogUtil.writeLog("?");
        if (isEmpty(encoding)) {
            encoding = "UTF-8";
        }
        String stringSign = resData.get(SDKConstants.param_signature);

        // ?certId ????Map?
        String certId = resData.get(SDKConstants.param_certId);

        LogUtil.writeLog("??[" + certId + "]");

        // Map???key1=value1&key2=value2?
        String stringData = coverMap2String(resData);

        LogUtil.writeLog("[" + stringData + "]");

        try {
            // ???????.
            return SecureUtil.validateSignBySoft(CertUtil.getValidateKey(certId),
                    SecureUtil.base64Decode(stringSign.getBytes(encoding)),
                    SecureUtil.sha1X16(stringData, encoding));
        } catch (UnsupportedEncodingException e) {
            LogUtil.writeErrorLog(e.getMessage(), e);
        } catch (Exception e) {
            LogUtil.writeErrorLog(e.getMessage(), e);
        }
        return false;
    }

    /**
     * ??HTTP POST?<br>
     * 
     * @param action
     *            ????<br>
     * @param hiddens
     *            MAP??<br>
     * @param encoding
     *            ?encoding<br>
     * @return HTTP POST?<br>
     */
    public static String createAutoFormHtml(String action, Map<String, String> hiddens, String encoding) {
        StringBuffer sf = new StringBuffer();
        sf.append("<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=" + encoding
                + "\"/></head><body>");
        sf.append("<form id = \"pay_form\" action=\"" + action + "\" method=\"post\">");
        if (null != hiddens && 0 != hiddens.size()) {
            Set<Entry<String, String>> set = hiddens.entrySet();
            Iterator<Entry<String, String>> it = set.iterator();
            while (it.hasNext()) {
                Entry<String, String> ey = it.next();
                String key = ey.getKey();
                String value = ey.getValue();
                sf.append(
                        "<input type=\"hidden\" name=\"" + key + "\" id=\"" + key + "\" value=\"" + value + "\"/>");
            }
        }
        sf.append("</form>");
        sf.append("</body>");
        sf.append("<script type=\"text/javascript\">");
        sf.append("document.all.pay_form.submit();");
        sf.append("</script>");
        sf.append("</html>");
        return sf.toString();
    }

    /**
     * ?DEFLATEBase64?? ???
     * 
     * @param filePath
     *            ?
     * @return
     */
    public static String enCodeFileContent(String filePath) {
        String baseFileContent = "";

        File file = new File(filePath);
        if (!file.exists()) {
            try {
                file.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        InputStream in = null;
        try {
            in = new FileInputStream(file);
            int fl = in.available();
            if (null != in) {
                byte[] s = new byte[fl];
                in.read(s, 0, fl);
                // ?.
                baseFileContent = new String(SecureUtil.base64Encode(SecureUtil.deflater(s)));
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (null != in) {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return baseFileContent;
    }

    /**
     * ?fileContent?  base64DEFLATE?<br>
     * ??<br>
     * 
     * @param resData<br>
     * @param encoding
     *            ?encoding<br>
     */
    public static void deCodeFileContent(Map<String, String> resData, String filePathRoot, String encoding) {
        // ?
        String fileContent = resData.get(SDKConstants.param_fileContent);
        if (null != fileContent && !"".equals(fileContent)) {
            try {
                byte[] fileArray = SecureUtil.inflater(SecureUtil.base64Decode(fileContent.getBytes(encoding)));
                String filePath = null;
                if (SDKUtil.isEmpty(resData.get("fileName"))) {
                    filePath = filePathRoot + File.separator + resData.get("merId") + "_" + resData.get("batchNo")
                            + "_" + resData.get("txnTime") + ".txt";
                } else {
                    filePath = filePathRoot + File.separator + resData.get("fileName");
                }
                File file = new File(filePath);
                if (file.exists()) {
                    file.delete();
                }
                file.createNewFile();
                FileOutputStream out = new FileOutputStream(file);
                out.write(fileArray, 0, fileArray.length);
                out.flush();
                out.close();

            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     *  ??base64,
     * 
     * @param fileContent
     * @return
     * @throws UnsupportedEncodingException
     * @throws IOException
     */
    public static String getFileContent(String fileContent, String encoding)
            throws UnsupportedEncodingException, IOException {
        return new String(SecureUtil.inflater(SecureUtil.base64Decode(fileContent.getBytes())), encoding);
    }

    /**
     * ???customerInfo<br>
     * ?????
     * customerInfo????cvn2??pin?<br>
     * 
     * @param customerInfoMap
     *            ?? key???value?,?<br>
     *            customerInfoMap.put("certifTp", "01"); //?<br>
     *            customerInfoMap.put("certifId", "341126197709218366"); //???
     *            <br>
     *            customerInfoMap.put("customerNm", "?"); //??<br>
     *            customerInfoMap.put("phoneNo", "13552535506"); //?<br>
     *            customerInfoMap.put("smsCode", "123456"); //??<br>
     *            customerInfoMap.put("pin", "111111"); //?<br>
     *            customerInfoMap.put("cvn2", "123"); //??cvn2??<br>
     *            customerInfoMap.put("expired", "1711"); // ???)<br>
     * @param accNo
     *            customerInfoMap?????,customerInfoMap??pin???<br>
     * @param encoding
     *            ?encoding<br>
     * @return base64????<br>
     */
    public static String getCustomerInfo(Map<String, String> customerInfoMap, String accNo, String encoding) {

        StringBuffer sf = new StringBuffer("{");

        for (Iterator<String> it = customerInfoMap.keySet().iterator(); it.hasNext();) {
            String key = it.next();
            String value = customerInfoMap.get(key);
            if (key.equals("pin")) {
                if (null == accNo || "".equals(accNo.trim())) {
                    LogUtil.writeLog(
                            "??PINgetCustomerInfoWithEncrypt???");
                    return "{}";
                } else {
                    value = SDKUtil.encryptPin(accNo, value, encoding);
                }
            }
            if (it.hasNext())
                sf.append(key + SDKConstants.EQUAL + value + SDKConstants.AMPERSAND);
            else
                sf.append(key + SDKConstants.EQUAL + value);
        }
        sf.append("}");

        String customerInfo = sf.toString();
        LogUtil.writeLog("customerInfo" + customerInfo);
        try {
            return new String(SecureUtil.base64Encode(sf.toString().getBytes(encoding)));
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return customerInfo;
    }

    /**
     * ???customerInfo???? pinphoneNocvn2expired <br>
     *  <br>
     * 
     * @param customerInfoMap
     *            ?? key???value?,? <br>
     *            customerInfoMap.put("certifTp", "01"); //? <br>
     *            customerInfoMap.put("certifId", "341126197709218366"); //???
     *            <br>
     *            customerInfoMap.put("customerNm", "?"); //?? <br>
     *            customerInfoMap.put("smsCode", "123456"); //?? <br>
     *            customerInfoMap.put("pin", "111111"); //? <br>
     *            customerInfoMap.put("phoneNo", "13552535506"); //? <br>
     *            customerInfoMap.put("cvn2", "123"); //??cvn2? <br>
     *            customerInfoMap.put("expired", "1711"); // ?? <br>
     * @param accNo
     *            customerInfoMap?????,customerInfoMap??PIN???<br>
     * @param encoding
     *            ?encoding
     * @return base64???? <br>
     */
    public static String getCustomerInfoWithEncrypt(Map<String, String> customerInfoMap, String accNo,
            String encoding) {

        StringBuffer sf = new StringBuffer("{");
        // ??
        StringBuffer encryptedInfoSb = new StringBuffer("");

        for (Iterator<String> it = customerInfoMap.keySet().iterator(); it.hasNext();) {
            String key = it.next();
            String value = customerInfoMap.get(key);
            if (key.equals("phoneNo") || key.equals("cvn2") || key.equals("expired")) {
                encryptedInfoSb.append(key + SDKConstants.EQUAL + value + SDKConstants.AMPERSAND);
            } else {
                if (key.equals("pin")) {
                    if (null == accNo || "".equals(accNo.trim())) {
                        LogUtil.writeLog(
                                "??PINgetCustomerInfoWithEncrypt???");
                        return "{}";
                    } else {
                        value = SDKUtil.encryptPin(accNo, value, encoding);
                    }
                }
                if (it.hasNext())
                    sf.append(key + SDKConstants.EQUAL + value + SDKConstants.AMPERSAND);
                else
                    sf.append(key + SDKConstants.EQUAL + value);
            }
        }

        if (!encryptedInfoSb.toString().equals("")) {
            // ?&?
            encryptedInfoSb.setLength(encryptedInfoSb.length() - 1);

            LogUtil.writeLog("customerInfo encryptedInfo" + encryptedInfoSb.toString());
            if (sf.toString().equals("{")) // phoneNocvn2expired?&
                sf.append("encryptedInfo" + SDKConstants.EQUAL);
            else
                sf.append(SDKConstants.AMPERSAND + "encryptedInfo" + SDKConstants.EQUAL);

            sf.append(SDKUtil.encryptEpInfo(encryptedInfoSb.toString(), encoding));
        }
        sf.append("}");

        String customerInfo = sf.toString();
        LogUtil.writeLog("customerInfo" + customerInfo);
        try {
            return new String(SecureUtil.base64Encode(sf.toString().getBytes(encoding)));
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return customerInfo;
    }

    /**
     * ??(cardTransData)<br>
     * ?{}???&???{???1=&???2=&???3=}<br>
     * ?????
     * 
     * @param contentData
     * @param encoding
     * @return
     */
    public static String getCardTransData(Map<String, ?> contentData, String encoding) {

        StringBuffer cardTransDataBuffer = new StringBuffer();

        // ???cardTransData,?
        String ICCardData = "uduiadniodaiooxnnxnnada";// IC??
        String ICCardSeqNumber = "123";// IC???
        String track2Data = "testtrack2Datauidanidnaidiadiada231";// ???
        String track3Data = "testtrack3Datadadaiiuiduiauiduia312117831";// ???
        String transSendMode = "b";// ??

        // ??? ?merId|orderId|txnTime|txnAmt|track2Data
        StringBuffer track2Buffer = new StringBuffer();
        track2Buffer.append(contentData.get("merId")).append(SDKConstants.COLON).append(contentData.get("orderId"))
                .append(SDKConstants.COLON).append(contentData.get("txnTime")).append(SDKConstants.COLON)
                .append(contentData.get("txnAmt")).append(SDKConstants.COLON).append(track2Data);

        String encryptedTrack2 = SDKUtil.encryptTrack(track2Buffer.toString(), encoding);

        // ??? ?merId|orderId|txnTime|txnAmt|track3Data
        StringBuffer track3Buffer = new StringBuffer();
        track3Buffer.append(contentData.get("merId")).append(SDKConstants.COLON).append(contentData.get("orderId"))
                .append(SDKConstants.COLON).append(contentData.get("txnTime")).append(SDKConstants.COLON)
                .append(contentData.get("txnAmt")).append(SDKConstants.COLON).append(track3Data);

        String encryptedTrack3 = SDKUtil.encryptTrack(track3Buffer.toString(), encoding);

        // ?MAP,??
        Map<String, String> cardTransDataMap = new HashMap<String, String>();
        cardTransDataMap.put("ICCardData", ICCardData);
        cardTransDataMap.put("ICCardSeqNumber", ICCardSeqNumber);
        cardTransDataMap.put("track2Data", encryptedTrack2);
        cardTransDataMap.put("track3Data", encryptedTrack3);
        cardTransDataMap.put("transSendMode", transSendMode);

        return cardTransDataBuffer.append(SDKConstants.LEFT_BRACE).append(SDKUtil.coverMap2String(cardTransDataMap))
                .append(SDKConstants.RIGHT_BRACE).toString();
    }

    /**
     * ???(SHA1?)
     * 
     * @param data
     *            ???Map?
     * @param encoding
     *            ?
     * @return ????
     */
    public static boolean sign(Map<String, String> data, String encoding) {
        if (isEmpty(encoding)) {
            encoding = "UTF-8";
        }
        // ?????
        data.put(SDKConstants.param_certId, CertUtil.getSignCertId());
        // Map???key1=value1&key2=value2?
        String stringData = coverMap2String(data);
        System.out.println("??:[" + stringData + "]");
        /**
         * ??\base64?
         */
        byte[] byteSign = null;
        String stringSign = null;
        try {
            // SHA1?16
            byte[] signDigest = SecureUtil.sha1X16(stringData, encoding);
            byteSign = SecureUtil.base64Encode(SecureUtil.signBySoft(CertUtil.getSignCertPrivateKey(), signDigest));
            stringSign = new String(byteSign);
            // ??
            data.put(SDKConstants.param_signature, stringSign);
            return true;
        } catch (Exception e) {
            LogUtil.writeErrorLog("??", e);
            return false;
        }
    }

    /**
     * ????????????<br>
     * 
     * @param data
     *            ???Map?
     * @param encoding
     *            ?
     * @param certPath
     *            ??
     * @param certPwd
     *            ??
     * @return ??
     */
    public static boolean signByCertInfo(Map<String, String> data, String encoding, String certPath,
            String certPwd) {
        if (isEmpty(encoding)) {
            encoding = "UTF-8";
        }
        if (isEmpty(certPath) || isEmpty(certPwd)) {
            LogUtil.writeLog("Invalid Parameter:CertPath=[" + certPath + "],CertPwd=[" + certPwd + "]");
            return false;
        }
        // ?????
        data.put(SDKConstants.param_certId, CertUtil.getCertIdByKeyStoreMap(certPath, certPwd));
        // Map???key1=value1&key2=value2?
        String stringData = coverMap2String(data);
        /**
         * ??\base64?
         */
        byte[] byteSign = null;
        String stringSign = null;
        try {
            byte[] signDigest = SecureUtil.sha1X16(stringData, encoding);
            byteSign = SecureUtil.base64Encode(
                    SecureUtil.signBySoft(CertUtil.getSignCertPrivateKeyByStoreMap(certPath, certPwd), signDigest));
            stringSign = new String(byteSign);
            // ??
            data.put(SDKConstants.param_signature, stringSign);
            return true;
        } catch (Exception e) {
            LogUtil.writeErrorLog("??", e);
            return false;
        }
    }

    /**
     * ?.
     * 
     * @param card
     *            ??
     * @param pwd
     *            ?
     * @param encoding
     *            ?
     * @return ?
     */
    public static String encryptPin(String card, String pwd, String encoding) {
        return SecureUtil.EncryptPin(pwd, card, encoding, CertUtil.getEncryptCertPublicKey());
    }

    /**
     * CVN2.
     * 
     * @param cvn2
     *            CVN2
     * @param encoding
     *            ?
     * @return ??
     */
    public static String encryptCvn2(String cvn2, String encoding) {
        return SecureUtil.EncryptData(cvn2, encoding, CertUtil.getEncryptCertPublicKey());
    }

    /**
     * CVN2
     * 
     * @param base64cvn2
     *            ?CVN2
     * @param encoding
     *            ?
     * @return ??
     */
    public static String decryptCvn2(String base64cvn2, String encoding) {
        return SecureUtil.DecryptedData(base64cvn2, encoding, CertUtil.getSignCertPrivateKey());
    }

    /**
     * .
     * 
     * @param date
     *            
     * @param encoding
     *            ?
     * @return ??
     */
    public static String encryptAvailable(String date, String encoding) {
        return SecureUtil.EncryptData(date, encoding, CertUtil.getEncryptCertPublicKey());
    }

    /**
     * .
     * 
     * @param base64Date
     *            
     * @param encoding
     *            ?
     * @return ??
     */
    public static String decryptAvailable(String base64Date, String encoding) {
        return SecureUtil.DecryptedData(base64Date, encoding, CertUtil.getSignCertPrivateKey());
    }

    /**
     * ??.
     * 
     * @param pan
     *            ??
     * @param encoding
     *            ?
     * @return ???
     */
    public static String encryptPan(String pan, String encoding) {
        return SecureUtil.EncryptData(pan, encoding, CertUtil.getEncryptCertPublicKey());
    }

    /**
     * ??.
     * 
     * @param base64Pan
     *            ????
     * @param encoding
     * @return
     */
    public static String decryptPan(String base64Pan, String encoding) {
        return SecureUtil.DecryptedData(base64Pan, encoding, CertUtil.getSignCertPrivateKey());
    }

    /**
     * ??encryptedInfo
     * 
     * @param date
     *            
     * @param encoding
     *            ?
     * @return ??
     */
    public static String encryptEpInfo(String encryptedInfo, String encoding) {
        return SecureUtil.EncryptData(encryptedInfo, encoding, CertUtil.getEncryptCertPublicKey());
    }

    /**
     * ??encryptedInfo.
     * 
     * @param base64Date
     *            
     * @param encoding
     *            ?
     * @return ??
     */
    public static String decryptEpInfo(String base64EncryptedInfo, String encoding) {
        return SecureUtil.DecryptedData(base64EncryptedInfo, encoding, CertUtil.getSignCertPrivateKey());
    }

    /**
     * ???
     * 
     * @param trackData
     *            ???
     * @param encoding
     *            ??
     * @return String
     */
    public static String encryptTrack(String trackData, String encoding) {
        return SecureUtil.EncryptData(trackData, encoding, CertUtil.getEncryptTrackCertPublicKey());
    }

    /**
     * ???
     * 
     * @param trackData
     *            ???
     * @param encoding
     *            ??
     * @param modulus
     *            
     * @param exponent
     *            
     * @return
     */
    public static String encryptTrack(String trackData, String encoding, String modulus, String exponent) {
        return SecureUtil.EncryptData(trackData, encoding,
                CertUtil.getEncryptTrackCertPublicKey(modulus, exponent));
    }

    /**
     * ???????
     * 
     * @return
     */
    public static String getEncryptCertId() {
        return CertUtil.getEncryptCertId();
    }

    /**
     * Map???Keyascii???key1=value1&key2=value2? ????signature
     * 
     * @param data
     *            Map?
     * @return ?
     */
    public static String coverMap2String(Map<String, String> data) {
        TreeMap<String, String> tree = new TreeMap<String, String>();
        Iterator<Entry<String, String>> it = data.entrySet().iterator();
        while (it.hasNext()) {
            Entry<String, String> en = it.next();
            if (SDKConstants.param_signature.equals(en.getKey().trim())) {
                continue;
            }
            tree.put(en.getKey(), en.getValue());
        }
        it = tree.entrySet().iterator();
        StringBuffer sf = new StringBuffer();
        while (it.hasNext()) {
            Entry<String, String> en = it.next();
            sf.append(en.getKey() + SDKConstants.EQUAL + en.getValue() + SDKConstants.AMPERSAND);
        }
        return sf.substring(0, sf.length() - 1);
    }

    /**
     * ? key=value&key=value?Map
     * 
     * @param result
     * @return
     */
    public static Map<String, String> coverResultString2Map(String result) {
        return convertResultStringToMap(result);
    }

    /**
     * key=value&key=value?Map
     * 
     * @param result
     * @return
     */
    public static Map<String, String> convertResultStringToMap(String result) {
        Map<String, String> map = null;
        try {

            if (StringUtils.isNotBlank(result)) {
                if (result.startsWith("{") && result.endsWith("}")) {
                    System.out.println(result.length());
                    result = result.substring(1, result.length() - 1);
                }
                map = parseQString(result);
            }

        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return map;
    }

    /**
     * ???
     * 
     * @param str
     *            ??
     * @return ?map
     * @throws UnsupportedEncodingException
     */
    public static Map<String, String> parseQString(String str) throws UnsupportedEncodingException {

        Map<String, String> map = new HashMap<String, String>();
        int len = str.length();
        StringBuilder temp = new StringBuilder();
        char curChar;
        String key = null;
        boolean isKey = true;
        boolean isOpen = false;// 
        char openName = 0;
        if (len > 0) {
            for (int i = 0; i < len; i++) {// ???
                curChar = str.charAt(i);// ??
                if (isKey) {// ??key

                    if (curChar == '=') {// ?=
                        key = temp.toString();
                        temp.setLength(0);
                        isKey = false;
                    } else {
                        temp.append(curChar);
                    }
                } else {// ??value
                    if (isOpen) {
                        if (curChar == openName) {
                            isOpen = false;
                        }

                    } else {// ?
                        if (curChar == '{') {// ?
                            isOpen = true;
                            openName = '}';
                        }
                        if (curChar == '[') {
                            isOpen = true;
                            openName = ']';
                        }
                    }
                    if (curChar == '&' && !isOpen) {// ?&,??map
                        putKeyValueToMap(temp, isKey, key, map);
                        temp.setLength(0);
                        isKey = true;
                    } else {
                        temp.append(curChar);
                    }
                }

            }
            putKeyValueToMap(temp, isKey, key, map);
        }
        return map;
    }

    private static void putKeyValueToMap(StringBuilder temp, boolean isKey, String key, Map<String, String> map)
            throws UnsupportedEncodingException {
        if (isKey) {
            key = temp.toString();
            if (key.length() == 0) {
                throw new RuntimeException("QString format illegal");
            }
            map.put(key, "");
        } else {
            if (key.length() == 0) {
                throw new RuntimeException("QString format illegal");
            }
            map.put(key, temp.toString());
        }
    }

    /**
     * ?NULL
     * 
     * @param s
     *            ?
     * @return  true- false-?
     */
    public static boolean isEmpty(String s) {
        return null == s || "".equals(s.trim());
    }

}