Jelajahi Sumber

feat:“添加长隆微信支付“

soobin 1 tahun lalu
induk
melakukan
d3c01cc09c

+ 2 - 0
src/main/java/com/szwl/constant/JoinpayConstant.java

@@ -41,6 +41,7 @@ public class JoinpayConstant {
      */
 //    public final static String Notify_Url = "http://pay.sunzee.com.cn:49013/tOrder/notify";
     public final static String Notify_Url = "https://sz.sunzee.com.cn/PAY-SERVER/tOrder/notify";
+    public final static String WECHAT_NOTIFY_URL = "https://sz.sunzee.com.cn/PAY-SERVER/wechatPay/notify";
 //    public final static String Notify_Url = "http://szwltest.sunzee.com.cn:49002/PAY-SERVER/tOrder/notify";
 //    public final static String Notify_Url = "http://slb.sunzee.com.cn/api/order/notify.htm";
 
@@ -59,6 +60,7 @@ public class JoinpayConstant {
      */
     public final static String Notify_Refund_Url = "http://app.sunzee.com.cn/api/order/notifyRefund";
     public final static String Admin_Notify_Refund_Url = "http://app.sunzee.com.cn/api/order/adminNotifyRefund";
+    public final static String WECHAT_NOTIFY_REFUND_URL = "https://sz.sunzee.com.cn/PAY-SERVER/wechatPay/notify";
 
 
     /**

+ 92 - 2
src/main/java/com/szwl/controller/TOrderController.java

@@ -1130,7 +1130,6 @@ public class TOrderController {
                         } else {
                             price1 = productPrice.multiply(discount).divide(new BigDecimal(10)).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);
                     }
@@ -2986,7 +2985,8 @@ public class TOrderController {
                     if (paySuccess.equals("success")) {
                         order.setIsNotified("1");
                     }
-                }            }
+                }
+            }
             orderService.updateById(order);
 //            equipmentService.sentMessage(equipment.getClientId(), PushUtils.buildJson("pay_success", kindData.toString()).toString());
             try {
@@ -4713,5 +4713,95 @@ public class TOrderController {
         return altInfo.toString();
     }
 
+    /**
+     * 汇聚查询退款更新订单状态
+     *
+     * @param sn  订单号
+     * @param refundTrxNo 退款流水号
+     * @return
+     */
+        @RequestMapping(value = "/queryRefund", method = RequestMethod.GET)
+    @ResponseBody
+    public Object queryRefund(String sn, String refundTrxNo) {
+
+        JSONObject resultJson = orderService.queryRefund(refundTrxNo);
+        String refundStatus = resultJson.getString("ra_Status");
+        System.out.println("退款状态:" + refundStatus);
+
+        LambdaQueryWrapper<TOrder> query = Wrappers.lambdaQuery();
+        query.eq(TOrder::getSn,sn);
+        TOrder order = orderService.getOne(query);
+
+        if (order == null) {
+            return "error";
+        }
+        if (order.getStatus() == 3) {
+            return "success";
+        }
+        if (JoinpayConstant.r6_Status_100.equals(refundStatus)) {
+            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);
+                }
+            }
+            // r4_refundAmount: 退款金额
+            BigDecimal r4_refundAmount = new BigDecimal(resultJson.getString("r3_RefundAmount"));
+            if(order.getRefundMarketingAmount()!=null){
+                r4_refundAmount =r4_refundAmount.add(order.getRefundMarketingAmount());
+            }
+            // price: 订单金额, refundAmount:已退款的金额
+            BigDecimal price = order.getPrice();
+            BigDecimal refundAmount = order.getRefundAmount();
+            TProportion proportion = R.getDataIfSuccess(szwlFeign.getProportion(String.valueOf(order.getEquipmentId())));
+            if(order.getRefundAmount() != null) {
+                BigDecimal newRefundAmount =  refundAmount.add(r4_refundAmount);
+                order.setRefundAmount(refundAmount.add(r4_refundAmount));
+                // 如果小于订单金额
+                if(newRefundAmount.compareTo(price) < 0) {
+                    JSONArray altInfo = getAltInfo(proportion, price.subtract(newRefundAmount));
+                    order.setAltInfo(altInfo.toString());
+                } else {
+                    JSONArray altInfo = getAltInfo(proportion, price);
+                    order.setAltInfo(altInfo.toString());
+                }
+            } else {
+                order.setRefundAmount(r4_refundAmount);
+                if(r4_refundAmount.compareTo(price) < 0) {
+                    JSONArray altInfo = getAltInfo(proportion, price.subtract(r4_refundAmount));
+                    order.setAltInfo(altInfo.toString());
+                }
+            }
+            
+            try {
+                esTOrderService.updateDataById(order);
+            }catch (Exception e) {
+                e.printStackTrace();
+            }finally {
+                orderService.updateById(order);
+            }
+            return "success";
+        }
+        return "success";
+    }
+
 }
 

+ 513 - 0
src/main/java/com/szwl/controller/TWechatPayConfigController.java

@@ -0,0 +1,513 @@
+package com.szwl.controller;
+
+
+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.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.model.utils.PushUtils;
+import com.szwl.service.*;
+import com.szwl.utils.HuifuUtils;
+import com.szwl.utils.IDGenerator;
+import com.szwl.weixin.util.HttpUtils;
+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 io.swagger.annotations.ApiOperation;
+import org.apache.commons.lang.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.*;
+
+import static com.wechat.pay.java.service.refund.model.Status.PROCESSING;
+
+/**
+ * <p>
+ *  前端控制器
+ * </p>
+ *
+ * @author wuhs
+ * @since 2024-03-07
+ */
+@RestController
+@RequestMapping("/wechatPay")
+public class TWechatPayConfigController {
+
+    @Autowired
+    SzwlFeign szwlFeign;
+
+    @Autowired
+    OrderFeign orderFeign;
+
+    @Autowired
+    TOrderService orderService;
+
+    @Autowired
+    TWeixinPayConfigService weixinPayConfigService;
+
+    @Autowired
+    TWechatPayConfigService wechatPayConfigService;
+
+    @Autowired
+    TEquipmentService equipmentService;
+
+    @Autowired
+    TOrderDetailsService orderDetailsService;
+
+    @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());
+
+        // 订单明细表
+        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());
+    }
+
+    /**
+     * 处理微信支付成功回调的通知。
+     *
+     * @param request HttpServletRequest对象,用于接收来自微信的支付通知数据。
+     * @return 返回处理结果,"success"表示处理成功,"fail"表示处理失败。
+     */
+    @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";
+    }
+
+    /**
+     * 发起退款
+     * @return
+     */
+    @PostMapping("/refund")
+    public ResponseModel<?> refund(@RequestBody TOrder torder){
+        // 退款金额: refusePrice
+        BigDecimal refusePrice = torder.getPrice().setScale(2, RoundingMode.HALF_DOWN);
+        // 退款数量: refundNumber
+        Integer refundNumber = torder.getProductNumber();
+        // 退款明细: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);
+            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);
+                }
+            }
+//            if(refundReason != null){
+//                order.setRefundReason(refundReason);
+//                orderService.update(order);
+//            }
+            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);
+        return R.ok(result);
+    }
+}
+

