package com.hugnew.sps.services.pay.strategy;
import com.alibaba.fastjson.JSONObject;
import com.hugnew.core.util.PropertiesUtil;
import com.hugnew.sps.services.pay.util.app.wechat.util.MD5;
import com.hugnew.sps.services.pay.util.app.wechat.util.Util;
import com.hugnew.sps.enums.PayType;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import org.slf4j.Logger;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserFactory;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.util.*;
/**
* 微信app支付
* Created by Martin on 2016/7/01.
*/
public class WechatPayAppStrategy implements PayStrategy {
private static Logger logger = org.slf4j.LoggerFactory.getLogger(WechatPayAppStrategy.class);
@Override
public String generatePayParams(PayType payType, Map<String, Object> params) {
String url = String.format("https://api.mch.weixin.qq.com/pay/unifiedorder");
String entity = genProductArgs(params);
byte[] buf = Util.httpPost(url, entity);
String content = new String(buf);
if(logger.isDebugEnabled()){
logger.debug("wechat content:{}", content);
}
Map<String, String> xml = decodeXml(content);
if(logger.isDebugEnabled()){
logger.debug("wechat xml:{}", xml.toString());
}
List<NameValuePair> toRet = genPayReq(xml.get("prepay_id"));
Map<String, Object> map = new HashMap<>();
for (NameValuePair var : toRet) {
if ("package".equals(var.getName())) {
map.put("_package", var.getValue());
} else {
map.put(var.getName(), var.getValue());
}
}
return JSONObject.toJSONString(map);
}
public Map<String, String> decodeXml(String content) {
try {
Map<String, String> xml = new HashMap<String, String>();
XmlPullParser parser = XmlPullParserFactory.newInstance().newPullParser();
parser.setInput(new StringReader(content));
int event = parser.getEventType();
while (event != XmlPullParser.END_DOCUMENT) {
String nodeName = parser.getName();
switch (event) {
case XmlPullParser.START_DOCUMENT:
break;
case XmlPullParser.START_TAG:
if ("xml".equals(nodeName) == false) {
//实例化student对象
xml.put(nodeName, parser.nextText());
}
break;
case XmlPullParser.END_TAG:
break;
}
event = parser.next();
}
return xml;
} catch (Exception e) {
logger.error("decode xml error,ex:{}", e.toString());
}
return null;
}
private String genProductArgs(Map<String, Object> params) {
StringBuffer xml = new StringBuffer();
try {
String nonceStr = genNonceStr();
xml.append("</xml>");
List<NameValuePair> packageParams = new LinkedList<NameValuePair>();
packageParams.add(new BasicNameValuePair("appid", PropertiesUtil.getValue("pay.request.wechart.appid")));
String orderCode = (String) params.get("orderCode");
if (StringUtils.isNotBlank(orderCode)) {
packageParams.add(new BasicNameValuePair("body", "hugnew-订单编号:" + orderCode));
} else {
packageParams.add(new BasicNameValuePair("body", "hugnew订单支付"));
}
packageParams.add(new BasicNameValuePair("mch_id", PropertiesUtil.getValue("pay.request.wechart.mch_id")));
packageParams.add(new BasicNameValuePair("nonce_str", nonceStr));
packageParams.add(new BasicNameValuePair("notify_url", PropertiesUtil.getValue("wechat.pay.notify.url")));
packageParams.add(new BasicNameValuePair("out_trade_no", (String) params.get("payCode")));
packageParams.add(new BasicNameValuePair("spbill_create_ip", PropertiesUtil.getValue("pay.request.wechart.spbill_create_ip")));
packageParams.add(new BasicNameValuePair("total_fee", String.valueOf(((BigDecimal)params.get("toPay")).multiply(BigDecimal.valueOf(100)).longValue())));
packageParams.add(new BasicNameValuePair("trade_type", PropertiesUtil.getValue("pay.request.wechart.trade_type")));
String sign = genPackageSign(packageParams);
packageParams.add(new BasicNameValuePair("sign", sign));
String xmlstring = toXml(packageParams);
return new String(xmlstring.getBytes("UTF-8"), "ISO-8859-1");
} catch (Exception e) {
logger.error("genProductArgs error, ex:{} ", e.getMessage());
}
return null;
}
private String genPackageSign(List<NameValuePair> params) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < params.size(); i++) {
sb.append(params.get(i).getName());
sb.append('=');
sb.append(params.get(i).getValue());
sb.append('&');
}
sb.append("key=");
sb.append(PropertiesUtil.getValue("pay.request.wechart.API_KEY"));
String packageSign = null;
try {
packageSign = MD5.getMessageDigest(sb.toString().getBytes("utf-8")).toUpperCase();
} catch (UnsupportedEncodingException e) {
logger.error("packageSign md5 error, ex:{} ", e.getMessage());
}
if(logger.isDebugEnabled()){
logger.debug("wechat packageSign:{}", packageSign);
}
return packageSign;
}
private String genNonceStr() {
Random random = new Random();
return MD5.getMessageDigest(String.valueOf(random.nextInt(10000)).getBytes());
}
private String genAppSign(List<NameValuePair> params) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < params.size(); i++) {
sb.append(params.get(i).getName());
sb.append('=');
sb.append(params.get(i).getValue());
sb.append('&');
}
sb.append("key=");
sb.append(PropertiesUtil.getValue("pay.request.wechart.API_KEY"));
String appSign = MD5.getMessageDigest(sb.toString().getBytes()).toUpperCase();
if(logger.isDebugEnabled()){
logger.debug("wechat appSign:{}", appSign);
}
return appSign;
}
private String toXml(List<NameValuePair> params) {
StringBuilder sb = new StringBuilder();
sb.append("<xml>");
for (int i = 0; i < params.size(); i++) {
sb.append("<" + params.get(i).getName() + ">");
sb.append(params.get(i).getValue());
sb.append("</" + params.get(i).getName() + ">");
}
sb.append("</xml>");
if(logger.isDebugEnabled()){
logger.debug("packageParams toxml:{}", sb.toString());
}
return sb.toString();
}
private List<NameValuePair> genPayReq(String prepayId) {
List<NameValuePair> signParams = new LinkedList<NameValuePair>();
signParams.add(new BasicNameValuePair("appid", PropertiesUtil.getValue("pay.request.wechart.appid")));
signParams.add(new BasicNameValuePair("noncestr", genNonceStr()));
signParams.add(new BasicNameValuePair("package", PropertiesUtil.getValue("pay.request.wechart.package")));
signParams.add(new BasicNameValuePair("partnerid", PropertiesUtil.getValue("pay.request.wechart.mch_id")));
signParams.add(new BasicNameValuePair("prepayid", prepayId));
signParams.add(new BasicNameValuePair("timestamp", String.valueOf(System.currentTimeMillis() / 1000)));
String sign = genAppSign(signParams);
signParams.add(new BasicNameValuePair("sign", sign));
if(logger.isDebugEnabled()){
logger.debug("signParams:{}", signParams.toString());
}
return signParams;
}
}