com.sammyun.plugin.alipayWap.AlipayWapPlugin.java Source code

Java tutorial

Introduction

Here is the source code for com.sammyun.plugin.alipayWap.AlipayWapPlugin.java

Source

/*
 * Copyright 2012-2014 sammyun.com.cn. All rights reserved.
 * Support: http://www.sammyun.com.cn
 * License: http://www.sammyun.com.cn/license
 */
package com.sammyun.plugin.alipayWap;

import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.lang.StringUtils;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import com.sammyun.entity.Payment;
import com.sammyun.entity.PluginConfig;
import com.sammyun.plugin.PaymentPlugin;
import com.sammyun.plugin.alipayDirect.AlipayDirectPlugin;
import com.sammyun.plugin.alipayWap.httpClient.HttpProtocolHandler;
import com.sammyun.plugin.alipayWap.httpClient.HttpRequest;
import com.sammyun.plugin.alipayWap.httpClient.HttpResponse;
import com.sammyun.plugin.alipayWap.httpClient.HttpResultType;
import com.sammyun.util.DateUtil;
import com.sammyun.util.MD5;
import com.sammyun.util.RSAUtils;

/**
 * Plugin - ?()
 * 
 * @author Sencloud Team
 * @version 3.0
 */
@Component("alipayWapPlugin")
public class AlipayWapPlugin extends PaymentPlugin {

    /** logger */
    private static final Logger logger = LoggerFactory.getLogger(AlipayDirectPlugin.class);

    @Override
    public String getName() {
        return "?()";
    }

    @Override
    public String getVersion() {
        return "1.0";
    }

    @Override
    public String getAuthor() {
        return "Sencloud";
    }

    @Override
    public String getSiteUrl() {
        return "http://www.sammyun.com.cn";
    }

    @Override
    public String getInstallUrl() {
        return "alipay_wap/install.ct";
    }

    @Override
    public String getUninstallUrl() {
        return "alipay_wap/uninstall.ct";
    }

    @Override
    public String getSettingUrl() {
        return "alipay_wap/setting.ct";
    }

    @Override
    public String getRequestUrl() {
        return "http://wappaygw.alipay.com/service/rest.htm?";
    }

    @Override
    public RequestMethod getRequestMethod() {
        return RequestMethod.get;
    }

    @Override
    public String getRequestCharset() {
        return "UTF-8";
    }

    @Override
    public Map<String, Object> getParameterMap(String sn, String description, HttpServletRequest request) {
        PluginConfig pluginConfig = getPluginConfig();
        Payment payment = getPayment(sn);

        String sellerAccountName = pluginConfig.getAttribute("partner");
        String subject = StringUtils.abbreviate(description.replaceAll("[^0-9a-zA-Z\\u4e00-\\u9fa5 ]", ""), 60);
        String totalFee = payment.getAmount().setScale(2).toString();
        String merchantUrl = getMobileNotifyUrl(sn, NotifyMethod.sync);
        // ?
        String format = "xml";
        // ??
        // ?
        String v = "2.0";

        // ?
        String reqDataToken = "<direct_trade_create_req><notify_url>" + getMobileNotifyUrl(sn, NotifyMethod.async)
                + "</notify_url><call_back_url>" + getMobileNotifyUrl(sn, NotifyMethod.sync)
                + "</call_back_url><seller_account_name>" + "moco.tmall@moco-paris.com"
                + "</seller_account_name><out_trade_no>" + sn + "</out_trade_no><subject>" + subject
                + "</subject><total_fee>" + totalFee + "</total_fee><merchant_url>" + merchantUrl
                + "</merchant_url></direct_trade_create_req>";

        Map<String, Object> parameterMapToken = new HashMap<String, Object>();
        parameterMapToken.put("service", "alipay.wap.trade.create.direct");
        parameterMapToken.put("partner", pluginConfig.getAttribute("partner"));
        parameterMapToken.put("_input_charset", "utf-8");
        // ???0001(RSA)?MD5
        // ????rsasign_type0001?RSA
        parameterMapToken.put("sec_id", PluginConfig.SIGN_TYPE);
        parameterMapToken.put("format", format);
        parameterMapToken.put("v", v);
        parameterMapToken.put("req_id", DateUtil.getOrderNum());
        parameterMapToken.put("req_data", reqDataToken);

        String requestToken = "";
        // URLDECODE?
        try {
            // 
            String sHtmlTextToken = buildRequest(getRequestUrl(), parameterMapToken);
            // sHtmlTextToken =
            // sHtmlTextToken.replaceAll("%(?![0-9a-fA-F]{2})",
            // "%25");
            // sHtmlTextToken = sHtmlTextToken.replaceAll("\\+", "%2B");
            sHtmlTextToken = URLDecoder.decode(sHtmlTextToken, "utf-8");
            requestToken = super.getRequestToken(sHtmlTextToken);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            logger.error(e.getMessage());
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getMessage());
        }

