#51 1017-tag

Birleştirildi
mangpiao mangpiao/master 1 yıl önce içindeki mangpiao/mp-20231016 işlemelerini 369 ile birleştirdi
58 değiştirilmiş dosya ile 2253 ekleme ve 246 silme
  1. 2 1
      README.md
  2. 3 0
      mp-admin/src/main/java/com/qs/mp/handler/auth/WebConfigurer.java
  3. 3 0
      mp-admin/src/main/java/com/qs/mp/web/controller/api/admin/ChannelMgrController.java
  4. 384 0
      mp-admin/src/main/java/com/qs/mp/web/controller/api/callback/YsPayCallBackController.java
  5. 19 0
      mp-admin/src/main/java/com/qs/mp/web/controller/api/channel/ChannelController.java
  6. 168 1
      mp-admin/src/main/java/com/qs/mp/web/controller/api/channel/ChannelWithdrawController.java
  7. 0 77
      mp-admin/src/main/java/com/qs/mp/web/controller/api/user/ChannelController.java
  8. 58 0
      mp-admin/src/main/java/com/qs/mp/web/controller/api/user/UserChannelController.java
  9. 7 2
      mp-admin/src/main/java/com/qs/mp/web/controller/api/user/UserDeliverOrderController.java
  10. 8 3
      mp-admin/src/main/java/com/qs/mp/web/controller/api/user/UserTicketOrderController.java
  11. 15 0
      mp-admin/src/main/resources/application-dev.yml
  12. 35 20
      mp-admin/src/main/resources/application-test.yml
  13. 12 1
      mp-admin/src/main/resources/application.yml
  14. 1 1
      mp-admin/src/main/resources/logback-8091.xml
  15. 1 1
      mp-admin/src/main/resources/logback-spring.xml
  16. 311 20
      mp-admin/src/test/java/com/qs/mp/task/MyTest.java
  17. 7 0
      mp-common/pom.xml
  18. 17 0
      mp-common/src/main/java/com/qs/mp/common/constant/DivisionLogStatusConstants.java
  19. 17 0
      mp-common/src/main/java/com/qs/mp/common/constant/PayConstants.java
  20. 28 0
      mp-common/src/main/java/com/qs/mp/common/constant/YsPayMethodConstants.java
  21. 16 0
      mp-common/src/main/java/com/qs/mp/common/constant/YsServerApiConstants.java
  22. 6 1
      mp-common/src/main/java/com/qs/mp/common/enums/ChannelWithdrawStatusEnum.java
  23. 46 0
      mp-common/src/main/java/com/qs/mp/common/enums/DivisionStatusEnum.java
  24. 2 1
      mp-common/src/main/java/com/qs/mp/common/enums/TicketStatusEnum.java
  25. 52 0
      mp-common/src/main/java/com/qs/mp/common/enums/YsCallBizTypeEnum.java
  26. 91 91
      mp-common/src/main/java/com/qs/mp/common/pulsar/PulsarClientService.java
  27. 3 3
      mp-generator/src/main/java/com/qs/mp/generator/DbGenerator.java
  28. 13 13
      mp-quartz/src/main/java/com/qs/mp/quartz/task/OperateToolTask.java
  29. 1 0
      mp-service/src/main/java/com/qs/mp/admin/service/ITicketAwardsPrizeService.java
  30. 78 0
      mp-service/src/main/java/com/qs/mp/channel/domain/ChannelBank.java
  31. 23 0
      mp-service/src/main/java/com/qs/mp/channel/domain/ChannelBankCard.java
  32. 6 0
      mp-service/src/main/java/com/qs/mp/channel/domain/ChannelWithdraw.java
  33. 34 0
      mp-service/src/main/java/com/qs/mp/channel/domain/param/ChannelBankCardCreateParam.java
  34. 1 1
      mp-service/src/main/java/com/qs/mp/channel/domain/param/ChannelWithdrawParam.java
  35. 1 1
      mp-service/src/main/java/com/qs/mp/channel/domain/param/OrderPayParam.java
  36. 22 0
      mp-service/src/main/java/com/qs/mp/channel/domain/param/UserChannelQrCodeParam.java
  37. 1 0
      mp-service/src/main/java/com/qs/mp/channel/domain/vo/ChannelVO.java
  38. 13 0
      mp-service/src/main/java/com/qs/mp/channel/mapper/ChannelBankMapper.java
  39. 16 0
      mp-service/src/main/java/com/qs/mp/channel/service/IChannelBankService.java
  40. 20 0
      mp-service/src/main/java/com/qs/mp/channel/service/impl/ChannelBankServiceImpl.java
  41. 0 2
      mp-service/src/main/java/com/qs/mp/channel/service/impl/ChannelTicketTransferServiceImpl.java
  42. 113 3
      mp-service/src/main/java/com/qs/mp/channel/service/impl/ChannelWithdrawServiceImpl.java
  43. 97 0
      mp-service/src/main/java/com/qs/mp/common/domain/YsCallLog.java
  44. 13 0
      mp-service/src/main/java/com/qs/mp/common/mapper/YsCallLogMapper.java
  45. 16 0
      mp-service/src/main/java/com/qs/mp/common/service/IYsCallLogService.java
  46. 20 0
      mp-service/src/main/java/com/qs/mp/common/service/impl/YsCallLogServiceImpl.java
  47. 96 0
      mp-service/src/main/java/com/qs/mp/pay/domain/DivisionLog.java
  48. 6 2
      mp-service/src/main/java/com/qs/mp/pay/domain/PayOrder.java
  49. 13 0
      mp-service/src/main/java/com/qs/mp/pay/mapper/DivisionLogMapper.java
  50. 16 0
      mp-service/src/main/java/com/qs/mp/pay/service/IDivisionLogService.java
  51. 19 0
      mp-service/src/main/java/com/qs/mp/pay/service/IWalletService.java
  52. 20 0
      mp-service/src/main/java/com/qs/mp/pay/service/impl/DivisionLogServiceImpl.java
  53. 215 0
      mp-service/src/main/java/com/qs/mp/pay/service/impl/WalletServiceImpl.java
  54. 1 0
      mp-service/src/main/java/com/qs/mp/system/mapper/SysUserRoleMapper.java
  55. 21 0
      mp-service/src/main/resources/mapper/channel/ChannelBankMapper.xml
  56. 22 0
      mp-service/src/main/resources/mapper/common/YsCallLogMapper.xml
  57. 23 0
      mp-service/src/main/resources/mapper/pay/DivisionLogMapper.xml
  58. 1 1
      mp-service/src/main/resources/mapper/system/SysUserRoleMapper.xml

+ 2 - 1
README.md

@@ -1 +1,2 @@
-云管铺
+云管铺
+

+ 3 - 0
mp-admin/src/main/java/com/qs/mp/handler/auth/WebConfigurer.java

@@ -33,6 +33,9 @@ public class WebConfigurer implements WebMvcConfigurer {
             "/service/notify/wxcallback",
             "/service/notify/payCallback",
             "/service/notify/alipayCallback",
+            "/service/notify/ysCallback",
+            "/service/notify/ysDivCallback",
+            "/service/notify/ysWithdrawCallback",
             "/captchaImage");
     }
 

+ 3 - 0
mp-admin/src/main/java/com/qs/mp/web/controller/api/admin/ChannelMgrController.java

@@ -17,6 +17,8 @@ import com.qs.mp.common.core.page.TableDataInfo;
 import com.qs.mp.common.enums.BusinessType;
 import com.qs.mp.common.enums.ChannelRoleEnum;
 import com.qs.mp.common.enums.ErrorCodeEnum;
+import com.qs.mp.system.domain.SysUser;
+import com.qs.mp.system.domain.SysUserRole;
 import com.qs.mp.system.service.ISysUserService;
 import com.qs.mp.user.service.IUserTicketOrderService;
 import com.qs.mp.web.controller.common.BaseApiController;
@@ -31,6 +33,7 @@ import java.util.Map;
 import java.util.stream.Collectors;
 
 import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.stereotype.Component;

+ 384 - 0
mp-admin/src/main/java/com/qs/mp/web/controller/api/callback/YsPayCallBackController.java

@@ -0,0 +1,384 @@
+package com.qs.mp.web.controller.api.callback;
+
+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.conditions.update.LambdaUpdateWrapper;
+import com.baomidou.mybatisplus.core.toolkit.StringUtils;
+import com.eptok.yspay.opensdkjava.common.Constants;
+import com.eptok.yspay.opensdkjava.fund.MercFundApi;
+import com.eptok.yspay.opensdkjava.orderpay.OrderQueryApi;
+import com.eptok.yspay.opensdkjava.pojo.vo.OnlineReqDataVo;
+import com.eptok.yspay.opensdkjava.util.DateUtil;
+import com.eptok.yspay.opensdkjava.util.YsOnlineSignUtils;
+import com.eptok.yspay.opensdkjava.util.YsfSignUtil;
+import com.qs.mp.channel.domain.ChannelWithdraw;
+import com.qs.mp.channel.service.IChannelWithdrawService;
+import com.qs.mp.common.constant.DivisionLogStatusConstants;
+import com.qs.mp.common.constant.YsServerApiConstants;
+import com.qs.mp.common.domain.YsCallLog;
+import com.qs.mp.common.enums.ChannelWithdrawStatusEnum;
+import com.qs.mp.common.enums.DivisionStatusEnum;
+import com.qs.mp.common.enums.PayOrderStatusEnum;
+import com.qs.mp.common.enums.YsCallBizTypeEnum;
+import com.qs.mp.common.service.IYsCallLogService;
+import com.qs.mp.common.utils.LogUtil;
+import com.qs.mp.pay.domain.DivisionLog;
+import com.qs.mp.pay.domain.PayOrder;
+import com.qs.mp.pay.service.IDivisionLogService;
+import com.qs.mp.pay.service.IPayOrderService;
+import com.qs.mp.pay.service.IWalletService;
+import java.io.IOException;
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.bouncycastle.util.test.TestRandomBigInteger;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * 银盛支付回调控制类
+ *
+ * @author Evan
+ * @date 2023/3/28
+ */
+@RestController
+@RequestMapping("/service/notify")
+public class YsPayCallBackController {
+
+    private final Logger logger = LoggerFactory.getLogger(this.getClass().getSimpleName());
+
+
+    @Value("${ys-pay.private-key-path}")
+    private String privateKeyPath;
+
+    @Value("${ys-pay.public-key-path}")
+    private String publicKeyPath;
+
+
+    @Value("${ys-pay.partner-id}")
+    private String partnerId;
+
+    @Value("${ys-pay.private-key-pass}")
+    private String privateKeyPass;
+
+    @Value("${ys-pay.div-notify-url}")
+    private String ysDivNotifyUrl;
+
+
+    @Autowired
+    private IPayOrderService payOrderService;
+
+    @Autowired
+    private IWalletService walletService;
+
+    @Autowired
+    private IYsCallLogService ysCallLogService;
+
+    @Autowired
+    private IDivisionLogService divisionLogService;
+
+    @Autowired
+    private IChannelWithdrawService channelWithdrawService;
+
+
+    @RequestMapping(value = "/ysCallback", method = RequestMethod.POST)
+    public void payCallback(HttpServletRequest request, HttpServletResponse response) throws Exception {
+        Map<String, String[]> reqParams = request.getParameterMap();
+
+        Map<String, String> params = new HashMap<>();
+        for (String key : reqParams.keySet()) {
+            String[] values = reqParams.get(key);
+            String valueStr = "";
+            for (int i = 0; i < values.length; i++) {
+                valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
+            }
+            params.put(key, valueStr);
+        }
+        logger.info("Ys支付回调:{}", JSON.toJSONString(params));
+
+        String sign = params.get("sign");
+        boolean flag = YsOnlineSignUtils.rsaCheckContent(params, sign, Constants.CHARSET_UTF_8, publicKeyPath);
+        if (!flag) {
+            logger.error("ys支付回调-check sign error");
+            responseWrite(response, "fail");
+            return;
+        }
+        String tradeNo = params.get("out_trade_no");
+        String orderNo = params.get("trade_no");
+        String tradeStatus = params.get("trade_status");
+        String completeDate = params.get("notify_time");
+        int totalAmount = new BigDecimal(request.getParameter("total_amount")).multiply(new BigDecimal(100)).intValue();
+        logger.info("data: tradeNo:"+tradeNo +" orderNo:"+orderNo +" totalAmount:"+totalAmount+ "tradeStatus:"+tradeStatus);
+
+        if (StringUtils.isBlank(tradeNo) || StringUtils.isBlank(orderNo) || StringUtils.isBlank(tradeStatus)) {
+            logger.error("ys支付回调-参数错误");
+            responseWrite(response, "fail");
+            return;
+        }
+
+        PayOrder order = payOrderService.getOne(new LambdaQueryWrapper<PayOrder>()
+            .eq(PayOrder::getTradeNo, tradeNo));
+
+        YsCallLog payYsCallLog = ysCallLogService.getOne(new LambdaQueryWrapper<YsCallLog>()
+            .eq(YsCallLog::getBizId, order.getOrderId())
+            .eq(YsCallLog::getBizType, YsCallBizTypeEnum.ORDER_PAY));
+        if (payYsCallLog != null) {
+            ysCallLogService.update(new LambdaUpdateWrapper<YsCallLog>()
+                .set(YsCallLog::getCallbackJson, JSONObject.toJSONString(params))
+                .eq(YsCallLog::getId, payYsCallLog.getId()));
+        }
+
+        if (PayOrderStatusEnum.SUCCESS.getValue().equals(order.getOrderStatus())) {
+            logger.info("支付订单已成功,消息忽略,shopOrderNo:" + orderNo);
+            responseWrite(response,"true");
+        }
+
+
+        if (!"TRADE_SUCCESS".equals(tradeStatus)) {
+            logger.error("ys-非支付成功消息,忽略");
+            responseWrite(response,"fail");
+            return;
+        }
+
+        //回调金额与订单金额一致性校验
+        if(order.getTransactionAmount() != totalAmount){
+            logger.error("回调金额与订单金额不一致");
+            responseWrite(response,"fail");
+            return;
+        }
+
+
+        PayOrder payOrder = payOrderService.getById(order.getOrderId());
+        payOrder.setOrderNo(orderNo);
+        payOrder.setCompleteDate(completeDate);
+//        payOrder.setChannelNo(channelNo);
+        payOrder.setOrderStatus(PayOrderStatusEnum.SUCCESS.getValue());
+
+
+        try {
+            // 更新订单,单个事务处理
+            logger.info("ys支付回调消息更新成功 orderId:" + order.getOrderId());
+            walletService.payOrderStatusHandle(payOrder);
+
+            // 订单支付状态单独保存
+            LambdaUpdateWrapper<PayOrder> updateWrapper = new LambdaUpdateWrapper<>();
+            updateWrapper.eq(PayOrder::getOrderStatus, PayOrderStatusEnum.WAIT.getValue());
+            updateWrapper.eq(PayOrder::getOrderId, order.getOrderId());
+            boolean ret = payOrderService.update(payOrder, updateWrapper);
+            if (!ret) {
+                LogUtil.error(logger, "ys支付回调消息更新支付单状态失败 orderId:" + order.getOrderId());
+                responseWrite(response,"fail");
+            }
+        } catch (Exception e){
+            LogUtil.error(logger, e, "ys支付回调消息处理异常 orderId:" + order.getOrderId());
+            responseWrite(response,"fail");
+        }
+
+        // 调用分账登记接口
+        OnlineReqDataVo req = new OnlineReqDataVo();
+        req.setReqUrl(YsServerApiConstants.COMMON_API);
+        req.setNotifyUrl(ysDivNotifyUrl);
+        req.setPartnerId(partnerId);
+        req.setPrivateKeyFilePath(privateKeyPath);
+        req.setPrivateKeyPassword(privateKeyPass);
+        req.setYsPublicKeyFilePath(publicKeyPath);
+        // 分账登记业务参数
+        Map<String, Object> bizContent = new HashMap<>();
+        String divTradeNo = order.getTradeNo();
+        bizContent.put("out_trade_no", divTradeNo);
+        bizContent.put("payee_usercode", partnerId);
+        bizContent.put("total_amount", request.getParameter("total_amount"));
+        bizContent.put("is_divistion", "02");
+        bizContent.put("is_again_division", "N");
+        bizContent.put("division_mode", "01");
+        // 分账明细
+//        JSONArray divList = new JSONArray();
+//        JSONObject divObject = new JSONObject();
+//        divObject.put("division_mer_usercode", partnerId);
+//        divObject.put("div_ratio", "1");
+//        divObject.put("is_chargeFee", "02");
+//        divList.add(divObject);
+        //分账明细
+//        bizContent.put("div_list", divList);
+        req.setParamData(bizContent);
+        String result = null;
+        DivisionLog divisionLog = new DivisionLog();
+        divisionLog.setStatus(DivisionStatusEnum.INIT);
+        YsCallLog ysCallLog = new YsCallLog();
+        ysCallLog.setInterfaceId("ysepay.single.division.online.accept");
+        ysCallLog.setReqJson(JSONObject.toJSONString(req));
+        ysCallLog.setBizType(YsCallBizTypeEnum.DIVISION);
+        ysCallLog.setBizId(divTradeNo);
+        try{
+            logger.info("分账登记调用sdk接口addScanMerc请求入参为:"+ JSONObject.toJSONString(req));
+            result = MercFundApi.divisionOnlineAccept(req);
+            JSONObject resultJson = JSON.parseObject(result);
+            if (!"Success".equals(resultJson.get("msg"))) {
+                divisionLog.setStatus(DivisionStatusEnum.SUBMIT_FAIL);
+            }
+            ysCallLog.setResJson(result);
+            logger.info("分账登记调用addScanMerc出参为:"+ result);
+            //根据返回结果处理自己的业务逻辑,result内容详见接口文档
+        }catch (Exception e){
+            divisionLog.setStatus(DivisionStatusEnum.SUBMIT_FAIL);
+            logger.error("线上分账登记接口失败:"+ e.getMessage());
+        }
+        // 保存调用日志
+        ysCallLogService.save(ysCallLog);
+
+        // 保存分账登记记录
+        divisionLog.setTradeNo(divTradeNo);
+        divisionLog.setAmount(totalAmount);
+        divisionLog.setOrderNo(orderNo);
+        divisionLog.setBizId(payOrder.getOrderId());
+        boolean res = divisionLogService.save(divisionLog);
+        if (!res) {
+            logger.error("分账登记记录保存失败,orderNo:{}", orderNo);
+        }
+        responseWrite(response, "success");
+    }
+
+    /**
+     * 分账回调
+     * @param request
+     * @param response
+     * @throws Exception
+     */
+    @RequestMapping(value = "/ysDivCallback", method = RequestMethod.POST)
+    public void divCallback(HttpServletRequest request, HttpServletResponse response) {
+        Map<String, String[]> reqParams = request.getParameterMap();
+
+        Map<String, String> params = new HashMap<>();
+        for (String key : reqParams.keySet()) {
+            String[] values = reqParams.get(key);
+            String valueStr = "";
+            for (int i = 0; i < values.length; i++) {
+                valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
+            }
+            params.put(key, valueStr);
+        }
+
+        logger.info("分账回调的数据 = " + JSONObject.toJSONString(params));
+        String divTradeNo = params.get("out_trade_no");
+        String divisionStatusCode = params.get("division_status_code");
+        YsCallLog ysCallLog = ysCallLogService.getOne(new LambdaQueryWrapper<YsCallLog>()
+            .eq(YsCallLog::getBizId, divTradeNo)
+            .eq(YsCallLog::getBizType, YsCallBizTypeEnum.DIVISION));
+        if (ysCallLog != null) {
+            ysCallLogService.update(new LambdaUpdateWrapper<YsCallLog>()
+                .set(YsCallLog::getCallbackJson, JSONObject.toJSONString(params))
+                .eq(YsCallLog::getId, ysCallLog.getId()));
+        }
+        DivisionLog divisionLog = divisionLogService.getOne(
+            new LambdaQueryWrapper<DivisionLog>().eq(DivisionLog::getTradeNo, divTradeNo));
+
+        if ("00".equals(divisionStatusCode) || "02".equals(divisionStatusCode)) {
+            divisionLog.setStatus(DivisionStatusEnum.COMPLETE);
+        } else {
+            divisionLog.setStatus(DivisionStatusEnum.FAIL);
+        }
+
+        boolean res = divisionLogService.update(new LambdaUpdateWrapper<DivisionLog>()
+            .set(DivisionLog::getStatus, divisionLog.getStatus())
+            .eq(DivisionLog::getStatus, DivisionStatusEnum.INIT)
+            .eq(DivisionLog::getId, divisionLog.getId()));
+        if (!res) {
+            logger.error("更新分账状态失败,分账tradeNo:" + divTradeNo);
+        }
+
+        responseWrite(response, "success");
+    }
+
+    /**
+     * 提现回调
+     * @param request
+     * @param response
+     */
+    @RequestMapping(value = "/ysWithdrawCallback", method = RequestMethod.POST)
+    public void withdrawCallback(HttpServletRequest request, HttpServletResponse response) {
+        /*Map<String, String[]> reqParams = request.getParameterMap();
+
+        Map<String, String> params = new HashMap<>();
+        for (String key : reqParams.keySet()) {
+            String[] values = reqParams.get(key);
+            String valueStr = "";
+            for (int i = 0; i < values.length; i++) {
+                valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
+            }
+            params.put(key, valueStr);
+        }
+
+        logger.info("提现回调的数据 = " + JSONObject.toJSONString(params));
+        String tradeNo = params.get("out_trade_no");
+
+        ChannelWithdraw channelWithdraw = channelWithdrawService.getOne(new LambdaQueryWrapper<ChannelWithdraw>()
+            .eq(ChannelWithdraw::getTradeNo, tradeNo));
+        if (channelWithdraw == null) {
+            logger.error("提现记录不存在,不处理回调,tradeNo:" + tradeNo);
+            responseWrite(response, "fail");
+            return;
+        }
+
+        // 记录回调数据
+        // 类型,一般账户 和 待结算账户
+        YsCallLog ysCallLog = ysCallLogService.getOne(new LambdaQueryWrapper<YsCallLog>()
+            .eq(YsCallLog::getBizId, channelWithdraw.getId())
+            .eq(YsCallLog::getBizType, YsCallBizTypeEnum.WITHDRAW));
+        if (ysCallLog != null) {
+            ysCallLogService.update(new LambdaUpdateWrapper<YsCallLog>()
+                .set(YsCallLog::getCallbackJson, JSONObject.toJSONString(params))
+                .eq(YsCallLog::getId, ysCallLog.getId()));
+        }
+
+
+        if (!ChannelWithdrawStatusEnum.WITHDRAW_PROCESS.equals(channelWithdraw.getStatus())) {
+            logger.error("提现状态不是银盛提现处理中,不处理回调,tradeNo:" + tradeNo);
+            responseWrite(response, "fail");
+            return;
+        }
+
+        String tradeStatus = params.get("trade_status");
+        if (!"TRADE_SUCCESS".equals(tradeStatus)) {
+            logger.error("提现处理失败,tradeNo:{},desc:{}",tradeNo, params.get("trade_status_description"));
+            channelWithdrawService.update(new LambdaUpdateWrapper<ChannelWithdraw>()
+                .set(ChannelWithdraw::getStatus, ChannelWithdrawStatusEnum.YS_WITHDRAW_FAILED)
+                .eq(ChannelWithdraw::getId, channelWithdraw.getId())
+                .eq(ChannelWithdraw::getStatus, ChannelWithdrawStatusEnum.WITHDRAW_PROCESS));
+            responseWrite(response, "fail");
+            return;
+        }
+
+        // 处理提现成功后的逻辑
+        channelWithdrawService.verify(channelWithdraw, ChannelWithdrawStatusEnum.FINISHED,"");
+        // 提现成功,状态修改
+//        boolean res = channelWithdrawService.update(new LambdaUpdateWrapper<ChannelWithdraw>()
+//            .set(ChannelWithdraw::getStatus, ChannelWithdrawStatusEnum.FINISHED)
+//            .eq(ChannelWithdraw::getId, channelWithdraw.getId())
+//            .eq(ChannelWithdraw::getStatus, ChannelWithdrawStatusEnum.WITHDRAW_PROCESS));
+//        if (!res) {
+//            logger.error("更新提现记录状态失败,tradeNo:{}", tradeNo);
+//        }*/
+        responseWrite(response, "success");
+    }
+
+
+    private void responseWrite(HttpServletResponse response,String echostr){
+        try {
+            response.getWriter().write(echostr);
+            response.getWriter().flush();
+            response.getWriter().close();
+        } catch (IOException e) {
+            LogUtil.error(logger, e, "微信公众号设置url回调处理异常");
+        }
+    }
+}