+ 321 - 321
src/main/java/com/szwl/controller/TWeixinPayController.java

@@ -60,333 +60,333 @@ public class TWeixinPayController {
     TEquipmentService equipmentService;
 
 
-    @ApiOperation(value = "购物车 请求在线支付 ")
-    @PostMapping("/carsPay")
-    public Object carsPay(String clientId, @RequestBody Map<String,String> productNameMap) {
-        if(productNameMap==null){
-            return  JsonMessage.error("数据出错");
-        }
-        StringBuffer productName1 = new StringBuffer();
-        StringBuffer note = new StringBuffer();
-        StringBuffer productName = new StringBuffer();
-        TEquipment equipment = R.getDataIfSuccess(szwlFeign.findEquipmentByClientId(clientId));
-        if(equipment==null||equipment.getId()==null){
-            return JsonMessage.error("找不到设备");
-        }
-        BigDecimal price = new BigDecimal("0.00");
-//        JSONObject mapList = JSON.parseObject(productNameMap);
-        TEquipmentDesc equipmentDesc = R.getDataIfSuccess(szwlFeign.findEquipmentById(equipment.getId()));
-        if(equipmentDesc==null||equipmentDesc.getEquipmentId()==null||equipmentDesc.getPayType()==null||equipmentDesc.getPayType().equals("0")){
-            //1,type=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();
-//                            TPromoCode tPromoCode = R.getDataIfSuccess(szwlFeign.selectTPromoCode(code, equipment.getAdminId().toString()));
-                            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];
-                productName.append(productNamea).append(num);
-                note.append(productNamea).append(num).append(":");
-                productName1.append(productNamea).append(num);
-                //确定价格,然后叠加R.getDataIfSuccess(szwlFeign.getProduct(String.valueOf(equipmentId), productName));
-                TProduct product = R.getDataIfSuccess(szwlFeign.getProduct(String.valueOf(equipment.getId()), productNamea));
-                if (product == null) {
-                    return JsonMessage.error("找不到商品");
-                }
-                BigDecimal productPrice = product.getRmbPrice();
-                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(",");
-                }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(",");
-                }
-            }
-        }else {
-            //2,type=1,第二件半价
-            //2.1 判定是否有第二件,有多少个第二件半价
-            for (String key : productNameMap.keySet()) {
-//                System.out.println("key= "+ key + " and value= " + productNameMap.get(key));
-                String entryValue = String.valueOf(productNameMap.get(key));
-                List<String> value = JSON.parseArray(entryValue, String.class);
-                String[] productNum = key.split("-");
-                String productNamea = productNum[0];
-                String num = productNum[1];
-                TProduct product = R.getDataIfSuccess(szwlFeign.getProduct(String.valueOf(equipment.getId()), productNamea));
-                BigDecimal productPrice = product.getRmbPrice();
-                productName.append(productNamea).append(num);
-                productName1.append(productNamea).append(num);
-                note.append(productNamea).append(num).append(":");
-                switch (num) {
-                    case "1":
-                        //1个  0个半价
-                        price =price.add(productPrice);
-                        note.append(price).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(",");
-                        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(",");
-                        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(",");
-                        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(",");
-                        break;
-                }
-            }
-        }
-
-        if (equipment == null) {
-            return JsonMessage.error("找不到设备");
-        }
-
-        Long equipmentId = equipment.getId();
-        //查找商品
-//        TProduct product =  R.getDataIfSuccess(szwlFeign.getProduct(String.valueOf(equipmentId), productName.toString()));
-//        if (product == null) {
-//            return JsonMessage.error("找不到商品");
+//    @ApiOperation(value = "购物车 请求在线支付 ")
+//    @PostMapping("/carsPay")
+//    public Object carsPay(String clientId, @RequestBody Map<String,String> productNameMap) {
+//        if(productNameMap==null){
+//            return  JsonMessage.error("数据出错");
+//        }
+//        StringBuffer productName1 = new StringBuffer();
+//        StringBuffer note = new StringBuffer();
+//        StringBuffer productName = new StringBuffer();
+//        TEquipment equipment = R.getDataIfSuccess(szwlFeign.findEquipmentByClientId(clientId));
+//        if(equipment==null||equipment.getId()==null){
+//            return JsonMessage.error("找不到设备");
+//        }
+//        BigDecimal price = new BigDecimal("0.00");
+////        JSONObject mapList = JSON.parseObject(productNameMap);
+//        TEquipmentDesc equipmentDesc = R.getDataIfSuccess(szwlFeign.findEquipmentById(equipment.getId()));
+//        if(equipmentDesc==null||equipmentDesc.getEquipmentId()==null||equipmentDesc.getPayType()==null||equipmentDesc.getPayType().equals("0")){
+//            //1,type=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();
+////                            TPromoCode tPromoCode = R.getDataIfSuccess(szwlFeign.selectTPromoCode(code, equipment.getAdminId().toString()));
+//                            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];
+//                productName.append(productNamea).append(num);
+//                note.append(productNamea).append(num).append(":");
+//                productName1.append(productNamea).append(num);
+//                //确定价格,然后叠加R.getDataIfSuccess(szwlFeign.getProduct(String.valueOf(equipmentId), productName));
+//                TProduct product = R.getDataIfSuccess(szwlFeign.getProduct(String.valueOf(equipment.getId()), productNamea));
+//                if (product == null) {
+//                    return JsonMessage.error("找不到商品");
+//                }
+//                BigDecimal productPrice = product.getRmbPrice();
+//                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(",");
+//                }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(",");
+//                }
+//            }
+//        }else {
+//            //2,type=1,第二件半价
+//            //2.1 判定是否有第二件,有多少个第二件半价
+//            for (String key : productNameMap.keySet()) {
+////                System.out.println("key= "+ key + " and value= " + productNameMap.get(key));
+//                String entryValue = String.valueOf(productNameMap.get(key));
+//                List<String> value = JSON.parseArray(entryValue, String.class);
+//                String[] productNum = key.split("-");
+//                String productNamea = productNum[0];
+//                String num = productNum[1];
+//                TProduct product = R.getDataIfSuccess(szwlFeign.getProduct(String.valueOf(equipment.getId()), productNamea));
+//                BigDecimal productPrice = product.getRmbPrice();
+//                productName.append(productNamea).append(num);
+//                productName1.append(productNamea).append(num);
+//                note.append(productNamea).append(num).append(":");
+//                switch (num) {
+//                    case "1":
+//                        //1个  0个半价
+//                        price =price.add(productPrice);
+//                        note.append(price).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(",");
+//                        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(",");
+//                        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(",");
+//                        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(",");
+//                        break;
+//                }
+//            }
+//        }
+//
+//        if (equipment == null) {
+//            return JsonMessage.error("找不到设备");
+//        }
+//
+//        Long equipmentId = equipment.getId();
+//        //查找商品
+////        TProduct product =  R.getDataIfSuccess(szwlFeign.getProduct(String.valueOf(equipmentId), productName.toString()));
+////        if (product == null) {
+////            return JsonMessage.error("找不到商品");
+////        }
+//
+//        if (BigDecimal.ZERO.compareTo(price) >= 0) {
+//            return JsonMessage.error("商品价格异常");
+//        }
+//        Long client6 = Long.parseLong(clientId.substring(clientId.length() - 6));
+//        String sn1 = orderService.initSn(client6);
+//        //获取分销  关联设备
+//        TAdmin admin = R.getDataIfSuccess(szwlFeign.getAdmin(String.valueOf(equipment.getAdminId())));
+//        if (admin == null) {
+//            return JsonMessage.error("找不到设备商家");
+//        }
+//        JSONArray altInfo = new JSONArray();
+//        String orderNo1 = sn1;
+//        BigDecimal amount = price.setScale(2, RoundingMode.HALF_DOWN);
+//        amount = amount.multiply(new BigDecimal(100));
+//        String notifyUrl = JoinpayConstant.Notify_Url;
+//        String frpCode1 = "WEIXIN_NATIVE";
+//        TOrder order = new TOrder();
+//        order.setId(IDGenerator.orderID());
+//        order.setCreateDate(new Date());
+//        order.setModifyDate(new Date());
+//        order.setAdminId(admin.getId());
+//        order.setSn(sn1);
+//        order.setProductName(productName.toString());
+//        order.setPrice(price);
+//        order.setClientId(equipment.getClientId());
+//        order.setEquipmentId(equipmentId);
+//        order.setFrpCode(frpCode1);
+//        order.setAltInfo(altInfo.toString());
+//        order.setStatus(0);
+//        String payPlatform = "3";
+//        order.setPayPlatform(payPlatform);
+//        if(StringUtils.isNotEmpty(payPlatform)&&payPlatform.equals("1")){
+//            order.setIsSettlement("0");
+//        }
+//        order.setNote(note.toString());
+//        orderService.save(order);
+//        Iterator<Object> iterator = altInfo.iterator();
+//        while (iterator.hasNext()) {
+//            JSONObject jsonObject = (JSONObject) iterator.next();
+//            String altAmount = jsonObject.getString("altAmount");
+//            if (altAmount.equals("0.00")) {
+//                iterator.remove();
+//            }
+//        }
+//
+//        String result = null;
+//
+//            try {
+//                result = orderService.weixinPay(
+//                        orderNo1, amount, productName.toString(), admin.getId(), notifyUrl
+//                );
+//            } catch (Exception e) {
+//                e.printStackTrace();
+//                return JsonMessage.error("申请支付失败");
+//            }
+//            // 微信支付支付申请返回支付二维码图片
+//            JSONObject kindData = new JSONObject();
+//            kindData.put("sn", sn1);
+//            kindData.put("code_url", result);
+//            return JsonMessage.success(kindData.toString());
 //        }