        // 
        String reqData = "<auth_and_execute_req><request_token>" + requestToken
                + "</request_token></auth_and_execute_req>";
        // 
        Map<String, Object> parameterMap = new HashMap<String, Object>();
        parameterMap.put("service", "alipay.wap.auth.authAndExecute");
        parameterMap.put("partner", sellerAccountName);
        parameterMap.put("_input_charset", "utf-8");
        parameterMap.put("sec_id", PluginConfig.SIGN_TYPE);
        parameterMap.put("format", format);
        parameterMap.put("v", v);
        parameterMap.put("req_data", reqData);
        return buildRequestPara(parameterMap);
    }

    @SuppressWarnings("unchecked")
    @Override
    public boolean verifyNotify(String sn, NotifyMethod notifyMethod, HttpServletRequest request) {
        PluginConfig pluginConfig = getPluginConfig();
        Payment payment = getPayment(sn);
        if (generateSign(request.getParameterMap()).equals(request.getParameter("sign"))
                && pluginConfig.getAttribute("partner").equals(request.getParameter("seller_id"))
                && sn.equals(request.getParameter("out_trade_no"))
                && ("TRADE_SUCCESS".equals(request.getParameter("trade_status"))
                        || "TRADE_FINISHED".equals(request.getParameter("trade_status")))
                && payment.getAmount().compareTo(new BigDecimal(request.getParameter("total_fee"))) == 0) {
            Map<String, Object> parameterMap = new HashMap<String, Object>();
            parameterMap.put("service", "notify_verify");
            parameterMap.put("partner", pluginConfig.getAttribute("partner"));
            parameterMap.put("notify_id", request.getParameter("notify_id"));
            if ("true".equals(post("https://mapi.alipay.com/gateway.do", parameterMap))) {
                return true;
            }
        }
        return false;
    }

    @Override
    public boolean verifyMobileNotify(String sn, NotifyMethod notifyMethod, HttpServletRequest request) {
        Map<String, Object> params = generateMobileSign(request);
        // ???
        if (NotifyMethod.sync.equals(notifyMethod)) {
            if (null != params && params.size() > 0) {
                // ???
                // ??
                String outTradeNo = params.get("out_trade_no").toString();
                // ?
                String result = params.get("result").toString();
                if (verifyReturn(params) && sn.equals(outTradeNo) && ("success".equals(result))) {
                    return true;
                }
            } else {
                return false;
            }
        } else {
            // RSA??
            if (PluginConfig.SIGN_TYPE.equals("0001")) {
                params = decrypt(params);
            }
            // XML?notify_data?
            Document doc_notify_data = null;
            try {
                doc_notify_data = DocumentHelper.parseText(params.get("notify_data").toString());
            } catch (DocumentException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            if (doc_notify_data != null) {
                // ??
                String outTradeNo = doc_notify_data.selectSingleNode("//notify/out_trade_no").getText();
                // ?
                String tradeStatus = doc_notify_data.selectSingleNode("//notify/trade_status").getText();
                if (verifyNotify(params) && sn.equals(outTradeNo)
                        && ("TRADE_FINISHED".equals(tradeStatus) || "TRADE_SUCCESS".equals(tradeStatus))) {
                    return true;
                }
            }
        }

        return false;
    }

    /**
     * RSA??
     * 
     * @return ??
     * @throws Exception
     */
    private Map<String, Object> generateMobileSign(HttpServletRequest request) {
        // ??POST????
        Map<String, Object> params = new HashMap<String, Object>();
        Map requestParams = request.getParameterMap();
        for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext();) {
            String name = (String) iter.next();
            String[] values = (String[]) requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
            }
            // ???mysignsign???
            params.put(name, valueStr);
        }
        return params;
    }

    /**
     * 
     * 
     * @param inputPara ??
     * @return ?
     */
    public Map<String, Object> decrypt(Map<String, Object> inputPara) {
        try {
            inputPara.put("notify_data", RSAUtils.decrypt(inputPara.get("notify_data").toString(),
                    PluginConfig.ALI_PRIVATE_KEY, PluginConfig.INPUT_CHARSET));
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getMessage());
        }
        return inputPara;
    }

    @Override
    public String getNotifyMessage(String sn, NotifyMethod notifyMethod, HttpServletRequest request) {
        if (notifyMethod == NotifyMethod.async) {
            return "success";
        }
        return null;
    }

    @Override
    public Integer getTimeout() {
        return 21600;
    }

    /**
     * ???
     * 
     * @param parameterMap ?
     * @return ??
     */
    private String generateSign(Map<String, ?> parameterMap) {
        PluginConfig pluginConfig = getPluginConfig();
        return DigestUtils.md5Hex(joinKeyValue(new TreeMap<String, Object>(parameterMap), null,
                pluginConfig.getAttribute("key"), "&", true, "sign_type", "sign"));
    }

    /**
     * ????
     * 
     * @param sParaTemp ??
     * @return ??
     */
    private Map<String, Object> buildRequestPara(Map<String, Object> sParaTemp) {
        // ???
        Map<String, Object> sPara = paraFilter(sParaTemp);
        // ???
        String mysign = buildRequestMysign(sPara);
        // ????????
        sPara.put("sign", mysign);
        if (!sPara.get("service").equals("alipay.wap.trade.create.direct")
                && !sPara.get("service").equals("alipay.wap.auth.authAndExecute")) {
            sPara.put("sign_type", PluginConfig.SIGN_TYPE);
        }
        return sPara;
    }

    /**
     * ???
     * 
     * @param sPara ???
     * @return ??
     */
    public String buildRequestMysign(Map<String, Object> sPara) {
        String prestr = createLinkString(sPara); // ?=???&??
        String mysign = "";
        PluginConfig pluginConfig = getPluginConfig();

        String key = pluginConfig.getAttribute("key");
        if (PluginConfig.SIGN_TYPE.equals("MD5")) {
            mysign = MD5.sign(prestr, key, PluginConfig.INPUT_CHARSET);
        }
        if (PluginConfig.SIGN_TYPE.equals("0001")) {
            mysign = RSAUtils.sign(prestr, PluginConfig.ALI_PRIVATE_KEY, PluginConfig.INPUT_CHARSET);
        }
        return mysign;
    }

    /**
     * HTTPPOST????
     * ??strParaFileNamestrFilePath buildRequest("",
     * "",sParaTemp)
     * 
     * @paramALIPAY_GATEWAY_NEW ??
     * @param strParaFileName ???
     * @param strFilePath 
     * @param sParaTemp ?
     * @return ??
     * @throws Exception
     */
    public String buildRequest(String url, Map<String, Object> sParaTemp) throws Exception {
        // ?
        Map<String, Object> sPara = buildRequestPara(sParaTemp);
        HttpProtocolHandler httpProtocolHandler = HttpProtocolHandler.getInstance();
        HttpRequest request = new HttpRequest(HttpResultType.BYTES);
        // ?
        request.setCharset(PluginConfig.INPUT_CHARSET);
        request.setParameters(generatNameValuePair(sPara));
        request.setUrl(url + "_input_charset=" + PluginConfig.INPUT_CHARSET);
        HttpResponse response = httpProtocolHandler.execute(request, "", "");
        if (response == null) {
            return null;
        }
        String strResult = response.getStringResult();
        return strResult;
    }

    /**
     * MAP??NameValuePair
     * 
     * @param properties MAP
     * @return NameValuePair
     */
    private static NameValuePair[] generatNameValuePair(Map<String, Object> properties) {
        NameValuePair[] nameValuePair = new NameValuePair[properties.size()];
        int i = 0;
        for (Map.Entry<String, Object> entry : properties.entrySet()) {
            nameValuePair[i++] = new NameValuePair(entry.getKey(), entry.getValue().toString());
        }
        return nameValuePair;
    }

    /**
     * ????????callback
     * 
     * @param params ??
     * @return ?
     */
    public boolean verifyReturn(Map<String, Object> params) {
        String sign = "";
        // ????
        if (params.get("sign") != null) {
            sign = params.get("sign").toString();
        }
        // ???
        boolean isSign = getSignVeryfy(params, sign, true);

        // ???
        String sWord = "isSign=" + isSign + "\n ??" + createLinkString(params);
        // System.out.println(sWord);
        // isSign?true
        // isSign?true????????
        if (isSign) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * ?????????
     * 
     * @param params ??
     * @return ?
     */
    public boolean verifyNotify(Map<String, Object> params) {
        // ???????
        String responseTxt = "true";
        try {
            // XML?notify_data??notify_id
            Document document = DocumentHelper.parseText(params.get("notify_data").toString());
            String notify_id = document.selectSingleNode("//notify/notify_id").getText();
            responseTxt = verifyResponse(notify_id);
        } catch (Exception e) {
            responseTxt = e.toString();
        }
        // ????
        String sign = "";
        if (params.get("sign") != null) {
            sign = params.get("sign").toString();
        }
        boolean isSign = getSignVeryfy(params, sign, false);
        // responsetTxt?trueisSign?true
        // responsetTxt?true???ID?notify_id
        // isSign?true????????
        if (isSign && responseTxt.equals("true")) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * ????????
     * 
     * @param Params ??
     * @param sign ??
     * @param isSort ??
     * @return ???
     */
    private boolean getSignVeryfy(Map<String, Object> params, String sign, boolean isSort) {
        PluginConfig pluginConfig = getPluginConfig();

        String key = pluginConfig.getAttribute("key");
        // ?signsign_type?
        Map<String, Object> sParaNew = paraFilter(params);
        // ???
        String preSignStr = "";
        if (isSort) {
            preSignStr = createLinkString(sParaNew);
        } else {
            preSignStr = createLinkStringNoSort(sParaNew);
        }
        // ???
        boolean isSign = false;
        if (PluginConfig.SIGN_TYPE.equals("MD5")) {
            isSign = MD5.verify(preSignStr, sign, key, PluginConfig.INPUT_CHARSET);
        }
        if (PluginConfig.SIGN_TYPE.equals("0001")) {
            isSign = RSAUtils.verify(preSignStr, sign, PluginConfig.ALI_PUBLIC_KEY, PluginConfig.INPUT_CHARSET);
        }
        return isSign;
    }

    /**
     * ??ATN,?URL
     * 
     * @param notify_id ID
     * @return ?ATN ? invalid?? ?partnerkey?
     *         true ? false ??????
     */
    private String verifyResponse(String notify_id) {
        // ??ATN??????
        PluginConfig pluginConfig = getPluginConfig();
        String partner = pluginConfig.getAttribute("partner");
        Map<String, Object> parameterMap = new HashMap<String, Object>();
        parameterMap.put("service", "notify_verify");
        parameterMap.put("partner", partner);
        parameterMap.put("notify_id", notify_id);
        return post("https://mapi.alipay.com/gateway.do", parameterMap);
    }
}