package jframe.pay.alipay.query;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
import jframe.pay.alipay.AlipayConfig;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.alipay.sign.MD5;
import com.alipay.util.HttpUtil;
/* *
*类名:AlipaySubmit
*功能:支付宝各接口请求提交类
*详细:构造支付宝各接口表单HTML文本,获取远程HTTP数据
*版本:3.3
*日期:2012-08-13
*说明:
*以下代码只是为了方便商户测试而提供的样例代码,商户可以根据自己网站的需要,按照技术文档编写,并非一定要使用该代码。
*该代码仅供学习和研究支付宝接口使用,只是提供一个参考。
*/
public class AlipaySubmit {
static Logger LOG = LoggerFactory.getLogger(AlipaySubmit.class);
/**
* 支付宝提供给商户的服务接入网关URL(新)
*/
private static final String ALIPAY_GATEWAY_NEW = "https://mapi.alipay.com/gateway.do?";
/**
* 生成签名结果
* @param sPara 要签名的数组
* @return 签名结果字符串
*/
public static String buildRequestMysign(Map<String, String> sPara) {
String prestr = AlipayCore.createLinkString(sPara); //把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串
String mysign = "";
if(AlipayConfig.getConf(AlipayConfig.SIGN_TYPE_QUERY).equals("MD5") ) {
mysign = MD5.sign(prestr, AlipayConfig.getConf(AlipayConfig.KEY), AlipayConfig.getConf(AlipayConfig.INPUT_CHARSET));
}
return mysign;
}
/**
* 生成要请求给支付宝的参数数组
* @param sParaTemp 请求前的参数数组
* @return 要请求的参数数组
*/
private static String buildRequestPara(Map<String, String> sParaTemp) {
sParaTemp.put("service", "single_trade_query");
sParaTemp.put("partner", AlipayConfig.getConf(AlipayConfig.PARTNER));
sParaTemp.put("_input_charset", AlipayConfig.getConf(AlipayConfig.INPUT_CHARSET));
//除去数组中的空值和签名参数
Map<String, String> sPara = AlipayCore.paraFilter(sParaTemp);
//生成签名结果
String mysign = buildRequestMysign(sPara);
try {
// 仅需对sign 做URL编码
mysign = URLEncoder.encode(mysign, AlipayConfig.getConf(AlipayConfig.INPUT_CHARSET));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
//签名结果与签名方式加入请求提交参数组中
sPara.put("sign", mysign);
sPara.put("sign_type", AlipayConfig.getConf(AlipayConfig.SIGN_TYPE_QUERY));
//String param = prestr + "&sign=" + mysign + "&sign_type=" + AlipayConfig.getConf(AlipayConfig.SIGN_TYPE);
String param = AlipayCore.createLinkString(sPara);
return param;
}
/**
* 建立请求,以模拟远程HTTP的POST请求方式构造并获取支付宝的处理结果
* 如果接口中没有上传文件参数,那么strParaFileName与strFilePath设置为空值
* 如:buildRequest("", "",sParaTemp)
* @param strParaFileName 文件类型的参数名
* @param strFilePath 文件路径
* @param sParaTemp 请求参数数组
* @return 支付宝处理结果
* @throws Exception
*/
public static Map<String,String> buildRequest(Map<String, String> sParaTemp) throws Exception {
//待请求参数数组
String sPara = buildRequestPara(sParaTemp);
String response = HttpUtil.doPost(ALIPAY_GATEWAY_NEW, null, sPara, AlipayConfig.getConf(AlipayConfig.INPUT_CHARSET));
return parseRespose(response);
}
/**
* 用于防钓鱼,调用接口query_timestamp来获取时间戳的处理函数
* 注意:远程解析XML出错,与服务器是否支持SSL等配置有关
* @return 时间戳字符串
* @throws Exception
* @throws UnsupportedEncodingException
* @throws IOException
* @throws DocumentException
* @throws MalformedURLException
*/
public static Map<String,String> parseRespose(String reponse) throws Exception {
Map<String,String> respMap = new HashMap<String,String>();
try {
SAXReader reader = new SAXReader();
Document doc = reader.read(new ByteArrayInputStream(reponse.getBytes("GBK")));
Node isSuccessNode = doc.selectSingleNode("//alipay/is_success");
if (isSuccessNode.getText().equals("T")) {
// 判断是否有成功标示
Node tradeStatusNode = doc.selectSingleNode("//response/trade/trade_status");
respMap.put("trade_status", tradeStatusNode.getText());
}
respMap.put("is_success", isSuccessNode.getText());
} catch (Exception e) {
LOG.error(e.getMessage(),reponse);
}
return respMap;
}
}