package com.stylefeng.guns.modular.shunfeng.controller;
|
|
import com.baomidou.mybatisplus.mapper.EntityWrapper;
|
import com.stylefeng.guns.core.util.SpringContextHolder;
|
import com.stylefeng.guns.modular.shunfeng.model.Financial;
|
import com.stylefeng.guns.modular.shunfeng.model.OrderRide;
|
import com.stylefeng.guns.modular.shunfeng.service.IFinancialService;
|
import com.stylefeng.guns.modular.shunfeng.service.IOrderRideService;
|
import com.stylefeng.guns.modular.shunfeng.tencent.WXPay;
|
import com.stylefeng.guns.modular.shunfeng.tencent.common.Configure;
|
import com.stylefeng.guns.modular.shunfeng.tencent.common.Signature;
|
import com.stylefeng.guns.modular.shunfeng.tencent.common.XMLParser;
|
import com.stylefeng.guns.modular.shunfeng.tencent.protocol.AppPayReqData;
|
import com.stylefeng.guns.modular.shunfeng.tencent.protocol.RefundReqData;
|
import com.stylefeng.guns.modular.shunfeng.tencent.protocol.UnifiedorderReqData;
|
import com.stylefeng.guns.modular.shunfeng.util.ApiUtil;
|
import com.stylefeng.guns.modular.system.service.ISystemNoticeService;
|
import org.slf4j.Logger;
|
import org.slf4j.LoggerFactory;
|
|
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletResponse;
|
import java.io.IOException;
|
import java.io.PrintWriter;
|
import java.util.Date;
|
import java.util.HashMap;
|
import java.util.Iterator;
|
import java.util.Map;
|
import java.util.regex.Matcher;
|
import java.util.regex.Pattern;
|
|
/**
|
* <b>支付处理工具类</b>
|
* <p>
|
* 封装【支付宝支付、微信支付、余额支付】
|
* </p>
|
*
|
* @author tzj
|
* @version 1.0
|
* @data 2017年6月17日
|
*/
|
|
public class PayUtil {
|
|
/**
|
* 日志记录(记录打印报文)
|
*/
|
Logger log = LoggerFactory.getLogger(getClass());
|
|
private ISystemNoticeService systemNoticeService = SpringContextHolder.getBean(ISystemNoticeService.class);
|
private IOrderRideService orderRideService = SpringContextHolder.getBean(IOrderRideService.class);
|
|
private IFinancialService financialService = SpringContextHolder.getBean(IFinancialService.class);
|
|
/**
|
* 获取支付信息
|
*
|
* @param userId 用户ID
|
* @param type 支付类型 1=支付宝,2 = 微信 3:银行卡 4:小程序
|
* @param ordernum 订单编号
|
* @param price 金额
|
* @return
|
*/
|
|
public Object getPayInfo(Integer type, String orderNum, String openId,
|
HttpServletRequest request) {
|
Double price = 0.0;
|
String subject = "";
|
String body = "";
|
try {
|
if (orderNum.contains("ride")) {
|
//顺风车支付
|
OrderRide orderRide = orderRideService.selectOne(new EntityWrapper<OrderRide>().eq("orderNum", orderNum));
|
price = Double.valueOf(orderRide.getMoney());
|
body = "全客通-顺风车支付";
|
subject = "全客通-顺风车支付";
|
}
|
Map<String, Object> map = new HashMap<String, Object>();
|
if (type == 1) {
|
} else if (type == 2) {
|
// 微信下单
|
return wxpay(1, orderNum, body, price, request);
|
} else if (type == 4) {
|
//小程序
|
return wxpayX(orderNum, body, price, "JSAPI", openId);
|
|
}
|
|
} catch (Exception e) {
|
e.printStackTrace();
|
}
|
return ApiUtil.putFailObj("获取异常");
|
}
|
|
/**
|
* 小程序
|
*/
|
private Map<String, Object> wxpayX(String orderNo, String body, Double price, String trade_type, String openId)
|
throws Exception {// JSAPI
|
Map<String, Object> map = new HashMap<String, Object>();
|
Map<String, Object> appPayMap = new HashMap<String, Object>();
|
// 构建接口请求参数
|
UnifiedorderReqData unifiedorderReqData = new UnifiedorderReqData(orderNo, body, price, Configure.wx_notify_url,
|
trade_type, openId);
|
|
// 请求接口获取返回接口
|
String result = WXPay.requestUnifiedorderService(2, unifiedorderReqData);
|
System.out.println("WxpayController.createOrder__result:\n" + result);
|
|
// 获取预支付接口返回参数
|
map = XMLParser.getMapFromXML(result);
|
System.out.println("WxpayController.createOrder__result:\n" + result);
|
|
// 捕获预支付接口错误提示
|
if ("FAIL".equals(map.get("result_code")) || "FAIL".equals(map.get("return_code"))) {
|
return ApiUtil.putFailObj(String.valueOf(map.get("return_msg")));
|
}
|
|
// 对获取预支付返回接口参数进行封装(生成支付订单接口数据)
|
AppPayReqData appPay = new AppPayReqData(1, (String) map.get("appid"), (String) map.get("mch_id"),
|
(String) map.get("prepay_id"), unifiedorderReqData.getNonce_str());
|
|
// 对获取预支付返回接口参数进行封装(生成支付订单接口数据)
|
appPayMap.put("appId", appPay.getAppid());// 公众账号ID
|
appPayMap.put("nonceStr", appPay.getNoncestr());// 随机字符串(32位)
|
appPayMap.put("package", "prepay_id=" + appPay.getPrepayid());
|
appPayMap.put("signType", "MD5");// 签名类型
|
appPayMap.put("timeStamp", appPay.getTimestamp());// 时间戳
|
// 公众号参与签名的参数: appId, timeStamp, nonceStr, package, signType
|
appPayMap.put("paySign", Signature.getSign(2, appPayMap));// 根据API给的签名规则进行签名
|
return appPayMap;
|
}
|
|
|
|
|
|
/**
|
* 服务器异步通知处理支付宝
|
*
|
* @param request
|
* @param res
|
*/
|
|
public void notifyUrl(HttpServletRequest request, HttpServletResponse res) {
|
HttpServletResponse response = (HttpServletResponse) res;
|
response.setContentType("text/html;charset=UTF-8");
|
PrintWriter out;
|
try {
|
out = response.getWriter();
|
// 获取支付宝POST过来反馈信息
|
Map<String, String> params = new HashMap<String, String>();
|
Map requestParams = request.getParameterMap();
|
log.debug("AlipayController.notifyUrl__requestParams:\n" + requestParams);
|
System.out.println("支付宝回调:=================" + requestParams);
|
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] + ",";
|
}
|
// 乱码解决,这段代码在出现乱码时使用。如果mysign和sign不相等也可以使用这段代码转化
|
valueStr = new String(valueStr.getBytes("ISO-8859-1"), "gbk");
|
params.put(name, valueStr);
|
}
|
|
Financial financial = getPayLog_alipay(request);
|
// 验证成功
|
if ("TRADE_FINISHED".equals(financial.getTradeStatus())) {
|
System.out.println("AlipayController.notifyUrl__验证成功:success");
|
// 支付失败
|
} else if ("TRADE_SUCCESS".equals(financial.getTradeStatus())) {
|
// 支付成功
|
try {
|
if (financial.getOrderNum().contains("ride")) {
|
//顺风车支付
|
//修改订单表中的订单流水和支付方式
|
OrderRide order = orderRideService.selectOne(new EntityWrapper<OrderRide>().eq("orderNum", financial.getOrderNum()));
|
|
order.setOutNum(financial.getLsType());//流水
|
order.setPayTime(new Date());
|
order.setPayType(3);//支付宝
|
order.setState(2);
|
financial.setPwType(8);//顺风车
|
financial.setUserId(order.getUserId());
|
financial.setLx(1);//1=用户 2=司机
|
financial.setOrderType(4);//顺风车
|
financialService.insert(financial);
|
orderRideService.updateById(order);
|
/*添加系统消息*/
|
try {
|
systemNoticeService.addSystemNotice(1, "您成功支付从" + order.getStartName() + "到" + order.getEndName() + "的顺风车订单", order.getUserId(), 1);
|
} catch (Exception e) {
|
throw new RuntimeException(e);
|
}
|
|
}
|
// ——请根据您的业务逻辑来编写程序(以上代码仅作参考)——
|
log.debug("AlipayController.notifyUrl__回调处理:success");
|
out.println("success"); // 请不要修改或删除
|
} catch (Exception e) {
|
log.debug("AlipayController.notifyUrl__回调逻辑代码处理异常!fail");
|
// 返回失败
|
out.println("fail");
|
e.printStackTrace();
|
}
|
// ////////////////////////////////////////////////////////////////////////////////////////
|
} else {// 验证失败
|
log.debug("AlipayController.notifyUrl__回调处理失败!fail");
|
out.println("fail");
|
}
|
} catch (IOException e) {
|
log.debug("AlipayController.notifyUrl__支付宝服务器异步通知数据处理失败!");
|
e.printStackTrace();
|
}
|
}
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
/**
|
* 统一下单
|
*
|
* @param apptype
|
* @param outTradeNo
|
* @param body
|
* @param price
|
* @param request
|
* @return
|
*/
|
public static Map<String, Object> wxpay(Integer apptype, String outTradeNo, String body, Double price,
|
HttpServletRequest request) {
|
// 获取预支付接口返回参数
|
Map<String, Object> map = new HashMap<String, Object>();
|
Map<String, Object> appPayMap = new HashMap<String, Object>();
|
try {
|
// 构建接口请求参数
|
UnifiedorderReqData unifiedorderReqData = new UnifiedorderReqData(apptype, outTradeNo, body, price,
|
Configure.wx_notify_url);
|
// 请求接口获取返回接口
|
String result = WXPay.requestUnifiedorderService(apptype, unifiedorderReqData);
|
System.out.println(result);
|
System.out.println("WxpayController.createOrder__result:\n" + result);
|
// 获取预支付接口返回参数
|
map = XMLParser.getMapFromXML(result);
|
System.out.println("WxpayController.createOrder__result:\n" + result);
|
// 捕获预支付接口错误提示
|
if ("FAIL".equals(map.get("result_code")) || "FAIL".equals(map.get("return_code"))) {
|
return ApiUtil.putFailObj(String.valueOf(map.get("return_msg")));
|
}
|
|
// 对获取预支付返回接口参数进行封装(生成支付订单接口数据)
|
AppPayReqData appPay = new AppPayReqData(apptype, (String) map.get("appid"), (String) map.get("mch_id"),
|
(String) map.get("prepay_id"), unifiedorderReqData.getNonce_str());
|
|
// 对获取预支付返回接口参数进行封装(生成支付订单接口数据)
|
appPayMap.put("appid", appPay.getAppid());// 公众账号ID
|
appPayMap.put("nonceStr", appPay.getNoncestr());// 随机字符串(32位)
|
appPayMap.put("package", appPay.get_package());// 扩展字段(暂填写固定值Sign=WXPay)
|
appPayMap.put("partnerId", appPay.getPartnerid());// 商户号
|
appPayMap.put("prepayId", appPay.getPrepayid());// 预支付编号(微信返回的支付交易会话ID)
|
appPayMap.put("timeStamp", appPay.getTimestamp());// 时间戳
|
appPayMap.put("sign", appPay.getSign());// 根据API给的签名规则进行签名
|
return appPayMap;
|
} catch (Exception e) {
|
System.out.println("统一下单_API_处理异常!");
|
e.printStackTrace();
|
}
|
return ApiUtil.putFailObj("统一下单失败");
|
}
|
|
/**
|
* 微信支付回调(参考财付通回调接口)
|
*
|
* @param request
|
* @param response
|
*/
|
public void wxnotify(HttpServletRequest request, HttpServletResponse response) {
|
try {
|
System.out.println("微信支付回调!!!!!!!!!!!!!!!!!!!!!!!!!");
|
// 异步通知返回报文
|
StringBuffer notityXml = new StringBuffer();
|
String inputLine;
|
while ((inputLine = request.getReader().readLine()) != null) {
|
notityXml.append(inputLine);
|
}
|
request.getReader().close();
|
// log.debug("WxpayController.notify__notityXml:\n" + notityXml);
|
System.out.println("WxpayController.notify__notityXml:\n" + notityXml);
|
|
// 验证签名
|
if (Signature.checkIsSignValidFromResponseString(1, notityXml.toString())
|
|| Signature.checkIsSignValidFromResponseString(2, notityXml.toString())) {
|
Map<String, Object> map = XMLParser.getMapFromXML(notityXml.toString());
|
// log.debug("WxpayController.notify__map:\n" + map);
|
// 接口返回状态
|
String result_code = (String) map.get("result_code");
|
if ("SUCCESS".equals(result_code)) {
|
// // 商户订单号
|
String out_trade_no = (String) map.get("out_trade_no");
|
// // 微信支付交易号
|
String trade_no = (String) map.get("transaction_id");
|
// // 金额,以分为单位
|
String total_fee = (String) map.get("total_fee");
|
// // 优惠金额
|
// String discount = (String) map.get("discount");
|
// // 支付完成时间
|
String time_end = (String) map.get("time_end");
|
// // 支付者唯一Id(对应买家账号的一个加密串 )
|
String buyer_id = (String) map.get("buyer_id");
|
|
///////////////////////////// 这里程序处理支付回调逻辑
|
///////////////////////////// ////////////////////
|
String orderNum = out_trade_no;
|
Financial financial = new Financial();
|
financial.setType(1);//类型 1=收入 2=支出
|
financial.setPayType("2");//支付类型 1=余额 2=微信 3=支付宝
|
financial.setMoney(Double.parseDouble(total_fee) / 100);//支付金额
|
financial.setOrderNum(out_trade_no);//我们本地的订单号
|
financial.setLsType(trade_no);//流水号
|
financial.setAddTime(new Date());
|
financial.setTradeStatus(result_code);
|
if (orderNum.contains("ride")) {
|
//顺风车支付
|
//修改订单表中的订单流水和支付方式
|
OrderRide order = orderRideService.selectOne(new EntityWrapper<OrderRide>().eq("orderNum", orderNum));
|
order.setOutNum(financial.getLsType());//流水
|
order.setPayTime(new Date());
|
order.setPayType(2);
|
order.setState(2);
|
financial.setPwType(8);//顺风车
|
financial.setUserId(order.getUserId());
|
financial.setLx(1);//1=用户 2=司机
|
financial.setOrderType(4);//顺风车
|
financialService.insert(financial);
|
orderRideService.updateById(order);
|
/*添加系统消息*/
|
try {
|
systemNoticeService.addSystemNotice(1, "您成功支付从" + order.getStartName() + "到" + order.getEndName() + "的顺风车订单", order.getUserId(), 1);
|
} catch (Exception e) {
|
throw new RuntimeException(e);
|
}
|
|
}
|
log.debug("WxpayController.notify__回调处理成功:SUCCESS");
|
response.getOutputStream().print("success");
|
} else {
|
log.debug("WxpayController.notify__回调处理:验证状态错误!" + result_code);
|
System.out.println("验证状态错误!" + result_code);
|
}
|
} else {
|
log.debug("WxpayController.notify__回调处理:通知签名验证失败!");
|
System.out.println("通知签名验证失败!");
|
}
|
} catch (Exception e) {
|
e.printStackTrace();
|
}
|
}
|
|
/**
|
* 微信退款
|
*
|
* @param transactionID 【支付交易号】是微信系统为每一笔支付交易分配的订单号,通过这个订单号可以标识这笔交易,
|
* 它由支付订单API支付成功时返回的数据里面获取到。建议优先使用
|
* @param outTradeNo 【商品订单编号】商户系统内部的订单号,transaction_id
|
* 、out_trade_no二选一,如果同时存在优先级:transaction_id>out_trade_no
|
* @param outRefundNo 【退款编号】商户系统内部的退款单号,商户系统内部唯一,同一退款单号多次请求只退一笔
|
* @param totalFeetotalFee 订单总金额,单位为分
|
* @param refundFee 退款总金额,单位为分,可以做部分退款
|
* @return
|
*/
|
public static boolean refundForWxpay(Integer apptype, String transactionID, String outTradeNo, String outRefundNo,
|
Integer totalFee, Integer refundFee, String pay_type) {
|
Map<String, Object> map = new HashMap<String, Object>();
|
try {
|
// 构建接口请求参数
|
RefundReqData refundReqData = new RefundReqData(transactionID, outTradeNo, outRefundNo, totalFee, refundFee,
|
pay_type);
|
|
// 请求接口返回结果
|
String result = WXPay.requestRefundService(apptype, refundReqData);
|
System.out.println("微信退款返回内容:" + result);
|
// 获取预支付接口返回参数
|
map = XMLParser.getMapFromXML(result);
|
System.out.println("微信退款返回参数:" + map);
|
// 退款成功处理
|
if ("SUCCESS".equals(map.get("result_code"))) {
|
return true;
|
}
|
} catch (Exception e) {
|
e.printStackTrace();
|
return false;
|
}
|
return false;
|
}
|
|
/**
|
* 获取支付宝
|
*
|
* @param request
|
* @return
|
* @throws Exception
|
*/
|
private Financial getPayLog_alipay(HttpServletRequest request) throws IOException {
|
//////// 获取支付宝的通知返回参数,可参考技术文档中页面跳转同步通知参数列表(以下仅供参考)////////
|
// 商户订单号
|
String out_trade_no = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"), "UTF-8");
|
// 支付宝交易号
|
String trade_no = new String(request.getParameter("trade_no").getBytes("ISO-8859-1"), "UTF-8");
|
// 交易状态
|
String trade_status = new String(request.getParameter("trade_status").getBytes("ISO-8859-1"), "UTF-8");
|
// 支付者唯一Id
|
String buyer_id = new String(request.getParameter("buyer_id").getBytes("ISO-8859-1"), "UTF-8");
|
// 支付帐号
|
String buyer_email = "";
|
if (request.getParameter("buyer_logon_id") != null && !request.getParameter("buyer_logon_id").equals("")) {
|
buyer_email = new String(request.getParameter("buyer_logon_id").getBytes("ISO-8859-1"), "UTF-8");
|
}
|
// 支付金额
|
String total_fee = new String(request.getParameter("total_amount").getBytes("ISO-8859-1"), "UTF-8");
|
// 支付时间
|
String notify_time = new String(request.getParameter("notify_time").getBytes("ISO-8859-1"), "UTF-8");
|
|
//////// 获取支付宝的通知返回参数,可参考技术文档中页面跳转同步通知参数列表(以下仅供参考)////////
|
Financial financial = new Financial();
|
financial.setType(1);//类型 1=收入 2=支出
|
financial.setPayType("3");//支付类型 1=余额 2=微信 3=支付宝
|
financial.setMoney(Double.parseDouble(total_fee));//支付金额
|
financial.setOrderNum(out_trade_no);//我们本地的订单号
|
financial.setLsType(trade_no);//流水号
|
financial.setAddTime(new Date());
|
financial.setTradeStatus(trade_status);
|
return financial;
|
}
|
|
|
public boolean judgeContainsStr(String cardNum) {
|
String regex = ".*[a-zA-Z]+.*";
|
Matcher m = Pattern.compile(regex).matcher(cardNum);
|
return m.matches();
|
}
|
|
public static void main(String[] args) {
|
//模拟退款
|
refundForWxpay(1, "4200000680202009309013911024", "ride20093008510001", "ride200930085100012", 25753, 25753, "2");
|
|
}
|
|
}
|