记录下自己的学习,有坑。欢迎指正,轮子很多。小伙伴们可以去其他地方找找,我参考了好多能直接跑起来的代码,想贴链接的,找不到了。。。。。
微信支付:
public class WxPay {
/**
*
* @param request
* @param orderSum //订单金额
* @param order //订单
* @param payMethod //支付方式---只有微信支付
* @param attach // 附加数据,在查询API和支付通知中原样返回,可作为自定义参数使用。
* @return
*/
public JSONObject wechatPay(HttpServletRequest request,Double orderSum,Order order, Integer payMethod, String attach) {
SortedMap<String, String> payInfo = null;
Date now = new Date();
Customer customer = null;
logger.error("..............微信支付.......");
if (null != order) {
customer = customerService.selectById(order.getCustomerId());
if (null != customer) {
// 微信支付统一下单
XMLReturn rb = wxUnifiedOrder(order.getCode(), orderSum, customer.getOpenId(),
request.getRemoteAddr(), attach);
if (null != rb.getResultCode() && rb.getResultCode().equals("SUCCESS") && rb.getReturnCode().equals("SUCCESS")) {
String prepayId = rb.getPrepayId(); //微信生成的预支付会话标识,用于后续接口调用中使用,该值有效期为2小时
if (!StringUtils.isEmpty(prepayId)) {
//业务逻辑部分
String packages = "prepay_id=" + prepayId;
/***
* 备注:prepay_id 通过 微信支付统一下单接口 拿到,paySign 采用统一的微信支付 Sign 签名生成方法,
* 注意这里 appId 也要参与签名,appId 与 config 中传入的 appId 一致,
* 即最后参与签名的参数有appId, timeStamp, nonceStr, package, signType。
*/
payInfo = this.wxPay(packages, Config.MCHKEY); //MCHKEY-微信支付商户密钥
logger.error("返回payInfo:" + payInfo.toString());
jsonObj.put("payInfo", payInfo);
jsonObj.put("code", 100000);
jsonObj.put("msg", "SUCCESS");
}
} else {
logger.error("支付失败,错误码为:" + rb.getErrCode() + ", 错误原因:" + rb.getErrCodeDes());
jsonObj.put("code", 100003);
jsonObj.put("msg", "支付失败");
}
} else {
jsonObj.put("code", 100004);
jsonObj.put("msg", "当前用户不存在");
}
}
return jsonObj;
}
//统一下单
public XMLReturn wxUnifiedOrder(String orderCode, Double totalFee, String openid, String userIP, String attach) {
NumberFormat f = NumberFormat.getIntegerInstance();
f.setGroupingUsed(false);
SortedMap<String, String> params = new TreeMap<String, String>();
params.put("appid", Config.APPID);
params.put("attach", attach);
params.put("mch_id", Config.MCHID);
params.put("body", "");
params.put("nonce_str", UUID.randomUUID().toString().replaceAll("-", ""));
params.put("out_trade_no", orderCode);
params.put("total_fee", f.format(totalFee * 100)); //单位:分
params.put("fee_type", "1");
params.put("notify_url", Config.NOTIFYURL); //回调的url
params.put("spbill_create_ip", userIP);
params.put("openid", openid);
params.put("trade_type", "JSAPI");
String xml = createSign(params, AppKey); //AppKey
try {
XMLReturn ret = this.xmlPost(Config.UNIFIEDORDER_URL, xml.toString());
return ret;
} catch (WeixinApiException e) {
e.printStackTrace();
}
return null;
}
//排序
private SortedMap<String, String> wxPay(String packages, String paySignKey) {
SortedMap<String, String> params = new TreeMap<String, String>();
params.put("appId", Config.APPID);
params.put("timeStamp", String.valueOf(System.currentTimeMillis() / 1000));
params.put("nonceStr", "");//支付签名随机串,不长于 32 位
params.put("package", packages);
params.put("signType", "MD5");
String signature = createSign(params, paySignKey);
params.put("paySign", signature);
return params;
}
/**
* @param params
* @Author: HONGLINCHEN
* @Description:请求值转换为xml格式 SortedMap转xml
* @Date: 2017-9-7 17:18
*/
private String SortedMaptoXml(SortedMap<String, String> params) {
StringBuilder sb = new StringBuilder();
Set es = params.entrySet();
Iterator it = es.iterator();
sb.append("<xml>\n");
while (it.hasNext()) {
Map.Entry entry = (Map.Entry) it.next();
String k = (String) entry.getKey();
Object v = entry.getValue();
sb.append("<" + k + ">");
sb.append(v);
sb.append("</" + k + ">\n");
}
sb.append("</xml>");
return sb.toString();
}
/**
* 创建md5摘要,规则是:按参数名称a-z排序,遇到空值的参数不参加签名。
*/
private String createSign(SortedMap<String, String> packageParams, String AppKey) {
StringBuffer sb = new StringBuffer();
Set es = packageParams.entrySet();
Iterator it = es.iterator();
while (it.hasNext()) {
Map.Entry entry = (Map.Entry) it.next();
String k = (String) entry.getKey();
String v = (String) entry.getValue();
if (null != v && !"".equals(v) && !"sign".equals(k) && !"key".equals(k)) {
sb.append(k + "=" + v + "&");
}
}
sb.append("key=" + AppKey);
String sign = MD5Util.md5Encode(sb.toString(), "UTF-8").toUpperCase();
return sign;
}
}
支付回调:
public String callbackWx(HttpServletRequest request) {
try {
logger.error("............回调成功....");
BufferedReader reader = null;
reader = request.getReader();
String line = "";
String xmlString = null;
StringBuffer inputString = new StringBuffer();
while ((line = reader.readLine()) != null) {
inputString.append(line);
}
xmlString = inputString.toString();
request.getReader().close();
System.out.println("----接收到的数据如下:---" + xmlString);
WeChatPayResultLog chatPayResultLog = (WeChatPayResultLog) XmlUtils.stringToObject(xmlString, WeChatPayResultLog.class);
// 业务逻辑部分 -- 做出判断 return 结果告诉微信
} catch (Exception e) {
e.printStackTrace();
}
return "success";
}
其他说明:
/**
* 回调类 --- WeChatPayResultLog / XMReturn xml与对象的互相转的工具类,也有很多的。
*/
@XmlRootElement(name="xml")
@XmlAccessorType(XmlAccessType.FIELD)
public class WeChatPayResultLog implements Serializable {
private static final long serialVersionUID = 8152863814242851179L;
@XmlElement(name="return_code")
private String returnCode;
@XmlElement(name="return_msg")
private String returnMsg;
@XmlElement(name="appid")
private String appid;
@XmlElement(name="mch_id")
private String mchId;
//省略部分,以及 getter/setter
}