+ 19 - 0
mp-admin/src/main/java/com/qs/mp/web/controller/api/channel/ChannelController.java

@@ -4,7 +4,10 @@ import com.alibaba.druid.sql.visitor.functions.If;
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.qs.mp.admin.domain.TicketBox;
+import com.qs.mp.admin.domain.param.TicketBoxQueryParam;
 import com.qs.mp.admin.domain.vo.TicketCntVO;
+import com.qs.mp.admin.service.ITicketBoxService;
 import com.qs.mp.admin.service.ITicketService;
 import com.qs.mp.channel.domain.Channel;
 import com.qs.mp.channel.domain.ChannelCommission;
@@ -653,6 +656,22 @@ public class ChannelController extends BaseApiController {
         }
         return AjaxResult.success("门店'" + channel.getName() + "'二维码更新成功");
     }
+
+    @ApiOperation(value = "查询门店二维码信息", notes = "查询门店二维码信息")
+    @PostMapping("query/qrCode")
+    public AjaxResult queryQrCode(@Validated @RequestBody UserChannelQrCodeParam qrCodeParam){
+        if (null == qrCodeParam || null == qrCodeParam.getChannelId()) {
+            return error(ErrorCodeEnum.ERROR_CODE_1001);
+        }
+        Channel channel = null;
+        try {
+            channel = channelService.getById(qrCodeParam.getChannelId());
+        } catch (Exception e) {
+            return AjaxResult.error("门店'" + channel.getName() + "'二维码更新失败");
+        }
+        return AjaxResult.success("",channel.getQrCodePic());
+    }
+
     /**
      * 经销商认证审核
      *

+ 168 - 1
mp-admin/src/main/java/com/qs/mp/web/controller/api/channel/ChannelWithdrawController.java

@@ -10,12 +10,22 @@
 
 package com.qs.mp.web.controller.api.channel;
 
+import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
+import com.alibaba.fastjson.parser.Feature;
+import com.alibaba.fastjson.serializer.SerializerFeature;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.eptok.yspay.opensdkjava.fund.BankAuthorityApi;
+import com.eptok.yspay.opensdkjava.pojo.vo.OnlineReqDataVo;
+import com.eptok.yspay.opensdkjava.util.DateUtil;
+import com.eptok.yspay.opensdkjava.util.SrcDesUtil;
+import com.eptok.yspay.opensdkjava.util.YsOnlineSignUtils;
 import com.qs.mp.channel.domain.Channel;
+import com.qs.mp.channel.domain.ChannelBank;
 import com.qs.mp.channel.domain.ChannelBankCard;
 import com.qs.mp.channel.domain.ChannelCart;
 import com.qs.mp.channel.domain.ChannelWithdraw;
+import com.qs.mp.channel.domain.param.ChannelBankCardCreateParam;
 import com.qs.mp.channel.domain.param.ChannelCartParam;
 import com.qs.mp.channel.domain.param.ChannelWithdrawParam;
 import com.qs.mp.channel.domain.vo.ChannelCartVO;
@@ -24,24 +34,34 @@ import com.qs.mp.channel.service.IChannelBankCardService;
 import com.qs.mp.channel.service.IChannelCartService;
 import com.qs.mp.channel.service.IChannelService;
 import com.qs.mp.channel.service.IChannelWithdrawService;
+import com.qs.mp.common.constant.YsPayMethodConstants;
+import com.qs.mp.common.constant.YsServerApiConstants;
 import com.qs.mp.common.core.domain.AjaxResult;
 import com.qs.mp.common.core.redis.RedisCache;
+import com.qs.mp.common.domain.YsCallLog;
 import com.qs.mp.common.domain.param.BatchLongIdsParam;
 import com.qs.mp.common.enums.ChannelStatusEnum;
+import com.qs.mp.common.enums.YsCallBizTypeEnum;
+import com.qs.mp.common.service.IYsCallLogService;
 import com.qs.mp.common.utils.StringUtils;
+import com.qs.mp.common.utils.http.OkHttpUtil;
 import com.qs.mp.system.service.ISysConfigService;
 import com.qs.mp.utils.SecurityUtils;
 import com.qs.mp.web.controller.common.BaseApiController;
 import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiModelProperty;
 import io.swagger.annotations.ApiOperation;
 import java.math.BigDecimal;
 import java.math.RoundingMode;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.concurrent.TimeUnit;
 import javax.validation.Valid;
 import lombok.AllArgsConstructor;
 import ma.glasnost.orika.MapperFacade;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestBody;
@@ -52,7 +72,6 @@ import org.springframework.web.bind.annotation.RestController;
 @RestController
 @RequestMapping("/api/v1/mp/channel")
 @Api(tags = "渠道提现接口")
-@AllArgsConstructor
 public class ChannelWithdrawController extends BaseApiController {
 
 
@@ -82,6 +101,151 @@ public class ChannelWithdrawController extends BaseApiController {
    */
   private final String FEE_RATE_DEFAULT_VALUE = "0.8";
 
+
+  @Value("${ys-pay.partner-id}")
+  private String partnerId;
+
+  @Value("${ys-pay.private-key-pass}")
+  private String privateKeyPass;
+
+  @Value("${ys-pay.private-key-path}")
+  private String privateKeyPath;
+
+  @Value("${ys-pay.public-key-path}")
+  private String publicKeyPath;
+
+  @Autowired
+  private IYsCallLogService ysCallLogService;
+
+//  @ApiOperation(value = "银行卡实名认证绑定")
+//  @PostMapping("/withdraw/bankCardAuth")
+//  public AjaxResult bankCardAuth(@Validated @RequestBody ChannelBankCardCreateParam param) {
+//    Long channelId = SecurityUtils.getLoginUser().getChannelId();
+//
+//    // 判断是否已经绑定过银行卡
+//    int count = channelBankCardService.count(new LambdaQueryWrapper<ChannelBankCard>()
+//        .eq(ChannelBankCard::getChannelId, channelId));
+//    if (count > 0) {
+//      return AjaxResult.error("已经绑定过银行卡");
+//    }
+//
+//
+//    OnlineReqDataVo req = new OnlineReqDataVo();
+//    //商户在银盛支付平台开设的用户号[商户号],接入时需要替换成自己的
+//    req.setPartnerId(partnerId);
+//    req.setReqUrl(YsServerApiConstants.OPEN_API);
+//    req.setPrivateKeyFilePath(privateKeyPath);
+//    req.setPrivateKeyPassword(privateKeyPass);
+//    req.setYsPublicKeyFilePath(publicKeyPath);
+//    //银行实名认证三要素下单业务参数
+//    Map<String, Object> bizContent = new HashMap<>();
+//    String tradeNo = DateUtil.getDateNowYmd() + DateUtil.getRandom(14);
+//    //商户生成的订单号,生成规则前8位必须为交易日期,如20180525,范围跨度支持包含当天在内的前后一天
+//    bizContent.put("out_trade_no", tradeNo);
+//    //商户日期(该参数做交易与查询时需要一致)该日期需在当日的前后一天时间范围之内
+//    bizContent.put("shopdate", DateUtil.getDateNowYmd());
+//    //实名认证姓名--请填写真实信息
+//    bizContent.put("bank_account_name", param.getUserName());
+//    //银行帐号,支持对公对私
+//    bizContent.put("bank_account_no", param.getCardNo());
+//    //证件号码,目前只支持身份证
+//    bizContent.put("id_card", param.getIdCard());
+//    req.setParamData(bizContent);
+//    String result = null;
+//    try{
+//      logger.info("银行实名认证三要素调用sdk接口addScanMerc请求入参为:"+ JSONObject.toJSONString(req));
+//      //根据返回结果处理自己的业务逻辑,result内容详见接口文档
+//      result = BankAuthorityApi.sendBankAuthThreePrecise(req);
+//    }catch (Exception e){
+//      logger.info("银行实名认证三要素失败:"+ e.getMessage());
+//    }
+//    logger.info("银行实名认证三要素result =" + result);
+//
+////    Map<String, String> mapData = new HashMap<>();
+////    mapData.put("partner_id", partnerId);
+////    mapData.put("method", YsPayMethodConstants.BANK_CARD_AUTH_METHOD);
+////    mapData.put("timestamp", DateUtil.getDateNow());
+////    mapData.put("sign_type", "RSA");
+////    mapData.put("charset", "utf-8");
+////    mapData.put("version", "3.0");
+////
+////    JSONObject json = new JSONObject();
+////    String tradeNo = DateUtil.getDateNowYmd() + DateUtil.getRandom(14);
+////    json.put("out_trade_no", tradeNo);
+////    json.put("shopdate", DateUtil.getDateNowYmd());
+////    json.put("bank_account_name", param.getUserName());
+////    json.put("bank_account_no", param.getCardNo());
+////    json.put("id_card", param.getIdCard());
+////    mapData.put("biz_content", json.toString());
+////    //参数签名
+////    try {
+////      String sign = YsOnlineSignUtils.sign(mapData, privateKeyPass, privateKeyPath);
+////      mapData.put("sign", sign);
+////      logger.info("认证信息签名成功,sign = " + sign);
+////    } catch (Exception e) {
+////      System.err.println("签名异常" + e);
+////    }
+////
+////    String result = null;
+////    try {
+////      logger.info("银行实名认证三要素调用sdk接口addScanMerc请求入参为:"+ JSONObject.toJSONString(mapData));
+////      result = OkHttpUtil.post("https://openapi.ysepay.com/gateway.do", mapData);
+////    } catch (Exception e) {
+////      logger.info("银行实名认证三要素失败:"+ e.getMessage());
+////
+////    }
+//
+//    // 解析结果
+////    JSONObject jsonObject = JSON.parseObject(result, Feature.OrderedField);
+////    // 加签内容
+////    String content = JSONObject.toJSONString(
+////        jsonObject.get("ysepay_authenticate_three_key_element_precise_response"),
+////        SerializerFeature.WriteMapNullValue);
+////    JSONObject contentJsonObject = JSON.parseObject(content);
+////
+////    // 校验结果
+////    String orderStatus = (String) contentJsonObject.get("order_status");
+////    if (StringUtils.isBlank(orderStatus) || !"SUCCESS".equals(orderStatus)) {
+////      return AjaxResult.error("绑卡认证失败,请核实信息正确性");
+////    }
+//
+//
+//    // 保存银行认证的请求记录
+//    YsCallLog ysCallLog = new YsCallLog();
+//    ysCallLog.setBizId(tradeNo);
+//    ysCallLog.setBizType(YsCallBizTypeEnum.BANK_CARD_AUTH);
+//    ysCallLog.setInterfaceId(YsPayMethodConstants.BANK_CARD_AUTH_METHOD);
+//    ysCallLog.setReqJson(JSONObject.toJSONString(bizContent));
+//    ysCallLog.setResJson(result);
+//    ysCallLogService.save(ysCallLog);
+//
+//    if (StringUtils.isBlank(result)) {
+//      logger.error("银行实名认证三要素失败,res为空,req =" + JSONObject.toJSONString(bizContent));
+//      return AjaxResult.error("认证失败");
+//    }
+//
+//    // 校验结果
+//    JSONObject response = JSONObject.parseObject(result);
+//    String orderStatus = (String) response.get("order_status");
+//    if (StringUtils.isBlank(orderStatus) || !"SUCCESS".equals(orderStatus)) {
+//      return AjaxResult.error("绑卡认证失败,请核实信息正确性");
+//    }
+//
+//    // 进行绑卡
+//    ChannelBankCard channelBankCard = new ChannelBankCard();
+//    channelBankCard.setChannelId(channelId);
+//    channelBankCard.setBankName(param.getBankName());
+////    channelBankCard.setIdCard(param.getIdCard());
+//    channelBankCard.setCardNo(param.getCardNo());
+//    channelBankCard.setUserName(param.getUserName());
+//    boolean res = channelBankCardService.save(channelBankCard);
+//    if (!res) {
+//      return AjaxResult.error("绑卡失败");
+//    }
+//    return AjaxResult.success();
+//  }
+
+
   /**
    * 渠道提现计算手续费
    */