-
-        if (BigDecimal.ZERO.compareTo(price) >= 0) {
-            return JsonMessage.error("商品价格异常");
-        }
-        Long client6 = Long.parseLong(clientId.substring(clientId.length() - 6));
-        String sn1 = orderService.initSn(client6);
-        //获取分销  关联设备
-        TAdmin admin = R.getDataIfSuccess(szwlFeign.getAdmin(String.valueOf(equipment.getAdminId())));
-        if (admin == null) {
-            return JsonMessage.error("找不到设备商家");
-        }
-        JSONArray altInfo = new JSONArray();
-        String orderNo1 = sn1;
-        BigDecimal amount = price.setScale(2, RoundingMode.HALF_DOWN);
-        amount = amount.multiply(new BigDecimal(100));
-        String notifyUrl = JoinpayConstant.Notify_Url;
-        String frpCode1 = "WEIXIN_NATIVE";
-        TOrder order = new TOrder();
-        order.setId(IDGenerator.orderID());
-        order.setCreateDate(new Date());
-        order.setModifyDate(new Date());
-        order.setAdminId(admin.getId());
-        order.setSn(sn1);
-        order.setProductName(productName.toString());
-        order.setPrice(price);
-        order.setClientId(equipment.getClientId());
-        order.setEquipmentId(equipmentId);
-        order.setFrpCode(frpCode1);
-        order.setAltInfo(altInfo.toString());
-        order.setStatus(0);
-        String payPlatform = "3";
-        order.setPayPlatform(payPlatform);
-        if(StringUtils.isNotEmpty(payPlatform)&&payPlatform.equals("1")){
-            order.setIsSettlement("0");
-        }
-        order.setNote(note.toString());
-        orderService.save(order);
-        Iterator<Object> iterator = altInfo.iterator();
-        while (iterator.hasNext()) {
-            JSONObject jsonObject = (JSONObject) iterator.next();
-            String altAmount = jsonObject.getString("altAmount");
-            if (altAmount.equals("0.00")) {
-                iterator.remove();
-            }
-        }
-
-        String result = null;
-
-            try {
-                result = orderService.weixinPay(
-                        orderNo1, amount, productName.toString(), admin.getId(), notifyUrl
-                );
-            } catch (Exception e) {
-                e.printStackTrace();
-                return JsonMessage.error("申请支付失败");
-            }
-            // 微信支付支付申请返回支付二维码图片
-            JSONObject kindData = new JSONObject();
-            kindData.put("sn", sn1);
-            kindData.put("code_url", result);
-            return JsonMessage.success(kindData.toString());
-        }
     /**
      * 成功回调  微信
      *
      * @return
      */
