| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264 | 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*/@Servicepublic class WxPayServiceImpl implements WxPayService {@Autowiredprivate RedisTemplate<String, String> redisTemplate;@Resourceprivate UserPayListMapper userPayListMapper;private WxPayConfig wxPayConfig;private WXPay wxPay;@Resourceprivate OrdersMapper ordersMapper;@Resourceprivate UserInfoMapper userInfoMapper;@Resourceprivate SystemOptionMapper systemOptionMapper;@Resourceprivate IntegralLogMapper integralLogMapper;/*** @param out_trade_no 商戶訂單號* @param total_fee 標價金額* @param userId 用戶id* @param productId 商品id* @return 微信支付所需的二維碼生成的 短鏈接*/@Overridepublic 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")) {//獲取二維碼URLcode_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;}@Overridepublic 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;}@Overridepublic 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();// 轉換成mapMap<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*/@Overridepublic 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;}} |