@@ -99,6 +263,9 @@ public class ChannelWithdrawController extends BaseApiController {
     if (param.getMoney() > channel.getMoney() ) {
       return AjaxResult.error("提现金额超出了余额");
     }
+//    if (param.getMoney() < 500) {
+//      return AjaxResult.error("提现金额不能小于5元");
+//    }
     int feeAmt = new BigDecimal(param.getMoney()).multiply(feeRate)
         .divide(new BigDecimal(100), 0, RoundingMode.HALF_UP).intValue();
     ChannelWithdraw channelWithdraw = new ChannelWithdraw();

+ 0 - 77
mp-admin/src/main/java/com/qs/mp/web/controller/api/user/ChannelController.java

@@ -1,77 +0,0 @@
-package com.qs.mp.web.controller.api.user;
-
-import com.alibaba.fastjson.JSONObject;
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
-import com.qs.mp.admin.domain.vo.TicketCntVO;
-import com.qs.mp.admin.service.ITicketService;
-import com.qs.mp.channel.domain.Channel;
-import com.qs.mp.channel.domain.ChannelCommission;
-import com.qs.mp.channel.domain.ChannelOrderDetail;
-import com.qs.mp.channel.domain.ChannelUserRel;
-import com.qs.mp.channel.domain.param.ChannelParam;
-import com.qs.mp.channel.domain.param.ChannelQrCodeParam;
-import com.qs.mp.channel.domain.param.SiteQueryParam;
-import com.qs.mp.channel.domain.param.VerifyParam;
-import com.qs.mp.channel.domain.vo.ChannelOperDataVO;
-import com.qs.mp.channel.domain.vo.ChannelVO;
-import com.qs.mp.channel.service.IChannelCommissionService;
-import com.qs.mp.channel.service.IChannelService;
-import com.qs.mp.channel.service.IChannelUserRelService;
-import com.qs.mp.common.constant.UserConstants;
-import com.qs.mp.common.core.domain.AjaxResult;
-import com.qs.mp.common.core.page.TableDataInfo;
-import com.qs.mp.common.enums.*;
-import com.qs.mp.common.utils.DateUtils;
-import com.qs.mp.system.service.ISysUserService;
-import com.qs.mp.user.domain.UserAddr;
-import com.qs.mp.user.domain.UserTicketOrder;
-import com.qs.mp.user.service.IUserAddrService;
-import com.qs.mp.user.service.IUserTicketOrderService;
-import com.qs.mp.utils.SecurityUtils;
-import com.qs.mp.web.controller.common.BaseApiController;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import io.swagger.annotations.ApiResponse;
-import io.swagger.annotations.ApiResponses;
-import ma.glasnost.orika.MapperFacade;
-import org.apache.commons.lang3.StringUtils;
-import org.springframework.beans.BeanUtils;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Component;
-import org.springframework.util.CollectionUtils;
-import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.*;
-
-import java.math.BigDecimal;
-import java.util.*;
-import java.util.stream.Collectors;
-
-@Api(tags = "渠道管理API")
-@RestController
-@RequestMapping("/api/v1/mp/user")
-@Component
-public class ChannelController extends BaseApiController {
-
-    @Autowired
-    private IChannelService channelService;
-
-
-    @ApiOperation(value = "更新门店二维码信息", notes = "更新门店二维码信息")
-    @PostMapping("site/update/qrCode")
-    public AjaxResult siteUpdateQrCode(@Validated @RequestBody ChannelQrCodeParam qrCodeParam){
-        if (null == qrCodeParam || null == qrCodeParam.getChannelId()) {
-            return error(ErrorCodeEnum.ERROR_CODE_1001);
-        }
-        Channel channel =  channelService.getById(qrCodeParam.getChannelId());
-        channel.setQrCodePic(qrCodeParam.getQrCode());
-        try {
-            channelService.updateById(channel);
-        } catch (Exception e) {
-            return AjaxResult.error("门店'" + channel.getName() + "'二维码更新失败");
-        }
-        return AjaxResult.success("门店'" + channel.getName() + "'二维码更新成功");
-    }
-
-
-}

+ 58 - 0
mp-admin/src/main/java/com/qs/mp/web/controller/api/user/UserChannelController.java

@@ -0,0 +1,58 @@
+package com.qs.mp.web.controller.api.user;
+
+import com.qs.mp.channel.domain.Channel;
+import com.qs.mp.channel.domain.param.*;
+import com.qs.mp.channel.service.IChannelService;
+import com.qs.mp.common.core.domain.AjaxResult;
+import com.qs.mp.common.enums.*;
+import com.qs.mp.web.controller.common.BaseApiController;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+@Api(tags = "渠道管理API")
+@RestController
+@RequestMapping("/api/v1/mp/user")
+@Component
+public class UserChannelController extends BaseApiController {
+
+    @Autowired
+    private IChannelService channelService;
+
+
+    @ApiOperation(value = "更新门店二维码信息", notes = "更新门店二维码信息")
+    @PostMapping("site/update/qrCode")
+    public AjaxResult siteUpdateQrCode(@Validated @RequestBody ChannelQrCodeParam qrCodeParam){
+        if (null == qrCodeParam || null == qrCodeParam.getChannelId()) {
+            return error(ErrorCodeEnum.ERROR_CODE_1001);
+        }
+        Channel channel =  channelService.getById(qrCodeParam.getChannelId());
+        channel.setQrCodePic(qrCodeParam.getQrCode());
+        try {
+            channelService.updateById(channel);
+        } catch (Exception e) {
+            return AjaxResult.error("门店'" + channel.getName() + "'二维码更新失败");
+        }
+        return AjaxResult.success("门店'" + channel.getName() + "'二维码更新成功");
+    }
+
+    @ApiOperation(value = "查询门店二维码信息", notes = "查询门店二维码信息")
+    @PostMapping("query/qrCode")
+    public AjaxResult queryQrCode(@Validated @RequestBody UserChannelQrCodeParam qrCodeParam){
+        if (null == qrCodeParam || null == qrCodeParam.getChannelId()) {
+            return error(ErrorCodeEnum.ERROR_CODE_1001);
+        }
+        Channel channel = null;
+        try {
+            channel = channelService.getById(qrCodeParam.getChannelId());
+        } catch (Exception e) {
+            return AjaxResult.error("门店'" + channel.getName() + "'二维码更新失败");
+        }
+        return AjaxResult.success("",channel.getQrCodePic());
+    }
+
+
+}

+ 7 - 2
mp-admin/src/main/java/com/qs/mp/web/controller/api/user/UserDeliverOrderController.java

@@ -14,6 +14,7 @@ import com.qs.mp.admin.service.IGoodsService;
 import com.qs.mp.admin.service.IGoodsSkuService;
 import com.qs.mp.channel.domain.ChannelOrder;
 import com.qs.mp.channel.domain.param.OrderPayParam;
+import com.qs.mp.common.constant.PayConstants;
 import com.qs.mp.common.core.domain.AjaxResult;
 import com.qs.mp.common.core.page.TableDataInfo;
 import com.qs.mp.common.core.redis.RedisCache;
@@ -397,11 +398,11 @@ public class UserDeliverOrderController extends BaseApiController {
         Long userId = SecurityUtils.getLoginUser().getUserId();
         SysUser sysUser = sysUserService.selectUserById(userId);
         String openId = "";
-        if (param.getPayType() == 1) {
+        if (PayConstants.ALI_PAY_TYPE.equals(param.getPayType())) {
             if (StringUtils.isBlank(sysUser.getAliuserId())) {
                 return AjaxResult.error(ErrorCodeEnum.ERROR_CODE_1026);
             }
-        } else {
+        } else if (PayConstants.WX_PAY_TYPE.equals(param.getPayType())) {
             AppSourceEnum appSourceEnum = AppSourceEnum.getByValue(param.getAppSource());
             if (AppSourceEnum.MSDQ.equals(appSourceEnum)) {
                 if (StringUtils.isBlank(sysUser.getMsdqOpenId())) {
@@ -424,6 +425,10 @@ public class UserDeliverOrderController extends BaseApiController {
                 jsonObject = walletService.directAliPay(BizTypeEnum.DELIVER_ORDER, param.getOrderId(),
                     sysUser.getAliuserId(),
                     deliverOrder.getPayAmt(), "盲票--提货订单");
+            } else if (PayConstants.H5_PAY_TYPE.equals(param.getPayType())) {
+                // h5支付
+                jsonObject = walletService.h5Pay(BizTypeEnum.DELIVER_ORDER, param.getOrderId(),
+                    deliverOrder.getPayAmt(), "盲票--提货订单");
             } else {
                 // 微信支付
                 jsonObject = walletService.pay(BizTypeEnum.DELIVER_ORDER, param.getOrderId(), openId,

+ 8 - 3
mp-admin/src/main/java/com/qs/mp/web/controller/api/user/UserTicketOrderController.java

@@ -17,6 +17,7 @@ import com.qs.mp.channel.domain.ChannelOrder;
 import com.qs.mp.channel.domain.param.OrderPayParam;
 import com.qs.mp.channel.domain.vo.PromoterVO;
 import com.qs.mp.channel.service.IPromoterUserService;
+import com.qs.mp.common.constant.PayConstants;
 import com.qs.mp.common.core.domain.AjaxResult;
 import com.qs.mp.common.core.page.TableDataInfo;
 import com.qs.mp.common.core.redis.RedisCache;
@@ -282,11 +283,11 @@ public class UserTicketOrderController extends BaseApiController {
         Long userId = SecurityUtils.getLoginUser().getUserId();
         SysUser sysUser = sysUserService.selectUserById(userId);
         String openId = "";
-        if (param.getPayType() == 1) {
+        if (PayConstants.ALI_PAY_TYPE.equals(param.getPayType())) {
             if (StringUtils.isBlank(sysUser.getAliuserId())) {
                 return AjaxResult.error(ErrorCodeEnum.ERROR_CODE_1026);
             }
-        } else {
+        } else if (PayConstants.WX_PAY_TYPE.equals(param.getPayType())){
             AppSourceEnum appSourceEnum = AppSourceEnum.getByValue(param.getAppSource());
             if (AppSourceEnum.MSDQ.equals(appSourceEnum)) {
                 if (StringUtils.isBlank(sysUser.getMsdqOpenId())) {
@@ -304,10 +305,14 @@ public class UserTicketOrderController extends BaseApiController {
         UserTicketOrder ticketOrder = userTicketOrderService.getById(param.getOrderId());
         JSONObject jsonObject;
         try {
-            if (param.getPayType() == 1) {
+            if (PayConstants.ALI_PAY_TYPE.equals(param.getPayType())) {
                 // 支付宝支付
                 jsonObject = walletService.directAliPay(BizTypeEnum.TICKET_ORDER, param.getOrderId(), sysUser.getAliuserId(),
                     ticketOrder.getPayAmt(), ticketOrder.getTitle());
+            } else if ((PayConstants.H5_PAY_TYPE.equals(param.getPayType()))) {
+                // H5支付
+                jsonObject = walletService.h5Pay(BizTypeEnum.TICKET_ORDER, param.getOrderId(),
+                    ticketOrder.getPayAmt(), ticketOrder.getTitle());
             } else {
                 // 微信支付
                 jsonObject = walletService.pay(BizTypeEnum.TICKET_ORDER, param.getOrderId(), openId,

+ 15 - 0
mp-admin/src/main/resources/application-dev.yml

@@ -141,3 +141,18 @@ shipping:
     channel: 7
 bind:
     channelId: 2
+
+# 银盛支付配置
+ys-pay:
+    private-key-path: /Users/cup/WORK/data/ysPay/ysPayPre.pfx
+    public-key-path: /Users/cup/WORK/data/ysPay/businessgate.cer
+    # 支付完后跳转
+    return-url: https://test-mp-h5.quanshu123.com
+    # 支付回调地址
+    pay-notify-url: https://test-mp.quanshu123.com/service/notify/ysCallback
+    # 分账回调地址
+    div-notify-url: https://test-mp.quanshu123.com/service/notify/ysDivCallback
+    # 提现回调地址
+    withdraw-notify-url: https://test-mp.quanshu123.com/service/notify/ysWithdrawCallback
+
+

+ 35 - 20
mp-admin/src/main/resources/application-test.yml

@@ -1,10 +1,9 @@
 mp:
-  # 文件路径 示例( Windows配置D:/ygp/uploadPath,Linux配置 /home/ygp/uploadPath)
-  profile: /home/quanshu/mp-server
+  profile: /home/mangpiao/mp-server
 pay:
-  callbackUrl: https://test-mp.quanshu123.com/service/notify/payCallback
+  callbackUrl: https://test-mp-adm.kaimanghe.net/test-api/service/notify/payCallback
 alipay:
-  callbackUrl: https://test-mp.quanshu123.com/service/notify/alipayCallback
+  callbackUrl: https://test-mp-adm.kaimanghe.net/test-api/service/notify/alipayCallback
 
 # 日志配置
 logging:
@@ -20,9 +19,9 @@ logging:
 # 数据源配置
 spring:
     redis:
-      host: 172.17.16.14
+      host: 43.143.93.199
       port: 6379
-      password: '@9(s2sWppxkess'
+      password: 1PQd[NOc$8pWGNJ
       # 连接超时时间(毫秒)
       timeout: 10000
       jedis:
@@ -41,9 +40,9 @@ spring:
         druid:
             # 主库数据源
             master:
-                url: jdbc:mysql://172.17.16.14:3306/mpdb_test?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
-                username: mptest
-                password: wan789*@dfhzHu518!dr2xosn
+                url: jdbc:mysql://43.143.93.199:3306/mpdb_test?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+                username: root
+                password: mp@666888
             # 从库数据源
             slave:
                 # 从数据源开关/默认关闭
@@ -113,21 +112,22 @@ client:
 # cloud
 cloud:
   # 存储对象公开可访问
-  public-bucket-name: mp-public-test-1307117429
+  public-bucket-name: mp-public-test-1309783959
   # 存储对象公开不可访问,需要通过应用下载
-  private-bucket-name: mp-auth-test-1307117429
+  private-bucket-name: mp-auth-test-1309783959
 
-  accessKey: AKIDDF4dwzlGVTAmCMGvLVP4UfbHiuqVzFEw
-  secretKey: TgbFcjZ8HDse9ToujIabLo1yf5YqtfBX
+  accessKey: AKIDue8LHwKSJsBDySgdJjslNilY4JHyOXPz
+  secretKey: SdXAWbPwDDvMXR5SYOxtYw3sQhhQs2wZ
   region: ap-shanghai
 
-mq:
-  consumer-conn: true
-  service-url: http://pulsar-op4bzppa37m4.tdmq-pulsar.ap-sh.public.tencenttdmq.com:8080
-  auth-token: eyJrZXlJZCI6InB1bHNhci1vcDRienBwYTM3bTQiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJwdWxzYXItb3A0YnpwcGEzN200X21wLXNlcnZlci10ZXN0In0.GVeFHHSqIYqTeOtXItWOT-NfydCSNvvVVS2FlpFZNKY
-  topic-ticket-generate: pulsar-op4bzppa37m4/test-share/topic-ticket-generate
-  topic-ticket-pay: pulsar-op4bzppa37m4/test-share/topic-ticket-pay
-  consumer-topics: pulsar-op4bzppa37m4/test-share/topic-ticket-generate,pulsar-op4bzppa37m4/test-share/topic-ticket-pay
+# 注释mq
+#mq:
+#  consumer-conn: true
+#  service-url: http://pulsar-op4bzppa37m4.tdmq-pulsar.ap-sh.public.tencenttdmq.com:8080
+#  auth-token: eyJrZXlJZCI6InB1bHNhci1vcDRienBwYTM3bTQiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJwdWxzYXItb3A0YnpwcGEzN200X21wLXNlcnZlci10ZXN0In0.GVeFHHSqIYqTeOtXItWOT-NfydCSNvvVVS2FlpFZNKY
+#  topic-ticket-generate: pulsar-op4bzppa37m4/test-share/topic-ticket-generate
+#  topic-ticket-pay: pulsar-op4bzppa37m4/test-share/topic-ticket-pay
+#  consumer-topics: pulsar-op4bzppa37m4/test-share/topic-ticket-generate,pulsar-op4bzppa37m4/test-share/topic-ticket-pay
 
 
 # 小程序
@@ -145,3 +145,18 @@ shipping:
   channel: 7
 bind:
   channelId: 2
+
+
+# 银盛支付配置
+ys-pay:
+  private-key-path: /home/mangpiao/mp-server/data/ysPayPre.pfx
+  public-key-path: /home/mangpiao/mp-server/data/businessgate.cer
+  # 支付完后跳转
+  return-url: https://test-mp-adm.kaimanghe.net
+  # 回调地址
+  pay-notify-url: https://test-mp-adm.kaimanghe.net/service/notify/ysCallback
+  # 分账回调地址
+  div-notify-url: https://test-mp-adm.kaimanghe.net/service/notify/ysDivCallback
+  # 提现回调地址
+  withdraw-notify-url: https://test-mp-adm.kaimanghe.net/service/notify/ysWithdrawCallback
+

+ 12 - 1
mp-admin/src/main/resources/application.yml

@@ -30,7 +30,7 @@ spring:
     # 国际化资源文件路径
     basename: i18n/messages
   profiles:
-    active: dev
+    active: test
   # 文件上传
   servlet:
      multipart:
@@ -158,6 +158,17 @@ pay:
   msdq-shopNo: 1657242588900
   msdq-sign: e39069383c6944a18abc0b03a4ad0217
 
+# 银盛支付配置
+ys-pay:
+  serverUrl: https://openapi.ysepay.com/gateway.do
+  # 商户号
+  partner-id: ecoloshare
+  private-key-pass: FAl9S8TmGB80
+  # 主收款商户号
+  master-seller-id: 0000400267870283
+  # 子商户号
+  child-seller-id: 0000400267870291
+
 #幸运数字加密密钥对
 rsa:
   private-key: MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAJsdnYuNQGwzutcBPzVXXP9oizi5nVMlI4IohcoLH5iV2dZ39XkcWMbjithn4FBe2Y7N7lougVCRtSyOCLc63vJ9V2w7NrqHnQVIOkse9XhiBNEpQy9PKEm1lM9lZZL6fya4UDaYzGZUD9qq7FzNBBvXwhlXP3Bj4uSodf1M4HmBAgMBAAECgYB43EJ9Ebo4lLXoANi3PzL+7v5LXJTwy+c260wTeUdNJLVvHljt3OBvV6w/ofBtrvnlAx/MtJ+dn2qDJMg1vHEpWPVwTvL+8cqih5RwD6TBG9WH4ERF1fb40Z5FD+muDHK5ubgZNGicPH7T0/L6GYrGCeF9PS6sP+FvdywE5xHKgQJBANI2cpqM8B4c+LC3yQEQDJFbid1EaJEWeX9pHglAn7HhAJgpVCPO3vLainZ9Y2mgyR9ZntWW46YmtRWEOha/Lp0CQQC85u9CE1JPJGyYhIPw8+VVvdWlXzOzYIxtuQjr7ryMMYJttXLbp2q30rCRICyzsmpR26s+GXFGgo5XusvRoS81AkEAwID8EmxeuDTvyWWEvWRlHfgmGGs9FyDtwrAQwYhcthjG4pF2bBRWNy/K/Rd2opSLmhoISrETaGSqEDo2t/38QQJAK69sXWeCfXL6+jqLGMoOm0mPgvMFTdJiJ23HNmi7ieBZPW3c5hdNgr1iv+0k6Vm1ZMDcVTwlCh1fNcKpKA2SkQJBAL0DAXA26tk6LUWdBkXp54dJV/nm4/NDN6KWB+Tu5kcqteW7qCqgBToWJsxv6wLIcd5T20875gns1Btt1Vsq9Ss=

+ 1 - 1
mp-admin/src/main/resources/logback-8091.xml

@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <configuration>
     <!-- 日志存放路径 -->
-	<property name="log.path" value="/home/quanshu/mp-server" />
+	<property name="log.path" value="/home/quanshu/mp-server"/>
     <!-- 日志输出格式 -->
     <!-- You can override this to have a custom pattern -->
 	<property name="CONSOLE_LOG_PATTERN" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" />

+ 1 - 1
mp-admin/src/main/resources/logback-spring.xml

@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <configuration>
     <!-- 日志存放路径 -->
-	<property name="log.path" value="/Users/Steven/Documents/logs" />
+	<property name="log.path" value="/Users/Cup/Documents/logs" />
     <!-- 日志输出格式 -->
     <!-- You can override this to have a custom pattern -->
 	<property name="CONSOLE_LOG_PATTERN" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" />

+ 311 - 20
mp-admin/src/test/java/com/qs/mp/task/MyTest.java

@@ -9,8 +9,22 @@ import cn.hutool.crypto.SecureUtil;
 import cn.hutool.crypto.symmetric.DES;
 import cn.hutool.crypto.symmetric.SymmetricAlgorithm;
 import cn.hutool.crypto.symmetric.SymmetricCrypto;
+import cn.hutool.http.HttpRequest;
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.alibaba.fastjson.parser.Feature;
+import com.alibaba.fastjson.serializer.SerializerFeature;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.eptok.yspay.opensdkjava.fund.BankAuthorityApi;
+import com.eptok.yspay.opensdkjava.fund.MercFundApi;
+import com.eptok.yspay.opensdkjava.pojo.vo.OnlineReqDataVo;
+import com.eptok.yspay.opensdkjava.util.Base64Utils;
+import com.eptok.yspay.opensdkjava.util.DateUtil;
+import com.eptok.yspay.opensdkjava.util.SrcDesUtil;
+import com.eptok.yspay.opensdkjava.util.YsOnlineSignUtils;
+import com.eptok.yspay.opensdkjava.util.YsfSignUtil;
 import com.qs.mp.admin.domain.Coupon;
 import com.qs.mp.admin.domain.CouponTicket;
 import com.qs.mp.admin.domain.GoodsCard;
@@ -19,17 +33,23 @@ import com.qs.mp.admin.service.ICouponChannelService;
 import com.qs.mp.admin.service.ICouponService;
 import com.qs.mp.admin.service.ICouponTicketService;
 import com.qs.mp.admin.service.IGoodsCardService;
+import com.qs.mp.common.constant.YsServerApiConstants;
 import com.qs.mp.common.core.redis.DistributedLocker;
 import com.qs.mp.common.core.redis.RedisCache;
+import com.qs.mp.common.domain.YsCallLog;
+import com.qs.mp.common.enums.DivisionStatusEnum;
 import com.qs.mp.common.enums.UserTypeEnum;
+import com.qs.mp.common.enums.YsCallBizTypeEnum;
 import com.qs.mp.common.utils.AESUtil;
 import com.qs.mp.common.utils.DateUtils;
 import com.qs.mp.common.utils.RSAUtil;
 import com.qs.mp.common.utils.WebhookService;
 import com.qs.mp.common.utils.html.EscapeUtil;
+import com.qs.mp.common.utils.http.OkHttpUtil;
 import com.qs.mp.common.utils.uuid.IdUtils;
 import com.qs.mp.common.utils.uuid.UUID;
 import com.qs.mp.framework.service.IWxSubscribeMessage;
+import com.qs.mp.pay.domain.DivisionLog;
 import com.qs.mp.pay.service.IWalletService;
 import com.qs.mp.quartz.task.DayStatTask;
 import com.qs.mp.quartz.task.MarketingTask;
@@ -38,13 +58,16 @@ import com.qs.mp.system.service.id.BizIdGenerator;
 import com.qs.mp.user.domain.MarketingUserCode;
 import com.qs.mp.user.service.IMarketingUserCodeService;
 import com.qs.mp.utils.SecurityUtils;
+import com.taobao.api.Constants;
 import java.util.concurrent.TimeUnit;
 import org.apache.commons.lang3.RandomStringUtils;
 import org.apache.commons.lang3.StringUtils;
+import org.apache.http.client.methods.HttpRequestBase;
 import org.junit.jupiter.api.Test;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.boot.test.context.SpringBootTest;
 
 import java.io.IOException;
@@ -57,6 +80,7 @@ import java.util.*;
  */
 @SpringBootTest
 public class MyTest {
+
     protected final Logger logger = LoggerFactory.getLogger(this.getClass());
 
 
@@ -102,11 +126,279 @@ public class MyTest {
     @Autowired
     private TicketOrderTask ticketOrderTask;
 
-    public static void main(String[] args) {
-        WebhookService.sendAlertDing("mayday,mayday,上上下下,左右左右,BABA");
+    @Value("${ys-pay.serverUrl}")
+    private String serverUrl;
+
+    @Value("${ys-pay.partner-id}")
+    private String partnerId;
+
+    @Value("${ys-pay.private-key-pass}")
+    private String privateKeyPass;
+
+    @Value("${ys-pay.private-key-path}")
+    private String privateKeyPath;
+
+    @Value("${ys-pay.public-key-path}")
+    private String publicKeyPath;
+
+
+    @Value("${ys-pay.withdraw-notify-url}")
+    private String ysWithdrawNotifyUrl;
+
+
+    /**
+     * 分账查询测试
+     */
+    @Test
+    void test22() {
+        // test232
+        OnlineReqDataVo req = new OnlineReqDataVo();
+
+        //请求路径,建议配置在项目的配置文件里面
+        String reqUrl = "https://commonapi.ysepay.com/gateway.do";
+
+        //银盛支付服务器主动通知商户网站里指定的页面http路径
+        String notifyUrl = "http://api.test.ysepay.net/atinterface/receive_return.htm";
+        req.setNotifyUrl(notifyUrl);
+
+        //商户在银盛支付平台开设的用户号[商户号],接入时需要替换成自己的
+        req.setPartnerId(partnerId);
+        req.setReqUrl(reqUrl);
+        req.setPrivateKeyFilePath(privateKeyPath);
+        req.setPrivateKeyPassword(privateKeyPass);
+        req.setYsPublicKeyFilePath(publicKeyPath);
+        //线上分账查询接口业务参数
+        Map<String, Object> bizContent = new HashMap<>();
+        bizContent.put("src_usercode", partnerId);//原交易发起方
+        bizContent.put("out_trade_no", "20230414176151484");//原订单号
+        bizContent.put("sys_flag", "DD");//可空。系统标志 DD:订单交易,DS:代收交易,默认是DD,订单交易
+        req.setParamData(bizContent);
+        String result = null;
+        try{
+            logger.info("线上分账查询调用sdk接口addScanMerc请求入参为:"+ JSONObject.toJSONString(req));
+            result = MercFundApi.divisionOnlineQuery(req);
+            System.out.println("result = " + result);
+            //根据返回结果处理自己的业务逻辑,result内容详见接口文档
+        }catch (Exception e){
+            logger.info("线上分账查询接口失败:"+ e.getMessage());
+        }
 
-        String decrypt = AESUtil.decrypt("75213771c6c781d62136e39180303be03f0a99761114c1264f116051a9e95108");
-        System.out.println("decrypt = " + decrypt);
+
+    }
+
+
+    /**
+     * 分账测试
+     */
+    @Test
+    void test21() {
+        // 调用分账登记接口
+        OnlineReqDataVo req = new OnlineReqDataVo();
+        req.setReqUrl(YsServerApiConstants.COMMON_API);
+        req.setNotifyUrl("https://test-mp.quanshu123.com/service/notify/ysDivCallback");
+        req.setPartnerId(partnerId);
+        req.setPrivateKeyFilePath(privateKeyPath);
+        req.setPrivateKeyPassword(privateKeyPass);
+        req.setYsPublicKeyFilePath(publicKeyPath);
+        // 分账登记业务参数
+        Map<String, Object> bizContent = new HashMap<>();
+        String divTradeNo = DateUtil.getDateNowYmd() + DateUtil.getRandom(14);
+        divTradeNo = "2023041335526144";
+        bizContent.put("out_trade_no", divTradeNo);
+        bizContent.put("payee_usercode", partnerId);
+        bizContent.put("total_amount", "0.10");
+        bizContent.put("is_divistion", "02");
+        bizContent.put("is_again_division", "N");
+        bizContent.put("division_mode", "01");
+        // 分账明细
+//        JSONArray divList = new JSONArray();
+//        JSONObject divObject = new JSONObject();
+//        divObject.put("division_mer_usercode", partnerId);
+//        divObject.put("div_ratio", "1");
+//        divObject.put("is_chargeFee", "02");
+//        divList.add(divObject);
+        //分账明细
+//        bizContent.put("div_list", divList);
+        req.setParamData(bizContent);
+        String result = null;
+        DivisionLog divisionLog = new DivisionLog();
+        divisionLog.setStatus(DivisionStatusEnum.INIT);
+        try{
+            logger.info("分账登记调用sdk接口addScanMerc请求入参为:"+ JSONObject.toJSONString(req));
+            result = MercFundApi.divisionOnlineAccept(req);
+            logger.info("分账登记调用addScanMerc出参为:"+ result);
+            //根据返回结果处理自己的业务逻辑,result内容详见接口文档
+        }catch (Exception e){
+            divisionLog.setStatus(DivisionStatusEnum.SUBMIT_FAIL);
+            logger.error("线上分账登记接口失败:"+ e.getMessage());
+        }
+    }
+
+    /**
+     * 提现测试方法
+     */
+    @Test
+    void test20() {
+
+
+
+        String tradeNo = DateUtil.getDateNowYmd() + DateUtil.getRandom(14);
+
+
+        OnlineReqDataVo req = new OnlineReqDataVo();
+        req.setReqUrl(YsServerApiConstants.COMMON_API);
+        req.setPrivateKeyFilePath(privateKeyPath);
+        req.setYsPublicKeyFilePath(publicKeyPath);
+        req.setPrivateKeyPassword(privateKeyPass);
+        req.setNotifyUrl(ysWithdrawNotifyUrl);
+        req.setPartnerId(partnerId);
+
+        //实时提现(一般户到银行卡)业务参数
+        Map<String, Object> bizContent = new HashMap<>();
+        //商户生成的订单号,生成规则前8位必须为交易日期,如20180525,范围跨度支持包含当天在内的前后一天
+        bizContent.put("out_trade_no", tradeNo);
+        //商户号
+        bizContent.put("merchant_usercode", partnerId);
+        //暂时只支持币种:CNY(人民币)
+        bizContent.put("currency", "CNY");
+        //提现的总金额。单位为:RMB Yuan。取值范围为[0.01,99999999.99],精确到小数点后两位。Number(10,2)指10位长度,2位精度
+        bizContent.put("total_amount", "0.04");
+        //订单说明
+        bizContent.put("subject", "提现了");
+        //商户日期(该参数做交易与查询时需要一致) 该日期需在当日的前后一天时间范围之内
+        bizContent.put("shopdate", DateUtil.getDateNowYmd());
+        //银行帐号
+        bizContent.put("bank_account_no", "6212260488888888888");
+        req.setParamData(bizContent);
+        String result = null;
+        try{
+            logger.info("实时提现(一般户到银行卡)调用sdk接口addScanMerc请求入参为:"+ JSONObject.toJSONString(req));
+            //根据返回结果处理自己的业务逻辑,result内容详见接口文档
+            result = MercFundApi.withdrawQuick(req);
+        }catch (Exception e){
+            logger.info("实时提现(一般户到银行卡)失败:"+ e.getMessage());
+        }
+
+        System.out.println("result = " + result);
+    }
+
+    @Test
+    void test19() {
+        // 调用接口校验
+        OnlineReqDataVo req = new OnlineReqDataVo();
+        req.setReqUrl(YsServerApiConstants.OPEN_API);
+        req.setPartnerId(partnerId);
+        req.setPrivateKeyFilePath(privateKeyPath);
+        req.setYsPublicKeyFilePath(publicKeyPath);
+        req.setPrivateKeyPassword(privateKeyPass);
+
+        //银行实名认证三要素下单业务参数
+        Map<String, Object> bizContent = new HashMap<>();
+        String tradeNo = DateUtil.getDateNowYmd() + DateUtil.getRandom(14);
+        //商户生成的订单号,生成规则前8位必须为交易日期,如20180525,范围跨度支持包含当天在内的前后一天
+        bizContent.put("out_trade_no", tradeNo);
+        //商户日期(该参数做交易与查询时需要一致)该日期需在当日的前后一天时间范围之内
+        bizContent.put("shopdate", DateUtil.getDateNowYmd());
+        //实名认证姓名--请填写真实信息
+        bizContent.put("bank_account_name", "张三");
+        //银行帐号,支持对公对私
+        bizContent.put("bank_account_no", "6212260488888888888");
+        //证件号码,目前只支持身份证
+        bizContent.put("id_card", "41022319940916602X");
+        req.setParamData(bizContent);
+
+        String result = null;
+        try {
+            logger.info("银行实名认证三要素调用sdk接口addScanMerc请求入参为:" + JSONObject.toJSONString(req));
+            //根据返回结果处理自己的业务逻辑,result内容详见接口文档
+            result = BankAuthorityApi.sendBankAuthThreePrecise(req);
+        } catch (Exception e) {
+            logger.info("银行实名认证三要素失败:" + e.getMessage());
+        }
+        System.out.println("result = " + result);
+    }
+
+    @Test
+    void test18() {
+        walletService.h5Pay(null, "0239021091224323", 100, "测试测试测试");
+    }
+
+    /**
+     * 实名认证方法
+     */
+    @Test
+    void test17() {
+        OnlineReqDataVo req = new OnlineReqDataVo();
+        //商户在银盛支付平台开设的用户号[商户号],接入时需要替换成自己的
+        req.setPartnerId(partnerId);
+        req.setReqUrl(YsServerApiConstants.OPEN_API);
+        req.setPrivateKeyFilePath(privateKeyPath);
+        req.setPrivateKeyPassword(privateKeyPass);
+        req.setYsPublicKeyFilePath(publicKeyPath);
+        //银行实名认证三要素下单业务参数
+        Map<String, Object> bizContent = new HashMap<>();
+        bizContent.put("out_trade_no", DateUtil.getDateNowYmd() + DateUtil.getRandom(6));//商户生成的订单号,生成规则前8位必须为交易日期,如20180525,范围跨度支持包含当天在内的前后一天
+        bizContent.put("shopdate", DateUtil.getDateNowYmd());//商户日期(该参数做交易与查询时需要一致)该日期需在当日的前后一天时间范围之内
+        bizContent.put("bank_account_name", "李四");//实名认证姓名--请填写真实信息
+        bizContent.put("bank_account_no", "6212260488888888888");//银行帐号,支持对公对私
+        bizContent.put("id_card","41022319940916602X");//证件号码,目前只支持身份证
+        req.setParamData(bizContent);
+        String result = null;
+        try{
+            logger.info("银行实名认证三要素调用sdk接口addScanMerc请求入参为:"+ JSONObject.toJSONString(req));
+            //根据返回结果处理自己的业务逻辑,result内容详见接口文档
+            result = BankAuthorityApi.sendBankAuthThreePrecise(req);
+        }catch (Exception e){
+            logger.info("银行实名认证三要素失败:"+ e.getMessage());
+        }
+        System.out.println("result = " + result);
+
+    }
+
+    /**
+     * 实名认证测试方法
+     * @throws Exception
+     */
+    @Test
+    void test16() throws Exception {
+
+        Map<String, String> mapData = new HashMap<>();
+        mapData.put("partner_id", partnerId);
+        mapData.put("method", "ysepay.authenticate.three.key.element.precise");
+        mapData.put("timestamp", DateUtil.getDateNow());
+        mapData.put("sign_type", "RSA");
+        mapData.put("charset", "utf-8");
+        mapData.put("version", "3.0");
+//        mapData.put("out_trade_no", "202003276843192280647119");
+
+        JSONObject json = new JSONObject();
+        json.put("out_trade_no", DateUtil.getDateNowYmd() + DateUtil.getRandom(6));
+        json.put("shopdate", DateUtil.getDateNowYmd());
+        json.put("bank_account_name", "蒋浩");
+        json.put("bank_account_no", "6212260488888888888");
+        json.put("id_card", SrcDesUtil.encryptData(partnerId, "331081199909124619"));
+        mapData.put("biz_content", json.toString());
+        //参数签名
+        try {
+            String sign = YsOnlineSignUtils.sign(mapData, privateKeyPass, privateKeyPath);
+            mapData.put("sign", sign);
+            System.out.println("sign = " + sign);
+        } catch (Exception e) {
+            System.err.println("签名异常" + e);
+        }
+
+        String result = OkHttpUtil.post("https://openapi.ysepay.com/gateway.do", mapData);
+
+        // 结果验签
+        JSONObject jsonObject = JSON.parseObject(result, Feature.OrderedField);
+        // 加签内容
+        String content = JSONObject.toJSONString(
+            jsonObject.get("ysepay_authenticate_three_key_element_precise_response"),
+            SerializerFeature.WriteMapNullValue);
+
+
+        System.out.println("返回" + result);
+        System.out.println("content = " + content);
 
     }
 
@@ -118,7 +410,7 @@ public class MyTest {
 
     @Test
     void test14() {
-        distributedLocker.tryLock("goods_card_lock_key_466",0,-1, TimeUnit.SECONDS);
+        distributedLocker.tryLock("goods_card_lock_key_466", 0, -1, TimeUnit.SECONDS);
     }
 
     @Test
@@ -145,9 +437,9 @@ public class MyTest {
 
 
     @Test
-    void test10(){
+    void test10() {
         for (int i = 0; i < 1; i++) {
-            couponService.distributeByMarketing(188L,"56");
+            couponService.distributeByMarketing(188L, "56");
         }
 
     }
@@ -162,7 +454,7 @@ public class MyTest {
     }
 
     @Test
-    void test8(){
+    void test8() {
         dayStatTask.stat("20220713");
     }
 
@@ -177,34 +469,34 @@ public class MyTest {
 
 
     @Test
-    void test6(){
+    void test6() {
 //        List<MarketingUserCode> userCodeList = marketingUserCodeService.list(new LambdaQueryWrapper<MarketingUserCode>()
 //                .select(MarketingUserCode::getUserId)
 //                .eq(MarketingUserCode::getMarketingId, 102)
 ////                .eq(MarketingUserCode::getUserType, UserTypeEnum.ORDINARY.getValue())
 //                .groupBy(MarketingUserCode::getUserId));
         List<MarketingUserCode> userCodeList = marketingUserCodeService.list(new LambdaQueryWrapper<MarketingUserCode>()
-                .select(MarketingUserCode::getUserId)
-                .eq(MarketingUserCode::getUserType, UserTypeEnum.ORDINARY.getValue())
-                .groupBy(MarketingUserCode::getUserId));
+            .select(MarketingUserCode::getUserId)
+            .eq(MarketingUserCode::getUserType, UserTypeEnum.ORDINARY.getValue())
+            .groupBy(MarketingUserCode::getUserId));
         userCodeList.forEach(System.out::println);
     }
 
     @Test
     void test5() {
-        Set<String> testSet =new HashSet<>();
+        Set<String> testSet = new HashSet<>();
         testSet.add("test1");
         testSet.add("test2");
         testSet.add("test3");
         testSet.add("test4");
-        redisCache.setCacheSet("testSet",testSet);
+        redisCache.setCacheSet("testSet", testSet);
         List<Object> list = new ArrayList<>();
         list.add("test1");
         list.add("test3");
         list.add("test5");
         list.add("test6");
         list.add("test7");
-        redisCache.removeSetValueByKey("testSet",list);
+        redisCache.removeSetValueByKey("testSet", list);
 
 
     }
@@ -223,7 +515,7 @@ public class MyTest {
 //        wxSubscribeMessage.sendMarketingHelp(188L, marketing);
 //        wxSubscribeMessage.sendMarketingHelp(79L, marketing);
     }
-    
+
     @Test
     void test2() throws IOException {
         marketingTask.lottery();
@@ -231,7 +523,7 @@ public class MyTest {
     }
 
     @Test
-    void test3(){
+    void test3() {
         for (int i = 0; i < 20; i++) {
             System.out.println("bizIdGenerator = " + bizIdGenerator.newId());
         }
@@ -239,10 +531,9 @@ public class MyTest {
     }
 
 
-
     @Test
-    void test1(){
-        walletService.refund("968527112497659906",10,"测试");
+    void test1() {
+        walletService.refund("968527112497659906", 10, "测试");
     }
 
 }

+ 7 - 0
mp-common/pom.xml

@@ -22,6 +22,13 @@
 
     <dependencies>
 
+        <!-- 盈盛支付sdk -->
+        <dependency>
+            <groupId>io.github.ysgatesdk</groupId>
+            <artifactId>yspay-opensdk-java</artifactId>
+            <version>1.0.1</version>
+        </dependency>
+
         <!--dingtalk-->
         <dependency>
             <groupId>com.aliyun</groupId>

+ 17 - 0
mp-common/src/main/java/com/qs/mp/common/constant/DivisionLogStatusConstants.java

@@ -0,0 +1,17 @@
+package com.qs.mp.common.constant;
+
+/**
+ * 分账状态常量
+ * @author Evan
+ * @date 2023/3/29
+ */
+public class DivisionLogStatusConstants {
+
+    /** 初始化 */
+    public static int INIT = 0;
+    /** 成功 */
+    public static int SUCCESS = 1;
+    /** 失败 */
+    public static int FAIL = 2;
+
+}

+ 17 - 0
mp-common/src/main/java/com/qs/mp/common/constant/PayConstants.java

@@ -0,0 +1,17 @@
+package com.qs.mp.common.constant;
+
+/**
+ * 支付相关常量定义
+ * @author Evan
+ * @date 2023/3/27
+ */
+public class PayConstants {
+
+    /** 支付宝*/
+    public static Integer ALI_PAY_TYPE = 1;
+    /** 微信*/
+    public static Integer WX_PAY_TYPE = 2;
+    /** H5*/
+    public static Integer H5_PAY_TYPE = 3;
+
+}

+ 28 - 0
mp-common/src/main/java/com/qs/mp/common/constant/YsPayMethodConstants.java

@@ -0,0 +1,28 @@
+package com.qs.mp.common.constant;
+
+/**
+ * 银盛相关方法常量
+ * @author Evan
+ * @date 2023/3/28
+ */
+public class YsPayMethodConstants {
+
+    /** H5支付方法 */
+    public static String H5_PAY_METHOD = "ysepay.online.wap.directpay.createbyuser";
+
+
+    /** 分账登记方法 */
+    public static String DIVISION_SUBMIT_METHOD = "ysepay.single.division.online.accept";
+
+    public static String DIVISION_QUERY_METHOD = "ysepay.single.division.online.query";
+
+    public static String BANK_CARD_AUTH_METHOD = "ysepay.authenticate.three.key.element.precise";
+
+
+    /** 一般账户提现方法 */
+    public static String GENERAL_ACCOUNT_WITHDRAW_METHOD = "ysepay.merchant.withdraw.quick.accept";
+
+    /** 待结算账户提现方法 */
+    public static String SETTLED_ACCOUNT_WITHDRAW_METHOD = "ysepay.merchant.withdraw.d0.accept";
+
+}

+ 16 - 0
mp-common/src/main/java/com/qs/mp/common/constant/YsServerApiConstants.java

@@ -0,0 +1,16 @@
+package com.qs.mp.common.constant;
+
+/**
+ * 盈盛服务API地址常量
+ * @author Evan
+ * @date 2023/3/28
+ */
+public class YsServerApiConstants {
+
+    public static String OPEN_API = "https://openapi.ysepay.com/gateway.do";
+
+    public static String SEARCH_API = "https://search.ysepay.com/gateway.do";
+
+    public static String COMMON_API = "https://commonapi.ysepay.com/gateway.do";
+
+}

+ 6 - 1
mp-common/src/main/java/com/qs/mp/common/enums/ChannelWithdrawStatusEnum.java

@@ -15,7 +15,12 @@ public enum ChannelWithdrawStatusEnum implements IEnum<Integer> {
 
   WITHDRAWING(1, "待提现"),
   FINISHED(2, "已完成"),
-  FAILED(3, "提现失败");
+  FAILED(3, "提现失败"),
+
+  WITHDRAW_PROCESS(4,"提现处理中"),
+
+  YS_WITHDRAW_FAILED(5, "银盛提现失败"),
+  ;
 
 
   private final int value;

+ 46 - 0
mp-common/src/main/java/com/qs/mp/common/enums/DivisionStatusEnum.java

@@ -0,0 +1,46 @@
+package com.qs.mp.common.enums;
+
+import com.alibaba.fastjson.JSONObject;
+import com.alibaba.fastjson.annotation.JSONType;
+import com.baomidou.mybatisplus.annotation.IEnum;
+import com.qs.mp.common.json.EnumValueDeserializer;
+
+/**
+ * 分账状态枚举
+ * @author Evan
+ * @date 2023/3/30
+ */
+@JSONType(deserializer = EnumValueDeserializer.class)
+public enum DivisionStatusEnum implements IEnum<Integer> {
+
+    INIT(0,"初始化"),
+    COMPLETE(1,"完成"),
+    SUBMIT_FAIL(2,"登记失败"),
+    FAIL(3,"失败");
+
+
+    private final int value;
+    private final String desc;
+
+    DivisionStatusEnum(final int value, final String desc) {
+        this.value = value;
+        this.desc = desc;
+    }
+
+    @Override
+    public Integer getValue() {
+        return value;
+    }
+
+    /**
+     * 重写toString,单个转化成json
+     * @return
+     */
+    @Override
+    public String toString() {
+        JSONObject object = new JSONObject();
+        object.put("value",value);
+        object.put("desc", desc);
+        return object.toString();
+    }
+}

+ 2 - 1
mp-common/src/main/java/com/qs/mp/common/enums/TicketStatusEnum.java

@@ -14,7 +14,8 @@ import com.qs.mp.common.json.EnumValueDeserializer;
 public enum TicketStatusEnum implements IEnum<Integer> {
   NOT_PAY(1, "未付款"),
   ACTIVATED(2, "待兑奖"),
-  CASHED(3, "已兑奖"),;
+  CASHED(3, "已兑奖");
+//  STOP(5,"已停售");
 
   private final int value;
   private final String desc;

+ 52 - 0
mp-common/src/main/java/com/qs/mp/common/enums/YsCallBizTypeEnum.java

@@ -0,0 +1,52 @@
+package com.qs.mp.common.enums;
+
+import com.alibaba.fastjson.JSONObject;
+import com.alibaba.fastjson.annotation.JSONType;
+import com.baomidou.mybatisplus.annotation.IEnum;
+import com.qs.mp.common.json.EnumValueDeserializer;
+
+/**
+ * 盈盛调用业务类型枚举
+ * @author Evan
+ * @date 2023/3/30
+ */
+@JSONType(deserializer = EnumValueDeserializer.class)
+public enum YsCallBizTypeEnum implements IEnum<Integer> {
+
+    ORDER_PAY(1,"订单支付"),
+
+    DIVISION(2,"分账"),
+
+
+    BANK_CARD_AUTH(3, "银行实名认证三要素"),
+
+    WITHDRAW(4,"提现")
+
+    ;
+
+
+    private final int value;
+    private final String desc;
+
+    YsCallBizTypeEnum(final int value, final String desc) {
+        this.value = value;
+        this.desc = desc;
+    }
+
+    @Override
+    public Integer getValue() {
+        return value;
+    }
+
+    /**
+     * 重写toString,单个转化成json
+     * @return
+     */
+    @Override
+    public String toString() {
+        JSONObject object = new JSONObject();
+        object.put("value",value);
+        object.put("desc", desc);
+        return object.toString();
+    }
+}

+ 91 - 91
mp-common/src/main/java/com/qs/mp/common/pulsar/PulsarClientService.java

@@ -34,54 +34,54 @@ public class PulsarClientService {
   private PulsarClient client;
   private Consumer<byte[]> consumer;
 
-  @Value("${mq.service-url}")
-  private String serviceUrl;
+//  @Value("${mq.service-url}")
+//  private String serviceUrl;
 
-  @Value("${mq.auth-token}")
-  private String authToken;
+//  @Value("${mq.auth-token}")
+//  private String authToken;
 
-  @Value("${mq.topic-ticket-generate}")
-  private String topicTicketGenerate;
+//  @Value("${mq.topic-ticket-generate}")
+//  private String topicTicketGenerate;
 
-  @Value("${mq.topic-ticket-pay}")
-  private String topicTicketPay;
+//  @Value("${mq.topic-ticket-pay}")
+//  private String topicTicketPay;
 
-  @Value("${mq.consumer-conn}")
-  private boolean consumerConn;
+//  @Value("${mq.consumer-conn}")
+//  private boolean consumerConn;
 
-  @Value("${mq.consumer-topics}")
-  private String topics;
+//  @Value("${mq.consumer-topics}")
+//  private String topics;
 
   @Autowired
   private PulsarConsumer pulsarConsumer;
 
   private final ConcurrentHashMap<String, Producer<byte[]>> Producers = new ConcurrentHashMap<String, Producer<byte[]>>();
 
-  @PostConstruct
-  public void init() throws PulsarClientException {
-    client = PulsarClient.builder()
-        .serviceUrl(serviceUrl)//【集群管理】接入地址处复制
-        .authentication(AuthenticationFactory.token(authToken))
-        .build();
-
-    if (consumerConn) {
-      consumer = client.newConsumer()
-          .topic(topics.split(","))//topic完整路径,格式为persistent://集群(租户)ID/命名空间/Topic名称
-          .subscriptionName("mp")//需要现在控制台或者通过控制台API创建好一个订阅,此处填写订阅名
-          .subscriptionType(SubscriptionType.Exclusive)//声明消费模式为exclusive(独占)模式
-          .subscriptionInitialPosition(
-              SubscriptionInitialPosition.Earliest)//配置从最早开始消费,否则可能会消费不到历史消息
-          .subscribe();
-      new Thread(() -> {
-        try {
-          loop();
-        } catch (Exception e) {
-          logger.error("消费Pulsar数据异常,停止Pulsar连接:", e);
-          close();
-        }
-      }).start();
-    }
-  }
+//  @PostConstruct
+//  public void init() throws PulsarClientException {
+//    client = PulsarClient.builder()
+//        .serviceUrl(serviceUrl)//【集群管理】接入地址处复制
+//        .authentication(AuthenticationFactory.token(authToken))
+//        .build();
+
+//    if (consumerConn) {
+//      consumer = client.newConsumer()
+//          .topic(topics.split(","))//topic完整路径,格式为persistent://集群(租户)ID/命名空间/Topic名称
+//          .subscriptionName("mp")//需要现在控制台或者通过控制台API创建好一个订阅,此处填写订阅名
+//          .subscriptionType(SubscriptionType.Exclusive)//声明消费模式为exclusive(独占)模式
+//          .subscriptionInitialPosition(
+//              SubscriptionInitialPosition.Earliest)//配置从最早开始消费,否则可能会消费不到历史消息
+//          .subscribe();
+//      new Thread(() -> {
+//        try {
+//          loop();
+//        } catch (Exception e) {
+//          logger.error("消费Pulsar数据异常,停止Pulsar连接:", e);
+//          close();
+//        }
+//      }).start();
+//    }
+//  }
 
   private void loop() throws Exception {
     //消费消息
@@ -104,60 +104,60 @@ public class PulsarClientService {
     }
   }
 
-  /**
-   * @param mqTopicType
-   * @param data        内容为json格式
-   * @throws PulsarClientException
-   */
-  public void producer(MqTopicType mqTopicType, String data) throws PulsarClientException {
-    logger.info("start producer mq data:" + data);
-    String topic = "";
-    if (mqTopicType.getValue() == MqTopicType.ticket_generate.getValue()) {
-      topic = topicTicketGenerate; // 盲票生成
-    } else if (mqTopicType.getValue() == MqTopicType.ticket_pay.getValue()) {
-      topic = topicTicketPay; // 盲票付款成功
-    }
-    Producer<byte[]> producer = null;
-    if (Producers.containsKey(mqTopicType.getValue())) {
-      producer = Producers.get(mqTopicType.getValue());
-    } else {
-      producer = client.newProducer()
-          .topic(topic)//topic完整路径,格式为persistent://集群(租户)ID/命名空间/Topic名称
-          .enableBatching(true)
-          .create();
-      Producers.put(mqTopicType.getValue(), producer);
-    }
-
-    /*
-    producer.newMessage()//发送消息
-        .key(mqTopicType.getValue())
-        .value(data.getBytes())
-            .send();
-
-
-     */
-    CompletableFuture<MessageId> messageIdFuture = producer.newMessage()
-        .key(mqTopicType.getValue())
-        .value(data.getBytes())
-        .sendAsync();
-    Producer<byte[]> finalProducer = producer;
-    messageIdFuture.whenComplete(((messageId, throwable) -> {
-      if (null != throwable) {
-        logger.error("【消息投递异常,开始重试】mq data:" + data, throwable);
-        //todo 失败重试策略
-        try {
-          finalProducer.newMessage().deliverAfter(5, TimeUnit.SECONDS
-          ).key(mqTopicType.getValue()).value(data.getBytes()).send();
-        } catch (PulsarClientException e) {
-          logger.error("重试投递失败", e);
-          //todo 保存数据库,增加失败重试,通过体系化重试框架保证消息投递完整性
-        }
-      } else {
-        logger.info("【消息成功投递】");
-      }
-    }));
-
-  }
+//  /**
+//   * @param mqTopicType
+//   * @param data        内容为json格式
+//   * @throws PulsarClientException
+//   */
+//  public void producer(MqTopicType mqTopicType, String data) throws PulsarClientException {
+//    logger.info("start producer mq data:" + data);
+//    String topic = "";
+//    if (mqTopicType.getValue() == MqTopicType.ticket_generate.getValue()) {
+//      topic = topicTicketGenerate; // 盲票生成
+//    } else if (mqTopicType.getValue() == MqTopicType.ticket_pay.getValue()) {
+//      topic = topicTicketPay; // 盲票付款成功
+//    }
+//    Producer<byte[]> producer = null;
+//    if (Producers.containsKey(mqTopicType.getValue())) {
+//      producer = Producers.get(mqTopicType.getValue());
+//    } else {
+//      producer = client.newProducer()
+//          .topic(topic)//topic完整路径,格式为persistent://集群(租户)ID/命名空间/Topic名称
+//          .enableBatching(true)
+//          .create();
+//      Producers.put(mqTopicType.getValue(), producer);
+//    }
+//
+//    /*
+//    producer.newMessage()//发送消息
+//        .key(mqTopicType.getValue())
+//        .value(data.getBytes())
+//            .send();
+//
+//
+//     */
+//    CompletableFuture<MessageId> messageIdFuture = producer.newMessage()
+//        .key(mqTopicType.getValue())
+//        .value(data.getBytes())
+//        .sendAsync();
+//    Producer<byte[]> finalProducer = producer;
+//    messageIdFuture.whenComplete(((messageId, throwable) -> {
+//      if (null != throwable) {
+//        logger.error("【消息投递异常,开始重试】mq data:" + data, throwable);
+//        //todo 失败重试策略
+//        try {
+//          finalProducer.newMessage().deliverAfter(5, TimeUnit.SECONDS
+//          ).key(mqTopicType.getValue()).value(data.getBytes()).send();
+//        } catch (PulsarClientException e) {
+//          logger.error("重试投递失败", e);
+//          //todo 保存数据库,增加失败重试,通过体系化重试框架保证消息投递完整性
+//        }
+//      } else {
+//        logger.info("【消息成功投递】");
+//      }
+//    }));
+//
+//  }
 
   public void consumer() throws PulsarClientException {
 

+ 3 - 3
mp-generator/src/main/java/com/qs/mp/generator/DbGenerator.java

@@ -49,13 +49,13 @@ public class DbGenerator {
      */
     private static final boolean REST_CONTROLLER_STYLE = true;
 
-    public static final String JDBC_MYSQL_URL = "jdbc:mysql://110.40.236.236:3306/mpdb_test?useUnicode=true&useSSL=false&characterEncoding=utf8";
+    public static final String JDBC_MYSQL_URL = "jdbc:mysql://43.143.93.199:3306/mpdb_test?useUnicode=true&useSSL=false&characterEncoding=utf8";
 
     public static final String JDBC_DRIVER_NAME = "com.mysql.cj.jdbc.Driver";
 
-    public static final String JDBC_USERNAME = "mptest";
+    public static final String JDBC_USERNAME = "root";
 
-    public static final String JDBC_PASSWORD = "wan789*@dfhzHu518!dr2xosn";
+    public static final String JDBC_PASSWORD = "mp@666888";
 
     public static void main(String[] args) {
         String moduleName = scanner("模块名");

+ 13 - 13
mp-quartz/src/main/java/com/qs/mp/quartz/task/OperateToolTask.java

@@ -21,8 +21,8 @@ public class OperateToolTask {
 
   protected final Logger logger = LoggerFactory.getLogger(this.getClass().getSimpleName());
 
-  @Autowired
-  private PulsarClientService pulsarClientService;
+//  @Autowired
+//  private PulsarClientService pulsarClientService;
 
   @Autowired
   private IWalletService walletService;
@@ -30,17 +30,17 @@ public class OperateToolTask {
   /**
    * 重新发送消息
    */
-  public void resendTicketPayMsg(String orderId) {
-    LogUtil.info(logger, "...重新发送盲票支付消息任务开始...");
-
-    try {
-      pulsarClientService.producer(MqTopicType.ticket_pay, orderId);
-    } catch (Exception e) {
-      LogUtil.error(logger, e, "重新发送盲票支付消息异常。orderId:{0}", orderId);
-    }
-
-    LogUtil.info(logger, "...重新发送盲票支付消息任务结束...");
-  }
+//  public void resendTicketPayMsg(String orderId) {
+//    LogUtil.info(logger, "...重新发送盲票支付消息任务开始...");
+//
+//    try {
+//      pulsarClientService.producer(MqTopicType.ticket_pay, orderId);
+//    } catch (Exception e) {
+//      LogUtil.error(logger, e, "重新发送盲票支付消息异常。orderId:{0}", orderId);
+//    }
+//
+//    LogUtil.info(logger, "...重新发送盲票支付消息任务结束...");
+//  }
 
 
   /**

+ 1 - 0
mp-service/src/main/java/com/qs/mp/admin/service/ITicketAwardsPrizeService.java

@@ -9,6 +9,7 @@ import com.qs.mp.admin.domain.vo.TicketAwardsPrizeVO;
 import com.qs.mp.admin.domain.vo.TicketBoxGoodsListVO;
 
 import java.util.List;
+import org.apache.ibatis.annotations.Param;
 
 /**
  * <p>

+ 78 - 0
mp-service/src/main/java/com/qs/mp/channel/domain/ChannelBank.java

@@ -0,0 +1,78 @@
+package com.qs.mp.channel.domain;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.baomidou.mybatisplus.annotation.IdType;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import java.util.Date;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableLogic;
+import com.baomidou.mybatisplus.annotation.TableField;
+import java.io.Serializable;
+import com.baomidou.mybatisplus.annotation.*;
+import lombok.Data;
+
+/**
+ * @describe 渠道银行卡表实体类
+ * @auther quanshu
+ * @create 2023-03-27 14:24:40
+ */
+@TableName("mp_channel_bank")
+@Data
+@ApiModel("渠道银行卡表实体类")
+public class ChannelBank implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主键
+     */
+    @ApiModelProperty("主键")
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * 渠道id
+     */
+    @ApiModelProperty("渠道id")
+    @TableField("channel_id")
+    private Long channelId;
+
+    /**
+     * 银行卡号
+     */
+    @ApiModelProperty("银行卡号")
+    @TableField("bank_no")
+    private String bankNo;
+
+    /**
+     * 银行名称
+     */
+    @ApiModelProperty("银行名称")
+    @TableField("bank_name")
+    private String bankName;
+
+    /**
+     * 创建时间
+     */
+    @ApiModelProperty("创建时间")
+    @TableField("created_time")
+    private Date createdTime;
+
+    /**
+     * 更新时间
+     */
+    @ApiModelProperty("更新时间")
+    @TableField("updated_time")
+    private Date updatedTime;
+
+    /**
+     * 逻辑删除标识
+     */
+    @ApiModelProperty("逻辑删除标识")
+    @TableField("is_deleted")
+    @TableLogic
+    private Integer isDeleted;
+
+
+}

+ 23 - 0
mp-service/src/main/java/com/qs/mp/channel/domain/ChannelBankCard.java

@@ -3,7 +3,10 @@ package com.qs.mp.channel.domain;
 import com.baomidou.mybatisplus.annotation.IdType;
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableLogic;
 import com.baomidou.mybatisplus.annotation.TableName;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
 import java.io.Serializable;
 import java.util.Date;
 import lombok.Data;
@@ -15,66 +18,86 @@ import lombok.Data;
  */
 @TableName("mp_channel_bank_card")
 @Data
+@ApiModel("渠道银行卡实体类")
 public class ChannelBankCard implements Serializable {
 
   private static final long serialVersionUID = 1L;
 
+  @ApiModelProperty("id")
   @TableId(value = "id" , type = IdType.AUTO)
   private Long id;
 
   /**
    * 渠道id
    */
+  @ApiModelProperty("渠道id")
   @TableField("channel_id")
   private Long channelId;
 
   /**
    * 持卡人
    */
+  @ApiModelProperty("持卡人名字")
   @TableField("user_name")
   private String userName;
 
+//  @ApiModelProperty("身份证号")
+//  @TableField("id_card")
+//  private String idCard;
+
   /**
    * 卡号
    */
+  @ApiModelProperty("卡号")
   @TableField("card_no")
   private String cardNo;
 
   /**
    * 银行卡所属银行
    */
+  @ApiModelProperty("所属银行")
   @TableField("bank_name")
   private String bankName;
 
   /**
    * 开户行
    */
+  @ApiModelProperty("开户行")
   @TableField("branch_name")
   private String branchName;
 
   /**
    * 预留手机号码
    */
+  @ApiModelProperty("预留手机号")
   @TableField("mobile")
   private String mobile;
 
   /**
    * 1默认
    */
+  @ApiModelProperty("1默认卡")
   @TableField("default_card")
   private Integer defaultCard;
 
   /**
    * 添加时间
    */
+  @ApiModelProperty("创建时间")
   @TableField("create_time")
   private Date createTime;
 
   /**
    * 修改时间
    */
+  @ApiModelProperty("更新时间")
   @TableField("update_time")
   private Date updateTime;
 
+//  @ApiModelProperty("逻辑删除")
+//  @TableLogic
+//  @TableField("is_deleted")
+//  private Integer isDeleted;
+
 
 }

+ 6 - 0
mp-service/src/main/java/com/qs/mp/channel/domain/ChannelWithdraw.java

@@ -5,6 +5,7 @@ import com.alibaba.fastjson.serializer.SerializerFeature;
 import com.baomidou.mybatisplus.annotation.IdType;
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableLogic;
 import com.baomidou.mybatisplus.annotation.TableName;
 import com.qs.mp.common.enums.ChannelWithdrawStatusEnum;
 import java.io.Serializable;
@@ -37,6 +38,10 @@ public class ChannelWithdraw implements Serializable {
   @TableField("channel_id")
   private Long channelId;
 
+//  @ApiModelProperty("提现交易单号")
+//  @TableField("trade_no")
+//  private String tradeNo;
+
   /**
    * 提现金额
    */
@@ -144,4 +149,5 @@ public class ChannelWithdraw implements Serializable {
   private Date updateTime;
 
 
+
 }

+ 34 - 0
mp-service/src/main/java/com/qs/mp/channel/domain/param/ChannelBankCardCreateParam.java

@@ -0,0 +1,34 @@
+package com.qs.mp.channel.domain.param;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import javax.validation.constraints.NotBlank;
+import lombok.Data;
+
+/**
+ * 渠道银行卡创建入参类
+ * @author Evan
+ * @date 2023/3/30
+ */
+@ApiModel("渠道银行卡创建入参类")
+@Data
+public class ChannelBankCardCreateParam {
+
+    @NotBlank(message = "姓名不内外空")
+    @ApiModelProperty("用户名称")
+    private String userName;
+
+    @NotBlank(message = "身份证号不能为空")
+    @ApiModelProperty("身份证号")
+    private String idCard;
+
+    @NotBlank(message = "银行名称不能为空")
+    @ApiModelProperty("银行名称")
+    private String bankName;
+
+    @NotBlank(message = "银行卡号不能为空")
+    @ApiModelProperty("银行卡号")
+    private String cardNo;
+
+
+}

+ 1 - 1
mp-service/src/main/java/com/qs/mp/channel/domain/param/ChannelWithdrawParam.java

@@ -34,7 +34,7 @@ public class ChannelWithdrawParam {
   @ApiModelProperty(value = "银行名",required=false)
   private String bankName;
 
-  @NotNull(message = "开户行不能为空")
+//  @NotNull(message = "开户行不能为空")
   @ApiModelProperty(value = "开户行",required=true)
   private String branchName;
 }

+ 1 - 1
mp-service/src/main/java/com/qs/mp/channel/domain/param/OrderPayParam.java

@@ -15,7 +15,7 @@ public class OrderPayParam {
 	private String orderId;
 
 	@NotNull(message = "支付方式不能为空")
-	@ApiModelProperty(value = "支付方式:1支付宝,2微信",required=true)
+	@ApiModelProperty(value = "支付方式:1支付宝,2微信,3-H5",required=true)
 	private Integer payType;
 
 

+ 22 - 0
mp-service/src/main/java/com/qs/mp/channel/domain/param/UserChannelQrCodeParam.java

@@ -0,0 +1,22 @@
+package com.qs.mp.channel.domain.param;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotNull;
+
+/**
+ * 门店二维码更新
+ *
+ * @author Cup
+ * @date 2022/8/9
+ */
+@ApiModel("门店二维码入参类")
+@Data
+public class UserChannelQrCodeParam {
+
+    @ApiModelProperty("所属门店id")
+    private Long channelId;
+
+}

+ 1 - 0
mp-service/src/main/java/com/qs/mp/channel/domain/vo/ChannelVO.java

@@ -1,5 +1,6 @@
 package com.qs.mp.channel.domain.vo;
 
+import com.baomidou.mybatisplus.annotation.TableLogic;
 import com.qs.mp.channel.domain.Channel;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;

+ 13 - 0
mp-service/src/main/java/com/qs/mp/channel/mapper/ChannelBankMapper.java

@@ -0,0 +1,13 @@
+package com.qs.mp.channel.mapper;
+
+import com.qs.mp.channel.domain.ChannelBank;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+ * @auther quanshu
+ * @create 2023-03-27 14:24:40
+ * @describe 渠道银行卡表mapper类
+ */
+public interface ChannelBankMapper extends BaseMapper<ChannelBank> {
+
+}

+ 16 - 0
mp-service/src/main/java/com/qs/mp/channel/service/IChannelBankService.java

@@ -0,0 +1,16 @@
+package com.qs.mp.channel.service;
+
+import com.qs.mp.channel.domain.ChannelBank;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ * 渠道银行卡表 服务类
+ * </p>
+ *
+ * @author quanshu
+ * @since 2023-03-27
+ */
+public interface IChannelBankService extends IService<ChannelBank> {
+
+}

+ 20 - 0
mp-service/src/main/java/com/qs/mp/channel/service/impl/ChannelBankServiceImpl.java

@@ -0,0 +1,20 @@
+package com.qs.mp.channel.service.impl;
+
+import com.qs.mp.channel.domain.ChannelBank;
+import com.qs.mp.channel.mapper.ChannelBankMapper;
+import com.qs.mp.channel.service.IChannelBankService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ * 渠道银行卡表 服务实现类
+ * </p>
+ *
+ * @author quanshu
+ * @since 2023-03-27
+ */
+@Service
+public class ChannelBankServiceImpl extends ServiceImpl<ChannelBankMapper, ChannelBank> implements IChannelBankService {
+
+}

+ 0 - 2
mp-service/src/main/java/com/qs/mp/channel/service/impl/ChannelTicketTransferServiceImpl.java

@@ -37,7 +37,6 @@ public class ChannelTicketTransferServiceImpl extends ServiceImpl<ChannelTicketT
     @Override
     @Transactional(rollbackFor = Exception.class)
     public boolean transferTicket(Long transferChannelId, ChannelTicketTransferParam channelTicketTransferParam) {
-
         // 转让盲票
         ChannelTicketTransfer channelTicketTransfer = new ChannelTicketTransfer();
         channelTicketTransfer.setTransferChannelId(transferChannelId);
@@ -54,7 +53,6 @@ public class ChannelTicketTransferServiceImpl extends ServiceImpl<ChannelTicketT
                 .set(ChannelOrderDetail::getChannelId, channelTicketTransferParam.getChannelId())
                 .eq(ChannelOrderDetail::getPkgId, channelTicketTransferParam.getPkgId())
                 .eq(ChannelOrderDetail::getChannelId, transferChannelId));
-
         return true;
     }
 

+ 113 - 3
mp-service/src/main/java/com/qs/mp/channel/service/impl/ChannelWithdrawServiceImpl.java

@@ -1,8 +1,12 @@
 package com.qs.mp.channel.service.impl;
 
+import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.Wrapper;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import com.eptok.yspay.opensdkjava.fund.MercFundApi;
+import com.eptok.yspay.opensdkjava.pojo.vo.OnlineReqDataVo;
+import com.eptok.yspay.opensdkjava.util.DateUtil;
 import com.qs.mp.channel.domain.Channel;
 import com.qs.mp.channel.domain.ChannelBankCard;
 import com.qs.mp.channel.domain.ChannelMoneyLog;
@@ -14,15 +18,26 @@ import com.qs.mp.channel.service.IChannelMoneyLogService;
 import com.qs.mp.channel.service.IChannelService;
 import com.qs.mp.channel.service.IChannelWithdrawService;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.qs.mp.common.constant.YsPayMethodConstants;
+import com.qs.mp.common.constant.YsServerApiConstants;
+import com.qs.mp.common.domain.YsCallLog;
 import com.qs.mp.common.enums.ChannelMoneyEnum;
 import com.qs.mp.common.enums.ChannelWithdrawStatusEnum;
+import com.qs.mp.common.enums.YsCallBizTypeEnum;
+import com.qs.mp.common.exception.ServiceException;
+import com.qs.mp.common.service.IYsCallLogService;
 import com.qs.mp.common.utils.LogUtil;
 import com.qs.mp.common.utils.WebhookService;
 import java.math.BigDecimal;
 import java.math.RoundingMode;
 import java.util.Date;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.Assert;
@@ -38,6 +53,31 @@ import org.springframework.util.Assert;
 @Service
 public class ChannelWithdrawServiceImpl extends ServiceImpl<ChannelWithdrawMapper, ChannelWithdraw> implements IChannelWithdrawService {
 
+  private final Logger logger = LoggerFactory.getLogger(this.getClass().getSimpleName());
+
+
+  @Value("${ys-pay.private-key-path}")
+  private String privateKeyPath;
+
+  @Value("${ys-pay.public-key-path}")
+  private String publicKeyPath;
+
+
+  @Value("${ys-pay.partner-id}")
+  private String partnerId;
+
+  @Value("${ys-pay.private-key-pass}")
+  private String privateKeyPass;
+
+  @Value("${ys-pay.withdraw-notify-url}")
+  private String ysWithdrawNotifyUrl;
+
+  @Value(value = "${server.env}")
+  private String env;
+
+  @Autowired
+  private IYsCallLogService ysCallLogService;
+
   @Autowired
   private IChannelBankCardService channelBankCardService;
 
@@ -48,13 +88,15 @@ public class ChannelWithdrawServiceImpl extends ServiceImpl<ChannelWithdrawMappe
   private IChannelMoneyLogService channelMoneyLogService;
 
   @Override
-  @Transactional
+  @Transactional(rollbackFor = Exception.class)
   public boolean apply(Channel channel, ChannelWithdraw channelWithdraw) {
 
     // 更新用户的银行卡信息
     ChannelBankCard bankCard = channelBankCardService.getOne(new LambdaQueryWrapper<ChannelBankCard>()
         .eq(ChannelBankCard::getChannelId, channel.getChannelId()));
     if (null == bankCard) {
+//      throw new RuntimeException("请先绑定银行卡");
+//    }
       bankCard = new ChannelBankCard();
       bankCard.setChannelId(channel.getChannelId());
       bankCard.setCardNo(channelWithdraw.getCardNo());
@@ -105,7 +147,7 @@ public class ChannelWithdrawServiceImpl extends ServiceImpl<ChannelWithdrawMappe
   }
 
   @Override
-  @Transactional
+  @Transactional(rollbackFor = Exception.class)
   public boolean verify(ChannelWithdraw withdraw, ChannelWithdrawStatusEnum status, String verifyContent) {
     if (status == ChannelWithdrawStatusEnum.FINISHED) {
       boolean rtn = update(new LambdaUpdateWrapper<ChannelWithdraw>()
@@ -125,7 +167,75 @@ public class ChannelWithdrawServiceImpl extends ServiceImpl<ChannelWithdrawMappe
           .eq(Channel::getChannelId, withdraw.getChannelId())
           .eq(Channel::getFrozenMoney, channel.getFrozenMoney()));
       Assert.isTrue(updateRtn, "提现申请审核通过,更新账号冻结金额。channelId:" + channel.getChannelId());
-    } else if (status == ChannelWithdrawStatusEnum.FAILED) {
+    }
+    // 银盛提现接口调用
+    /*
+    else if (status == ChannelWithdrawStatusEnum.WITHDRAW_PROCESS) {
+      String tradeNo = DateUtil.getDateNowYmd() + DateUtil.getRandom(14);;
+
+      // 更新状态为提现处理中
+      boolean rtn = update(new LambdaUpdateWrapper<ChannelWithdraw>()
+          .set(ChannelWithdraw::getTradeNo, tradeNo)
+          .set(ChannelWithdraw::getStatus, status)
+          .eq(ChannelWithdraw::getId, withdraw.getId())
+          .in(ChannelWithdraw::getStatus, ChannelWithdrawStatusEnum.WITHDRAWING, ChannelWithdrawStatusEnum.YS_WITHDRAW_FAILED));
+      Assert.isTrue(rtn, "调用银盛提现接口失败。id:" + withdraw.getId());
+
+      // 调用银盛发起提现
+      OnlineReqDataVo req = new OnlineReqDataVo();
+
+      //银盛支付服务器主动通知商户网站里指定的页面http路径
+      req.setNotifyUrl(ysWithdrawNotifyUrl);
+
+      //商户在银盛支付平台开设的用户号[商户号],接入时需要替换成自己的
+      req.setPartnerId("hyfz_test2");
+      req.setReqUrl(YsServerApiConstants.COMMON_API);
+      req.setPrivateKeyFilePath(privateKeyPath);
+      req.setPrivateKeyPassword(privateKeyPass);
+      req.setYsPublicKeyFilePath(publicKeyPath);
+      //实时提现(一般户到银行卡)业务参数
+      Map<String, Object> bizContent = new HashMap<>();
+      //商户生成的订单号,生成规则前8位必须为交易日期,如20180525,范围跨度支持包含当天在内的前后一天
+      bizContent.put("out_trade_no", tradeNo);
+      //商户号
+      bizContent.put("merchant_usercode", partnerId);
+      //暂时只支持币种:CNY(人民币)
+      bizContent.put("currency", "CNY");
+      //提现的总金额。单位为:RMB Yuan。取值范围为[0.01,99999999.99],精确到小数点后两位。Number(10,2)指10位长度,2位精度
+      if ("prod".equals(env)) {
+        bizContent.put("total_amount", new BigDecimal(withdraw.getMoney()).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP).toString());
+      } else {
+        bizContent.put("total_amount", "1.00");
+      }
+      //订单说明
+      bizContent.put("subject", "提现");
+      //商户日期(该参数做交易与查询时需要一致) 该日期需在当日的前后一天时间范围之内
+      bizContent.put("shopdate", DateUtil.getDateNowYmd());
+      //银行帐号
+      bizContent.put("bank_account_no", withdraw.getCardNo());
+      req.setParamData(bizContent);
+      String result = null;
+
+      YsCallLog ysCallLog = new YsCallLog();
+      try{
+        logger.info("实时提现(一般户到银行卡)调用sdk接口addScanMerc请求入参为:"+ JSONObject.toJSONString(req));
+        //根据返回结果处理自己的业务逻辑,result内容详见接口文档
+        result = MercFundApi.withdrawQuick(req);
+        ysCallLog.setResJson(result);
+        logger.info("实时提现(一般户到银行卡)调用sdk接口addScanMerc请求出参为:"+ result);
+      }catch (Exception e){
+        logger.info("实时提现(一般户到银行卡)失败:"+ e.getMessage());
+        throw new ServiceException("调用银盛发起提现失败");
+      }
+
+      ysCallLog.setBizId(String.valueOf(withdraw.getId()));
+      ysCallLog.setBizType(YsCallBizTypeEnum.WITHDRAW);
+      ysCallLog.setInterfaceId(YsPayMethodConstants.GENERAL_ACCOUNT_WITHDRAW_METHOD);
+      ysCallLog.setReqJson(JSONObject.toJSONString(bizContent));
+      ysCallLogService.save(ysCallLog);
+      */
+
+     else if (status == ChannelWithdrawStatusEnum.FAILED) {
       boolean rtn = update(new LambdaUpdateWrapper<ChannelWithdraw>()
           .set(ChannelWithdraw::getStatus, status)
           .set(ChannelWithdraw::getVerifyContent, verifyContent)

+ 97 - 0
mp-service/src/main/java/com/qs/mp/common/domain/YsCallLog.java

@@ -0,0 +1,97 @@
+package com.qs.mp.common.domain;
+
+import com.alibaba.fastjson.annotation.JSONField;
+import com.alibaba.fastjson.serializer.SerializerFeature;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.qs.mp.common.enums.YsCallBizTypeEnum;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import java.util.Date;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableLogic;
+import com.baomidou.mybatisplus.annotation.TableField;
+import java.io.Serializable;
+import com.baomidou.mybatisplus.annotation.*;
+import lombok.Data;
+
+/**
+ * @describe 银盛调用日志表实体类
+ * @auther quanshu
+ * @create 2023-03-27 14:24:03
+ */
+@TableName("mp_ys_call_log")
+@Data
+@ApiModel("银盛调用日志实体类")
+public class YsCallLog implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主键
+     */
+    @ApiModelProperty("主键")
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * 请求id
+     */
+    @ApiModelProperty("关联id")
+    @TableField("biz_id")
+    private String bizId;
+
+    @ApiModelProperty("关联业务")
+    @TableField("biz_Type")
+    @JSONField(serialzeFeatures = SerializerFeature.WriteEnumUsingToString)
+    private YsCallBizTypeEnum bizType;
+
+    /**
+     * 请求接口
+     */
+    @ApiModelProperty("请求接口")
+    @TableField("interface_id")
+    private String interfaceId;
+
+    /**
+     * 请求参数
+     */
+    @ApiModelProperty("请求参数")
+    @TableField("req_json")
+    private String reqJson;
+
+    /**
+     * 响应参数
+     */
+    @ApiModelProperty("响应参数")
+    @TableField("res_json")
+    private String resJson;
+
+    @ApiModelProperty("回调数据")
+    @TableField("callback_json")
+    private String callbackJson;
+
+    /**
+     * 创建时间
+     */
+    @ApiModelProperty("创建时间")
+    @TableField("created_time")
+    private Date createdTime;
+
+    /**
+     * 更新时间
+     */
+    @ApiModelProperty("更新时间")
+    @TableField("updated_time")
+    private Date updatedTime;
+
+    /**
+     * 逻辑删除标识
+     */
+    @ApiModelProperty("逻辑删除标识")
+    @TableField("is_deleted")
+    @TableLogic
+    private Integer isDeleted;
+
+
+}

+ 13 - 0
mp-service/src/main/java/com/qs/mp/common/mapper/YsCallLogMapper.java

@@ -0,0 +1,13 @@
+package com.qs.mp.common.mapper;
+
+import com.qs.mp.common.domain.YsCallLog;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+ * @auther quanshu
+ * @create 2023-03-27 14:24:03
+ * @describe 银盛调用日志表mapper类
+ */
+public interface YsCallLogMapper extends BaseMapper<YsCallLog> {
+
+}

+ 16 - 0
mp-service/src/main/java/com/qs/mp/common/service/IYsCallLogService.java

@@ -0,0 +1,16 @@
+package com.qs.mp.common.service;
+
+import com.qs.mp.common.domain.YsCallLog;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ * 银盛调用日志表 服务类
+ * </p>
+ *
+ * @author quanshu
+ * @since 2023-03-27
+ */
+public interface IYsCallLogService extends IService<YsCallLog> {
+
+}

+ 20 - 0
mp-service/src/main/java/com/qs/mp/common/service/impl/YsCallLogServiceImpl.java

@@ -0,0 +1,20 @@
+package com.qs.mp.common.service.impl;
+
+import com.qs.mp.common.domain.YsCallLog;
+import com.qs.mp.common.mapper.YsCallLogMapper;
+import com.qs.mp.common.service.IYsCallLogService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ * 银盛调用日志表 服务实现类
+ * </p>
+ *
+ * @author quanshu
+ * @since 2023-03-27
+ */
+@Service
+public class YsCallLogServiceImpl extends ServiceImpl<YsCallLogMapper, YsCallLog> implements IYsCallLogService {
+
+}

+ 96 - 0
mp-service/src/main/java/com/qs/mp/pay/domain/DivisionLog.java

@@ -0,0 +1,96 @@
+package com.qs.mp.pay.domain;
+
+import com.alibaba.fastjson.annotation.JSONField;
+import com.alibaba.fastjson.serializer.SerializerFeature;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.qs.mp.common.enums.DivisionStatusEnum;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import java.util.Date;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableLogic;
+import com.baomidou.mybatisplus.annotation.TableField;
+import java.io.Serializable;
+import com.baomidou.mybatisplus.annotation.*;
+import lombok.Data;
+
+/**
+ * @describe 分账记录表实体类
+ * @auther quanshu
+ * @create 2023-03-27 14:24:26
+ */
+@TableName("mp_division_log")
+@Data
+@ApiModel("分账记录表实体类")
+public class DivisionLog implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主键
+     */
+    @ApiModelProperty("主键")
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * 分账单号
+     */
+    @ApiModelProperty("分账单号")
+    @TableField("trade_no")
+    private String tradeNo;
+
+    /**
+     * 关联支付单号
+     */
+    @ApiModelProperty("关联支付单号")
+    @TableField("order_no")
+    private String orderNo;
+
+    /**
+     * 关联业务单号
+     */
+    @ApiModelProperty("关联业务单号")
+    @TableField("biz_id")
+    private String bizId;
+
+    /**
+     * 分账金额
+     */
+    @ApiModelProperty("分账金额")
+    @TableField("amount")
+    private Integer amount;
+
+    /**
+     * 状态:1初始化,2完成,3失败
+     */
+    @ApiModelProperty("状态:0初始化,1完成,2登记失败,3失败")
+    @TableField("status")
+    @JSONField(serialzeFeatures = SerializerFeature.WriteEnumUsingToString)
+    private DivisionStatusEnum status;
+
+    /**
+     * 创建时间
+     */
+    @ApiModelProperty("创建时间")
+    @TableField("created_time")
+    private Date createdTime;
+
+    /**
+     * 更新时间
+     */
+    @ApiModelProperty("更新时间")
+    @TableField("updated_time")
+    private Date updatedTime;
+
+    /**
+     * 逻辑删除标识
+     */
+    @ApiModelProperty("逻辑删除标识")
+    @TableField("is_deleted")
+    @TableLogic
+    private Integer isDeleted;
+
+
+}

+ 6 - 2
mp-service/src/main/java/com/qs/mp/pay/domain/PayOrder.java

@@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
 import com.qs.mp.common.enums.BizTypeEnum;
+import io.swagger.annotations.ApiModelProperty;
 import java.io.Serializable;
 import java.util.Date;
 import lombok.Data;
@@ -26,6 +27,9 @@ public class PayOrder implements Serializable {
   @TableId(value = "order_id" , type = IdType.INPUT)
   private String orderId;
 
+  @ApiModelProperty("商户系统生成的订单号")
+  private String tradeNo;
+
   /**
    * 订单类型,1:渠道订单,2用户订单
    */
@@ -51,14 +55,14 @@ public class PayOrder implements Serializable {
   private String orderTime;
 
   /**
-   * 支付来源 1:支付宝  2:微信支付 5:云闪付
+   * 支付来源 1:支付宝  2:微信支付 5:云闪付,3银盛
    * 增加直连来源(2022.7) 10:支付宝直连
    */
   @TableField("pay_resource")
   private String payResource;
 
   /**
-   * 1004:支付宝CTB;1008:微信公众号(需要绑定支付目录)1014: 支付宝服务窗1016:云闪付CTB1017:微信小程序1019:支付宝小程序(请用1014编码)
+   * 1004:支付宝CTB;1008:微信公众号(需要绑定支付目录)1014: 支付宝服务窗1016:云闪付CTB1017:微信小程序1019:支付宝小程序(请用1014编码),1020:银盛H5
    *
    */
   @TableField("trans_type_code")

+ 13 - 0
mp-service/src/main/java/com/qs/mp/pay/mapper/DivisionLogMapper.java

@@ -0,0 +1,13 @@
+package com.qs.mp.pay.mapper;
+
+import com.qs.mp.pay.domain.DivisionLog;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+ * @auther quanshu
+ * @create 2023-03-27 14:24:26
+ * @describe 分账记录表mapper类
+ */
+public interface DivisionLogMapper extends BaseMapper<DivisionLog> {
+
+}

+ 16 - 0
mp-service/src/main/java/com/qs/mp/pay/service/IDivisionLogService.java

@@ -0,0 +1,16 @@
+package com.qs.mp.pay.service;
+
+import com.qs.mp.pay.domain.DivisionLog;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ * 分账记录表 服务类
+ * </p>
+ *
+ * @author quanshu
+ * @since 2023-03-27
+ */
+public interface IDivisionLogService extends IService<DivisionLog> {
+
+}

+ 19 - 0
mp-service/src/main/java/com/qs/mp/pay/service/IWalletService.java

@@ -11,6 +11,18 @@ import com.qs.mp.pay.domain.PayOrder;
  */
 public interface IWalletService {
 
+
+  /**
+   * 银盛h5支付
+   * @param bizType
+   * @param bizId
+   * @param money
+   * @param orderRemark
+   * @return
+   */
+  JSONObject h5Pay(BizTypeEnum bizType, String bizId, int money, String orderRemark);
+
+
   /**
    * 支付宝直连支付
    * @param bizType
@@ -59,6 +71,13 @@ public interface IWalletService {
    */
   boolean refund(String bizId, Integer refundAmount, String remark);
 
+  /**
+   * 银盛提现
+   * @param bizId
+   * @return
+   */
+  boolean withdrawal(String bizId);
+
 
   /**
    *

+ 20 - 0
mp-service/src/main/java/com/qs/mp/pay/service/impl/DivisionLogServiceImpl.java

@@ -0,0 +1,20 @@
+package com.qs.mp.pay.service.impl;
+
+import com.qs.mp.pay.domain.DivisionLog;
+import com.qs.mp.pay.mapper.DivisionLogMapper;
+import com.qs.mp.pay.service.IDivisionLogService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ * 分账记录表 服务实现类
+ * </p>
+ *
+ * @author quanshu
+ * @since 2023-03-27
+ */
+@Service
+public class DivisionLogServiceImpl extends ServiceImpl<DivisionLogMapper, DivisionLog> implements IDivisionLogService {
+
+}

+ 215 - 0
mp-service/src/main/java/com/qs/mp/pay/service/impl/WalletServiceImpl.java

@@ -9,16 +9,32 @@ import com.alipay.api.request.AlipayTradeCreateRequest;
 import com.alipay.api.response.AlipayTradeCreateResponse;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import com.eptok.yspay.opensdkjava.common.Constants;
+import com.eptok.yspay.opensdkjava.fund.MercFundApi;
+import com.eptok.yspay.opensdkjava.orderpay.AppPayApi;
+import com.eptok.yspay.opensdkjava.pojo.vo.OnlineReqDataVo;
+import com.eptok.yspay.opensdkjava.util.DateUtil;
+import com.eptok.yspay.opensdkjava.util.HttpClientUtil;
+import com.eptok.yspay.opensdkjava.util.StringUtil;
+import com.eptok.yspay.opensdkjava.util.YsOnlineSignUtils;
+import com.qs.mp.channel.domain.ChannelWithdraw;
 import com.qs.mp.channel.service.IChannelGoodsOrderService;
 import com.qs.mp.channel.service.IChannelGoodsSettleOrderService;
 import com.qs.mp.channel.service.IChannelOrderService;
+import com.qs.mp.channel.service.IChannelWithdrawService;
+import com.qs.mp.common.constant.YsPayMethodConstants;
+import com.qs.mp.common.constant.YsServerApiConstants;
+import com.qs.mp.common.domain.YsCallLog;
 import com.qs.mp.common.enums.AppSourceEnum;
 import com.qs.mp.common.enums.AsyncTaskTypeEnum;
 import com.qs.mp.common.enums.BizTypeEnum;
+import com.qs.mp.common.enums.ChannelWithdrawStatusEnum;
 import com.qs.mp.common.enums.MqTopicType;
 import com.qs.mp.common.enums.PayOrderStatusEnum;
+import com.qs.mp.common.enums.YsCallBizTypeEnum;
 import com.qs.mp.common.exception.ServiceException;
 import com.qs.mp.common.pulsar.PulsarClientService;
+import com.qs.mp.common.service.IYsCallLogService;
 import com.qs.mp.common.utils.DateUtils;
 import com.qs.mp.common.utils.LogUtil;
 import com.qs.mp.common.utils.StringUtils;
@@ -85,6 +101,14 @@ public class WalletServiceImpl implements IWalletService {
   @Autowired
   private IChannelGoodsSettleOrderService settleOrderService;
 
+  @Autowired
+  private IChannelWithdrawService channelWithdrawService;
+
+  @Autowired
+  private IYsCallLogService ysCallLogService;
+
+  @Autowired
+
   @Value("${pay.notifyUrl}")
   private String notifyUrl;  //支付成功前端跳转地址
   @Value("${pay.callbackUrl}")
@@ -139,6 +163,117 @@ public class WalletServiceImpl implements IWalletService {
   private AlipayClient alipayClient = null;
 
 
+  @Value("${ys-pay.partner-id}")
+  private String partnerId;
+
+  @Value("${ys-pay.private-key-pass}")
+  private String privateKeyPass;
+
+  @Value("${ys-pay.private-key-path}")
+  private String privateKeyPath;
+
+  @Value("${ys-pay.public-key-path}")
+  private String publicKeyPath;
+
+  @Value("${ys-pay.master-seller-id}")
+  private String masterSellerId;
+
+  @Value("${ys-pay.child-seller-id}")
+  private String childSellerId;
+
+  @Value("${ys-pay.return-url}")
+  private String ysReturnUrl;
+  @Value("${ys-pay.pay-notify-url}")
+  private String ysPayNotifyUrl;
+
+  @Value("${ys-pay.withdraw-notify-url}")
+  private String ysWithdrawNotifyUrl;
+
+  @Override
+  public JSONObject h5Pay(BizTypeEnum bizType, String bizId, int money, String orderRemark) {
+    Map<String, String> params = new HashMap<>();
+    String orderId = String.valueOf(bizIdGenerator.newId());
+    String tradeNo = DateUtil.getDateNowYmd() + DateUtil.getRandom(14);
+    // 返回页面拼接
+
+    String returnUrl = ysReturnUrl;
+    if (BizTypeEnum.TICKET_ORDER.equals(bizType)) {
+      UserTicketOrder userTicketOrder = userTicketOrderService.getById(bizId);
+      returnUrl = returnUrl + "?boxId=" + userTicketOrder.getBoxId() + "&orderId=" + bizId + "&istry=0";
+    }
+    params.put("method", YsPayMethodConstants.H5_PAY_METHOD);
+    params.put("partner_id", partnerId);
+    params.put("timestamp", DateUtil.getDateNow());
+    params.put("charset", Constants.CHARSET_UTF_8);
+    params.put("sign_type", "RSA");
+    params.put("notify_url", ysPayNotifyUrl);
+    params.put("return_url", returnUrl);
+    params.put("seller_id", partnerId);
+    params.put("version","3.0");
+    params.put("out_trade_no", tradeNo);
+    params.put("shopdate", DateUtil.getDateNowYmd());
+    params.put("subject", orderRemark);
+    params.put("total_amount", new BigDecimal(money).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP).toString());
+    params.put("timeout_express","96h");
+    params.put("business_code", "3010002");
+    try {
+      String sign = YsOnlineSignUtils.sign(params, privateKeyPass, privateKeyPath);
+      params.put("sign", sign);
+    } catch (Exception e) {
+      logger.error("签名失败,bizId=" + bizId, e);
+      throw new ServiceException("支付发起签名失败");
+    }
+
+//    String result = OkHttpUtil.post("https://openapi.ysepay.com/gateway.do", params);
+//
+    // 保存调用记录
+    YsCallLog ysCallLog = new YsCallLog();
+    ysCallLog.setBizId(orderId);
+    ysCallLog.setBizType(YsCallBizTypeEnum.ORDER_PAY);
+    ysCallLog.setInterfaceId(YsPayMethodConstants.H5_PAY_METHOD);
+    ysCallLog.setReqJson(JSONObject.toJSONString(params));
+    ysCallLogService.save(ysCallLog);
+
+//
+//    String result = "https://openapi.ysepay.com/gateway.do?";
+//    for (String key : params.keySet()) {
+//      result += key + "=" + params.get(key);
+//      // 如果是最后一个,则不再末尾加上&
+//      if (key != params.keySet().toArray()[params.keySet().size() - 1]) {
+//          result += "&";
+//      }
+//    }
+//    System.out.println("result = " + result);
+
+//
+//    //保存订单记录
+    PayOrder payOrder = new PayOrder();
+    payOrder.setOrderId(orderId);
+    payOrder.setBizType(bizType);
+    payOrder.setBizId(bizId);
+    payOrder.setTradeNo(tradeNo);
+    payOrder.setOrderTime(DateUtils.getTime());
+    payOrder.setPayResource("3"); // 支付宝直连
+    payOrder.setTransTypeCode("1020"); // 支付宝小程序
+    payOrder.setTransactionAmount(money);
+    payOrder.setOrderRemark(orderRemark);
+    payOrder.setOrderName(orderRemark);
+    payOrder.setOrderStatus(PayOrderStatusEnum.WAIT.getValue());
+    boolean ret = payOrderService.save(payOrder);
+    if (!ret) {
+      LogUtil.error(logger, "支付订单数据保存失败.");
+      throw new ServiceException("支付订单保存失败");
+    }
+//
+//    JSONObject data = new JSONObject();
+//    data.put("payUrl", result);
+
+
+    JSONObject data = JSONObject.parseObject(JSONObject.toJSONString(params));
+    return data;
+  }
+
+
   @Override
   public JSONObject directAliPay(BizTypeEnum bizType, String bizId, String openId, int money, String orderRemark) {
     if (null == alipayClient) {
@@ -340,6 +475,86 @@ public class WalletServiceImpl implements IWalletService {
   }
 
 
+  @Override
+  @Transactional(rollbackFor = Exception.class)
+  public boolean withdrawal(String bizId) {
+    /*ChannelWithdraw channelWithdraw = channelWithdrawService.getById(bizId);
+
+    if (!ChannelWithdrawStatusEnum.WITHDRAWING.equals(channelWithdraw.getStatus())) {
+        throw new ServiceException("提现状态不正确");
+    }
+
+    String tradeNo = DateUtil.getDateNowYmd() + DateUtil.getRandom(14);
+
+      boolean res = channelWithdrawService.update(new LambdaUpdateWrapper<ChannelWithdraw>()
+          .set(ChannelWithdraw::getTradeNo, tradeNo)
+          .set(ChannelWithdraw::getStatus, ChannelWithdrawStatusEnum.WITHDRAW_PROCESS)
+          .eq(ChannelWithdraw::getId, channelWithdraw.getId())
+          .eq(ChannelWithdraw::getStatus, ChannelWithdrawStatusEnum.WITHDRAWING));
+      if (!res) {
+          throw new ServiceException("提现状态更新失败");
+      }
+
+
+    OnlineReqDataVo req = new OnlineReqDataVo();
+    req.setReqUrl(YsServerApiConstants.COMMON_API);
+    req.setPrivateKeyFilePath(privateKeyPath);
+    req.setYsPublicKeyFilePath(publicKeyPath);
+    req.setPrivateKeyPassword(privateKeyPass);
+    req.setNotifyUrl(ysWithdrawNotifyUrl);
+    req.setPartnerId(partnerId);
+
+    //实时提现(一般户到银行卡)业务参数
+    Map<String, Object> bizContent = new HashMap<>();
+    //商户生成的订单号,生成规则前8位必须为交易日期,如20180525,范围跨度支持包含当天在内的前后一天
+    bizContent.put("out_trade_no", tradeNo);
+    //商户号
+    bizContent.put("merchant_usercode", partnerId);
+    //暂时只支持币种:CNY(人民币)
+    bizContent.put("currency", "CNY");
+    //提现的总金额。单位为:RMB Yuan。取值范围为[0.01,99999999.99],精确到小数点后两位。Number(10,2)指10位长度,2位精度
+    bizContent.put("total_amount", new BigDecimal(channelWithdraw.getMoney()).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP).toString());
+    //订单说明
+    bizContent.put("subject", "提现备注");
+    //商户日期(该参数做交易与查询时需要一致) 该日期需在当日的前后一天时间范围之内
+    bizContent.put("shopdate", DateUtil.getDateNowYmd());
+    //银行帐号
+    bizContent.put("bank_account_no", channelWithdraw.getCardNo());
+    req.setParamData(bizContent);
+    String result = null;
+    try{
+      logger.info("实时提现(一般户到银行卡)调用sdk接口addScanMerc请求入参为:"+ JSONObject.toJSONString(req));
+      //根据返回结果处理自己的业务逻辑,result内容详见接口文档
+      result = MercFundApi.withdrawQuick(req);
+    }catch (Exception e){
+      logger.info("实时提现(一般户到银行卡)失败:"+ e.getMessage());
+    }
+
+    logger.info("提现提交result = " + result);
+
+    // 保存调用日志
+      YsCallLog ysCallLog = new YsCallLog();
+      ysCallLog.setInterfaceId(YsPayMethodConstants.SETTLED_ACCOUNT_WITHDRAW_METHOD);
+      ysCallLog.setBizId(tradeNo);
+      ysCallLog.setBizType(YsCallBizTypeEnum.WITHDRAW);
+      ysCallLog.setReqJson(JSONObject.toJSONString(bizContent));
+      ysCallLog.setResJson(result);
+      ysCallLogService.save(ysCallLog);
+
+      if (StringUtils.isBlank(result)) {
+            throw new ServiceException("提现交易处理失败");
+    }
+
+    JSONObject response = JSONObject.parseObject(result);
+    String tradeStatus = (String) response.get("trade_status");
+    if (StringUtils.isBlank(tradeStatus) &&
+        (!"TRADE_ACCEPT_SUCCESS".equals(tradeStatus) || !"TRADE_SUCCESS".equals(tradeStatus))) {
+      logger.error("提现交易处理失败,result = " + result);
+        throw new ServiceException("提现交易处理失败");
+    }*/
+    return true;
+  }
+
   @Override
   public void payOrderStatusHandle(PayOrder payOrder) {
     String orderNo = payOrder.getOrderId();

+ 1 - 0
mp-service/src/main/java/com/qs/mp/system/mapper/SysUserRoleMapper.java

@@ -1,5 +1,6 @@
 package com.qs.mp.system.mapper;
 
+import com.qs.mp.system.domain.SysUser;
 import com.qs.mp.system.domain.SysUserRole;
 import java.util.List;
 import org.apache.ibatis.annotations.Param;

+ 21 - 0
mp-service/src/main/resources/mapper/channel/ChannelBankMapper.xml

@@ -0,0 +1,21 @@
+<?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.qs.mp.channel.mapper.ChannelBankMapper">
+
+    <!-- 通用查询映射结果 -->
+    <resultMap id="BaseResultMap" type="com.qs.mp.channel.domain.ChannelBank">
+        <id column="id" property="id" />
+        <result column="channel_id" property="channelId" />
+        <result column="bank_no" property="bankNo" />
+        <result column="bank_name" property="bankName" />
+        <result column="created_time" property="createdTime" />
+        <result column="updated_time" property="updatedTime" />
+        <result column="is_deleted" property="isDeleted" />
+    </resultMap>
+
+    <!-- 通用查询结果列 -->
+    <sql id="Base_Column_List">
+        id, channel_id, bank_no, bank_name, created_time, updated_time, is_deleted
+    </sql>
+
+</mapper>

+ 22 - 0
mp-service/src/main/resources/mapper/common/YsCallLogMapper.xml

@@ -0,0 +1,22 @@
+<?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.qs.mp.common.mapper.YsCallLogMapper">
+
+    <!-- 通用查询映射结果 -->
+    <resultMap id="BaseResultMap" type="com.qs.mp.common.domain.YsCallLog">
+        <id column="id" property="id" />
+        <result column="req_id" property="reqId" />
+        <result column="interface_id" property="interfaceId" />
+        <result column="req_json" property="reqJson" />
+        <result column="res_json" property="resJson" />
+        <result column="created_time" property="createdTime" />
+        <result column="updated_time" property="updatedTime" />
+        <result column="is_deleted" property="isDeleted" />
+    </resultMap>
+
+    <!-- 通用查询结果列 -->
+    <sql id="Base_Column_List">
+        id, req_id, interface_id, req_json, res_json, created_time, updated_time, is_deleted
+    </sql>
+
+</mapper>

+ 23 - 0
mp-service/src/main/resources/mapper/pay/DivisionLogMapper.xml

@@ -0,0 +1,23 @@
+<?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.qs.mp.pay.mapper.DivisionLogMapper">
+
+    <!-- 通用查询映射结果 -->
+    <resultMap id="BaseResultMap" type="com.qs.mp.pay.domain.DivisionLog">
+        <id column="id" property="id" />
+        <result column="trade_no" property="tradeNo" />
+        <result column="order_no" property="orderNo" />
+        <result column="biz_id" property="bizId" />
+        <result column="amount" property="amount" />
+        <result column="status" property="status" />
+        <result column="created_time" property="createdTime" />
+        <result column="updated_time" property="updatedTime" />
+        <result column="is_deleted" property="isDeleted" />
+    </resultMap>
+
+    <!-- 通用查询结果列 -->
+    <sql id="Base_Column_List">
+        id, trade_no, order_no, biz_id, amount, status, created_time, updated_time, is_deleted
+    </sql>
+
+</mapper>

+ 1 - 1
mp-service/src/main/resources/mapper/system/SysUserRoleMapper.xml

@@ -49,4 +49,4 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 	<update id="updateUserRole" parameterType="com.qs.mp.system.domain.SysUserRole">
 		update sys_user_role set role_id = #{roleId} where user_id=#{userId}
 	</update>
-</mapper> 
+</mapper>