-    @RequestMapping(value = "/notify", method = RequestMethod.POST)
-    @ResponseBody
-    public Object notify(HttpServletRequest request, HttpServletResponse response) {
-        Gson gson = new Gson();
-        //应答对象
-        Map<String, String> map = new HashMap<>();
-        String body = HttpUtils.readData(request);
-        Map<String, Object> bodyMap = gson.fromJson(body, HashMap.class);
-        //处理支付回调成功的订单
-        String plainText = weixinPayConfigService.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);
-                TOrder order = orderService.getOne(query);
-                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) {
-                    //LOGGER.error("时间转换错误, string = {}", s, e);
-                }
-                order.setPayDate(date);
-                order.setTrxNo(resultJson.getString("transaction_id"));
-                orderService.updateById(order);
-                TEquipment byClientId = R.getDataIfSuccess(szwlFeign.findEquipmentByClientId(order.getClientId()));
-                JSONObject kindData = new JSONObject();
-                kindData.put("sn", order.getSn());
-                kindData.put("productName", order.getProductName());
-                equipmentService.sentMessage(byClientId.getClientId(), PushUtils.buildJson("pay_success", kindData.toString()).toString());
-            }
-        }
-        return "success";
-    }
+//    @RequestMapping(value = "/notify", method = RequestMethod.POST)
+//    @ResponseBody
+//    public Object notify(HttpServletRequest request, HttpServletResponse response) {
+//        Gson gson = new Gson();
+//        //应答对象
+//        Map<String, String> map = new HashMap<>();
+//        String body = HttpUtils.readData(request);
+//        Map<String, Object> bodyMap = gson.fromJson(body, HashMap.class);
+//        //处理支付回调成功的订单
+//        String plainText = weixinPayConfigService.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);
+//                TOrder order = orderService.getOne(query);
+//                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) {
+//                    //LOGGER.error("时间转换错误, string = {}", s, e);
+//                }
+//                order.setPayDate(date);
+//                order.setTrxNo(resultJson.getString("transaction_id"));
+//                orderService.updateById(order);
+//                TEquipment byClientId = R.getDataIfSuccess(szwlFeign.findEquipmentByClientId(order.getClientId()));
+//                JSONObject kindData = new JSONObject();
+//                kindData.put("sn", order.getSn());
+//                kindData.put("productName", order.getProductName());
+//                equipmentService.sentMessage(byClientId.getClientId(), PushUtils.buildJson("pay_success", kindData.toString()).toString());
+//            }
+//        }
+//        return "success";
+//    }
 
-    @ApiOperation(value = "退款")
-    @GetMapping("/refund")
-    ResponseModel<String> refund(@RequestParam String sn,@RequestParam BigDecimal refusePrice){
-        if(StringUtils.isEmpty(sn)){
-            return R.fail("订单为空/error");
-        }
-        LambdaQueryWrapper<TOrder> query = Wrappers.lambdaQuery();
-        query.eq(TOrder::getSn,sn);
-        query.eq(TOrder::getStatus,1);
-        TOrder order = orderService.getOne(query);
-        if(order==null){
-            return R.fail("订单为空/error");
-        }
-        CreateRequest createRequest = new CreateRequest();
-        createRequest.setOutTradeNo(order.getSn());
-        AmountReq amount = new AmountReq();
-        amount.setRefund(refusePrice.multiply(new BigDecimal(100)).longValue());
-        if(order.getRefundAmount()!=null){
-            BigDecimal refusep = order.getPrice().add(order.getRefundAmount()).multiply(new BigDecimal(100));
-            amount.setTotal(refusep.longValue());
-        }else {
-            BigDecimal multiply = order.getPrice().multiply(new BigDecimal(100));
-            amount.setTotal(multiply.longValue());
-        }
-        amount.setCurrency("CNY");
-        createRequest.setAmount(amount);
-        Long client6 = Long.parseLong(order.getClientId().substring(order.getClientId().length() - 6));
-        String refundNo = orderService.initSn(client6);
-        createRequest.setOutRefundNo(refundNo);
-        createRequest.setNotifyUrl("https://app.sunzee.com.cn/PAY-SERVER/tWeixinPay/refundNotify");
-//        createRequest.setNotifyUrl("http://mianhuatang.gz2vip.91tunnel.com/tWeixinPay/refundNotify");
-//        createRequest.setNotifyUrl("http://soobin.5gzvip.91tunnel.com/tWeixinPay/refundNotify");
-        Refund refund = orderService.weixinRefundApi(createRequest,order.getAdminId());
-        System.out.println("退款参数"+refund.toString());
-        if(refund.getStatus()==PROCESSING){
-            return  R.ok("退款申请中,请30秒后再查询");
-        }else {
-            return  R.ok("退款失败,请重试");
-        }
-    };
-    @ApiOperation(value = "退款成功回调")
-    @PostMapping("/refundNotify")
-    ResponseModel<String> refundNotify(HttpServletRequest request, HttpServletResponse response){
-        String result = orderService.weixinRefund(request,response);
-        return R.ok(result);
-    };
+//    @ApiOperation(value = "退款")
+//    @GetMapping("/refund")
+//    ResponseModel<String> refund(@RequestParam String sn,@RequestParam BigDecimal refusePrice){
+//        if(StringUtils.isEmpty(sn)){
+//            return R.fail("订单为空/error");
+//        }
+//        LambdaQueryWrapper<TOrder> query = Wrappers.lambdaQuery();
+//        query.eq(TOrder::getSn,sn);
+//        query.eq(TOrder::getStatus,1);
+//        TOrder order = orderService.getOne(query);
+//        if(order==null){
+//            return R.fail("订单为空/error");
+//        }
+//        CreateRequest createRequest = new CreateRequest();
+//        createRequest.setOutTradeNo(order.getSn());
+//        AmountReq amount = new AmountReq();
+//        amount.setRefund(refusePrice.multiply(new BigDecimal(100)).longValue());
+//        if(order.getRefundAmount()!=null){
+//            BigDecimal refusep = order.getPrice().add(order.getRefundAmount()).multiply(new BigDecimal(100));
+//            amount.setTotal(refusep.longValue());
+//        }else {
+//            BigDecimal multiply = order.getPrice().multiply(new BigDecimal(100));
+//            amount.setTotal(multiply.longValue());
+//        }
+//        amount.setCurrency("CNY");
+//        createRequest.setAmount(amount);
+//        Long client6 = Long.parseLong(order.getClientId().substring(order.getClientId().length() - 6));
+//        String refundNo = orderService.initSn(client6);
+//        createRequest.setOutRefundNo(refundNo);
+//        createRequest.setNotifyUrl("https://app.sunzee.com.cn/PAY-SERVER/tWeixinPay/refundNotify");
+////        createRequest.setNotifyUrl("http://mianhuatang.gz2vip.91tunnel.com/tWeixinPay/refundNotify");
+////        createRequest.setNotifyUrl("http://soobin.5gzvip.91tunnel.com/tWeixinPay/refundNotify");
+//        Refund refund = orderService.weixinRefundApi(createRequest, order.getAdminId());
+//        System.out.println("退款参数"+refund.toString());
+//        if(refund.getStatus()==PROCESSING){
+//            return  R.ok("退款申请中,请30秒后再查询");
+//        }else {
+//            return  R.ok("退款失败,请重试");
+//        }
+//    };
+//    @ApiOperation(value = "退款成功回调")
+//    @PostMapping("/refundNotify")
+//    ResponseModel<String> refundNotify(HttpServletRequest request, HttpServletResponse response){
+//        String result = orderService.wechatRefund(request,response);
+//        return R.ok(result);
+//    };
 }
 

