Explorar el Código

1、调整直播支付
2、调整扫码回调
3、迁移取消收藏接口

yys hace 3 semanas
padre
commit
eb3769e2e5
Se han modificado 19 ficheros con 389 adiciones y 13 borrados
  1. 18 0
      fs-live-app/src/main/java/com/fs/framework/config/SecurityConfig.java
  2. 10 3
      fs-qw-api-msg/src/main/java/com/fs/app/controller/QwMsgController.java
  3. 9 0
      fs-service/src/main/java/com/fs/app/service/impl/AppPayServiceImpl.java
  4. 3 0
      fs-service/src/main/java/com/fs/course/mapper/FsUserCourseFavoriteMapper.java
  5. 2 0
      fs-service/src/main/java/com/fs/course/mapper/FsUserCourseMapper.java
  6. 1 0
      fs-service/src/main/java/com/fs/course/service/IFsUserCourseFavoriteService.java
  7. 2 0
      fs-service/src/main/java/com/fs/course/service/IFsUserCourseService.java
  8. 6 0
      fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseFavoriteServiceImpl.java
  9. 6 0
      fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseServiceImpl.java
  10. 4 0
      fs-service/src/main/java/com/fs/live/service/ILiveOrderService.java
  11. 239 0
      fs-service/src/main/java/com/fs/live/service/impl/LiveOrderServiceImpl.java
  12. 1 1
      fs-service/src/main/java/com/fs/qw/service/impl/QwUserServiceImpl.java
  13. 15 6
      fs-service/src/main/resources/mapper/course/FsUserCourseFavoriteMapper.xml
  14. 6 1
      fs-service/src/main/resources/mapper/course/FsUserCourseMapper.xml
  15. 10 0
      fs-user-app/src/main/java/com/fs/app/controller/CourseController.java
  16. 3 0
      fs-user-app/src/main/java/com/fs/app/controller/HuifuPayController.java
  17. 43 0
      fs-user-app/src/main/java/com/fs/app/controller/live/LiveOrderController.java
  18. 3 0
      fs-user-app/src/main/java/com/fs/app/controller/store/PayScrmController.java
  19. 8 2
      fs-user-app/src/main/java/com/fs/framework/config/SecurityConfig.java

+ 18 - 0
fs-live-app/src/main/java/com/fs/framework/config/SecurityConfig.java

@@ -6,6 +6,10 @@ import org.springframework.security.config.BeanIds;
 import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
 import org.springframework.security.config.annotation.web.builders.HttpSecurity;
 import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+import org.springframework.security.web.firewall.HttpFirewall;
+import org.springframework.security.web.firewall.StrictHttpFirewall;
+
+import java.util.Arrays;
 
 /**
  * spring security配置
@@ -46,5 +50,19 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
         return super.authenticationManagerBean();
     }
 
+    /**
+     * 允许 WebDAV 探测方法通过防火墙,避免外部扫描触发 RequestRejectedException 刷屏。
+     * 请求仍会因无对应接口而正常返回 404,不影响业务安全。
+     */
+    @Bean
+    public HttpFirewall httpFirewall() {
+        StrictHttpFirewall firewall = new StrictHttpFirewall();
+        firewall.setAllowUrlEncodedDoubleSlash(true);
+        firewall.setAllowedHttpMethods(Arrays.asList(
+                "GET", "POST", "PUT", "DELETE", "HEAD", "OPTIONS", "PATCH",
+                "PROPFIND", "PROPPATCH", "MKCOL", "COPY", "MOVE", "LOCK", "UNLOCK", "SEARCH"
+        ));
+        return firewall;
+    }
 
 }

+ 10 - 3
fs-qw-api-msg/src/main/java/com/fs/app/controller/QwMsgController.java

@@ -247,9 +247,10 @@ public class QwMsgController {
     }
 
 
-    @PostMapping("/callback/{serverId}")
+    @PostMapping("/callback/{serverId}/{isNewVersion}")
     @ResponseBody
