Prechádzať zdrojové kódy

feat:“添加微信直连付款码支付“

soobin 1 rok pred
rodič
commit
491d1e274e

+ 16 - 0
src/main/java/com/szwl/constant/WXPayConstants.java

@@ -0,0 +1,16 @@
+package com.szwl.constant;
+
+public class WXPayConstants {
+
+    public enum SignType {
+        MD5, HMACSHA256
+    }
+
+
+
+    public static final String FAIL     = "FAIL";
+    public static final String SUCCESS  = "SUCCESS";
+
+    public static final String FIELD_SIGN = "sign";
+
+}

+ 424 - 420
src/main/java/com/szwl/controller/TWechatPayConfigController.java

@@ -60,9 +60,6 @@ public class TWechatPayConfigController {
     TOrderService orderService;
 
     @Autowired
-    TWeixinPayConfigService weixinPayConfigService;
-
-    @Autowired
     TWechatPayConfigService wechatPayConfigService;
 
     @Autowired
@@ -74,438 +71,445 @@ public class TWechatPayConfigController {
     @ApiOperation(value = "购物车 请求在线支付 ")
     @PostMapping("/carsPay")
     public Object carsPay(String clientId, @RequestBody Map<String,String> productNameMap, HttpServletRequest request) {
-        if(productNameMap==null){
-            return  JsonMessage.error("数据出错");
-        }
-        StringBuffer note = new StringBuffer();
-        StringBuffer productName = new StringBuffer();
-        String productNo = "";
-        Map<String, Integer> productMap = new HashMap<>();
-        Integer productNumber = 0;
-
-        TEquipment equipment = R.getDataIfSuccess(szwlFeign.findEquipmentByClientId(clientId));
-        if(equipment==null||equipment.getId()==null){
-            return JsonMessage.error("找不到设备");
-        }
-        BigDecimal price = new BigDecimal("0.00");
-        TEquipmentDesc equipmentDesc = R.getDataIfSuccess(szwlFeign.findEquipmentById(equipment.getId()));
-        if(equipmentDesc==null||equipmentDesc.getEquipmentId()==null||equipmentDesc.getPayType()==null||equipmentDesc.getPayType().equals("0")){
-            for (String key : productNameMap.keySet()) {
-                String entryValue = String.valueOf(productNameMap.get(key));
-                List<String> value = JSON.parseArray(entryValue, String.class);
-                List<TPromoCode> promoCodeList = new ArrayList<>();
-                //1,校验优惠码
-                if(value.size()>0){
-                    for(String code:value){
-                        if(!code.equals("0")){
-                            TPromoCode promoCode = new TPromoCode();
-                            ResponseModel<TPromoCode> tPromoCodeResponseModel = szwlFeign.selectTPromoCode(code, equipment.getAdminId().toString());
-                            TPromoCode tPromoCode = tPromoCodeResponseModel.getData();
-                            promoCode = tPromoCode;
-                            if (tPromoCode == null||tPromoCode.getId()==null) {
-                                //不存在
-                                return JsonMessage.success("1");
-                            }
-                            Date lastUseDate = null;
-                            if (promoCode != null) {
-                                lastUseDate = promoCode.getLastUseDate();
-                            }
-
-                            if (lastUseDate != null && lastUseDate.getTime() < ((new Date()).getTime())) {
-                                promoCode.setIsUse("2");
-                                szwlFeign.updatePromoCode(String.valueOf(promoCode.getId()),"2");
-                                //过期
-                                return JsonMessage.success("4");
-                            }
-                            if (promoCode.getId() == null) {
-                                //不存在
-                                return JsonMessage.success("1");
-                            }
-                            if (promoCode.getIsUse().equals("1")) {
-                                //被使用
-                                return JsonMessage.success("2");
-                            }
-                            if(!promoCode.getAdminId().equals("1")){
-                                if (String.valueOf(equipment.getAdminId()).equals(promoCode.getAdminId())) {
-
-                                } else {
-                                    //不是本机
-                                    return JsonMessage.success("3");
-                                }
-                            }
-                            if (promoCode.getDiscount() == null) {
-                                //旧优惠码
-                                return JsonMessage.success("0");
-                            }
-                            if (promoCode.getDiscount() != null && promoCode.getDiscount() == 0) {
-                                //0折
-                                return JsonMessage.success("0");
-                            }
-                            promoCodeList.add(promoCode);
-                        }
-                    }
-                }
-                String[] productNum = key.split("-");
-                String productNamea = productNum[0];
-                String num = productNum[1];
-                productMap.put(productNamea,Integer.valueOf(num));
-                productNumber += Integer.valueOf(num);
-                productName.append(productNamea).append("x").append(num).append(",");
-                TProduct product = R.getDataIfSuccess(szwlFeign.getProduct(String.valueOf(equipment.getId()), productNamea));
-                if (product == null) {
-                    return JsonMessage.error("找不到商品");
-                }
-                note.append(productNamea).append("-").append(product.getNo()).append(":");
-                BigDecimal productPrice = product.getRmbPrice();
-                productNo = product.getNo();
-                if(promoCodeList.size()>0){
-                    //有优惠码
-                    BigDecimal onePrice = new BigDecimal("0.00");
-                    int i;
-                    for( i = 0;i<promoCodeList.size();i++){
-                        BigDecimal discount = BigDecimal.valueOf(promoCodeList.get(i).getDiscount()).setScale(2, RoundingMode.HALF_DOWN);
-                        BigDecimal price1 = productPrice.multiply(discount).divide(new BigDecimal(10)).setScale(2, RoundingMode.HALF_DOWN);
-                        price = price.add(price1);
-                        onePrice = onePrice.add(price1);
-                    }
-                    if(i<Integer.valueOf(num)){
-                        int a = Integer.valueOf(num)-i;
-                        BigDecimal price2 = productPrice.multiply(new BigDecimal(a)).setScale(2, RoundingMode.HALF_DOWN);
-                        price =price.add(price2);
-                        onePrice = onePrice.add(price2);
-                    }
-                    note.append(onePrice).append("-").append(num).append(",");
-                }else {
-                    //1,type=0,原始设定,没有第二件半价
-                    int a = Integer.valueOf(num);
-                    BigDecimal price2 = productPrice.multiply(new BigDecimal(a)).setScale(2, RoundingMode.HALF_DOWN);
-                    price =price.add(price2);
-                    note.append(price2).append("-").append(num).append(",");
-                }
-            }
-        }else {
-
-            for (String key : productNameMap.keySet()) {
-                String[] productNum = key.split("-");
-                String productNamea = productNum[0];
-                String num = productNum[1];
-                productMap.put(productNamea,Integer.valueOf(num));
-                TProduct product = R.getDataIfSuccess(szwlFeign.getProduct(String.valueOf(equipment.getId()), productNamea));
-                productNo = product.getNo();
-                BigDecimal productPrice = product.getRmbPrice();
-                productName.append(productNamea).append("x").append(num).append(",");
-                note.append(productNamea).append("-").append(product.getNo()).append(":");
-                switch (num) {
-                    case "1":
-                        //1个  0个半价
-                        price =price.add(productPrice);
-                        note.append(price).append("-").append(num).append(",");
-                        break;
-                    case "2":
-                        //2个  1个半价
-                        price =price.add(productPrice);
-                        price =price.add(productPrice.multiply(new BigDecimal(5)).divide(new BigDecimal(10)).setScale(2, RoundingMode.HALF_DOWN));
-                        note.append(price).append("-").append(num).append(",");
-                        break;
-                    case "3":
-                        //3个 1个半价
-                        price =price.add(productPrice);
-                        price =price.add(productPrice.multiply(new BigDecimal(5)).divide(new BigDecimal(10)).setScale(2, RoundingMode.HALF_DOWN));
-                        price =price.add(productPrice);
-                        note.append(price).append("-").append(num).append(",");
-                        break;
-                    case "4":
-                        //4个 2个半价
-                        price =price.add(productPrice);
-                        price =price.add(productPrice.multiply(new BigDecimal(5)).divide(new BigDecimal(10)).setScale(2, RoundingMode.HALF_DOWN));
-                        price =price.add(productPrice);
-                        price =price.add(productPrice.multiply(new BigDecimal(5)).divide(new BigDecimal(10)).setScale(2, RoundingMode.HALF_DOWN));
-                        note.append(price).append("-").append(num).append(",");
-                        break;
-                    case "5":
-                        //5个 2个半价
-                        price =price.add(productPrice);
-                        price =price.add(productPrice.multiply(new BigDecimal(5)).divide(new BigDecimal(10)).setScale(2, RoundingMode.HALF_DOWN));
-                        price =price.add(productPrice);
-                        price =price.add(productPrice.multiply(new BigDecimal(5)).divide(new BigDecimal(10)).setScale(2, RoundingMode.HALF_DOWN));
-                        price =price.add(productPrice);
-                        note.append(price).append("-").append(num).append(",");
-                        break;
-                }
-            }
-        }
-
-        if (equipment == null) {
-            return JsonMessage.error("找不到设备");
-        }
-
-        Long equipmentId = equipment.getId();
-        //查找商品
-        if (BigDecimal.ZERO.compareTo(price) >= 0) {
-            return JsonMessage.error("商品价格异常");
-        }
-        Long client6 = Long.parseLong(clientId.substring(clientId.length() - 6));
-        String sn = orderService.initSn(client6);
-        //获取分销  关联设备
-        TAdmin admin = R.getDataIfSuccess(szwlFeign.getAdmin(String.valueOf(equipment.getAdminId())));
-        String companyType = admin.getCompanyType();
-        if (admin == null) {
-            return JsonMessage.error("找不到设备商家");
-        }
-        JSONArray altInfo = new JSONArray();
-        BigDecimal amount = price.setScale(2, RoundingMode.HALF_DOWN);
-        amount = amount.multiply(new BigDecimal(100));
-        String notifyUrl = JoinpayConstant.WECHAT_NOTIFY_URL;
-        String frpCode = "WEIXIN_NATIVE";
-        TOrder order = new TOrder();
-        order.setId(IDGenerator.orderID());
-        order.setCreateDate(new Date());
-        order.setModifyDate(new Date());
-        order.setAdminId(admin.getId());
-        order.setSn(sn);
-        if(productNumber == 1) {
-            productName.delete(productName.length() - 3, productName.length());
-        } else {
-            productName.deleteCharAt(productName.length() - 1);
-        }
-        order.setProductName(productName.toString());
-        order.setPrice(price);
-        order.setClientId(equipment.getClientId());
-        order.setEquipmentId(equipmentId);
-        order.setFrpCode(frpCode);
-        order.setProductNumber(productNumber);
-        order.setAltInfo(altInfo.toString());
-        order.setStatus(0);
-        String payPlatform = "3";
-        order.setPayPlatform(payPlatform);
-        order.setCompanyType(companyType);
-        order.setMachineType(equipment.getMachineType());
-        order.setProductNo(productNo);
-        if(StringUtils.isNotEmpty(payPlatform)&&payPlatform.equals("1")){
-            order.setIsSettlement("0");
-        }
-        order.setNote(note.toString());
+        JsonMessage jsonMessage = wechatPayConfigService.carsPay(clientId, productNameMap, request);
+        return jsonMessage;
+//        if(productNameMap==null){
+//            return  JsonMessage.error("数据出错");
+//        }
+//        StringBuffer note = new StringBuffer();
+//        StringBuffer productName = new StringBuffer();
+//        String productNo = "";
+//        Map<String, Integer> productMap = new HashMap<>();
+//        Integer productNumber = 0;
+//
+//        TEquipment equipment = R.getDataIfSuccess(szwlFeign.findEquipmentByClientId(clientId));
+//        if(equipment==null||equipment.getId()==null){
+//            return JsonMessage.error("找不到设备");
+//        }
+//        BigDecimal price = new BigDecimal("0.00");
+//        TEquipmentDesc equipmentDesc = R.getDataIfSuccess(szwlFeign.findEquipmentById(equipment.getId()));
+//        if(equipmentDesc==null||equipmentDesc.getEquipmentId()==null||equipmentDesc.getPayType()==null||equipmentDesc.getPayType().equals("0")){
+//            for (String key : productNameMap.keySet()) {
+//                String entryValue = String.valueOf(productNameMap.get(key));
+//                List<String> value = JSON.parseArray(entryValue, String.class);
+//                List<TPromoCode> promoCodeList = new ArrayList<>();
+//                //1,校验优惠码
+//                if(value.size()>0){
+//                    for(String code:value){
+//                        if(!code.equals("0")){
+//                            TPromoCode promoCode = new TPromoCode();
+//                            ResponseModel<TPromoCode> tPromoCodeResponseModel = szwlFeign.selectTPromoCode(code, equipment.getAdminId().toString());
+//                            TPromoCode tPromoCode = tPromoCodeResponseModel.getData();
+//                            promoCode = tPromoCode;
+//                            if (tPromoCode == null||tPromoCode.getId()==null) {
+//                                //不存在
+//                                return JsonMessage.success("1");
+//                            }
+//                            Date lastUseDate = null;
+//                            if (promoCode != null) {
+//                                lastUseDate = promoCode.getLastUseDate();
+//                            }
+//
+//                            if (lastUseDate != null && lastUseDate.getTime() < ((new Date()).getTime())) {
+//                                promoCode.setIsUse("2");
+//                                szwlFeign.updatePromoCode(String.valueOf(promoCode.getId()),"2");
+//                                //过期
+//                                return JsonMessage.success("4");
+//                            }
+//                            if (promoCode.getId() == null) {
+//                                //不存在
+//                                return JsonMessage.success("1");
+//                            }
+//                            if (promoCode.getIsUse().equals("1")) {
+//                                //被使用
+//                                return JsonMessage.success("2");
+//                            }
+//                            if(!promoCode.getAdminId().equals("1")){
+//                                if (String.valueOf(equipment.getAdminId()).equals(promoCode.getAdminId())) {
+//
+//                                } else {
+//                                    //不是本机
+//                                    return JsonMessage.success("3");
+//                                }
+//                            }
+//                            if (promoCode.getDiscount() == null) {
+//                                //旧优惠码
+//                                return JsonMessage.success("0");
+//                            }
+//                            if (promoCode.getDiscount() != null && promoCode.getDiscount() == 0) {
+//                                //0折
+//                                return JsonMessage.success("0");
+//                            }
+//                            promoCodeList.add(promoCode);
+//                        }
+//                    }
+//                }
+//                String[] productNum = key.split("-");
+//                String productNamea = productNum[0];
+//                String num = productNum[1];
+//                productMap.put(productNamea,Integer.valueOf(num));
+//                productNumber += Integer.valueOf(num);
+//                productName.append(productNamea).append("x").append(num).append(",");
+//                TProduct product = R.getDataIfSuccess(szwlFeign.getProduct(String.valueOf(equipment.getId()), productNamea));
+//                if (product == null) {
+//                    return JsonMessage.error("找不到商品");
+//                }
+//                note.append(productNamea).append("-").append(product.getNo()).append(":");
+//                BigDecimal productPrice = product.getRmbPrice();
+//                productNo = product.getNo();
+//                if(promoCodeList.size()>0){
+//                    //有优惠码
+//                    BigDecimal onePrice = new BigDecimal("0.00");
+//                    int i;
+//                    for( i = 0;i<promoCodeList.size();i++){
+//                        BigDecimal discount = BigDecimal.valueOf(promoCodeList.get(i).getDiscount()).setScale(2, RoundingMode.HALF_DOWN);
+//                        BigDecimal price1 = productPrice.multiply(discount).divide(new BigDecimal(10)).setScale(2, RoundingMode.HALF_DOWN);
+//                        price = price.add(price1);
+//                        onePrice = onePrice.add(price1);
+//                    }
+//                    if(i<Integer.valueOf(num)){
+//                        int a = Integer.valueOf(num)-i;
+//                        BigDecimal price2 = productPrice.multiply(new BigDecimal(a)).setScale(2, RoundingMode.HALF_DOWN);
+//                        price =price.add(price2);
+//                        onePrice = onePrice.add(price2);
+//                    }
+//                    note.append(onePrice).append("-").append(num).append(",");
+//                }else {
+//                    //1,type=0,原始设定,没有第二件半价
+//                    int a = Integer.valueOf(num);
+//                    BigDecimal price2 = productPrice.multiply(new BigDecimal(a)).setScale(2, RoundingMode.HALF_DOWN);
+//                    price =price.add(price2);
+//                    note.append(price2).append("-").append(num).append(",");
+//                }
+//            }
+//        }else {
+//
+//            for (String key : productNameMap.keySet()) {
+//                String[] productNum = key.split("-");
+//                String productNamea = productNum[0];
+//                String num = productNum[1];
+//                productMap.put(productNamea,Integer.valueOf(num));
+//                TProduct product = R.getDataIfSuccess(szwlFeign.getProduct(String.valueOf(equipment.getId()), productNamea));
+//                productNo = product.getNo();
+//                BigDecimal productPrice = product.getRmbPrice();
+//                productName.append(productNamea).append("x").append(num).append(",");
+//                note.append(productNamea).append("-").append(product.getNo()).append(":");
+//                switch (num) {
+//                    case "1":
+//                        //1个  0个半价
+//                        price =price.add(productPrice);
+//                        note.append(price).append("-").append(num).append(",");
+//                        break;
+//                    case "2":
+//                        //2个  1个半价
+//                        price =price.add(productPrice);
+//                        price =price.add(productPrice.multiply(new BigDecimal(5)).divide(new BigDecimal(10)).setScale(2, RoundingMode.HALF_DOWN));
+//                        note.append(price).append("-").append(num).append(",");
+//                        break;
+//                    case "3":
+//                        //3个 1个半价
+//                        price =price.add(productPrice);
+//                        price =price.add(productPrice.multiply(new BigDecimal(5)).divide(new BigDecimal(10)).setScale(2, RoundingMode.HALF_DOWN));
+//                        price =price.add(productPrice);
+//                        note.append(price).append("-").append(num).append(",");
+//                        break;
+//                    case "4":
+//                        //4个 2个半价
+//                        price =price.add(productPrice);
+//                        price =price.add(productPrice.multiply(new BigDecimal(5)).divide(new BigDecimal(10)).setScale(2, RoundingMode.HALF_DOWN));
+//                        price =price.add(productPrice);
+//                        price =price.add(productPrice.multiply(new BigDecimal(5)).divide(new BigDecimal(10)).setScale(2, RoundingMode.HALF_DOWN));
+//                        note.append(price).append("-").append(num).append(",");
+//                        break;
+//                    case "5":
+//                        //5个 2个半价
+//                        price =price.add(productPrice);
+//                        price =price.add(productPrice.multiply(new BigDecimal(5)).divide(new BigDecimal(10)).setScale(2, RoundingMode.HALF_DOWN));
+//                        price =price.add(productPrice);
+//                        price =price.add(productPrice.multiply(new BigDecimal(5)).divide(new BigDecimal(10)).setScale(2, RoundingMode.HALF_DOWN));
+//                        price =price.add(productPrice);
+//                        note.append(price).append("-").append(num).append(",");
+//                        break;
+//                }
+//            }
+//        }
+//
+//        if (equipment == null) {
+//            return JsonMessage.error("找不到设备");
+//        }
+//
+//        Long equipmentId = equipment.getId();
+//        //查找商品
+//        if (BigDecimal.ZERO.compareTo(price) >= 0) {
+//            return JsonMessage.error("商品价格异常");
+//        }
+//        Long client6 = Long.parseLong(clientId.substring(clientId.length() - 6));
+//        String sn = orderService.initSn(client6);
+//        //获取分销  关联设备
+//        TAdmin admin = R.getDataIfSuccess(szwlFeign.getAdmin(String.valueOf(equipment.getAdminId())));
+//        String companyType = admin.getCompanyType();
+//        if (admin == null) {
+//            return JsonMessage.error("找不到设备商家");
+//        }
+//        JSONArray altInfo = new JSONArray();
+//        BigDecimal amount = price.setScale(2, RoundingMode.HALF_DOWN);
+//        amount = amount.multiply(new BigDecimal(100));
+//        String notifyUrl = JoinpayConstant.WECHAT_NOTIFY_URL;
+//        String frpCode = "WEIXIN_NATIVE";
+//        TOrder order = new TOrder();
+//        order.setId(IDGenerator.orderID());
+//        order.setCreateDate(new Date());
+//        order.setModifyDate(new Date());
+//        order.setAdminId(admin.getId());
+//        order.setSn(sn);
+//        if(productNumber == 1) {
+//            productName.delete(productName.length() - 3, productName.length());
+//        } else {
+//            productName.deleteCharAt(productName.length() - 1);
+//        }
+//        order.setProductName(productName.toString());
+//        order.setPrice(price);
+//        order.setClientId(equipment.getClientId());
+//        order.setEquipmentId(equipmentId);
+//        order.setFrpCode(frpCode);
+//        order.setProductNumber(productNumber);
+//        order.setAltInfo(altInfo.toString());
+//        order.setStatus(0);
+//        String payPlatform = "3";
+//        order.setPayPlatform(payPlatform);
+//        order.setCompanyType(companyType);
+//        order.setMachineType(equipment.getMachineType());
+//        order.setProductNo(productNo);
+//        if(StringUtils.isNotEmpty(payPlatform)&&payPlatform.equals("1")){
+//            order.setIsSettlement("0");
+//        }
+//        order.setNote(note.toString());
+//
+//        // 订单明细表
+//        TOrderDetails orderDetails = new TOrderDetails();
+//        orderDetails.setAdminId(admin.getId());
+//        orderDetails.setEquipmentId(equipmentId);
+//        orderDetails.setCreateDate(new Date());
+//        orderDetails.setCompanyType(companyType);
+//        orderDetails.setRefundStatus("0");
+//        orderDetails.setMachineType(equipment.getMachineType());
+//        // 添加到订单明细表
+//        for (String key : productMap.keySet()) {
+//            Integer productNum = productMap.get(key);
+//            TProduct product = R.getDataIfSuccess(szwlFeign.getProduct(String.valueOf(equipment.getId()), key));
+//            orderDetails.setProductNo(product.getNo());
+//            orderDetails.setProductName(key);
+//            orderDetails.setPrice(product.getRmbPrice());
+//            orderDetails.setProductNumber(productNum);
+//            orderDetails.setAmount(product.getRmbPrice().multiply(new BigDecimal(productNum)));
+//            orderDetails.setId(HuifuUtils.initDetailsId());
+//            orderDetails.setOrderSn(sn);
+//            orderDetailsService.save(orderDetails);
+//        }
+//        orderService.save(order);
+//        String productName1 = "";
+//        if(productNumber > 1) {
+//            productName1 = "棉花糖";
+//        } else {
+//            productName1 = productName.toString();
+//        }
+//        String result;
+//        try {
+//            result = orderService.wechatPay(
+//                    sn, amount, productName1, admin.getWechatPayId(), notifyUrl, clientId, request
+//            );
+//        } catch (Exception e) {
+//            e.printStackTrace();
+//            return JsonMessage.error("申请支付失败");
+//        }
+//        // 微信支付支付申请返回支付二维码图片
+//        JSONObject kindData = new JSONObject();
+//        kindData.put("sn", sn);
+//        kindData.put("code_url", result);
+//        return JsonMessage.success(kindData.toString());
+    }
 
-        // 订单明细表
-        TOrderDetails orderDetails = new TOrderDetails();
-        orderDetails.setAdminId(admin.getId());
-        orderDetails.setEquipmentId(equipmentId);
-        orderDetails.setCreateDate(new Date());
-        orderDetails.setCompanyType(companyType);
-        orderDetails.setRefundStatus("0");
-        orderDetails.setMachineType(equipment.getMachineType());
-        // 添加到订单明细表
-        for (String key : productMap.keySet()) {
-            Integer productNum = productMap.get(key);
-            TProduct product = R.getDataIfSuccess(szwlFeign.getProduct(String.valueOf(equipment.getId()), key));
-            orderDetails.setProductNo(product.getNo());
-            orderDetails.setProductName(key);
-            orderDetails.setPrice(product.getRmbPrice());
-            orderDetails.setProductNumber(productNum);
-            orderDetails.setAmount(product.getRmbPrice().multiply(new BigDecimal(productNum)));
-            orderDetails.setId(HuifuUtils.initDetailsId());
-            orderDetails.setOrderSn(sn);
-            orderDetailsService.save(orderDetails);
-        }
-        orderService.save(order);
-        String productName1 = "";
-        if(productNumber > 1) {
-            productName1 = "棉花糖";
-        } else {
-            productName1 = productName.toString();
-        }
-        String result;
-        try {
-            result = orderService.wechatPay(
-                    sn, amount, productName1, admin.getWechatPayId(), notifyUrl, clientId, request
-            );
-        } catch (Exception e) {
-            e.printStackTrace();
-            return JsonMessage.error("申请支付失败");
-        }
-        // 微信支付支付申请返回支付二维码图片
-        JSONObject kindData = new JSONObject();
-        kindData.put("sn", sn);
-        kindData.put("code_url", result);
-        return JsonMessage.success(kindData.toString());
+    @ApiOperation("微信付款码支付")
+    @PostMapping("/cardPay")
+    @ResponseBody
+    public Object cardPay(String authCode, String clientId, @RequestBody Map<String,String> productNameMap,HttpServletRequest request) {
+        JsonMessage jsonMessage = wechatPayConfigService.cardPay(authCode, clientId, productNameMap, request);
+        return jsonMessage;
     }
 
-    /**
-     * 处理微信支付成功回调的通知。
-     *
-     * @param request HttpServletRequest对象,用于接收来自微信的支付通知数据。
-     * @return 返回处理结果,"success"表示处理成功,"fail"表示处理失败。
-     */
+    @ApiOperation("处理微信支付成功回调的通知")
     @PostMapping(value = "/notify")
     @ResponseBody
     public Object notify(HttpServletRequest request) {
-        Gson gson = new Gson();
-        // 读取请求体中的数据
-        String body = HttpUtils.readData(request);
-        Map<String, Object> bodyMap = gson.fromJson(body, HashMap.class);
-        // 解密支付通知数据
-        String plainText = wechatPayConfigService.decryptFromResource(bodyMap);
-        if(StringUtils.isNotEmpty(plainText)){
-            JSONObject resultJson = JSONObject.parseObject(plainText);
-            // 根据订单号查询订单
-            String sn = resultJson.getString("out_trade_no");
-            if(StringUtils.isNotEmpty(sn)) {
-                LambdaQueryWrapper<TOrder> query = Wrappers.lambdaQuery();
-                query.eq(TOrder::getSn, sn);
-                query.eq(TOrder::getStatus, 0);
-                List<TOrder> list = orderService.list(query);
-                // 更新订单状态和支付信息
-                if (list != null && list.size() > 0) {
-                    TOrder order = list.get(0);
-                    order.setStatus(1);
-                    String success_time = resultJson.getString("success_time");
-                    Date date = new Date();
-                    try {
-                        date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(success_time);
-                    } catch (ParseException e) {
-                        // 忽略时间转换错误
-                    }
-                    order.setPayDate(date);
-                    order.setTrxNo(resultJson.getString("transaction_id"));
-                    // 更新订单明细状态
-                    LambdaQueryWrapper<TOrderDetails> lambdaQueryWrapper = new LambdaQueryWrapper<>();
-                    lambdaQueryWrapper.eq(TOrderDetails::getOrderSn,sn);
-                    List<TOrderDetails> orderDetails = orderDetailsService.list(lambdaQueryWrapper);
-                    for (TOrderDetails orderDetail : orderDetails) {
-                        orderDetail.setRefundStatus("1");
-                        orderDetailsService.updateById(orderDetail);
-                    }
-                    // 发送支付成功消息给设备
-                    TEquipment equipment = R.getDataIfSuccess(szwlFeign.findEquipmentByClientId(order.getClientId()));
-                    JSONObject kindData = new JSONObject();
-                    kindData.put("sn", order.getSn());
-                    kindData.put("productName", order.getProductName());
-                    if (!order.getIsNotified().equals("1")) {
-                        String paySuccess = equipmentService.sentMessage(equipment.getClientId(), PushUtils.buildJson("pay_success", kindData.toString()).toString());
-                        if (paySuccess.equals("success")) {
-                            order.setIsNotified("1");
-                        }
-                    }
-                    orderService.updateById(order);
-                    try {
-                        // 保存订单信息到ES
-                        if(order.getProductNumber()==null||order.getProductNumber()==0){
-                            order.setProductNumber(1);
-                        }
-                        orderFeign.saveToEs(order);
-                    }catch (Exception e) {
-                        e.printStackTrace();
-                    }
-                } else {
-                    LambdaQueryWrapper<TOrder> queryWrapper = Wrappers.lambdaQuery();
-                    query.eq(TOrder::getSn, sn);
-                    query.eq(TOrder::getStatus, 1);
-                    List<TOrder> orderList = orderService.list(queryWrapper);
-                    if (list != null && list.size() > 0) {
-                        TOrder tOrder = orderList.get(0);
-                        try {
-                            // 保存订单信息到ES
-                            if(tOrder.getProductNumber()==null||tOrder.getProductNumber()==0){
-                                tOrder.setProductNumber(1);
-                            }
-                            orderFeign.saveToEs(tOrder);
-                        }catch (Exception e) {
-                            e.printStackTrace();
-                        }
-                        return "success";
-                    }
-                    return "fail";
-                }
-            }
-        }
-        return "success";
+        String result = wechatPayConfigService.payNotify(request);
+        return result;
+//        Gson gson = new Gson();
+//        // 读取请求体中的数据
+//        String body = HttpUtils.readData(request);
+//        Map<String, Object> bodyMap = gson.fromJson(body, HashMap.class);
+//        // 解密支付通知数据
+//        String plainText = wechatPayConfigService.decryptFromResource(bodyMap);
+//        if(StringUtils.isNotEmpty(plainText)){
+//            JSONObject resultJson = JSONObject.parseObject(plainText);
+//            // 根据订单号查询订单
+//            String sn = resultJson.getString("out_trade_no");
+//            if(StringUtils.isNotEmpty(sn)) {
+//                LambdaQueryWrapper<TOrder> query = Wrappers.lambdaQuery();
+//                query.eq(TOrder::getSn, sn);
+//                query.eq(TOrder::getStatus, 0);
+//                List<TOrder> list = orderService.list(query);
+//                // 更新订单状态和支付信息
+//                if (list != null && list.size() > 0) {
+//                    TOrder order = list.get(0);
+//                    order.setStatus(1);
+//                    String success_time = resultJson.getString("success_time");
+//                    Date date = new Date();
+//                    try {
+//                        date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(success_time);
+//                    } catch (ParseException e) {
+//                        // 忽略时间转换错误
+//                    }
+//                    order.setPayDate(date);
+//                    order.setTrxNo(resultJson.getString("transaction_id"));
+//                    // 更新订单明细状态
+//                    LambdaQueryWrapper<TOrderDetails> lambdaQueryWrapper = new LambdaQueryWrapper<>();
+//                    lambdaQueryWrapper.eq(TOrderDetails::getOrderSn,sn);
+//                    List<TOrderDetails> orderDetails = orderDetailsService.list(lambdaQueryWrapper);
+//                    for (TOrderDetails orderDetail : orderDetails) {
+//                        orderDetail.setRefundStatus("1");
+//                        orderDetailsService.updateById(orderDetail);
+//                    }
+//                    // 发送支付成功消息给设备
+//                    TEquipment equipment = R.getDataIfSuccess(szwlFeign.findEquipmentByClientId(order.getClientId()));
+//                    JSONObject kindData = new JSONObject();
+//                    kindData.put("sn", order.getSn());
+//                    kindData.put("productName", order.getProductName());
+//                    if (!order.getIsNotified().equals("1")) {
+//                        String paySuccess = equipmentService.sentMessage(equipment.getClientId(), PushUtils.buildJson("pay_success", kindData.toString()).toString());
+//                        if (paySuccess.equals("success")) {
+//                            order.setIsNotified("1");
+//                        }
+//                    }
+//                    orderService.updateById(order);
+//                    try {
+//                        // 保存订单信息到ES
+//                        if(order.getProductNumber()==null||order.getProductNumber()==0){
+//                            order.setProductNumber(1);
+//                        }
+//                        orderFeign.saveToEs(order);
+//                    }catch (Exception e) {
+//                        e.printStackTrace();
+//                    }
+//                } else {
+//                    LambdaQueryWrapper<TOrder> queryWrapper = Wrappers.lambdaQuery();
+//                    query.eq(TOrder::getSn, sn);
+//                    query.eq(TOrder::getStatus, 1);
+//                    List<TOrder> orderList = orderService.list(queryWrapper);
+//                    if (list != null && list.size() > 0) {
+//                        TOrder tOrder = orderList.get(0);
+//                        try {
+//                            // 保存订单信息到ES
+//                            if(tOrder.getProductNumber()==null||tOrder.getProductNumber()==0){
+//                                tOrder.setProductNumber(1);
+//                            }
+//                            orderFeign.saveToEs(tOrder);
+//                        }catch (Exception e) {
+//                            e.printStackTrace();
+//                        }
+//                        return "success";
+//                    }
+//                    return "fail";
+//                }
+//            }
+//        }
+//        return "success";
     }
 
-    /**
-     * 发起退款
-     * @return
-     */
+    @ApiOperation("发起退款")
     @PostMapping("/refund")
     public ResponseModel<?> refund(@RequestBody TOrder torder){
-        // 退款金额: refusePrice
-        BigDecimal refusePrice = torder.getPrice().setScale(2, RoundingMode.HALF_DOWN);
-        // 退款数量: refundNumber
-        Integer refundNumber = torder.getProductNumber();
-        // 退款原因: refundReason
-        String refundReason = torder.getRefundReason();
-        // 退款明细:note
-        String note = torder.getNote();
-        String[] refundDetails = note.split(",");
-        Map<String, Integer> refundMap = new HashMap<>();
-        for (String refundDetail : refundDetails) {
-            String[] keyValue  = refundDetail.split("-");
-            String key = keyValue[0];
-            String value = keyValue[1];
-            refundMap.put(key, Integer.valueOf(value));
-        }
-
-        if(refusePrice.compareTo(new BigDecimal("0.00"))<=0){
-            return R.fail(ResponseCodesEnum.A0001,"退款金额非法");
-        }
-
-        TOrder order = orderService.getById(torder.getId());
-        if(order.getRefundQuantity() != null && order.getRefundQuantity()>0) {
-            order.setRefundQuantity(refundNumber + order.getRefundQuantity());
-        } else {
-            order.setRefundQuantity(refundNumber);
-        }
-
-        LambdaQueryWrapper<TOrderDetails> wrapper = new LambdaQueryWrapper<>();
-        wrapper.eq(TOrderDetails::getOrderSn, order.getSn());
-        List<TOrderDetails> orderDetails = orderDetailsService.list(wrapper);
-        if (order.getStatus().equals("0")) {
-            return R.fail(ResponseCodesEnum.A0002,"订单非支付状态");
-        }
-
-        CreateRequest createRequest = new CreateRequest();
-        createRequest.setOutTradeNo(order.getSn());
-        AmountReq amount = new AmountReq();
-        amount.setRefund(refusePrice.multiply(new BigDecimal(100)).longValue());
-        BigDecimal multiply = order.getPrice().multiply(new BigDecimal(100));
-        amount.setTotal(multiply.longValue());
-        amount.setCurrency("CNY");
-        createRequest.setAmount(amount);
-        String refundNo = orderService.initSn(order.getEquipmentId());
-        createRequest.setOutRefundNo(refundNo);
-        // 上线需要修改回调url
-        createRequest.setNotifyUrl(JoinpayConstant.WECHAT_NOTIFY_REFUND_URL);
-//		createRequest.setNotifyUrl("http://evxz5m.natappfree.cc/wechatPay/refundNotify");
-        TAdmin admin = R.getDataIfSuccess(szwlFeign.getAdmin(String.valueOf(order.getAdminId())));
-        Refund refund = orderService.weixinRefundApi(createRequest, admin.getWechatPayId());
-        System.out.println("退款参数"+refund.toString());
-        if(refund.getStatus()==PROCESSING){
-            order.setStatus(2);
-            order.setRefundReason(refundReason);
-            orderService.updateById(order);
-            // 修改订单明细
-            for (TOrderDetails orderDetail : orderDetails) {
-                String productNo = orderDetail.getProductNo();
-                Integer productNumber = refundMap.get(productNo);
-                if(productNumber != null) {
-                    // 退款中
-                    orderDetail.setRefundStatus("4");
-                    // 退款数量
-                    orderDetail.setRefundQuantity(productNumber);
-                    // 退款金额
-                    orderDetail.setRefundAmount(orderDetail.getPrice().multiply(new BigDecimal(productNumber)));
-                    orderDetailsService.updateById(orderDetail);
-                }
-            }
-            return R.ok("申请退款已成功");
-        }else {
-            return R.fail(ResponseCodesEnum.B0001,"申请退款失败,请重试");
-        }
+        ResponseModel result = wechatPayConfigService.refund(torder);
+        return result;
+//        // 退款金额: refusePrice
+//        BigDecimal refusePrice = torder.getPrice().setScale(2, RoundingMode.HALF_DOWN);
+//        // 退款数量: refundNumber
+//        Integer refundNumber = torder.getProductNumber();
+//        // 退款原因: refundReason
+//        String refundReason = torder.getRefundReason();
+//        // 退款明细:note
+//        String note = torder.getNote();
+//        String[] refundDetails = note.split(",");
+//        Map<String, Integer> refundMap = new HashMap<>();
+//        for (String refundDetail : refundDetails) {
+//            String[] keyValue  = refundDetail.split("-");
+//            String key = keyValue[0];
+//            String value = keyValue[1];
+//            refundMap.put(key, Integer.valueOf(value));
+//        }
+//
+//        if(refusePrice.compareTo(new BigDecimal("0.00"))<=0){
+//            return R.fail(ResponseCodesEnum.A0001,"退款金额非法");
+//        }
+//
+//        TOrder order = orderService.getById(torder.getId());
+//        if(order.getRefundQuantity() != null && order.getRefundQuantity()>0) {
+//            order.setRefundQuantity(refundNumber + order.getRefundQuantity());
+//        } else {
+//            order.setRefundQuantity(refundNumber);
+//        }
+//
+//        LambdaQueryWrapper<TOrderDetails> wrapper = new LambdaQueryWrapper<>();
+//        wrapper.eq(TOrderDetails::getOrderSn, order.getSn());
+//        List<TOrderDetails> orderDetails = orderDetailsService.list(wrapper);
+//        if (order.getStatus().equals("0")) {
+//            return R.fail(ResponseCodesEnum.A0002,"订单非支付状态");
+//        }
+//
+//        CreateRequest createRequest = new CreateRequest();
+//        createRequest.setOutTradeNo(order.getSn());
+//        AmountReq amount = new AmountReq();
+//        amount.setRefund(refusePrice.multiply(new BigDecimal(100)).longValue());
+//        BigDecimal multiply = order.getPrice().multiply(new BigDecimal(100));
+//        amount.setTotal(multiply.longValue());
+//        amount.setCurrency("CNY");
+//        createRequest.setAmount(amount);
+//        String refundNo = orderService.initSn(order.getEquipmentId());
+//        createRequest.setOutRefundNo(refundNo);
+//        // 上线需要修改回调url
+//        createRequest.setNotifyUrl(JoinpayConstant.WECHAT_NOTIFY_REFUND_URL);
+////		createRequest.setNotifyUrl("http://evxz5m.natappfree.cc/wechatPay/refundNotify");
+//        TAdmin admin = R.getDataIfSuccess(szwlFeign.getAdmin(String.valueOf(order.getAdminId())));
+//        Refund refund = orderService.weixinRefundApi(createRequest, admin.getWechatPayId());
+//        System.out.println("退款参数"+refund.toString());
+//        if(refund.getStatus()==PROCESSING){
+//            order.setStatus(2);
+//            order.setRefundReason(refundReason);
+//            orderService.updateById(order);
+//            // 修改订单明细
+//            for (TOrderDetails orderDetail : orderDetails) {
+//                String productNo = orderDetail.getProductNo();
+//                Integer productNumber = refundMap.get(productNo);
+//                if(productNumber != null) {
+//                    // 退款中
+//                    orderDetail.setRefundStatus("4");
+//                    // 退款数量
+//                    orderDetail.setRefundQuantity(productNumber);
+//                    // 退款金额
+//                    orderDetail.setRefundAmount(orderDetail.getPrice().multiply(new BigDecimal(productNumber)));
+//                    orderDetailsService.updateById(orderDetail);
+//                }
+//            }
+//            return R.ok("申请退款已成功");
+//        }else {
+//            return R.fail(ResponseCodesEnum.B0001,"申请退款失败,请重试");
+//        }
     }
 
     @ApiOperation(value = "退款成功回调")
     @PostMapping("/refundNotify")
     public Object refundNotify(HttpServletRequest request, HttpServletResponse response){
-        String result = orderService.wechatRefund(request,response);
+//        String result = orderService.wechatRefund(request,response);
+        String result = wechatPayConfigService.refundNotify(request,response);
         return R.ok(result);
     }
 }

+ 2 - 1
src/main/java/com/szwl/mapper/xml/TWechatPayConfigMapper.xml

@@ -9,6 +9,7 @@
         <result column="modify_date" property="modifyDate" />
         <result column="merchant_id" property="merchantId" />
         <result column="private_key_path" property="privateKeyPath" />
+        <result column="api_cert_path" property="apiCertPath" />
         <result column="merchant_serial_number" property="merchantSerialNumber" />
         <result column="app_id" property="appId" />
         <result column="apiv3key" property="apiv3key" />
@@ -18,7 +19,7 @@
 
     <!-- 通用查询结果列 -->
     <sql id="Base_Column_List">
-        id, create_date, modify_date, merchant_id, private_key_path, merchant_serial_number, app_id, apiv3key, apiv2key, merchant_name
+        id, create_date, modify_date, merchant_id, private_key_path, api_cert_path, merchant_serial_number, app_id, apiv3key, apiv2key, merchant_name
     </sql>
 
 </mapper>

+ 4 - 1
src/main/java/com/szwl/model/entity/TWechatPayConfig.java

@@ -15,7 +15,7 @@ import lombok.EqualsAndHashCode;
  * </p>
  *
  * @author wuhs
- * @since 2024-03-07
+ * @since 2024-03-26
  */
 @Data
 @EqualsAndHashCode(callSuper = false)
@@ -37,6 +37,9 @@ public class TWechatPayConfig implements Serializable {
     @ApiModelProperty(value = "商户API私钥路径")
     private String privateKeyPath;
 
+    @ApiModelProperty(value = "商户API证书路径")
+    private String apiCertPath;
+
     @ApiModelProperty(value = "商户证书序列号")
     private String merchantSerialNumber;
 

+ 50 - 0
src/main/java/com/szwl/service/TWechatPayConfigService.java

@@ -1,10 +1,15 @@
 package com.szwl.service;
 
+import com.szwl.model.bo.JsonMessage;
+import com.szwl.model.bo.ResponseModel;
+import com.szwl.model.entity.TOrder;
 import com.szwl.model.entity.TWechatPayConfig;
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.wechat.pay.java.core.Config;
 
 
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
 import java.util.Map;
 
 /**
@@ -23,4 +28,49 @@ public interface TWechatPayConfigService extends IService<TWechatPayConfig> {
 
     String decryptFromResource(Map<String, Object> bodyMap);
 
+    /**
+     * 微信直连主扫 购物车支付
+     *
+     * @param clientId
+     * @param productNameMap
+     * @param request
+     * @return
+     */
+    JsonMessage carsPay(String clientId, Map<String, String> productNameMap, HttpServletRequest request);
+
+    /**
+     * 微信支付回调
+     *
+     * @param request
+     * @return
+     */
+    String payNotify(HttpServletRequest request);
+
+    /**
+     * 微信退款
+     *
+     * @param torder
+     * @return
+     */
+    ResponseModel refund(TOrder torder);
+
+    /**
+     * 微信退款回调
+     *
+     * @param request
+     * @param response
+     * @return
+     */
+    String refundNotify(HttpServletRequest request, HttpServletResponse response);
+
+    /**
+     * 微信直连反扫 购物车支付
+     *
+     * @param authCode
+     * @param clientId
+     * @param productNameMap
+     * @param request
+     * @return
+     */
+    JsonMessage cardPay(String authCode, String clientId, Map<String, String> productNameMap, HttpServletRequest request);
 }

+ 943 - 4
src/main/java/com/szwl/service/impl/TWechatPayConfigServiceImpl.java

@@ -1,20 +1,56 @@
 package com.szwl.service.impl;
 
-import com.szwl.model.entity.TWechatPayConfig;
+import cn.hutool.core.util.XmlUtil;
+import cn.hutool.http.HttpUtil;
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.google.gson.Gson;
+import com.szwl.constant.JoinpayConstant;
+import com.szwl.constant.ResponseCodesEnum;
+import com.szwl.constant.WXPayConstants;
+import com.szwl.feign.bean.OrderFeign;
+import com.szwl.feign.bean.SzwlFeign;
+import com.szwl.model.bo.JsonMessage;
+import com.szwl.model.bo.R;
+import com.szwl.model.bo.ResponseModel;
+import com.szwl.model.entity.*;
 import com.szwl.mapper.TWechatPayConfigMapper;
+import com.szwl.model.utils.PushUtils;
+import com.szwl.service.TEquipmentService;
+import com.szwl.service.TOrderDetailsService;
+import com.szwl.service.TOrderService;
 import com.szwl.service.TWechatPayConfigService;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.szwl.utils.HuifuUtils;
+import com.szwl.utils.IDGenerator;
+import com.szwl.utils.MyWXPay;
+import com.szwl.utils.WXPayUtil;
+import com.szwl.weixin.util.HttpUtils;
 import com.wechat.pay.contrib.apache.httpclient.util.AesUtil;
 import com.wechat.pay.java.core.Config;
 import com.wechat.pay.java.core.RSAAutoCertificateConfig;
+import com.wechat.pay.java.service.refund.model.AmountReq;
+import com.wechat.pay.java.service.refund.model.CreateRequest;
+import com.wechat.pay.java.service.refund.model.Refund;
 import org.apache.commons.lang.StringUtils;
+import org.apache.http.HttpStatus;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
 import java.nio.charset.StandardCharsets;
 import java.security.GeneralSecurityException;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.*;
+
+import static com.wechat.pay.java.service.refund.model.Status.PROCESSING;
 
 /**
  * <p>
@@ -27,8 +63,28 @@ import java.util.Map;
 @Service
 public class TWechatPayConfigServiceImpl extends ServiceImpl<TWechatPayConfigMapper, TWechatPayConfig> implements TWechatPayConfigService {
 
+    /**
+     * 用户输入密码,尝试30秒内去查询支付结果
+     */
+    private static Integer remainingTimeMs = 90000;
+
     public static Map<Long, Config> configMap = new HashMap<>();
 
+    @Autowired
+    SzwlFeign szwlFeign;
+
+    @Autowired
+    OrderFeign orderFeign;
+
+    @Autowired
+    TOrderService orderService;
+
+    @Autowired
+    TEquipmentService equipmentService;
+
+    @Autowired
+    TOrderDetailsService orderDetailsService;
+
     @Override
     public Config getWechatConfig(Long id) {
         if(configMap==null){
@@ -80,4 +136,887 @@ public class TWechatPayConfigServiceImpl extends ServiceImpl<TWechatPayConfigMap
         }
         return plainText;
     }
+
+    @Override
+    public JsonMessage carsPay(String clientId, Map<String, String> productNameMap, HttpServletRequest request) {
+        if(productNameMap==null){
+            return  JsonMessage.error("数据出错");
+        }
+        StringBuffer note = new StringBuffer();
+        StringBuffer productName = new StringBuffer();
+        String productNo = "";
+        Map<String, Integer> productMap = new HashMap<>();
+        Integer productNumber = 0;
+
+        TEquipment equipment = R.getDataIfSuccess(szwlFeign.findEquipmentByClientId(clientId));
+        if(equipment==null||equipment.getId()==null){
+            return JsonMessage.error("找不到设备");
+        }
+        BigDecimal price = new BigDecimal("0.00");
+        TEquipmentDesc equipmentDesc = R.getDataIfSuccess(szwlFeign.findEquipmentById(equipment.getId()));
+        if(equipmentDesc==null||equipmentDesc.getEquipmentId()==null||equipmentDesc.getPayType()==null||equipmentDesc.getPayType().equals("0")){
+            for (String key : productNameMap.keySet()) {
+                String entryValue = String.valueOf(productNameMap.get(key));
+                List<String> value = JSON.parseArray(entryValue, String.class);
+                List<TPromoCode> promoCodeList = new ArrayList<>();
+                //1,校验优惠码
+                if(value.size()>0){
+                    for(String code:value){
+                        if(!code.equals("0")){
+                            TPromoCode promoCode = new TPromoCode();
+                            ResponseModel<TPromoCode> tPromoCodeResponseModel = szwlFeign.selectTPromoCode(code, equipment.getAdminId().toString());
+                            TPromoCode tPromoCode = tPromoCodeResponseModel.getData();
+                            promoCode = tPromoCode;
+                            if (tPromoCode == null||tPromoCode.getId()==null) {
+                                //不存在
+                                return JsonMessage.success("1");
+                            }
+                            Date lastUseDate = null;
+                            if (promoCode != null) {
+                                lastUseDate = promoCode.getLastUseDate();
+                            }
+
+                            if (lastUseDate != null && lastUseDate.getTime() < ((new Date()).getTime())) {
+                                promoCode.setIsUse("2");
+                                szwlFeign.updatePromoCode(String.valueOf(promoCode.getId()),"2");
+                                //过期
+                                return JsonMessage.success("4");
+                            }
+                            if (promoCode.getId() == null) {
+                                //不存在
+                                return JsonMessage.success("1");
+                            }
+                            if (promoCode.getIsUse().equals("1")) {
+                                //被使用
+                                return JsonMessage.success("2");
+                            }
+                            if(!promoCode.getAdminId().equals("1")){
+                                if (String.valueOf(equipment.getAdminId()).equals(promoCode.getAdminId())) {
+
+                                } else {
+                                    //不是本机
+                                    return JsonMessage.success("3");
+                                }
+                            }
+                            if (promoCode.getDiscount() == null) {
+                                //旧优惠码
+                                return JsonMessage.success("0");
+                            }
+                            if (promoCode.getDiscount() != null && promoCode.getDiscount() == 0) {
+                                //0折
+                                return JsonMessage.success("0");
+                            }
+                            promoCodeList.add(promoCode);
+                        }
+                    }
+                }
+                String[] productNum = key.split("-");
+                String productNamea = productNum[0];
+                String num = productNum[1];
+                productMap.put(productNamea,Integer.valueOf(num));
+                productNumber += Integer.valueOf(num);
+                productName.append(productNamea).append("x").append(num).append(",");
+                TProduct product = R.getDataIfSuccess(szwlFeign.getProduct(String.valueOf(equipment.getId()), productNamea));
+                if (product == null) {
+                    return JsonMessage.error("找不到商品");
+                }
+                note.append(productNamea).append("-").append(product.getNo()).append(":");
+                BigDecimal productPrice = product.getRmbPrice();
+                productNo = product.getNo();
+                if(promoCodeList.size()>0){
+                    //有优惠码
+                    BigDecimal onePrice = new BigDecimal("0.00");
+                    int i;
+                    for( i = 0;i<promoCodeList.size();i++){
+                        BigDecimal discount = BigDecimal.valueOf(promoCodeList.get(i).getDiscount()).setScale(2, RoundingMode.HALF_DOWN);
+                        BigDecimal price1 = productPrice.multiply(discount).divide(new BigDecimal(10)).setScale(2, RoundingMode.HALF_DOWN);
+                        price = price.add(price1);
+                        onePrice = onePrice.add(price1);
+                    }
+                    if(i<Integer.valueOf(num)){
+                        int a = Integer.valueOf(num)-i;
+                        BigDecimal price2 = productPrice.multiply(new BigDecimal(a)).setScale(2, RoundingMode.HALF_DOWN);
+                        price =price.add(price2);
+                        onePrice = onePrice.add(price2);
+                    }
+                    note.append(onePrice).append("-").append(num).append(",");
+                }else {
+                    //1,type=0,原始设定,没有第二件半价
+                    int a = Integer.valueOf(num);
+                    BigDecimal price2 = productPrice.multiply(new BigDecimal(a)).setScale(2, RoundingMode.HALF_DOWN);
+                    price =price.add(price2);
+                    note.append(price2).append("-").append(num).append(",");
+                }
+            }
+        }else {
+
+            for (String key : productNameMap.keySet()) {
+                String[] productNum = key.split("-");
+                String productNamea = productNum[0];
+                String num = productNum[1];
+                productMap.put(productNamea,Integer.valueOf(num));
+                TProduct product = R.getDataIfSuccess(szwlFeign.getProduct(String.valueOf(equipment.getId()), productNamea));
+                productNo = product.getNo();
+                BigDecimal productPrice = product.getRmbPrice();
+                productName.append(productNamea).append("x").append(num).append(",");
+                note.append(productNamea).append("-").append(product.getNo()).append(":");
+                switch (num) {
+                    case "1":
+                        //1个  0个半价
+                        price =price.add(productPrice);
+                        note.append(price).append("-").append(num).append(",");
+                        break;
+                    case "2":
+                        //2个  1个半价
+                        price =price.add(productPrice);
+                        price =price.add(productPrice.multiply(new BigDecimal(5)).divide(new BigDecimal(10)).setScale(2, RoundingMode.HALF_DOWN));
+                        note.append(price).append("-").append(num).append(",");
+                        break;
+                    case "3":
+                        //3个 1个半价
+                        price =price.add(productPrice);
+                        price =price.add(productPrice.multiply(new BigDecimal(5)).divide(new BigDecimal(10)).setScale(2, RoundingMode.HALF_DOWN));
+                        price =price.add(productPrice);
+                        note.append(price).append("-").append(num).append(",");
+                        break;
+                    case "4":
+                        //4个 2个半价
+                        price =price.add(productPrice);
+                        price =price.add(productPrice.multiply(new BigDecimal(5)).divide(new BigDecimal(10)).setScale(2, RoundingMode.HALF_DOWN));
+                        price =price.add(productPrice);
+                        price =price.add(productPrice.multiply(new BigDecimal(5)).divide(new BigDecimal(10)).setScale(2, RoundingMode.HALF_DOWN));
+                        note.append(price).append("-").append(num).append(",");
+                        break;
+                    case "5":
+                        //5个 2个半价
+                        price =price.add(productPrice);
+                        price =price.add(productPrice.multiply(new BigDecimal(5)).divide(new BigDecimal(10)).setScale(2, RoundingMode.HALF_DOWN));
+                        price =price.add(productPrice);
+                        price =price.add(productPrice.multiply(new BigDecimal(5)).divide(new BigDecimal(10)).setScale(2, RoundingMode.HALF_DOWN));
+                        price =price.add(productPrice);
+                        note.append(price).append("-").append(num).append(",");
+                        break;
+                }
+            }
+        }
+
+        Long equipmentId = equipment.getId();
+        //查找商品
+        if (BigDecimal.ZERO.compareTo(price) >= 0) {
+            return JsonMessage.error("商品价格异常");
+        }
+        Long client6 = Long.parseLong(clientId.substring(clientId.length() - 6));
+        String sn = orderService.initSn(client6);
+        //获取分销  关联设备
+        TAdmin admin = R.getDataIfSuccess(szwlFeign.getAdmin(String.valueOf(equipment.getAdminId())));
+        String companyType = admin.getCompanyType();
+        JSONArray altInfo = new JSONArray();
+        BigDecimal amount = price.setScale(2, RoundingMode.HALF_DOWN);
+        amount = amount.multiply(new BigDecimal(100));
+        String notifyUrl = JoinpayConstant.WECHAT_NOTIFY_URL;
+        String frpCode = "WEIXIN_NATIVE";
+        TOrder order = new TOrder();
+        order.setId(IDGenerator.orderID());
+        order.setCreateDate(new Date());
+        order.setModifyDate(new Date());
+        order.setAdminId(admin.getId());
+        order.setSn(sn);
+        if(productNumber == 1) {
+            productName.delete(productName.length() - 3, productName.length());
+        } else {
+            productName.deleteCharAt(productName.length() - 1);
+        }
+        order.setProductName(productName.toString());
+        order.setPrice(price);
+        order.setClientId(equipment.getClientId());
+        order.setEquipmentId(equipmentId);
+        order.setFrpCode(frpCode);
+        order.setProductNumber(productNumber);
+        order.setAltInfo(altInfo.toString());
+        order.setStatus(0);
+        String payPlatform = "3";
+        order.setPayPlatform(payPlatform);
+        order.setCompanyType(companyType);
+        order.setMachineType(equipment.getMachineType());
+        order.setProductNo(productNo);
+        if(StringUtils.isNotEmpty(payPlatform)&&payPlatform.equals("1")){
+            order.setIsSettlement("0");
+        }
+        order.setNote(note.toString());
+
+        // 订单明细表
+        TOrderDetails orderDetails = new TOrderDetails();
+        orderDetails.setAdminId(admin.getId());
+        orderDetails.setEquipmentId(equipmentId);
+        orderDetails.setCreateDate(new Date());
+        orderDetails.setCompanyType(companyType);
+        orderDetails.setRefundStatus("0");
+        orderDetails.setMachineType(equipment.getMachineType());
+        // 添加到订单明细表
+        for (String key : productMap.keySet()) {
+            Integer productNum = productMap.get(key);
+            TProduct product = R.getDataIfSuccess(szwlFeign.getProduct(String.valueOf(equipment.getId()), key));
+            orderDetails.setProductNo(product.getNo());
+            orderDetails.setProductName(key);
+            orderDetails.setPrice(product.getRmbPrice());
+            orderDetails.setProductNumber(productNum);
+            orderDetails.setAmount(product.getRmbPrice().multiply(new BigDecimal(productNum)));
+            orderDetails.setId(HuifuUtils.initDetailsId());
+            orderDetails.setOrderSn(sn);
+            orderDetailsService.save(orderDetails);
+        }
+        orderService.save(order);
+        String productName1 = "";
+        if(productNumber > 1) {
+            productName1 = "棉花糖";
+        } else {
+            productName1 = productName.toString();
+        }
+        String result;
+        try {
+            result = orderService.wechatPay(
+                    sn, amount, productName1, admin.getWechatPayId(), notifyUrl, clientId, request
+            );
+        } catch (Exception e) {
+            e.printStackTrace();
+            return JsonMessage.error("申请支付失败");
+        }
+        // 微信支付支付申请返回支付二维码图片
+        JSONObject kindData = new JSONObject();
+        kindData.put("sn", sn);
+        kindData.put("code_url", result);
+        return JsonMessage.success(kindData.toString());
+    }
+
+    @Override
+    public String payNotify(HttpServletRequest request) {
+        Gson gson = new Gson();
+        // 读取请求体中的数据
+        String body = HttpUtils.readData(request);
+        Map<String, Object> bodyMap = gson.fromJson(body, HashMap.class);
+        // 解密支付通知数据
+        String plainText = this.decryptFromResource(bodyMap);
+        if(StringUtils.isNotEmpty(plainText)){
+            JSONObject resultJson = JSONObject.parseObject(plainText);
+            // 根据订单号查询订单
+            String sn = resultJson.getString("out_trade_no");
+            if(StringUtils.isNotEmpty(sn)) {
+                LambdaQueryWrapper<TOrder> query = Wrappers.lambdaQuery();
+                query.eq(TOrder::getSn, sn);
+                query.eq(TOrder::getStatus, 0);
+                List<TOrder> list = orderService.list(query);
+                // 更新订单状态和支付信息
+                if (list != null && list.size() > 0) {
+                    TOrder order = list.get(0);
+                    order.setStatus(1);
+                    String success_time = resultJson.getString("success_time");
+                    Date date = new Date();
+                    try {
+                        date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(success_time);
+                    } catch (ParseException e) {
+                        // 忽略时间转换错误
+                    }
+                    order.setPayDate(date);
+                    order.setTrxNo(resultJson.getString("transaction_id"));
+                    // 更新订单明细状态
+                    LambdaQueryWrapper<TOrderDetails> lambdaQueryWrapper = new LambdaQueryWrapper<>();
+                    lambdaQueryWrapper.eq(TOrderDetails::getOrderSn,sn);
+                    List<TOrderDetails> orderDetails = orderDetailsService.list(lambdaQueryWrapper);
+                    for (TOrderDetails orderDetail : orderDetails) {
+                        orderDetail.setRefundStatus("1");
+                        orderDetailsService.updateById(orderDetail);
+                    }
+                    // 发送支付成功消息给设备
+                    TEquipment equipment = R.getDataIfSuccess(szwlFeign.findEquipmentByClientId(order.getClientId()));
+                    JSONObject kindData = new JSONObject();
+                    kindData.put("sn", order.getSn());
+                    kindData.put("productName", order.getProductName());
+                    if (!order.getIsNotified().equals("1")) {
+                        String paySuccess = equipmentService.sentMessage(equipment.getClientId(), PushUtils.buildJson("pay_success", kindData.toString()).toString());
+                        if (paySuccess.equals("success")) {
+                            order.setIsNotified("1");
+                        }
+                    }
+                    orderService.updateById(order);
+                    try {
+                        // 保存订单信息到ES
+                        if(order.getProductNumber()==null||order.getProductNumber()==0){
+                            order.setProductNumber(1);
+                        }
+                        orderFeign.saveToEs(order);
+                    }catch (Exception e) {
+                        e.printStackTrace();
+                    }
+                } else {
+                    LambdaQueryWrapper<TOrder> queryWrapper = Wrappers.lambdaQuery();
+                    query.eq(TOrder::getSn, sn);
+                    query.eq(TOrder::getStatus, 1);
+                    List<TOrder> orderList = orderService.list(queryWrapper);
+                    if (list != null && list.size() > 0) {
+                        TOrder tOrder = orderList.get(0);
+                        try {
+                            // 保存订单信息到ES
+                            if(tOrder.getProductNumber()==null||tOrder.getProductNumber()==0){
+                                tOrder.setProductNumber(1);
+                            }
+                            orderFeign.saveToEs(tOrder);
+                        }catch (Exception e) {
+                            e.printStackTrace();
+                        }
+                        return "success";
+                    }
+                    return "fail";
+                }
+            }
+        }
+        return "success";
+    }
+
+    @Override
+    public ResponseModel refund(TOrder torder) {
+        // 退款金额: refusePrice
+        BigDecimal refusePrice = torder.getPrice().setScale(2, RoundingMode.HALF_DOWN);
+        // 退款数量: refundNumber
+        Integer refundNumber = torder.getProductNumber();
+        // 退款原因: refundReason
+        String refundReason = torder.getRefundReason();
+        // 退款明细:note
+        String note = torder.getNote();
+        String[] refundDetails = note.split(",");
+        Map<String, Integer> refundMap = new HashMap<>();
+        for (String refundDetail : refundDetails) {
+            String[] keyValue  = refundDetail.split("-");
+            String key = keyValue[0];
+            String value = keyValue[1];
+            refundMap.put(key, Integer.valueOf(value));
+        }
+
+        if(refusePrice.compareTo(new BigDecimal("0.00"))<=0){
+            return R.fail(ResponseCodesEnum.A0001,"退款金额非法");
+        }
+
+        TOrder order = orderService.getById(torder.getId());
+        if(order.getRefundQuantity() != null && order.getRefundQuantity()>0) {
+            order.setRefundQuantity(refundNumber + order.getRefundQuantity());
+        } else {
+            order.setRefundQuantity(refundNumber);
+        }
+
+        LambdaQueryWrapper<TOrderDetails> wrapper = new LambdaQueryWrapper<>();
+        wrapper.eq(TOrderDetails::getOrderSn, order.getSn());
+        List<TOrderDetails> orderDetails = orderDetailsService.list(wrapper);
+        if (order.getStatus().equals("0")) {
+            return R.fail(ResponseCodesEnum.A0002,"订单非支付状态");
+        }
+
+        CreateRequest createRequest = new CreateRequest();
+        createRequest.setOutTradeNo(order.getSn());
+        AmountReq amount = new AmountReq();
+        amount.setRefund(refusePrice.multiply(new BigDecimal(100)).longValue());
+        BigDecimal multiply = order.getPrice().multiply(new BigDecimal(100));
+        amount.setTotal(multiply.longValue());
+        amount.setCurrency("CNY");
+        createRequest.setAmount(amount);
+        String refundNo = orderService.initSn(order.getEquipmentId());
+        createRequest.setOutRefundNo(refundNo);
+        // 上线需要修改回调url
+        createRequest.setNotifyUrl(JoinpayConstant.WECHAT_NOTIFY_REFUND_URL);
+//		createRequest.setNotifyUrl("http://evxz5m.natappfree.cc/wechatPay/refundNotify");
+        TAdmin admin = R.getDataIfSuccess(szwlFeign.getAdmin(String.valueOf(order.getAdminId())));
+        Refund refund = orderService.weixinRefundApi(createRequest, admin.getWechatPayId());
+        System.out.println("退款参数"+refund.toString());
+        if(refund.getStatus()==PROCESSING){
+            order.setStatus(2);
+            order.setRefundReason(refundReason);
+            orderService.updateById(order);
+            // 修改订单明细
+            for (TOrderDetails orderDetail : orderDetails) {
+                String productNo = orderDetail.getProductNo();
+                Integer productNumber = refundMap.get(productNo);
+                if(productNumber != null) {
+                    // 退款中
+                    orderDetail.setRefundStatus("4");
+                    // 退款数量
+                    orderDetail.setRefundQuantity(productNumber);
+                    // 退款金额
+                    orderDetail.setRefundAmount(orderDetail.getPrice().multiply(new BigDecimal(productNumber)));
+                    orderDetailsService.updateById(orderDetail);
+                }
+            }
+            return R.ok("申请退款已成功");
+        }else {
+            return R.fail(ResponseCodesEnum.B0001,"申请退款失败,请重试");
+        }
+    }
+
+    @Override
+    public String refundNotify(HttpServletRequest request, HttpServletResponse response) {
+        Gson gson = new Gson();
+        Map<String, Object> hashMap = new HashMap<>(3);
+
+        try {
+            // 处理退款通知参数
+            String body = HttpUtils.readData(request);
+            Map<String, Object> bodyMap = gson.fromJson(body, HashMap.class);
+            String eventType = (String)bodyMap.get("event_type");
+            if (eventType.equals("REFUND.SUCCESS")) {
+                // 处理退款单
+                processRefund(bodyMap);
+                //成功应答
+                response.setStatus(HttpStatus.SC_OK);
+//                hashMap.put("code", "SUCCESS");
+            } else {
+                response.setStatus(HttpStatus.SC_BAD_GATEWAY);
+                hashMap.put("code", "FAIL");
+                hashMap.put("message", "系统错误");
+            }
+            return gson.toJson(hashMap);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    @Override
+    public JsonMessage cardPay(String authCode, String clientId, Map<String, String> productNameMap, HttpServletRequest request) {
+        if(productNameMap==null){
+            return JsonMessage.error("数据出错");
+        }
+        StringBuilder note = new StringBuilder();
+        StringBuilder productName = new StringBuilder();
+        String productNo = "";
+        Map<String, Integer> productMap = new HashMap<>();
+        int productNumber = 0;
+
+        TEquipment equipment = R.getDataIfSuccess(szwlFeign.findEquipmentByClientId(clientId));
+        if(equipment==null||equipment.getId()==null){
+            return JsonMessage.error("找不到设备");
+        }
+        BigDecimal price = new BigDecimal("0.00");
+        TEquipmentDesc equipmentDesc = R.getDataIfSuccess(szwlFeign.findEquipmentById(equipment.getId()));
+        if(equipmentDesc==null||equipmentDesc.getEquipmentId()==null||equipmentDesc.getPayType()==null||equipmentDesc.getPayType().equals("0")){
+            for (String key : productNameMap.keySet()) {
+                String entryValue = String.valueOf(productNameMap.get(key));
+                List<String> value = JSON.parseArray(entryValue, String.class);
+                List<TPromoCode> promoCodeList = new ArrayList<>();
+                //1,校验优惠码
+                if(value.size()>0){
+                    for(String code:value){
+                        if(!code.equals("0")){
+                            TPromoCode promoCode = new TPromoCode();
+                            ResponseModel<TPromoCode> tPromoCodeResponseModel = szwlFeign.selectTPromoCode(code, equipment.getAdminId().toString());
+                            TPromoCode tPromoCode = tPromoCodeResponseModel.getData();
+                            promoCode = tPromoCode;
+                            if (tPromoCode == null||tPromoCode.getId()==null) {
+                                //不存在
+                                return JsonMessage.success("1");
+                            }
+                            Date lastUseDate = null;
+                            if (promoCode != null) {
+                                lastUseDate = promoCode.getLastUseDate();
+                            }
+
+                            if (lastUseDate != null && lastUseDate.getTime() < ((new Date()).getTime())) {
+                                promoCode.setIsUse("2");
+                                szwlFeign.updatePromoCode(String.valueOf(promoCode.getId()),"2");
+                                //过期
+                                return JsonMessage.success("4");
+                            }
+                            if (promoCode.getId() == null) {
+                                //不存在
+                                return JsonMessage.success("1");
+                            }
+                            if (promoCode.getIsUse().equals("1")) {
+                                //被使用
+                                return JsonMessage.success("2");
+                            }
+                            if(!promoCode.getAdminId().equals("1")){
+                                if (!String.valueOf(equipment.getAdminId()).equals(promoCode.getAdminId())) {
+                                    return JsonMessage.success("3");
+                                }
+                            }
+                            if (promoCode.getDiscount() == null) {
+                              //旧优惠码
+                              return JsonMessage.success("0");
+                            }
+                            if (promoCode.getDiscount() != null && promoCode.getDiscount() == 0) {
+                              //0折
+                              return JsonMessage.success("0");
+                            }
+                            promoCodeList.add(promoCode);
+                        }
+                  }
+                }
+                String[] productNum = key.split("-");
+                String productNamea = productNum[0];
+                String num = productNum[1];
+                productMap.put(productNamea,Integer.valueOf(num));
+                productNumber += Integer.parseInt(num);
+                productName.append(productNamea).append("x").append(num).append(",");
+                TProduct product = R.getDataIfSuccess(szwlFeign.getProduct(String.valueOf(equipment.getId()), productNamea));
+                if (product == null) {
+                    return JsonMessage.error("找不到商品");
+                }
+                note.append(productNamea).append("-").append(product.getNo()).append(":");
+                BigDecimal productPrice = product.getRmbPrice();
+                productNo = product.getNo();
+                if(promoCodeList.size()>0){
+                    //有优惠码
+                    BigDecimal onePrice = new BigDecimal("0.00");
+                    int i;
+                    for( i = 0;i<promoCodeList.size();i++){
+                        BigDecimal discount = BigDecimal.valueOf(promoCodeList.get(i).getDiscount()).setScale(2, RoundingMode.HALF_DOWN);
+                        BigDecimal price1 = productPrice.multiply(discount).divide(new BigDecimal(10)).setScale(2, RoundingMode.HALF_DOWN);
+                        price = price.add(price1);
+                        onePrice = onePrice.add(price1);
+                    }
+                    if(i<Integer.parseInt(num)){
+                        int a = Integer.parseInt(num)-i;
+                        BigDecimal price2 = productPrice.multiply(new BigDecimal(a)).setScale(2, RoundingMode.HALF_DOWN);
+                        price =price.add(price2);
+                        onePrice = onePrice.add(price2);
+                    }
+                    note.append(onePrice).append("-").append(num).append(",");
+                }else {
+                    //1,type=0,原始设定,没有第二件半价
+                    int a = Integer.parseInt(num);
+                    BigDecimal price2 = productPrice.multiply(new BigDecimal(a)).setScale(2, RoundingMode.HALF_DOWN);
+                    price =price.add(price2);
+                    note.append(price2).append("-").append(num).append(",");
+                }
+            }
+        }else {
+            for (String key : productNameMap.keySet()) {
+                String[] productNum = key.split("-");
+                String productNamea = productNum[0];
+                String num = productNum[1];
+                productMap.put(productNamea,Integer.valueOf(num));
+                TProduct product = R.getDataIfSuccess(szwlFeign.getProduct(String.valueOf(equipment.getId()), productNamea));
+                productNo = product.getNo();
+                BigDecimal productPrice = product.getRmbPrice();
+                productName.append(productNamea).append("x").append(num).append(",");
+                note.append(productNamea).append("-").append(product.getNo()).append(":");
+                switch (num) {
+                    case "1":
+                        //1个  0个半价
+                        price =price.add(productPrice);
+                        note.append(price).append("-").append(num).append(",");
+                        break;
+                    case "2":
+                        //2个  1个半价
+                        price =price.add(productPrice);
+                        price =price.add(productPrice.multiply(new BigDecimal(5)).divide(new BigDecimal(10)).setScale(2, RoundingMode.HALF_DOWN));
+                        note.append(price).append("-").append(num).append(",");
+                        break;
+                    case "3":
+                        //3个 1个半价
+                        price =price.add(productPrice);
+                        price =price.add(productPrice.multiply(new BigDecimal(5)).divide(new BigDecimal(10)).setScale(2, RoundingMode.HALF_DOWN));
+                        price =price.add(productPrice);
+                        note.append(price).append("-").append(num).append(",");
+                        break;
+                    case "4":
+                        //4个 2个半价
+                        price =price.add(productPrice);
+                        price =price.add(productPrice.multiply(new BigDecimal(5)).divide(new BigDecimal(10)).setScale(2, RoundingMode.HALF_DOWN));
+                        price =price.add(productPrice);
+                        price =price.add(productPrice.multiply(new BigDecimal(5)).divide(new BigDecimal(10)).setScale(2, RoundingMode.HALF_DOWN));
+                        note.append(price).append("-").append(num).append(",");
+                        break;
+                    case "5":
+                        //5个 2个半价
+                        price =price.add(productPrice);
+                        price =price.add(productPrice.multiply(new BigDecimal(5)).divide(new BigDecimal(10)).setScale(2, RoundingMode.HALF_DOWN));
+                        price =price.add(productPrice);
+                        price =price.add(productPrice.multiply(new BigDecimal(5)).divide(new BigDecimal(10)).setScale(2, RoundingMode.HALF_DOWN));
+                        price =price.add(productPrice);
+                        note.append(price).append("-").append(num).append(",");
+                        break;
+                }
+            }
+        }
+
+        Long equipmentId = equipment.getId();
+        //查找商品
+        if (BigDecimal.ZERO.compareTo(price) >= 0) {
+            return JsonMessage.error("商品价格异常");
+        }
+        Long client6 = Long.parseLong(clientId.substring(clientId.length() - 6));
+        String sn = orderService.initSn(client6);
+        //获取分销  关联设备
+        TAdmin admin = R.getDataIfSuccess(szwlFeign.getAdmin(String.valueOf(equipment.getAdminId())));
+        String companyType = admin.getCompanyType();
+        BigDecimal amount = price.setScale(2, RoundingMode.HALF_DOWN);
+        amount = amount.multiply(new BigDecimal(100)).setScale(0);
+        String frpCode = "WEIXIN_PAYCODE";
+        TOrder order = new TOrder();
+        order.setId(IDGenerator.orderID());
+        order.setCreateDate(new Date());
+        order.setModifyDate(new Date());
+        order.setAdminId(admin.getId());
+        order.setSn(sn);
+        if(productNumber == 1) {
+            productName.delete(productName.length() - 3, productName.length());
+        } else {
+            productName.deleteCharAt(productName.length() - 1);
+        }
+        order.setProductName(productName.toString());
+        order.setPrice(price);
+        order.setClientId(equipment.getClientId());
+        order.setEquipmentId(equipmentId);
+        order.setFrpCode(frpCode);
+        order.setProductNumber(productNumber);
+        order.setStatus(0);
+        String payPlatform = "3";
+        order.setPayPlatform(payPlatform);
+        order.setCompanyType(companyType);
+        order.setMachineType(equipment.getMachineType());
+        order.setProductNo(productNo);
+        order.setNote(note.toString());
+
+        // 订单明细表
+        TOrderDetails orderDetails = new TOrderDetails();
+        orderDetails.setAdminId(admin.getId());
+        orderDetails.setEquipmentId(equipmentId);
+        orderDetails.setCreateDate(new Date());
+        orderDetails.setCompanyType(companyType);
+        orderDetails.setRefundStatus("0");
+        orderDetails.setMachineType(equipment.getMachineType());
+        // 添加到订单明细表
+        for (String key : productMap.keySet()) {
+            Integer productNum = productMap.get(key);
+            TProduct product = R.getDataIfSuccess(szwlFeign.getProduct(String.valueOf(equipment.getId()), key));
+            orderDetails.setProductNo(product.getNo());
+            orderDetails.setProductName(key);
+            orderDetails.setPrice(product.getRmbPrice());
+            orderDetails.setProductNumber(productNum);
+            orderDetails.setAmount(product.getRmbPrice().multiply(new BigDecimal(productNum)));
+            orderDetails.setId(HuifuUtils.initDetailsId());
+            orderDetails.setOrderSn(sn);
+            orderDetailsService.save(orderDetails);
+        }
+        orderService.save(order);
+        String productName1 = "";
+        if(productNumber > 1) {
+            productName1 = "棉花糖";
+        } else {
+            productName1 = productName.toString();
+        }
+        String result;
+        try {
+            result = wechatCardPay(
+                    sn, amount, authCode, productName1, admin.getWechatPayId(), clientId, request
+            );
+        } catch (Exception e) {
+            e.printStackTrace();
+            return JsonMessage.error("申请支付失败");
+        }
+        // 微信支付支付申请返回支付二维码图片
+        if (result.equals(WXPayConstants.SUCCESS)) {
+            JSONObject kindData = new JSONObject();
+            kindData.put("sn", sn);
+            return JsonMessage.success(kindData.toString());
+        } else {
+            return JsonMessage.error(result);
+        }
+    }
+
+    private String wechatCardPay(String sn, BigDecimal amount, String authCode, String productName, Long wechatPayId, String clientId, HttpServletRequest request) throws Exception {
+        TWechatPayConfig wechatPayConfig = getById(wechatPayId);
+        Map<String, String> resData = new HashMap<>();
+        resData.put("appid", wechatPayConfig.getAppId());
+        resData.put("auth_code", authCode);
+        resData.put("body", productName);
+        resData.put("device_info", clientId);
+        resData.put("mch_id", wechatPayConfig.getMerchantId());
+        resData.put("nonce_str", WXPayUtil.generateNonceStr());
+        resData.put("out_trade_no", sn);
+        resData.put("spbill_create_ip", "127.0.0.1");
+        resData.put("total_fee", amount.toString());
+        String sign = WXPayUtil.generateSignature(resData, wechatPayConfig.getApiv2key());
+        // 参数转换成xml的String字符串
+        resData.put("sign", sign);
+        String xmlStr = WXPayUtil.mapToXml(resData);
+        System.out.println("请求参数:" + xmlStr);
+        // 开始时间(毫秒)
+        long startTimestampMs = System.currentTimeMillis();
+        String responseXml = HttpUtil.post("https://api.mch.weixin.qq.com/pay/micropay", xmlStr);
+        System.out.println("返回参数:" + responseXml);
+        // 再把响应的xml转换成map
+        Map<String, Object> responseMap = XmlUtil.xmlToMap(responseXml);
+        // 先判断 协议字段返回(return_code),再判断 业务返回,最后判断 交易状态(trade_state)
+        // 通信标识,非交易标识
+        String returnCode = responseMap.get("return_code").toString();
+        if (WXPayConstants.SUCCESS.equals(returnCode)) {
+            String errCode = responseMap.get("err_code").toString();
+            // 余额不足,信用卡失效
+            if ("USERPAYING".equals(errCode) || "SYSTEMERROR".equals(errCode) || "BANKERROR".equals(errCode)) {
+                // 查询订单
+                Map<String, Object> orderQueryMap = null;
+                Map<String, String> requestData =new HashMap<>();
+                requestData.put("appid", wechatPayConfig.getAppId());
+                requestData.put("mch_id", wechatPayConfig.getMerchantId());
+                requestData.put("out_trade_no", sn);
+                requestData.put("nonce_str", WXPayUtil.generateNonceStr());
+                String sign1 = WXPayUtil.generateSignature(requestData, wechatPayConfig.getApiv2key());
+                requestData.put("sign", sign1);
+                String xmlStr1 = WXPayUtil.mapToXml(requestData);
+                // 用户支付中,需要输入密码或系统错误则去重新查询订单API
+                // 每次循环时的当前系统时间 - 开始时记录的时间 > 设定的30秒时间就退出
+                while (System.currentTimeMillis() - startTimestampMs < remainingTimeMs) {
+                    // 商户收银台得到USERPAYING状态后,经过商户后台系统调用【查询订单API】查询实际支付结果。
+                    String responseXml1 = HttpUtil.post("https://api.mch.weixin.qq.com/pay/orderquery", xmlStr1);
+                    orderQueryMap = XmlUtil.xmlToMap(responseXml1);
+                    String returnCodeForQuery = orderQueryMap.get("return_code").toString();
+                    if (WXPayConstants.SUCCESS.equals(returnCodeForQuery)) {
+                        // 通讯成功
+                        String tradeState = orderQueryMap.get("trade_state").toString();
+                        if (WXPayConstants.SUCCESS.equals(tradeState)) {
+                            String transactionId = orderQueryMap.get("transaction_id").toString();
+                            String timeEnd = orderQueryMap.get("time_end").toString();
+                            LambdaQueryWrapper<TOrder> query = Wrappers.lambdaQuery();
+                            query.eq(TOrder::getSn, sn);
+                            query.eq(TOrder::getStatus, 0);
+                            List<TOrder> list = orderService.list(query);
+                            // 更新订单状态和支付信息
+                            if (list != null && list.size() > 0) {
+                                TOrder order = list.get(0);
+                                order.setStatus(1);
+                                order.setTrxNo(transactionId);
+                                Date date = new Date();
+                                try {
+                                    date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(timeEnd);
+                                } catch (ParseException e) {
+                                    // 忽略时间转换错误
+                                }
+                                order.setPayDate(date);
+                                // 更新订单明细状态
+                                LambdaQueryWrapper<TOrderDetails> lambdaQueryWrapper = new LambdaQueryWrapper<>();
+                                lambdaQueryWrapper.eq(TOrderDetails::getOrderSn,sn);
+                                List<TOrderDetails> orderDetails = orderDetailsService.list(lambdaQueryWrapper);
+                                for (TOrderDetails orderDetail : orderDetails) {
+                                    orderDetail.setRefundStatus("1");
+                                    orderDetailsService.updateById(orderDetail);
+                                }
+                                // 发送支付成功消息给设备
+                                TEquipment equipment = R.getDataIfSuccess(szwlFeign.findEquipmentByClientId(order.getClientId()));
+                                JSONObject kindData = new JSONObject();
+                                kindData.put("sn", order.getSn());
+                                kindData.put("productName", order.getProductName());
+                                if (!order.getIsNotified().equals("1")) {
+                                    String paySuccess = equipmentService.sentMessage(equipment.getClientId(), PushUtils.buildJson("pay_success", kindData.toString()).toString());
+                                    if (paySuccess.equals("success")) {
+                                        order.setIsNotified("1");
+                                    }
+                                }
+                                orderService.updateById(order);
+                                try {
+                                    // 保存订单信息到ES
+                                    if(order.getProductNumber()==null||order.getProductNumber()==0){
+                                        order.setProductNumber(1);
+                                    }
+                                    orderFeign.saveToEs(order);
+                                }catch (Exception e) {
+                                    e.printStackTrace();
+                                }
+                                // 如果成功了直接将查询结果返回
+                                return tradeState;
+                            }
+                        }
+                        // 如果支付结果仍为USERPAYING,则每隔5秒循环调用【查询订单API】判断实际支付结果
+                        Thread.sleep(10000);
+                    }
+                }
+                // 如果用户取消支付或累计90秒用户都未支付,商户收银台退出查询流程后继续调用【撤销订单API】撤销支付交易。
+                String tradeState = orderQueryMap.get("trade_state").toString();
+                if ("NOTPAY".equals(tradeState) || "PAYERROR".equals(tradeState)) {
+                    String result = "";
+                    // 调用撤销订单接口,并接受返回的结果
+                    try{
+                    result =
+                        MyWXPay.cancelOrder(wechatPayConfig.getMerchantId(), wechatPayConfig.getApiCertPath(),
+                        "https://api.mch.weixin.qq.com/secapi/pay/reverse", xmlStr1);
+                        System.out.println("=======================撤销订单返回数据:" + result);
+                    }catch (Exception e){
+                        e.printStackTrace();
+                    }
+                    Map<String, Object> reverseMap = XmlUtil.xmlToMap(result);
+                    String returnCodeForReverse = reverseMap.get("return_code").toString();
+                    String resultCode = reverseMap.get("result_code").toString();
+                    if (WXPayConstants.SUCCESS.equals(returnCodeForReverse) && WXPayConstants.SUCCESS.equals(resultCode)) {
+                        // 如果撤销成功,需要告诉客户端已经撤销订单了
+                        return "用户取消支付或尚未支付,后台已经撤销该订单,请重新支付!";
+                    }
+                }
+            }
+        }
+        return WXPayConstants.FAIL;
+    }
+
+
+    public void processRefund(Map<String, Object> bodyMap) {
+        String decrypt = this.decryptFromResource(bodyMap);
+        Gson gson = new Gson();
+        Map<String,Object> map = gson.fromJson(decrypt, HashMap.class);
+        String sn = map.get("out_trade_no").toString();
+        String refundNo = map.get("out_refund_no").toString();
+        String amount =map.get("amount").toString();
+        Map<String,Object> amountMap = gson.fromJson(amount, HashMap.class);
+        String refundPrice = amountMap.get("refund").toString();
+        if(StringUtils.isNotEmpty(sn)){
+            LambdaQueryWrapper<TOrder> query = Wrappers.lambdaQuery();
+            query.eq(TOrder::getSn,sn);
+            TOrder order = orderService.getOne(query);
+            // 已退款
+            if(order.getRefundQuantity() < order.getProductNumber()) {
+                order.setStatus(1);
+            } else {
+                order.setStatus(3);
+            }
+            // 更改订单明细表
+            LambdaQueryWrapper<TOrderDetails> queryWrapper = new LambdaQueryWrapper<>();
+            queryWrapper.eq(TOrderDetails::getOrderSn, sn);
+            // 处理退款中状态的明细
+            queryWrapper.eq(TOrderDetails::getRefundStatus, "4");
+            List<TOrderDetails> tOrderDetails = orderDetailsService.list(queryWrapper);
+            for (TOrderDetails tOrderDetail : tOrderDetails) {
+                Integer refundQuantity = tOrderDetail.getRefundQuantity();
+                Integer productNumber = tOrderDetail.getProductNumber();
+                if(refundQuantity < productNumber) {
+                    // 部分退款
+                    tOrderDetail.setRefundStatus("2");
+                    orderDetailsService.updateById(tOrderDetail);
+                } else {
+                    // 全部退款
+                    tOrderDetail.setRefundStatus("3");
+                    orderDetailsService.updateById(tOrderDetail);
+                }
+            }
+            //退款金额要除以100
+            BigDecimal r4_refundAmount = new BigDecimal(refundPrice).divide(new BigDecimal(100),2,BigDecimal.ROUND_HALF_UP).setScale(2, RoundingMode.HALF_DOWN);
+            BigDecimal refundAmount = order.getRefundAmount();
+            BigDecimal price = order.getPrice();
+            if(refundAmount != null) {
+                if (price.compareTo(refundAmount) == 0) {
+                    order.setRefundAmount(refundAmount);
+                } else {
+                    order.setRefundAmount(refundAmount.add(r4_refundAmount));
+                }
+            } else {
+                order.setRefundAmount(r4_refundAmount);
+            }
+            order.setRefundDate(new Date());
+            order.setModifyDate(new Date());
+            order.setRefundTrxNo(refundNo);
+            try {
+                orderFeign.saveToEs(order);
+            }catch (Exception e) {
+                e.printStackTrace();
+            }finally {
+                orderService.updateById(order);
+            }
+
+        }
+
+    }
 }

+ 80 - 0
src/main/java/com/szwl/utils/MyWXPay.java

@@ -0,0 +1,80 @@
+package com.szwl.utils;
+
+import org.apache.http.HttpEntity;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.ssl.SSLContexts;
+import org.apache.http.util.EntityUtils;
+
+import javax.net.ssl.SSLContext;
+import java.io.FileInputStream;
+import java.security.KeyStore;
+
+public class MyWXPay {
+    private static final String PAY_SUCCESS = "SUCCESS";
+    private static final String PAY_USERPAYING = "USERPAYING";
+
+    private MyWXPay(){}
+
+    /**
+     *
+     * @param mchId
+     * @param url
+     * @param data
+     * @return
+     * @throws Exception
+     */
+    public static String cancelOrder(String mchId, String filepath, String url, String data) throws Exception{
+        /**
+         * 注意PKCS12证书 是从微信商户平台-》账户设置-》 API安全 中下载的
+         */
+
+        KeyStore keyStore  = KeyStore.getInstance("PKCS12");
+        //P12文件目录 证书路径,这里需要你自己修改,linux下还是windows下的根路径
+        FileInputStream instream = new FileInputStream(filepath);
+        try {
+            keyStore.load(instream, mchId.toCharArray());//这里写密码..默认是你的MCHID
+        } finally {
+            instream.close();
+        }
+
+        // Trust own CA and all self-signed certs
+        SSLContext sslcontext = SSLContexts.custom()
+                .loadKeyMaterial(keyStore, mchId.toCharArray())//这里也是写密码的
+                .build();
+        // Allow TLSv1 protocol only
+        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
+                sslcontext,
+                SSLConnectionSocketFactory.getDefaultHostnameVerifier());
+        CloseableHttpClient httpclient = HttpClients.custom()
+                .setSSLSocketFactory(sslsf)
+                .build();
+        try {
+            HttpPost httpost = new HttpPost(url); // 设置响应头信息
+            httpost.addHeader("Connection", "keep-alive");
+            httpost.addHeader("Accept", "*/*");
+            httpost.addHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
+            httpost.addHeader("Host", "api.mch.weixin.qq.com");
+            httpost.addHeader("X-Requested-With", "XMLHttpRequest");
+            httpost.addHeader("Cache-Control", "max-age=0");
+            httpost.addHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0) ");
+            httpost.setEntity(new StringEntity(data, "UTF-8"));
+            CloseableHttpResponse response = httpclient.execute(httpost);
+            try {
+                HttpEntity entity = response.getEntity();
+
+                String jsonStr = EntityUtils.toString(response.getEntity(), "UTF-8");
+                EntityUtils.consume(entity);
+                return jsonStr;
+            } finally {
+                response.close();
+            }
+        } finally {
+            httpclient.close();
+        }
+    }
+}