+ 16 - 0
src/main/java/com/szwl/mapper/TWechatPayConfigMapper.java

@@ -0,0 +1,16 @@
+package com.szwl.mapper;
+
+import com.szwl.model.entity.TWechatPayConfig;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+ * <p>
+ *  Mapper 接口
+ * </p>
+ *
+ * @author wuhs
+ * @since 2024-03-07
+ */
+public interface TWechatPayConfigMapper extends BaseMapper<TWechatPayConfig> {
+
+}

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

@@ -34,6 +34,7 @@
         <result column="pay_platform" property="payPlatform" />
         <result column="relation_admin_id" property="relationAdminId" />
         <result column="company_type" property="companyType" />
+        <result column="wechat_pay_id" property="wechatPayId" />
     </resultMap>
 
     <!-- 通用查询结果列 -->
@@ -42,7 +43,7 @@
         locked_date, login_date, login_failure_count, login_ip, trade_merchant_no, name,
         parent_id, password, notice_id, type, username, phone, is_refund, if_foreign, open,
         promo_code_open, apply_start_time, apply_end_time, code, pay_platform, relation_admin_id,
-        company_type
+        company_type, wechat_pay_id
     </sql>
 
 </mapper>

+ 24 - 0
src/main/java/com/szwl/mapper/xml/TWechatPayConfigMapper.xml

@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.szwl.mapper.TWechatPayConfigMapper">
+
+    <!-- 通用查询映射结果 -->
+    <resultMap id="BaseResultMap" type="com.szwl.model.entity.TWechatPayConfig">
+        <id column="id" property="id" />
+        <result column="create_date" property="createDate" />
+        <result column="modify_date" property="modifyDate" />
+        <result column="merchant_id" property="merchantId" />
+        <result column="private_key_path" property="privateKeyPath" />
+        <result column="merchant_serial_number" property="merchantSerialNumber" />
+        <result column="app_id" property="appId" />
+        <result column="apiv3key" property="apiv3key" />
+        <result column="apiv2key" property="apiv2key" />
+        <result column="merchant_name" property="merchantName" />
+    </resultMap>
+
+    <!-- 通用查询结果列 -->
+    <sql id="Base_Column_List">
+        id, create_date, modify_date, merchant_id, private_key_path, merchant_serial_number, app_id, apiv3key, apiv2key, merchant_name
+    </sql>
+
+</mapper>

+ 3 - 0
src/main/java/com/szwl/model/entity/TAdmin.java

@@ -112,6 +112,9 @@ public class TAdmin implements Serializable {
     @ApiModelProperty(value = "公司平台,0或空为申泽,1为七云")
     private String companyType;
 
+    @ApiModelProperty(value = "微信支付配置ID")
+    private Long wechatPayId;
+
     @Transient
     public String getManagerId() {
 

+ 56 - 0
src/main/java/com/szwl/model/entity/TWechatPayConfig.java

@@ -0,0 +1,56 @@
+package com.szwl.model.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import java.util.Date;
+import com.baomidou.mybatisplus.annotation.TableId;
+import java.io.Serializable;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * <p>
+ * 
+ * </p>
+ *
+ * @author wuhs
+ * @since 2024-03-07
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@ApiModel(value="TWechatPayConfig对象", description="")
+public class TWechatPayConfig implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    private Date createDate;
+
+    private Date modifyDate;
+
+    @ApiModelProperty(value = "商户号")
+    private String merchantId;
+
+    @ApiModelProperty(value = "商户API私钥路径")
+    private String privateKeyPath;
+
+    @ApiModelProperty(value = "商户证书序列号")
+    private String merchantSerialNumber;
+
+    @ApiModelProperty(value = "微信公众号/小程序的APPID")
+    private String appId;
+
+    @ApiModelProperty(value = "商户v3密钥")
+    private String apiv3key;
+
+    @ApiModelProperty(value = "商户v2密钥")
+    private String apiv2key;
+
+    @ApiModelProperty(value = "商户名称")
+    private String merchantName;
+
+
+}

+ 36 - 0
src/main/java/com/szwl/model/utils/HttpClientUtils.java

@@ -34,6 +34,7 @@ import org.json.JSONObject;
 import org.json.JSONTokener;
 
 import javax.net.ssl.SSLContext;
+import javax.servlet.http.HttpServletRequest;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
@@ -180,6 +181,41 @@ public final static String Equipment_Url = "http://app.sunzee.com.cn/ShenzeeServ
         return status;
 //        return mres;
     }
+
+    /**
+     * 从request中获取请求方IP
+     * @param request
+     * @return
+     */
+    public static String getIpAddress(HttpServletRequest request) {
+        String ip = request.getHeader("x-forwarded-for");
+        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
+            ip = request.getHeader("Proxy-Client-IP");
+        }
+        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
+            ip = request.getHeader("WL-Proxy-Client-IP");
+        }
+        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
+            ip = request.getHeader("HTTP_CLIENT_IP");
+        }
+        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
+            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
+        }
+        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
+            // 若以上方式均为获取到ip则证明获得客户端并没有采用反向代理直接使用getRemoteAddr()获取客户端的ip地址
+            ip = request.getRemoteAddr();
+        }
+        // 多个路由时,取第一个非unknown的ip
+        final String[] arr = ip.split(",");
+        for (final String str : arr) {
+            if (!"unknown".equalsIgnoreCase(str)) {
+                ip = str;
+                break;
+            }
+        }
+        return ip;
+    }
+
     /**
      * post 键值对
      *

+ 8 - 5
src/main/java/com/szwl/service/TOrderService.java

@@ -1,14 +1,13 @@
 package com.szwl.service;
 
-import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
 import com.szwl.model.entity.TOrder;
 import com.baomidou.mybatisplus.extension.service.IService;
-import com.szwl.weixin.refund.model.CreateRequest;
+import com.wechat.pay.java.service.refund.model.CreateRequest;
 import com.wechat.pay.java.service.refund.model.Refund;
 
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
-import java.io.UnsupportedEncodingException;
 import java.math.BigDecimal;
 
 /**
@@ -28,14 +27,16 @@ public interface TOrderService extends IService<TOrder> {
     /**
      * 发起微信支付
      */
