Java tutorial
/* * 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); } }