+ 326 - 0
src/main/java/com/szwl/utils/WXPayUtil.java

@@ -0,0 +1,326 @@
+package com.szwl.utils;
+
+import cn.hutool.core.map.MapUtil;
+import cn.hutool.core.util.StrUtil;
+import com.szwl.constant.WXPayConstants;
+import com.szwl.constant.WXPayConstants.SignType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+import javax.crypto.Mac;
+import javax.crypto.spec.SecretKeySpec;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.io.StringWriter;
+import java.security.MessageDigest;
+import java.security.SecureRandom;
+import java.util.*;
+
+public class WXPayUtil {
+
+    private static final String SYMBOLS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
+
+    private static final Random RANDOM = new SecureRandom();
+
+    /**
+     * XML格式字符串转换为Map
+     *
+     * @param strXML XML字符串
+     * @return XML数据转换后的Map
+     * @throws Exception
+     */
+    public static Map<String, String> xmlToMap(String strXML) throws Exception {
+        try {
+            Map<String, String> data = new HashMap<String, String>();
+            DocumentBuilder documentBuilder = WXPayXmlUtil.newDocumentBuilder();
+            InputStream stream = new ByteArrayInputStream(strXML.getBytes("UTF-8"));
+            org.w3c.dom.Document doc = documentBuilder.parse(stream);
+            doc.getDocumentElement().normalize();
+            NodeList nodeList = doc.getDocumentElement().getChildNodes();
+            for (int idx = 0; idx < nodeList.getLength(); ++idx) {
+                Node node = nodeList.item(idx);
+                if (node.getNodeType() == Node.ELEMENT_NODE) {
+                    org.w3c.dom.Element element = (org.w3c.dom.Element) node;
+                    data.put(element.getNodeName(), element.getTextContent());
+                }
+            }
+            try {
+                stream.close();
+            } catch (Exception ex) {
+                // do nothing
+            }
+            return data;
+        } catch (Exception ex) {
+            WXPayUtil.getLogger().warn("Invalid XML, can not convert to map. Error message: {}. XML content: {}", ex.getMessage(), strXML);
+            throw ex;
+        }
+
+    }
+
+    /**
+     * 将Map转换为XML格式的字符串
+     *
+     * @param data Map类型数据
+     * @return XML格式的字符串
+     * @throws Exception
+     */
+    public static String mapToXml(Map<String, String> data) throws Exception {
+        org.w3c.dom.Document document = WXPayXmlUtil.newDocument();
+        org.w3c.dom.Element root = document.createElement("xml");
+        document.appendChild(root);
+        for (String key: data.keySet()) {
+            String value = data.get(key);
+            if (value == null) {
+                value = "";
+            }
+            value = value.trim();
+            org.w3c.dom.Element filed = document.createElement(key);
+            filed.appendChild(document.createTextNode(value));
+            root.appendChild(filed);
+        }
+        TransformerFactory tf = TransformerFactory.newInstance();
+        Transformer transformer = tf.newTransformer();
+        DOMSource source = new DOMSource(document);
+        transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
+        transformer.setOutputProperty(OutputKeys.INDENT, "yes");
+        StringWriter writer = new StringWriter();
+        StreamResult result = new StreamResult(writer);
+        transformer.transform(source, result);
+        String output = writer.getBuffer().toString(); //.replaceAll("\n|\r", "");
+        try {
+            writer.close();
+        }
+        catch (Exception ex) {
+        }
+        return output;
+    }
+
+
+    /**
+     * 生成带有 sign 的 XML 格式字符串
+     *
+     * @param data Map类型数据
+     * @param key API密钥
+     * @return 含有sign字段的XML
+     */
+//    public static String generateSignedXml(final Map<String, String> data, String key) throws Exception {
+//        return generateSignedXml(data, key, SignType.MD5);
+//    }
+
+    /**
+     * 生成带有 sign 的 XML 格式字符串
+     *
+     * @param data Map类型数据
+     * @param key API密钥
+     * @param signType 签名类型
+     * @return 含有sign字段的XML
+     */
+//    public static String generateSignedXml(final Map<String, String> data, String key, SignType signType) throws Exception {
+//        String sign = generateSignature(data, key, signType);
+//        data.put(WXPayConstants.FIELD_SIGN, sign);
+//        return mapToXml(data);
+//    }
+
+
+    /**
+     * 判断签名是否正确
+     *
+     * @param xmlStr XML格式数据
+     * @param key API密钥
+     * @return 签名是否正确
+     * @throws Exception
+     */
+//    public static boolean isSignatureValid(String xmlStr, String key) throws Exception {
+//        Map<String, String> data = xmlToMap(xmlStr);
+//        if (!data.containsKey(WXPayConstants.FIELD_SIGN) ) {
+//            return false;
+//        }
+//        String sign = data.get(WXPayConstants.FIELD_SIGN);
+//        return generateSignature(data, key).equals(sign);
+//    }
+
+    /**
+     * 判断签名是否正确,必须包含sign字段,否则返回false。使用MD5签名。
+     *
+     * @param data Map类型数据
+     * @param key API密钥
+     * @return 签名是否正确
+     * @throws Exception
+     */
+//    public static boolean isSignatureValid(Map<String, String> data, String key) throws Exception {
+//        return isSignatureValid(data, key, SignType.MD5);
+//    }
+
+    /**
+     * 判断签名是否正确,必须包含sign字段,否则返回false。
+     *
+     * @param data Map类型数据
+     * @param key API密钥
+     * @param signType 签名方式
+     * @return 签名是否正确
+     * @throws Exception
+     */
+//    public static boolean isSignatureValid(Map<String, String> data, String key, SignType signType) throws Exception {
+//        if (!data.containsKey(WXPayConstants.FIELD_SIGN) ) {
+//            return false;
+//        }
+//        String sign = data.get(WXPayConstants.FIELD_SIGN);
+//        return generateSignature(data, key, signType).equals(sign);
+//    }
+
+    /**
+     * 生成签名
+     *
+     * @param data 待签名数据
+     * @param key API密钥
+     * @return 签名
+     */
+    public static String generateSignature(final Map<String, String> data, String key) throws Exception {
+        return generateSignature(data, key, SignType.MD5);
+    }
+
+    /**
+     * 生成签名. 注意,若含有sign_type字段,必须和signType参数保持一致。
+     *
+     * @param data 待签名数据
+     * @param key API密钥
+     * @param signType 签名方式
+     * @return 签名
+     */
+    public static String generateSignature(final Map<String, String> data, String key, SignType signType) throws Exception {
+        Set<String> keySet = data.keySet();
+        String[] keyArray = keySet.toArray(new String[keySet.size()]);
+        Arrays.sort(keyArray);
+        StringBuilder sb = new StringBuilder();
+        for (String k : keyArray) {
+            if (k.equals(WXPayConstants.FIELD_SIGN)) {
+                continue;
+            }
+            if (data.get(k).trim().length() > 0) // 参数值为空,则不参与签名
+                sb.append(k).append("=").append(data.get(k).trim()).append("&");
+        }
+        sb.append("key=").append(key);
+        if (WXPayConstants.SignType.MD5.equals(signType)) {
+            return MD5(sb.toString()).toUpperCase();
+        }
+        else if (SignType.HMACSHA256.equals(signType)) {
+            return HMACSHA256(sb.toString(), key);
+        }
+        else {
+            throw new Exception(String.format("Invalid sign_type: %s", signType));
+        }
+    }
+
+
+    /**
+     * 获取随机字符串 Nonce Str
+     *
+     * @return String 随机字符串
+     */
+    public static String generateNonceStr() {
+        char[] nonceChars = new char[32];
+        for (int index = 0; index < nonceChars.length; ++index) {
+            nonceChars[index] = SYMBOLS.charAt(RANDOM.nextInt(SYMBOLS.length()));
+        }
+        return new String(nonceChars);
+    }
+
+
+    /**
+     * 生成 MD5
+     *
+     * @param data 待处理数据
+     * @return MD5结果
+     */
+    public static String MD5(String data) throws Exception {
+        java.security.MessageDigest md = MessageDigest.getInstance("MD5");
+        byte[] array = md.digest(data.getBytes("UTF-8"));
+        StringBuilder sb = new StringBuilder();
+        for (byte item : array) {
+            sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3));
+        }
+        return sb.toString().toUpperCase();
+    }
+
+    /**
+     * 生成 HMACSHA256
+     * @param data 待处理数据
+     * @param key 密钥
+     * @return 加密结果
+     * @throws Exception
+     */
+    public static String HMACSHA256(String data, String key) throws Exception {
+        Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
+        SecretKeySpec secret_key = new SecretKeySpec(key.getBytes("UTF-8"), "HmacSHA256");
+        sha256_HMAC.init(secret_key);
+        byte[] array = sha256_HMAC.doFinal(data.getBytes("UTF-8"));
+        StringBuilder sb = new StringBuilder();
+        for (byte item : array) {
+            sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3));
+        }
+        return sb.toString().toUpperCase();
+    }
+
+    /**
+     * 参数名ASCII字典序排序a->b->c
+     * 生成字符串末尾拼接商户key去支付的参数不需要商户key只有加密才用到
+     * @param map  这个map里的key没有sign
+     * @param partnerKey 商户key
+     * @return
+     */
+    public static String sortMap(Map<String, String> map, String partnerKey) {
+        if (map == null) {
+            return "";
+        }
+        TreeMap<String, String> sort = MapUtil.sort(map);
+        StringBuffer sb = new StringBuffer();
+        for (Map.Entry<String, String> entry : sort.entrySet()) {
+            //把商户key放到最后拼接
+            if (entry.getKey().equals("key")) {
+                continue;
+            }
+            sb.append(entry.getKey() + "=" + entry.getValue());
+            sb.append("&");
+        }
+        String s = sb.toString();
+        if (s.endsWith("&")) {
+            s = StrUtil.subBefore(s, "&", true);
+        }
+        s += "&key=" + partnerKey;
+        return s;
+    }
+
+
+    /**
+     * 日志
+     * @return
+     */
+    public static Logger getLogger() {
+        Logger logger = LoggerFactory.getLogger("wxpay java sdk");
+        return logger;
+    }
+
+    /**
+     * 获取当前时间戳,单位秒
+     * @return
+     */
+    public static long getCurrentTimestamp() {
+        return System.currentTimeMillis()/1000;
+    }
+
+    /**
+     * 获取当前时间戳,单位毫秒
+     * @return
+     */
+    public static long getCurrentTimestampMs() {
+        return System.currentTimeMillis();
+    }
+}

+ 27 - 0
src/main/java/com/szwl/utils/WXPayXmlUtil.java

@@ -0,0 +1,27 @@
+package com.szwl.utils;
+
+import org.w3c.dom.Document;
+
+import javax.xml.XMLConstants;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+public final class WXPayXmlUtil {
+    public static DocumentBuilder newDocumentBuilder() throws ParserConfigurationException {
+        DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
+        documentBuilderFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
+        documentBuilderFactory.setFeature("http://xml.org/sax/features/external-general-entities", false);
+        documentBuilderFactory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
+        documentBuilderFactory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
+        documentBuilderFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
+        documentBuilderFactory.setXIncludeAware(false);
+        documentBuilderFactory.setExpandEntityReferences(false);
+
+        return documentBuilderFactory.newDocumentBuilder();
+    }
+
+    public static Document newDocument() throws ParserConfigurationException {
+        return newDocumentBuilder().newDocument();
+    }
+}