-    String weixinPay(String orderNo1, BigDecimal amount, String productName, Long id, String notifyUrl);
+    String wechatPay(String sn, BigDecimal amount, String productName, Long id, String notifyUrl, String clientId,HttpServletRequest request);
+
     /**
      * 处理退款回调通知
      * @param request
      * @param response
      * @return
      */
-    String weixinRefund(HttpServletRequest request, HttpServletResponse response);
+    String wechatRefund(HttpServletRequest request, HttpServletResponse response);
+
     /**
      * 发起退款
      * @param
@@ -43,4 +44,6 @@ public interface TOrderService extends IService<TOrder> {
      * @return
      */
     Refund weixinRefundApi(CreateRequest createRequest, Long adminId);
+
+    JSONObject queryRefund(String refundTrxNo);
 }

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

@@ -0,0 +1,26 @@
+package com.szwl.service;
+
+import com.szwl.model.entity.TWechatPayConfig;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.wechat.pay.java.core.Config;
+
+
+import java.util.Map;
+
+/**
+ * <p>
+ *  服务类
+ * </p>
+ *
+ * @author wuhs
+ * @since 2024-03-07
+ */
+public interface TWechatPayConfigService extends IService<TWechatPayConfig> {
+
+    Config getWechatConfig(Long id);
+
+    void initConfig(Long id);
+
+    String decryptFromResource(Map<String, Object> bodyMap);
+
+}

+ 7 - 8
src/main/java/com/szwl/service/impl/NativePayService.java

@@ -12,20 +12,19 @@
 package com.szwl.service.impl;
 
 
-import com.szwl.weixin.core.Config;
-import com.szwl.weixin.http.*;
-import com.szwl.weixin.model.Transaction;
-import com.szwl.weixin.nativepay.model.*;
-import com.szwl.weixin.refund.model.CreateRequest;
+import com.wechat.pay.java.core.Config;
 import com.wechat.pay.java.core.exception.HttpException;
 import com.wechat.pay.java.core.exception.MalformedMessageException;
 import com.wechat.pay.java.core.exception.ServiceException;
 import com.wechat.pay.java.core.exception.ValidationException;
-import com.wechat.pay.java.core.util.GsonUtil;
+import com.wechat.pay.java.core.http.*;
+import com.wechat.pay.java.service.payments.model.Transaction;
+import com.wechat.pay.java.service.payments.nativepay.model.*;
+import com.wechat.pay.java.service.refund.model.CreateRequest;
 import com.wechat.pay.java.service.refund.model.Refund;
 
-import static com.szwl.weixin.http.UrlEncoder.urlEncode;
-import static com.szwl.weixin.util.GsonUtil.toJson;
+import static com.wechat.pay.java.core.http.UrlEncoder.urlEncode;
+import static com.wechat.pay.java.core.util.GsonUtil.toJson;
 import static java.util.Objects.requireNonNull;
 
 /** NativePayService服务 */

+ 134 - 97
src/main/java/com/szwl/service/impl/TOrderServiceImpl.java

@@ -1,42 +1,42 @@
 package com.szwl.service.impl;
 
+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.feign.bean.OrderFeign;
 import com.szwl.model.entity.TOrder;
 import com.szwl.mapper.TOrderMapper;
-import com.szwl.model.entity.TWeixinPayConfig;
-import com.szwl.service.TOrderService;
+import com.szwl.model.entity.TOrderDetails;
+import com.szwl.model.entity.TWechatPayConfig;
+import com.szwl.model.utils.HttpClientUtils;
+import com.szwl.service.*;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.szwl.service.TWeixinPayConfigService;
-import com.szwl.weixin.core.NativeWeChatPay2Validator;
-import com.szwl.weixin.nativepay.model.Amount;
-import com.szwl.weixin.nativepay.model.PrepayRequest;
-import com.szwl.weixin.nativepay.model.PrepayResponse;
-import com.szwl.weixin.core.Config;
-import com.szwl.weixin.refund.model.CreateRequest;
 import com.szwl.weixin.util.HttpUtils;
-import com.wechat.pay.contrib.apache.httpclient.auth.Verifier;
-import com.wechat.pay.java.core.exception.HttpException;
-import com.wechat.pay.java.core.exception.MalformedMessageException;
-import com.wechat.pay.java.core.exception.ServiceException;
-import com.wechat.pay.java.core.exception.ValidationException;
-import com.wechat.pay.java.core.http.*;
+import com.wechat.pay.java.core.Config;
+import com.wechat.pay.java.service.payments.nativepay.model.Amount;
+import com.wechat.pay.java.service.payments.nativepay.model.PrepayRequest;
+import com.wechat.pay.java.service.payments.nativepay.model.PrepayResponse;
+import com.wechat.pay.java.service.payments.nativepay.model.SceneInfo;
+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.apache.http.message.BasicNameValuePair;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
+import java.io.UnsupportedEncodingException;
 import java.math.BigDecimal;
 import java.math.RoundingMode;
 import java.text.SimpleDateFormat;
 import java.util.*;
 
