package com.shop.service.Impl;
import com.github.wxpay.sdk.WXPay;
import com.github.wxpay.sdk.WXPayUtil;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.common.BitMatrix;
import com.shop.constant.WxPayConfig;
import com.shop.mapper.*;
import com.shop.pojo.IntegralLog;
import com.shop.pojo.Orders;
import com.shop.pojo.SystemOption;
import com.shop.pojo.UserPayList;
import com.shop.service.UserPayListService;
import com.shop.service.WxPayService;
import com.shop.utils.WxPayUtils;
import com.shop.utils.XmlUtils;
import org.jdom2.JDOMException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.*;
import java.util.concurrent.TimeUnit;
import static com.shop.constant.PayConstant.*;
/**
* @author 阳十三
* @email wdful165177@gmail.com
* @blog http://www.item1024.com
* @date 2017/9/12
*/
@Service
public class WxPayServiceImpl implements WxPayService {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Resource
private UserPayListMapper userPayListMapper;
private WxPayConfig wxPayConfig;
private WXPay wxPay;
@Resource
private OrdersMapper ordersMapper;
@Resource
private UserInfoMapper userInfoMapper;
@Resource
private SystemOptionMapper systemOptionMapper;
@Resource
private IntegralLogMapper integralLogMapper;
/**
* @param out_trade_no 商户订单号
* @param total_fee 标价金额
* @param userId 用户id
* @param productId 商品id
* @return 微信支付所需的二维码生成的 短链接
*/
@Override
public String wxPayByQrcode(String out_trade_no, String total_fee, String productId, int userId) throws Exception {
System.out.println("Wxpay start");
//防止请求二维码的时候订单号会重复
if (redisTemplate.hasKey(out_trade_no)) {
System.out.println("Wxpay二维码存在 返回缓存的二维码");
return redisTemplate.opsForValue().get(out_trade_no);
}
UserPayList userPayList = new UserPayList();
userPayList.setOrderId((out_trade_no));
userPayList.setPayAmount(Double.valueOf(total_fee) / 100);
userPayList.setPayType(WEPAY);
userPayList.setPayCreatetime(new java.sql.Date(System.currentTimeMillis()));
userPayList.setUserId(userId);
userPayList.setpStatus(0);
String code_url = "订单重复了";
wxPayConfig = new WxPayConfig();
wxPay = new WXPay(wxPayConfig);
String currTime = WxPayUtils.getCurrTime();
String strTime = currTime.substring(8, currTime.length());
String strRandom = WxPayUtils.buildRandom(4) + "";
String nonce_str = strTime + strRandom;
//设置请求参数
Map<String, String> data = new HashMap<String, String>();
data.put("body", "奥农汇");
data.put("out_trade_no", out_trade_no);
data.put("nonce_str", nonce_str);
data.put("fee_type", "CNY");
data.put("total_fee", total_fee);
data.put("spbill_create_ip", CREATE_IP);
data.put("notify_url", NOTIFY_URL);
data.put("trade_type", TRADE_TYPE); // 此处指定为扫码支付
data.put("product_id", productId);
try {
//发起支付
Map<String, String> resp = wxPay.unifiedOrder(data);
System.out.println(resp);
if (resp.get("result_code").equals("SUCCESS")) {
//获取二维码URL
code_url = resp.get("code_url");
userPayListMapper.insertSelective(userPayList);
//存入redis 防止二次请求重复
redisTemplate.opsForValue().set(out_trade_no, code_url);
//设置半个小时二维码过期
redisTemplate.expire(out_trade_no, 15, TimeUnit.MINUTES);
}
} catch (Exception e) {
e.printStackTrace();
}
return code_url;
}
@Override
public String wxPayRefund(String out_trade_no, String total_fee, String out_refund_no, String refund_fee) throws Exception {
//设置请求参数
String flag = "FAIL";
HashMap<String, String> data = new HashMap<String, String>();
wxPayConfig = new WxPayConfig();
wxPay = new WXPay(wxPayConfig);
data.put("out_trade_no", out_trade_no);
data.put("out_refund_no", out_refund_no);
data.put("total_fee", total_fee);
data.put("refund_fee", refund_fee);
data.put("refund_fee_type", "CNY");
try {
//调用sdk发起退款
Map<String, String> result = wxPay.refund(data);
System.out.println(result);
if ("SUCCESS".equals(result.get("result_code"))) {
//TODO:更新订单
System.out.println("订单" + result.get("out_trade_no") + "微信退款成功");
try {
ordersMapper.updateStaByOrderIdAndSta(result.get("out_trade_no"), 8, 6);
flag = "SUCCESS";
} catch (Exception e) {
e.getStackTrace();
}
}
} catch (Exception e) {
e.printStackTrace();
}
return flag;
}
@Override
public void wxPayNotify(HttpServletRequest request, HttpServletResponse response) throws Exception {
// 读取回调内容
InputStream inputStream;
StringBuffer sb = new StringBuffer();
inputStream = request.getInputStream();
String s;
BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
while ((s = in.readLine()) != null) {
sb.append(s);
}
in.close();
inputStream.close();
// 支付结果通知的xml格式数据
String notifyData = sb.toString();
// 转换成map
Map<String, String> notifyMap = WXPayUtil.xmlToMap(notifyData);
//支付确认内容
String resXml = "";
wxPayConfig = new WxPayConfig();
wxPay = new WXPay(wxPayConfig);
//验证签名
if (wxPay.isPayResultNotifySignatureValid(notifyMap)) { // 签名正确
if (notifyMap.get("out_trade_no") != null) {
if ("SUCCESS".equals(notifyMap.get("result_code"))) { //交易成功
// TODO:更新订单
System.out.println("订单" + notifyMap.get("out_trade_no") + "微信支付成功");
try {
//更改订单状态
ordersMapper.updateStaByOrderIdAndSta(notifyMap.get("out_trade_no"), 1, 2);
//更改支付记录表状态
userPayListMapper.updateStaByOrderIdAndSta(notifyMap.get("out_trade_no"), 0, 1);
//增加用户积分
int userid = userPayListMapper.selectUserIdByOrderId(notifyMap.get("out_trade_no"));
//获取积分规则
SystemOption systemOption = systemOptionMapper.selectByPrimaryKey(1);
Double amount = Double.parseDouble(notifyMap.get("total_fee")) / 100 / systemOption.getIntegralMinusrule();
userInfoMapper.updateAmountByUserIdInc(amount, userid);
//积分日志
IntegralLog integralLog = new IntegralLog();
integralLog.setIntegralChangenum(amount);
integralLog.setIntegralChangereason("购买商品");
integralLog.setIntegralChangetime(new Date(System.currentTimeMillis()));
integralLog.setIntegralChangetype(1);
integralLog.setIntegralRestnum(0.00);
integralLogMapper.insertSelective(integralLog);
//设置成功确认内容
resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>" + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";
} catch (Exception e) {
System.out.println("更改订单状态异常");
e.getStackTrace();
}
} else { //交易失败
try {
ordersMapper.updateStaByOrderIdAndSta(notifyMap.get("out_trade_no"), null, 7);
} catch (Exception e) {
e.getStackTrace();
}
resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>" + "<return_msg></return_msg>" + "</xml> ";
System.out.println("订单" + notifyMap.get("out_trade_no") + "微信支付失败");
}
}
// 注意特殊情况:订单已经退款,但收到了支付结果成功的通知,不应把商户侧订单状态从退款改成支付成功
} else { // 签名错误,如果数据里没有sign字段,也认为是签名错误
//设置失败确认内容
resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>" + "<return_msg></return_msg>" + "</xml> ";
System.out.println("订单" + notifyMap.get("out_trade_no") + "微信支付失败");
}
//发送通知
response.getWriter().println(resXml);
}
/**
*
* @param out_trade_no 订单号
* @return
* @throws Exception
*/
@Override
public Map<String, String> wxPayQuery(String out_trade_no) throws Exception {
HashMap<String, String> data = new HashMap<String, String>();
Map<String, String> result = new HashMap<>();
wxPayConfig = new WxPayConfig();
wxPay = new WXPay(wxPayConfig);
data.put("out_trade_no", out_trade_no);
try {
//调用sdk发起退款
result = wxPay.orderQuery(data);
}catch (Exception e){
e.getStackTrace();
}
return result;
}
}