-    public Map<String,String> callback(@RequestBody String json,@PathVariable Long serverId ){
+    public Map<String,String> callback(@RequestBody String json, @PathVariable Long serverId, @PathVariable(required = false) Boolean isNewVersion){
+
       //  System.out.println(json);
         WxWorkMsgResp wxWorkMsgResp = JSON.parseObject(json, WxWorkMsgResp.class);
         Integer type = wxWorkMsgResp.getType();
@@ -321,7 +322,10 @@ public class QwMsgController {
                 log.info("id:{}, 需要二次验证:"+wxWorkMsgResp.getJson(), id);
 
                 redisCache.setCacheObject("qrCodeUid:"+wxWorkMsgResp.getUuid(),100012,10, TimeUnit.MINUTES);
-
+                QwUser qwUser1 = qwUserMapper.selectQwUserById(id);
+                if(qwUser1.getUid().equals(wxWorkMsgResp.getUuid())){
+                    qwUserService.atMsg(qwUser1, "需要二次验证(在销售后台,企微员工页面点击二次验证)");
+                }
                 break;
             case 100005:
 
@@ -355,6 +359,9 @@ public class QwMsgController {
                 break;
             case 102000:
                 WxWorkMessageDTO wxWorkMessageDTO = JSON.parseObject(wxWorkMsgResp.getJson(), WxWorkMessageDTO.class);
+                if (wxWorkMessageDTO.getIs_room()!=0){
+                    break;
+                }
                 if (wxWorkMessageDTO.getReferid()!=0){
                     break;
                 }

+ 9 - 0
fs-service/src/main/java/com/fs/app/service/impl/AppPayServiceImpl.java

@@ -29,6 +29,7 @@ import com.fs.his.mapper.FsUserWxMapper;
 import com.fs.his.param.FsPackageOrderDoPayParam;
 import com.fs.his.service.*;
 import com.fs.huifuPay.service.HuiFuService;
+import com.fs.live.service.ILiveOrderService;
 import com.fs.system.domain.SysConfig;
 import com.fs.system.mapper.SysConfigMapper;
 import com.fs.system.service.ISysConfigService;
@@ -73,6 +74,8 @@ public class AppPayServiceImpl implements AppPayService {
     private IFsUserCourseOrderService courseOrderService;
     @Autowired
     private IFsUserVipOrderService vipOrderService;
+    @Autowired
+    private ILiveOrderService liveOrderService;
 
     /**
      * 支付宝回调
@@ -111,6 +114,9 @@ public class AppPayServiceImpl implements AppPayService {
                 case "course":
                     courseOrderService.payConfirm("", arr[1],"","",1,tradeNo,"");
                     break;
+                case "applive":
+                    liveOrderService.payConfirm(1, null, arr[1], tradeNo, tradeNo, null);
+                    break;
             }
 
 
@@ -150,6 +156,9 @@ public class AppPayServiceImpl implements AppPayService {
             case "course":
                 courseOrderService.payConfirm("", tradeNoArr[1],"","",1,result.getTransactionId(),"");
                 break;
+            case "applive":
+                liveOrderService.payConfirm(1, null, tradeNoArr[1], result.getTransactionId(), result.getTransactionId(), null);
+                break;
         }
         return WxPayNotifyResponse.success("OK");
     }

+ 3 - 0
fs-service/src/main/java/com/fs/course/mapper/FsUserCourseFavoriteMapper.java

@@ -88,4 +88,7 @@ public interface FsUserCourseFavoriteMapper
             " order by f.create_time desc "+
             "</script>"})
     List<FsUserCourseFavoriteListUVO> selectFsUserCourseFavoriteListUVO(@Param("maps") FsUserCourseListUParam param);
+
+
+    int deleteBatchFavorite(@Param("courseIds") List<Long> courseIds, @Param("userId") long userId);
 }

+ 2 - 0
fs-service/src/main/java/com/fs/course/mapper/FsUserCourseMapper.java

@@ -311,4 +311,6 @@ public interface FsUserCourseMapper
     List<FsUserCourse> selectFsUserCourseByCourseIds(@Param("courseIds")List<Long> courseIds);
 
     int batchUpdateUserCourse(@Param("list")List<FsUserCourse> list);
+
+    int minusBatchFavorite(@Param("courseIds") List<Long> courseIds);
 }

+ 1 - 0
fs-service/src/main/java/com/fs/course/service/IFsUserCourseFavoriteService.java

@@ -71,4 +71,5 @@ public interface IFsUserCourseFavoriteService
 
     List<FsUserCourseFavoriteListUVO> selectFsUserCourseFavoriteListUVO(FsUserCourseListUParam param);
 
+    int deleteBatchFavorite(List<Long> courseIds, long l);
 }

+ 2 - 0
fs-service/src/main/java/com/fs/course/service/IFsUserCourseService.java

@@ -139,4 +139,6 @@ public interface IFsUserCourseService {
     void editConfig(Long id, String configJson);
 
     R batchUpdateUserCourse(FsUserCourseBatchUpdateParam param);
+
+    int minusBatchFavorite(List<Long> courseIds);
 }

+ 6 - 0
fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseFavoriteServiceImpl.java

@@ -112,4 +112,10 @@ public class FsUserCourseFavoriteServiceImpl implements IFsUserCourseFavoriteSer
     public List<FsUserCourseFavoriteListUVO> selectFsUserCourseFavoriteListUVO(FsUserCourseListUParam param) {
         return fsUserCourseFavoriteMapper.selectFsUserCourseFavoriteListUVO(param);
     }
+
+    @Override
+    public int deleteBatchFavorite(List<Long> courseIds, long userId) {
+        return fsUserCourseFavoriteMapper.deleteBatchFavorite(courseIds,userId);
+    }
+
 }

+ 6 - 0
fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseServiceImpl.java

@@ -852,6 +852,12 @@ public class FsUserCourseServiceImpl implements IFsUserCourseService
         return R.ok();
     }
 
+    @Override
+    public int minusBatchFavorite(List<Long> courseIds) {
+        return fsUserCourseMapper.minusBatchFavorite(courseIds);
+    }
+
+
 
     private Graphics2D initializeGraphics(BufferedImage combined) {
         Graphics2D graphics = combined.createGraphics();

+ 4 - 0
fs-service/src/main/java/com/fs/live/service/ILiveOrderService.java

@@ -17,6 +17,8 @@ import com.fs.live.vo.LiveOrderDeliveryNoteExportVO;
 import com.fs.store.domain.FsStoreDelivers;
 import org.springframework.web.bind.annotation.RequestBody;
 
+import javax.servlet.http.HttpServletRequest;
+
 import java.math.BigDecimal;
 import java.text.ParseException;
 import java.util.List;
@@ -242,6 +244,8 @@ public interface ILiveOrderService {
 
     R handleLiveOrderPay(LiveOrderPayParam param);
 
+    R appPayment(LiveOrderAppPayParam param, HttpServletRequest request);
+
     List<LiveOrder> selectLiveOrderItemJson();
 
     void refreshOrderSettlementStatus();

+ 239 - 0
fs-service/src/main/java/com/fs/live/service/impl/LiveOrderServiceImpl.java

@@ -28,6 +28,12 @@ import com.alibaba.fastjson.JSON;
 
 import com.alibaba.fastjson.JSONObject;
 import com.alibaba.fastjson.TypeReference;
+import com.alipay.api.AlipayClient;
+import com.alipay.api.DefaultAlipayClient;
+import com.alipay.api.diagnosis.DiagnosisUtils;
+import com.alipay.api.domain.AlipayTradeAppPayModel;
+import com.alipay.api.request.AlipayTradeAppPayRequest;
+import com.alipay.api.response.AlipayTradeAppPayResponse;
 import com.baomidou.mybatisplus.core.conditions.Wrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.fs.common.config.FSSysConfig;
@@ -83,6 +89,7 @@ import com.fs.common.utils.SnowflakeUtil;
 import com.fs.huifuPay.sdk.opps.core.utils.HuiFuUtils;
 import com.fs.his.domain.MerchantAppConfig;
 import com.fs.his.domain.FsPayConfig;
+import com.fs.his.service.IFsUserService;
 import com.fs.system.domain.SysConfig;
 import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl;
 import com.google.gson.Gson;
@@ -137,6 +144,7 @@ import org.springframework.transaction.interceptor.TransactionAspectSupport;
 
 import javax.annotation.PostConstruct;
 import javax.annotation.PreDestroy;
+import javax.servlet.http.HttpServletRequest;
 
 import static com.fs.hisStore.constants.StoreConstants.DELIVERY;
 
@@ -193,6 +201,9 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
     @Autowired
     FsUserScrmMapper userMapper;
 
+    @Autowired
+    private IFsUserService fsUserService;
+
     @Autowired
     private IErpOrderService erpOrderService;
 
@@ -3731,6 +3742,234 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
 
     }
 
+    @Override
+    @Transactional(rollbackFor = Throwable.class, propagation = Propagation.REQUIRED)
+    public R appPayment(LiveOrderAppPayParam param, HttpServletRequest request) {
+        LiveOrder order = baseMapper.selectLiveOrderByOrderId(String.valueOf(param.getOrderId()));
+        if (order == null) {
+            return R.error("订单不存在");
+        }
+        if (!order.getStatus().equals(OrderInfoEnum.STATUS_0.getValue())) {
+            return R.error("订单状态不正确");
+        }
+        String payingOrderId = redisCache.getCacheObject("isPaying:" + order.getOrderId());
+        if (StringUtils.isNotEmpty(payingOrderId) && order.getOrderId().toString().equals(payingOrderId)) {
+            return R.error(501, "正在支付中...");
+        }
+        FsUserScrm user = userMapper.selectFsUserById(Long.valueOf(order.getUserId()));
+        if (user == null) {
+            return R.error("未找到用户信息,请联系管理员!");
+        }
+
+        if (order.getIsEditMoney() == null || order.getIsEditMoney() != 1) {
+            String config = configService.selectConfigByKey("his.store");
+            com.fs.store.config.StoreConfig storeConfig = JSONUtil.toBean(config, com.fs.store.config.StoreConfig.class);
+            if (param.getOrderPayType().equals(1)) {
+                order.setPayType("1");
+                order.setPayMoney(order.getPayPrice());
+                order.setPayDelivery(BigDecimal.ZERO);
+            } else if (param.getOrderPayType().equals(2)) {
+                order.setPayType("2");
+                BigDecimal payMoney = order.getPayPrice().multiply(new BigDecimal(storeConfig.getPayRate())).divide(new BigDecimal(100));
+                payMoney = new BigDecimal(payMoney.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue());
+                if (payMoney.compareTo(new BigDecimal("0.01")) < 0) {
+                    return R.error("物流代收计算支付金额为0,不允许选择物流代收");
+                }
+                order.setPayDelivery(order.getPayPrice().subtract(payMoney));
+                order.setPayMoney(payMoney);
+            } else if (param.getOrderPayType().equals(3)) {
+                order.setPayType("3");
+                BigDecimal amount = redisCache.getCacheObject("orderAmount:" + order.getOrderId());
+                BigDecimal payMoney = BigDecimal.ZERO;
+                if (amount != null) {
+                    payMoney = amount;
+                }
+                BigDecimal payPostage = order.getPayPostage();
+                if (payPostage == null || payPostage.compareTo(BigDecimal.ZERO) <= 0) {
+                    payPostage = storeConfig.getPayPostage();
+                    if (payPostage == null) {
+                        payPostage = BigDecimal.ZERO;
+                    }
+                    order.setPayPrice(order.getPayPrice().add(payPostage));
+                }
+                order.setPayPostage(payPostage);
+                payMoney = payMoney.add(payPostage);
+                order.setPayMoney(payMoney);
+                order.setPayDelivery(order.getPayPrice().subtract(payMoney));
+            }
+            if (StringUtils.isNotEmpty(param.getAppId())) {
+                order.setAppId(param.getAppId());
+            }
+            baseMapper.updateLiveOrder(order);
+        }
+
+        if (order.getPayType().equals("3") && order.getPayMoney().compareTo(BigDecimal.ZERO) <= 0) {
+            this.payConfirm(2, order.getOrderId(), null, null, null, null);
+            return R.ok().put("payType", param.getOrderPayType()).put("isPay", 1);
+        }
+
+        if (order.getPayMoney().compareTo(BigDecimal.ZERO) <= 0) {
+            this.payConfirm(2, order.getOrderId(), null, null, null, null);
+            return R.ok().put("isPay", 1);
+        }
+
+        if (StringUtils.isBlank(param.getAppId())) {
+            throw new IllegalArgumentException("appId不能为空");
+        }
+        FsCoursePlaySourceConfig fsCoursePlaySourceConfig = fsCoursePlaySourceConfigMapper.selectCoursePlaySourceConfigByAppId(param.getAppId());
+        if (fsCoursePlaySourceConfig == null) {
+            throw new CustomException("未找到appId对应的配置: " + param.getAppId());
+        }
+        Long merchantConfigId = fsCoursePlaySourceConfig.getMerchantConfigId();
+        if (merchantConfigId == null || merchantConfigId <= 0) {
+            throw new CustomException("没有配置商户信息");
+        }
+        MerchantAppConfig merchantAppConfig = merchantAppConfigMapper.selectMerchantAppConfigById(fsCoursePlaySourceConfig.getMerchantConfigId());
+        FsPayConfig fsPayConfig = JSON.parseObject(merchantAppConfig.getDataJson(), FsPayConfig.class);
+
+        String openId = null;
+        String appId = param.getAppId();
+        if (request.getHeader("sourcetype") != null && "APP".equals(request.getHeader("sourcetype"))) {
+            FsUser fsUser = fsUserService.selectFsUserByUserId(Long.valueOf(order.getUserId()));
+            if (fsUser != null) {
+                openId = fsUser.getAppOpenId();
+            }
+        } else {
+            if (StringUtils.isNotBlank(appId)) {
+                Wrapper<FsUserWx> queryWrapper = Wrappers.<FsUserWx>lambdaQuery()
+                        .eq(FsUserWx::getFsUserId, order.getUserId())
+                        .eq(FsUserWx::getAppId, appId);
+                FsUserWx fsUserWx = fsUserWxMapper.selectOne(queryWrapper);
+                if (fsUserWx != null) {
+                    openId = fsUserWx.getOpenId();
+                }
+            } else {
+                appId = merchantAppConfig.getAppId();
+                openId = user.getMaOpenId();
+                if (StringUtils.isBlank(openId)) {
+                    Wrapper<FsUserWx> queryWrapper = Wrappers.<FsUserWx>lambdaQuery()
+                            .eq(FsUserWx::getFsUserId, order.getUserId())
+                            .eq(FsUserWx::getAppId, appId);
+                    FsUserWx fsUserWx = fsUserWxMapper.selectOne(queryWrapper);
+                    if (fsUserWx != null) {
+                        openId = fsUserWx.getOpenId();
+                    }
+                }
+            }
+        }
+
+        if ("hf".equals(merchantAppConfig.getMerchantType()) && "wx".equals(param.getPayType()) && StringUtils.isBlank(openId)) {
+            return R.error("用户OPENID不存在");
+        }
+
+        String payCode = OrderCodeUtils.getOrderSn();
+        if (StringUtils.isEmpty(payCode)) {
+            return R.error("订单生成失败,请重试");
+        }
+
+        LiveOrderPayment storePayment = new LiveOrderPayment();
+        storePayment.setCompanyId(order.getCompanyId());
+        storePayment.setCompanyUserId(order.getCompanyUserId());
+        storePayment.setPayMode(merchantAppConfig.getMerchantType());
+        storePayment.setStatus(0);
+        storePayment.setPayCode(payCode);
+        storePayment.setPayMoney(order.getPayMoney());
+        storePayment.setCreateTime(new Date());
+        storePayment.setPayTypeCode(param.getPayType());
+        storePayment.setBusinessType(9);
+        storePayment.setRemark("直播订单app支付");
+        storePayment.setOpenId(openId);
+        storePayment.setUserId(user.getUserId());
+        storePayment.setBusinessId(String.valueOf(order.getOrderId()));
+        storePayment.setBusinessCode(order.getOrderCode());
+        storePayment.setAppId(appId);
+        storePayment.setMerConfigId(merchantAppConfig.getId());
+        liveOrderPaymentMapper.insertLiveOrderPayment(storePayment);
+
+        if (!"hf".equals(merchantAppConfig.getMerchantType()) && !"appPay".equals(merchantAppConfig.getMerchantType())) {
+            return R.error("支付暂不可用!");
+        }
+
+        if ("hf".equals(merchantAppConfig.getMerchantType())) {
+            HuiFuCreateOrder o = new HuiFuCreateOrder();
+            o.setTradeType("wx".equals(param.getPayType()) ? "T_MINIAPP" : "A_NATIVE");
+            o.setOpenid(openId);
+            o.setAppId(appId);
+            o.setReqSeqId("applive-" + storePayment.getPayCode());
+            o.setTransAmt(storePayment.getPayMoney().toString());
+            o.setGoodsDesc("直播订单app支付");
+            HuifuCreateOrderResult result = huiFuService.createOrder(o);
+            if (result.getResp_code() != null && (result.getResp_code().equals("00000000") || result.getResp_code().equals("00000100"))) {
+                LiveOrderPayment mt = new LiveOrderPayment();
+                mt.setPaymentId(storePayment.getPaymentId());
+                mt.setTradeNo(result.getHf_seq_id());
+                mt.setAppId(appId);
+                liveOrderPaymentMapper.updateLiveOrderPayment(mt);
+                redisCache.setCacheObject("isPaying:" + order.getOrderId(), order.getOrderId().toString(), 1, TimeUnit.MINUTES);
+                Map<String, Object> resultMap = JSON.parseObject(result.getPay_info(), new TypeReference<Map<String, Object>>() {
+                });
+                if (resultMap != null && resultMap.get("package") != null) {
+                    resultMap.put("packageValue", resultMap.get("package"));
+                }
+                return R.ok().put("payType", param.getOrderPayType()).put("data", resultMap).put("type", "hf").put("isPay", 0);
+            }
+            return R.error(result.getResp_desc());
+        } else if ("appPay".equals(merchantAppConfig.getMerchantType()) && "wx".equals(param.getPayType())) {
+            WxPayConfig payConfig = new WxPayConfig();
+            payConfig.setAppId(appId);
+            payConfig.setMchId(fsPayConfig.getWxAppMchId());
+            payConfig.setMchKey(fsPayConfig.getWxAppMchKey());
+            payConfig.setSubAppId(org.apache.commons.lang3.StringUtils.trimToNull(null));
+            payConfig.setSubMchId(org.apache.commons.lang3.StringUtils.trimToNull(null));
+            payConfig.setKeyPath(null);
+            payConfig.setNotifyUrl(fsPayConfig.getWxAppNotifyUrl());
+            wxPayService.setConfig(payConfig);
+            WxPayUnifiedOrderRequest orderRequest = new WxPayUnifiedOrderRequest();
+            orderRequest.setBody("直播订单app支付");
+            orderRequest.setOutTradeNo("applive-" + storePayment.getPayCode());
+            orderRequest.setTotalFee(WxPayUnifiedOrderRequest.yuanToFen(storePayment.getPayMoney().toString()));
+            orderRequest.setTradeType("APP");
+            orderRequest.setSpbillCreateIp(IpUtils.getIpAddr(request));
+            orderRequest.setNotifyUrl(fsPayConfig.getNotifyUrlScrm());
+            try {
+                log.info("直播订单app支付 调用微信入参:{}", orderRequest);
+                Object result = wxPayService.createOrder(orderRequest);
+                redisCache.setCacheObject("isPaying:" + order.getOrderId(), order.getOrderId().toString(), 1, TimeUnit.MINUTES);
+                return R.ok().put("data", result).put("type", "wxApp").put("isPay", 0).put("payType", param.getOrderPayType());
+            } catch (WxPayException e) {
+                log.error("直播订单app支付失败", e);
+                throw new CustomException("直播订单app支付" + e.getMessage());
+            }
+        } else if ("appPay".equals(merchantAppConfig.getMerchantType()) && "ali".equals(param.getPayType())) {
+            AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do", fsPayConfig.getAliAppId(), fsPayConfig.getAliPrivateKey(), "json", "utf-8", fsPayConfig.getAliPublicKey(), "RSA2");
+            AlipayTradeAppPayRequest aliRequest = new AlipayTradeAppPayRequest();
+            AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
+            model.setOutTradeNo("applive-" + storePayment.getPayCode());
+            model.setTotalAmount(storePayment.getPayMoney().toString());
+            model.setSubject("直播订单app支付");
+            aliRequest.setBizModel(model);
+            aliRequest.setNotifyUrl(fsPayConfig.getAliNotifyUrl());
+            try {
+                log.info("直播订单app支付 调用支付宝入参:{}", aliRequest);
+                AlipayTradeAppPayResponse result = alipayClient.sdkExecute(aliRequest);
+                if (!result.isSuccess()) {
+                    String diagnosisUrl = DiagnosisUtils.getDiagnosisUrl(result);
+                    log.error("支付宝支付调用失败 诊断链接:{}", diagnosisUrl);
+                    throw new CustomException(result.getSubMsg());
+                }
+                redisCache.setCacheObject("isPaying:" + order.getOrderId(), order.getOrderId().toString(), 1, TimeUnit.MINUTES);
+                return R.ok().put("isPay", 0).put("data", result).put("type", "aliPay").put("payType", param.getOrderPayType());
+            } catch (CustomException e) {
+                throw e;
+            } catch (Exception e) {
+                log.error("支付宝支付异常", e);
+                throw new CustomException("支付系统异常,请稍后重试");
+            }
+        }
+
+        return R.error("支付暂不可用!");
+    }
+
     @Override
     public List<LiveOrder> selectLiveOrderItemJson() {
         return baseMapper.selectLiveOrderItemJson();

+ 1 - 1
fs-service/src/main/java/com/fs/qw/service/impl/QwUserServiceImpl.java

@@ -1236,7 +1236,7 @@ public class QwUserServiceImpl implements IQwUserService
         }
         WxWorkSetCallbackUrlDTO wxWorkSetCallbackUrlDTO = new WxWorkSetCallbackUrlDTO();
         System.out.println("回调地址"+aiHostProper.getIpadUrl()+"/msg/callback/"+serverId);
-        wxWorkSetCallbackUrlDTO.setUrl(aiHostProper.getIpadUrl()+"/msg/callback/"+serverId);
+        wxWorkSetCallbackUrlDTO.setUrl(aiHostProper.getIpadUrl()+"/msg/callback/"+serverId+"/"+false);
         wxWorkSetCallbackUrlDTO.setUuid(data.getUuid());
         wxWorkService.SetCallbackUrl(wxWorkSetCallbackUrlDTO,serverId);
 

+ 15 - 6
fs-service/src/main/resources/mapper/course/FsUserCourseFavoriteMapper.xml

@@ -3,7 +3,7 @@
 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper namespace="com.fs.course.mapper.FsUserCourseFavoriteMapper">
-    
+
     <resultMap type="FsUserCourseFavorite" id="FsUserCourseFavoriteResult">
         <result property="favoriteId"    column="favorite_id"    />
         <result property="userId"    column="user_id"    />
@@ -18,17 +18,17 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 
     <select id="selectFsUserCourseFavoriteList" parameterType="FsUserCourseFavorite" resultMap="FsUserCourseFavoriteResult">
         <include refid="selectFsUserCourseFavoriteVo"/>
-        <where>  
+        <where>
             <if test="userId != null "> and user_id = #{userId}</if>
             <if test="courseId != null "> and course_id = #{courseId}</if>
         </where>
     </select>
-    
+
     <select id="selectFsUserCourseFavoriteByFavoriteId" parameterType="Long" resultMap="FsUserCourseFavoriteResult">
         <include refid="selectFsUserCourseFavoriteVo"/>
         where favorite_id = #{favoriteId}
     </select>
-        
+
     <insert id="insertFsUserCourseFavorite" parameterType="FsUserCourseFavorite" useGeneratedKeys="true" keyProperty="favoriteId">
         insert into fs_user_course_favorite
         <trim prefix="(" suffix=")" suffixOverrides=",">
@@ -61,9 +61,18 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
     </delete>
 
     <delete id="deleteFsUserCourseFavoriteByFavoriteIds" parameterType="String">
-        delete from fs_user_course_favorite where favorite_id in 
+        delete from fs_user_course_favorite where favorite_id in
         <foreach item="favoriteId" collection="array" open="(" separator="," close=")">
             #{favoriteId}
         </foreach>
     </delete>
-</mapper>
+
+
+    <delete id="deleteBatchFavorite">
+        delete from fs_user_course_favorite  where course_id in
+        <foreach collection="courseIds" item="courseId" separator="," open="(" close=")">
+            #{courseId}
+        </foreach>
+        and user_id=#{userId}
+    </delete>
+</mapper>

+ 6 - 1
fs-service/src/main/resources/mapper/course/FsUserCourseMapper.xml

@@ -385,7 +385,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             #{item.courseId}
         </foreach>
     </update>
-
+    <update id="minusBatchFavorite">
+        update fs_user_course set favorite_num=favorite_num-1 where course_id in
+        <foreach collection="courseIds" item="courseId" open="(" close=")" separator=",">
+            #{courseId}
+        </foreach>
+    </update>
     <!--    <select id="getFsUserCourseList" resultType="com.fs.course.vo.newfs.FsUserCourseListVO">-->
 <!--        SELECT-->
 <!--        c.*,-->

+ 10 - 0
fs-user-app/src/main/java/com/fs/app/controller/CourseController.java

@@ -281,6 +281,16 @@ public class CourseController extends  AppBaseController{
         }
 
     }
+    @Login
+    @ApiOperation("批量取消收藏")
+    @PostMapping("/cancelFavorite")
+    @Transactional
+    public R cancelFavorite(@RequestBody List<Long> courseIds){
+        //取消点赞
+        courseFavoriteService.deleteBatchFavorite(courseIds,Long.parseLong(getUserId()));
+        courseService.minusBatchFavorite(courseIds);
+        return R.ok("已取消收藏");
+    }
 
     @Login
     @ApiOperation("点赞")

+ 3 - 0
fs-user-app/src/main/java/com/fs/app/controller/HuifuPayController.java

@@ -123,6 +123,9 @@ public class HuifuPayController {
 //                        logger.error("-------分账明细回调错误{}", e.getMessage());
 //                    }
                     break;
+                case "applive":
+                    liveOrderService.payConfirm(1,null,orderId[1], huiFuResult.getHf_seq_id(),huiFuResult.getOut_trans_id(),huiFuResult.getParty_order_id());
+                    break;
             }
         }
 

+ 43 - 0
fs-user-app/src/main/java/com/fs/app/controller/live/LiveOrderController.java

@@ -38,6 +38,7 @@ import com.fs.live.domain.LiveOrderPayment;
 import com.fs.live.dto.LiveOrderComputeDTO;
 import com.fs.live.mapper.LiveOrderPaymentMapper;
 import com.fs.live.param.FsMyLiveOrderQueryParam;
+import com.fs.live.param.LiveOrderAppPayParam;
 import com.fs.live.param.LiveOrderComputedParam;
 import com.fs.live.param.LiveOrderConfirmParam;
 import com.fs.live.param.LiveOrderPayParam;
@@ -381,6 +382,48 @@ public class LiveOrderController extends AppBaseController
         return result;
     }
 
+    @Login
+    @ApiOperation("app支付")
+    @PostMapping("/appPayment")
+    public R appPayment(HttpServletRequest request, @Validated @RequestBody LiveOrderAppPayParam param) {
+        if (StringUtils.isEmpty(param.getAppId())) {
+            return R.error("appId不能为空");
+        }
+        Long orderId = param.getOrderId();
+        logger.info("开始处理直播app支付请求, 订单号: {}, 支付渠道: {}, 订单支付方式: {}", orderId, param.getPayType(), param.getOrderPayType());
+        try {
+            Long existPayedRecordId = orderService.isExistPayedRecord(param.getOrderId());
+            if (null != existPayedRecordId) {
+                orderService.payConfirmPayment(existPayedRecordId);
+                return R.error("当前订单已支付");
+            }
+        } catch (Exception ex) {
+            log.error("校验当前订单是否存在已经支付的支付记录异常,param:{}", param, ex);
+        }
+
+        RLock lock = redissonClient.getLock(String.format(LOCK_KEY_PAY, orderId));
+        try {
+            boolean locked = lock.tryLock(100, 30000, TimeUnit.MILLISECONDS);
+            if (!locked) {
+                logger.warn("订单正在处理中,获取锁失败, 订单号: {}", orderId);
+                return R.error("订单正在处理中,请勿重复提交");
+            }
+            return orderService.appPayment(param, request);
+        } catch (InterruptedException e) {
+            logger.error("获取支付锁的过程被中断, 订单号: {}", orderId, e);
+            Thread.currentThread().interrupt();
+            return R.error("支付处理被中断,请稍后重试");
+        } catch (Throwable e) {
+            logger.error("app支付过程中发生异常, 订单号: {}", orderId, e);
+            throw e;
+        } finally {
+            if (lock.isHeldByCurrentThread()) {
+                lock.unlock();
+                logger.debug("app支付锁已释放, 订单号: {}", orderId);
+            }
+        }
+    }
+
     @Login
     @ApiOperation("取消支付")
     @PostMapping("/cancelPay")

+ 3 - 0
fs-user-app/src/main/java/com/fs/app/controller/store/PayScrmController.java

@@ -109,6 +109,9 @@ public class PayScrmController {
 //                        logger.error("-------分账明细回调错误{}", e.getMessage());
 //                    }
                     break;
+                case "applive":
+                    liveOrderService.payConfirm(1,null,order[1], o.getHf_seq_id(),o.getOut_trans_id(),o.getParty_order_id());
+                    break;
             }
 
         }

+ 8 - 2
fs-user-app/src/main/java/com/fs/framework/config/SecurityConfig.java

@@ -6,8 +6,11 @@ import org.springframework.security.config.BeanIds;
 import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
 import org.springframework.security.config.annotation.web.builders.HttpSecurity;
 import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+import org.springframework.security.web.firewall.HttpFirewall;
 import org.springframework.security.web.firewall.StrictHttpFirewall;
 
+import java.util.Arrays;
+
 /**
  * spring security配置
  *
@@ -47,10 +50,13 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
         return super.authenticationManagerBean();
     }
     @Bean
-    public StrictHttpFirewall httpFirewall() {
+    public HttpFirewall httpFirewall() {
         StrictHttpFirewall firewall = new StrictHttpFirewall();
-        // 允许URL编码的双斜杠
         firewall.setAllowUrlEncodedDoubleSlash(true);
+        firewall.setAllowedHttpMethods(Arrays.asList(
+                "GET", "POST", "PUT", "DELETE", "HEAD", "OPTIONS", "PATCH",
+                "PROPFIND", "PROPPATCH", "MKCOL", "COPY", "MOVE", "LOCK", "UNLOCK", "SEARCH"
+        ));
         return firewall;
     }