-import static com.wechat.pay.java.core.util.GsonUtil.toJson;
-import static java.util.Objects.requireNonNull;
+import static com.szwl.service.impl.TJoinpayMchServiceImpl.createHmacSign;
 
 /**
  * <p>
@@ -51,8 +51,15 @@ public class TOrderServiceImpl extends ServiceImpl<TOrderMapper, TOrder> impleme
 
     @Autowired
     private TWeixinPayConfigService weixinPayConfigService;
-//    @Autowired
-//    private Verifier verifier;
+
+    @Autowired
+    OrderFeign orderFeign;
+
+    @Autowired
+    private TWechatPayConfigService wechatPayConfigService;
+
+    @Autowired
+    private TOrderDetailsService orderDetailsService;
 
     @Override
     public synchronized String initSn(Long equipmentId) {
@@ -78,40 +85,34 @@ public class TOrderServiceImpl extends ServiceImpl<TOrderMapper, TOrder> impleme
     }
 
     @Override
-    public String weixinPay(String orderNo1, BigDecimal amount, String productName, Long id, String notifyUrl) {
-        // 使用自动更新平台证书的RSA配置
-        // 一个商户号只能初始化一个配置,否则会因为重复的下载任务报错
-        LambdaQueryWrapper<TWeixinPayConfig> query = Wrappers.lambdaQuery();
-        query.eq(TWeixinPayConfig::getAdminId,id);
-        TWeixinPayConfig weixinPayConfig = weixinPayConfigService.getOne(query);
-//        Config config =
-//                new RSAAutoCertificateConfig.Builder()
-//                        .merchantId(weixinPayConfig.getMerchantId())
-//                        .privateKeyFromPath(weixinPayConfig.getPrivateKeyPath())
-//                        .merchantSerialNumber(weixinPayConfig.getMerchantSerialNumber())
-//                        .apiV3Key(weixinPayConfig.getApiV3key())
-//                        .build();
-        Config config = weixinPayConfigService.getWechatConfig(String.valueOf(id));
+    public String wechatPay(String sn, BigDecimal amount, String productName, Long id, String notifyUrl, String clientId, HttpServletRequest request) {
+        TWechatPayConfig wechatPayConfig = wechatPayConfigService.getById(id);
+        Config config = wechatPayConfigService.getWechatConfig(id);
         if(config==null){
-            weixinPayConfigService.initConfig(id);
-            config = weixinPayConfigService.getWechatConfig(String.valueOf(id));
+            wechatPayConfigService.initConfig(id);
+            config = wechatPayConfigService.getWechatConfig(id);
         }
         // 构建service
         NativePayService service = new NativePayService.Builder().config(config).build();
-        // request.setXxx(val)设置所需参数,具体参数可见Request定义
-        PrepayRequest request = new PrepayRequest();
+        PrepayRequest payRequest = new PrepayRequest();
         Amount amount1 = new Amount();
         amount1.setTotal(amount.intValue());
-        request.setAmount(amount1);
-        request.setAppid(weixinPayConfig.getAppId());
-        request.setMchid(weixinPayConfig.getMerchantId());
-        request.setDescription(productName);
-        request.setNotifyUrl("https://app.sunzee.com.cn/PAY-SERVER/tWeixinPay/notify");
-//        request.setNotifyUrl("http://mianhuatang.gz2vip.91tunnel.com/tWeixinPay/notify");
-//        request.setNotifyUrl("http://soobin.5gzvip.91tunnel.com/tWeixinPay/notify");
-        request.setOutTradeNo(orderNo1);
+        payRequest.setAmount(amount1);
+        payRequest.setAppid(wechatPayConfig.getAppId());
+        payRequest.setMchid(wechatPayConfig.getMerchantId());
+        payRequest.setDescription(productName);
+        // 添加设备编号
+        String ipAddress = HttpClientUtils.getIpAddress(request);
+        SceneInfo sceneInfo = new SceneInfo();
+        sceneInfo.setPayerClientIp(ipAddress);
+        sceneInfo.setDeviceId(clientId);
+        payRequest.setSceneInfo(sceneInfo);
+
+        payRequest.setNotifyUrl(notifyUrl);
+//        payRequest.setNotifyUrl("http://evxz5m.natappfree.cc/wechatPay/notify");;
+        payRequest.setOutTradeNo(sn);
         // 调用下单方法,得到应答
-        PrepayResponse response = service.prepay(request);
+        PrepayResponse response = service.prepay(payRequest);
         return response.getCodeUrl();
     }
     /**
@@ -121,7 +122,7 @@ public class TOrderServiceImpl extends ServiceImpl<TOrderMapper, TOrder> impleme
      * @return
      */
     @Override
-    public String weixinRefund(HttpServletRequest request, HttpServletResponse response) {
+    public String wechatRefund(HttpServletRequest request, HttpServletResponse response) {
         Gson gson = new Gson();
         Map<String, Object> hashMap = new HashMap<>(3);
 
@@ -129,24 +130,18 @@ public class TOrderServiceImpl extends ServiceImpl<TOrderMapper, TOrder> impleme
             // 处理退款通知参数
             String body = HttpUtils.readData(request);
             Map<String, Object> bodyMap = gson.fromJson(body, HashMap.class);
-            String requestId = (String)bodyMap.get("id");
-//            NativeWeChatPay2Validator nativeWeChatPay2Validator = new NativeWeChatPay2Validator(verifier, requestId, body);
-//            if (!nativeWeChatPay2Validator.validate(request)){
-//                log.error("退款通知验签失败");
-//                //失败应答
-//                response.setStatus(HttpStatus.SC_INTERNAL_SERVER_ERROR);
-//                hashMap.put("code", "ERROR");
-//                hashMap.put("message", "通知验签失败");
-//                return gson.toJson(hashMap);
-//
-//            }
-//            log.info("退款通知验签成功");
-            // 处理退款单
-            processRefund(bodyMap);
-            //成功应答
-            response.setStatus(HttpStatus.SC_OK);
-            hashMap.put("code", "SUCCESS");
-            hashMap.put("message", "成功");
+            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_OK);
+                hashMap.put("code", "FAIL");
+                hashMap.put("message", "系统错误");
+            }
             return gson.toJson(hashMap);
         } catch (Exception e) {
             e.printStackTrace();
@@ -155,13 +150,11 @@ public class TOrderServiceImpl extends ServiceImpl<TOrderMapper, TOrder> impleme
     }
 
     @Override
-    public Refund weixinRefundApi(CreateRequest createRequest, Long adminId) {
-        // 使用自动更新平台证书的RSA配置
-        // 一个商户号只能初始化一个配置,否则会因为重复的下载任务报错
-        Config config = weixinPayConfigService.getWechatConfig(String.valueOf(adminId));
+    public Refund weixinRefundApi(CreateRequest createRequest, Long id) {
+        Config config = wechatPayConfigService.getWechatConfig(id);
         if(config==null){
-            weixinPayConfigService.initConfig(adminId);
-            config = weixinPayConfigService.getWechatConfig(String.valueOf(adminId));
+            wechatPayConfigService.initConfig(id);
+            config = wechatPayConfigService.getWechatConfig(id);
         }
         // 构建service
         NativePayService service = new NativePayService.Builder().config(config).build();
@@ -169,12 +162,41 @@ public class TOrderServiceImpl extends ServiceImpl<TOrderMapper, TOrder> impleme
         return refund;
     }
 
+    /**
+     * 汇聚查询退款状态
+     * @param refundTrxNo
+     * @return
+     */
+    @Override
+    public JSONObject queryRefund(String refundTrxNo) {
+        String url = "https://www.joinpay.com/trade/queryRefund.action";
+
+        List<BasicNameValuePair> data = new ArrayList<BasicNameValuePair>();
+
+        data.add(new BasicNameValuePair("p1_MerchantNo", JoinpayConstant.mch_no));
+        data.add(new BasicNameValuePair("p2_RefundOrderNo", refundTrxNo));
+        data.add(new BasicNameValuePair("p3_Version", "2.1"));
+        String hmac = null;
+        try {
+            hmac = createHmacSign(data, JoinpayConstant.key);
+        } catch (UnsupportedEncodingException e) {
+            e.printStackTrace();
+        }
+        data.add(new BasicNameValuePair("hmac", hmac));
+
+
+        String result = HttpClientUtils.postKeyValue(url, data);
+
+        JSONObject resultJson = JSONObject.parseObject(result);
+        return resultJson;
+    }
+
     public void processRefund(Map<String, Object> bodyMap) {
         String decrypt = weixinPayConfigService.decryptFromResource(bodyMap);
         Gson gson = new Gson();
         Map<String,Object> map = gson.fromJson(decrypt, HashMap.class);
         String sn = map.get("out_trade_no").toString();
-        String transactionId = map.get("transaction_id").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();
@@ -183,37 +205,52 @@ public class TOrderServiceImpl extends ServiceImpl<TOrderMapper, TOrder> impleme
             query.eq(TOrder::getSn,sn);
             TOrder order = getOne(query);
             // 已退款
-            order.setStatus(3);
-            //退款金额要除以100
-            BigDecimal r4_refundAmount = new BigDecimal(refundPrice).divide(new BigDecimal(100),2,BigDecimal.ROUND_HALF_UP).setScale(2, RoundingMode.HALF_DOWN);
-            if(order.getRefundMarketingAmount()!=null){
-                r4_refundAmount =r4_refundAmount.add(order.getRefundMarketingAmount());
-            }
-            BigDecimal price = order.getPrice();
-            if(r4_refundAmount.compareTo(price)==-1){
-                BigDecimal refundAmount = order.getRefundAmount();
-                if(refundAmount!=null){
-                    order.setRefundAmount(refundAmount.add(r4_refundAmount));
-                }else {
-                    // 退款金额
-                    order.setRefundAmount(r4_refundAmount);
-                }
+            if(order.getRefundQuantity() < order.getProductNumber()) {
                 order.setStatus(1);
-                order.setPrice(price.subtract(r4_refundAmount));
+            } else {
+                order.setStatus(3);
             }
-            if(r4_refundAmount.compareTo(price)==0){
-                BigDecimal refundAmount = order.getRefundAmount();
-                if(refundAmount!=null){
-                    order.setRefundAmount(refundAmount.add(r4_refundAmount));
-                    order.setPrice(order.getPrice().add(r4_refundAmount));
-                }else {
-                    // 退款金额
-                    order.setRefundAmount(r4_refundAmount);
+            // 更改订单明细表
+            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);
+//            if(order.getRefundMarketingAmount()!=null){
+//                r4_refundAmount =r4_refundAmount.add(order.getRefundMarketingAmount());
+//            }
+            BigDecimal refundAmount = order.getRefundAmount();
+            if(refundAmount != null) {
+                order.setRefundAmount(refundAmount.add(r4_refundAmount));
+            } else {
+                order.setRefundAmount(r4_refundAmount);
+            }
             order.setRefundDate(new Date());
             order.setModifyDate(new Date());
-            updateById(order);
+            order.setRefundTrxNo(refundNo);
+            try {
+                orderFeign.saveToEs(order);
+            }catch (Exception e) {
+                e.printStackTrace();
+            }finally {
+                updateById(order);
+            }
+
         }
 
     }

+ 83 - 0
src/main/java/com/szwl/service/impl/TWechatPayConfigServiceImpl.java

@@ -0,0 +1,83 @@
+package com.szwl.service.impl;
+
+import com.szwl.model.entity.TWechatPayConfig;
+import com.szwl.mapper.TWechatPayConfigMapper;
+import com.szwl.service.TWechatPayConfigService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.wechat.pay.contrib.apache.httpclient.util.AesUtil;
+import com.wechat.pay.java.core.Config;
+import com.wechat.pay.java.core.RSAAutoCertificateConfig;
+import org.apache.commons.lang.StringUtils;
+import org.springframework.stereotype.Service;
+
+import java.nio.charset.StandardCharsets;
+import java.security.GeneralSecurityException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * <p>
+ *  服务实现类
+ * </p>
+ *
+ * @author wuhs
+ * @since 2024-03-07
+ */
+@Service
+public class TWechatPayConfigServiceImpl extends ServiceImpl<TWechatPayConfigMapper, TWechatPayConfig> implements TWechatPayConfigService {
+
+    public static Map<Long, Config> configMap = new HashMap<>();
+
+    @Override
+    public Config getWechatConfig(Long id) {
+        if(configMap==null){
+            return null;
+        }
+        return configMap.get(id);
+    }
+
+    @Override
+    public void initConfig(Long id) {
+        TWechatPayConfig wechatPayConfig = this.getById(id);
+        Config config =
+            new RSAAutoCertificateConfig.Builder()
+                .merchantId(wechatPayConfig.getMerchantId())
+                .privateKeyFromPath(wechatPayConfig.getPrivateKeyPath())
+                .merchantSerialNumber(wechatPayConfig.getMerchantSerialNumber())
+                .apiV3Key(wechatPayConfig.getApiv3key())
+                .build();
+        configMap.put(wechatPayConfig.getId(), config);
+    }
+
+    @Override
+    public String decryptFromResource(Map<String, Object> bodyMap) {
+        // 通知数据
+        Map<String, String> resourceMap = (Map) bodyMap.get("resource");
+        // 数据密文
+        String ciphertext = resourceMap.get("ciphertext");
+        // 随机串
+        String nonce = resourceMap.get("nonce");
+        // 附加数据
+        String associatedData = resourceMap.get("associated_data");
+
+        List<TWechatPayConfig> list = this.list();
+        String plainText = null;
+        for (TWechatPayConfig wechatPayConfig : list) {
+            if(StringUtils.isEmpty(plainText)){
+                AesUtil aesUtil1 = new
+                        AesUtil(wechatPayConfig.getApiv3key().getBytes(StandardCharsets.UTF_8));
+                try {
+                    plainText = aesUtil1.decryptToString(associatedData.getBytes(StandardCharsets.UTF_8),
+                            nonce.getBytes(StandardCharsets.UTF_8),
+                            ciphertext);
+                } catch (GeneralSecurityException e) {
+                    e.printStackTrace();
+                }
+            } else {
+                break;
+            }
+        }
+        return plainText;
+    }
+}